diff --git a/components/lwp/lwp_user_mm.c b/components/lwp/lwp_user_mm.c index 18f10e176fe..6531b433084 100644 --- a/components/lwp/lwp_user_mm.c +++ b/components/lwp/lwp_user_mm.c @@ -504,6 +504,38 @@ void *lwp_user_memory_remap_to_kernel(rt_lwp_t lwp, void *uaddr, size_t length) return kaddr; } +static int _validate_mmap_flags(void *addr, int flags, int fd) { + rt_err_t rc = RT_EOK; + if (!flags) { + rc = -RT_EINVAL; + LOG_E("Invalid flags: flags cannot be 0. At least MAP_PRIVATE or MAP_SHARED is required."); + goto err; + } + + if ((flags & MAP_PRIVATE) && (flags & MAP_SHARED)) { + rc = -RT_EINVAL; + LOG_E("Invalid flags: MAP_PRIVATE and MAP_SHARED cannot be used together."); + goto err; + } + if ((flags & MAP_ANON) && !(flags & (MAP_PRIVATE | MAP_SHARED))) { + rc = -RT_EINVAL; + LOG_E("Invalid flags: MAP_ANON must be used with MAP_PRIVATE or MAP_SHARED."); + goto err; + } + if ((flags & MAP_FIXED) && (addr == NULL)) { + rc = -RT_EINVAL; + LOG_E("Invalid flags: MAP_FIXED requires a valid non-null address."); + goto err; + } + if ((flags & MAP_ANON) && (fd != -1)) { + rc = -RT_EINVAL; + LOG_E("Invalid flags: MAP_ANON requires fd to be -1.\n"); + goto err; + } +err: + return rc; +} + void *lwp_mmap2(struct rt_lwp *lwp, void *addr, size_t length, int prot, int flags, int fd, off_t pgoffset) { @@ -516,6 +548,13 @@ void *lwp_mmap2(struct rt_lwp *lwp, void *addr, size_t length, int prot, void *ret = 0; LOG_D("%s(addr=0x%lx,length=%ld,fd=%d)", __func__, addr, length, fd); + rc = _validate_mmap_flags(addr, flags, fd); + if(rc != RT_EOK) + { + ret = (void *)lwp_errno_to_posix(rc); + return ret; + } + if (fd == -1) { /** @@ -569,6 +608,11 @@ void *lwp_mmap2(struct rt_lwp *lwp, void *addr, size_t length, int prot, ret = (void *)lwp_errno_to_posix(rc); } } + else + { + rc = -RT_EINVAL; + ret = (void *)lwp_errno_to_posix(rc); + } } if ((long)ret <= 0) @@ -581,6 +625,14 @@ int lwp_munmap(struct rt_lwp *lwp, void *addr, size_t length) int ret; RT_ASSERT(lwp); + long offset = 0; + if ((rt_base_t)addr & ARCH_PAGE_MASK) + { + offset = (char *)addr - (char *)RT_ALIGN_DOWN((rt_base_t)addr, ARCH_PAGE_SIZE); + length += offset; + addr = (void *)RT_ALIGN_DOWN((rt_base_t)addr, ARCH_PAGE_SIZE); + + } ret = rt_aspace_unmap_range(lwp->aspace, addr, length); return lwp_errno_to_posix(ret); } diff --git a/components/mm/mm_aspace.c b/components/mm/mm_aspace.c index 38abc9002fc..0d7b139461a 100644 --- a/components/mm/mm_aspace.c +++ b/components/mm/mm_aspace.c @@ -31,6 +31,7 @@ #include #define ALIGNED(addr) (!((rt_size_t)(addr) & ARCH_PAGE_MASK)) +#define RESET_POINTER(ptr) ((ptr) = RT_NULL) static void *_find_free(rt_aspace_t aspace, void *prefer, rt_size_t req_size, void *limit_start, rt_size_t limit_size, @@ -656,6 +657,15 @@ static inline int _not_in_range(rt_size_t flags, void *start, rt_size_t length, return rc; } +static inline int _check_addr_overflow(rt_size_t flags, void *start, rt_size_t length, + void *limit_start, rt_size_t limit_size) +{ + rt_bool_t isfixednotset = (flags & MMF_MAP_FIXED) == RT_NULL; + if(isfixednotset && start != RT_NULL) + return (_IS_OVERFLOW(start, length) && _IS_OVERSIZE(start, length, limit_start, limit_size)); + return RT_EOK; +} + static inline int _not_align(void *start, rt_size_t length, rt_size_t mask) { return (start != RT_NULL) && @@ -684,16 +694,24 @@ int rt_aspace_map(rt_aspace_t aspace, void **addr, rt_size_t length, LOG_I("%s(%p, %p, %lx, %lx, %lx, %p, %lx): Invalid input", __func__, aspace, addr, length, attr, flags, mem_obj, offset); } - else if (_not_in_range(flags, *addr, length, aspace->start, aspace->size)) - { - err = -RT_EINVAL; - LOG_I("%s(addr:%p, len:%lx): out of range", __func__, *addr, length); - } else if (_not_support(flags)) { LOG_I("%s: no support flags 0x%lx", __func__, flags); err = -RT_ENOSYS; } + else if (_check_addr_overflow(flags, *addr, length, aspace->start, aspace->size)) + { + // When the address like -1, it serves as a placeholder indicating that the system should assign a suitable valid address. + // The system will not use -1 as an actual memory address. + RT_ASSERT((length & ARCH_PAGE_MASK) == 0); + RESET_POINTER(*addr); + err = _mm_aspace_map(aspace, &varea, addr, length, attr, flags, mem_obj, offset); + } + else if (_not_in_range(flags, *addr, length, aspace->start, aspace->size)) + { + err = -RT_EINVAL; + LOG_I("%s(addr:%p, len:%lx): out of range", __func__, *addr, length); + } else { RT_ASSERT((length & ARCH_PAGE_MASK) == 0);