diff --git a/arch/x86_64/kernel/syscall.c b/arch/x86_64/kernel/syscall.c index d01dcdc4..2f76662b 100644 --- a/arch/x86_64/kernel/syscall.c +++ b/arch/x86_64/kernel/syscall.c @@ -1702,13 +1702,18 @@ SYSCALL_DECLARE(mmap) } #define VALID_DUMMY_ADDR ((region->user_start + PTL3_SIZE - 1) & ~(PTL3_SIZE - 1)) - addr = (flags & MAP_FIXED)? addr0: VALID_DUMMY_ADDR; + addr = addr0; len = (len0 + pgsize - 1) & ~(pgsize - 1); +recheck: if ((addr & (pgsize - 1)) || (len == 0) || !(flags & (MAP_SHARED | MAP_PRIVATE)) || ((flags & MAP_SHARED) && (flags & MAP_PRIVATE)) || (off0 & (pgsize - 1))) { + if (!(flags & MAP_FIXED) && addr != VALID_DUMMY_ADDR) { + addr = VALID_DUMMY_ADDR; + goto recheck; + } ekprintf("sys_mmap(%lx,%lx,%x,%x,%x,%lx):EINVAL\n", addr0, len0, prot, flags0, fd, off0); error = -EINVAL; @@ -1718,6 +1723,10 @@ SYSCALL_DECLARE(mmap) if (addr < region->user_start || region->user_end <= addr || len > (region->user_end - region->user_start)) { + if (!(flags & MAP_FIXED) && addr != VALID_DUMMY_ADDR) { + addr = VALID_DUMMY_ADDR; + goto recheck; + } ekprintf("sys_mmap(%lx,%lx,%x,%x,%x,%lx):ENOMEM\n", addr0, len0, prot, flags0, fd, off0); error = -ENOMEM; diff --git a/kernel/syscall.c b/kernel/syscall.c index 182dab66..ce9e208c 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -1533,13 +1533,21 @@ static int search_free_space(size_t len, int pgshift, uintptr_t *addrp) struct thread *thread = cpu_local_var(current); struct vm_regions *region = &thread->vm->region; intptr_t addr; - int error; + int error = 0; struct vm_range *range; size_t pgsize = (size_t)1 << pgshift; dkprintf("%s: len: %lu, pgshift: %d\n", __FUNCTION__, len, pgshift); + /* try given addr first */ + addr = *addrp; + if (addr != 0) { + range = lookup_process_memory_range(thread->vm, addr, addr+len); + if (range == NULL) + goto out; + } + addr = region->map_end; for (;;) { addr = (addr + pgsize - 1) & ~(pgsize - 1); @@ -1560,7 +1568,6 @@ static int search_free_space(size_t len, int pgshift, uintptr_t *addrp) } region->map_end = addr + len; - error = 0; *addrp = addr; out: