Index: sys/amd64/amd64/exec_machdep.c =================================================================== --- sys/amd64/amd64/exec_machdep.c +++ sys/amd64/amd64/exec_machdep.c @@ -77,6 +77,7 @@ #include #include #include +#include #ifdef DDB #ifndef KDB @@ -203,7 +204,7 @@ fpstate_drop(td); regs->tf_rsp = (long)sfp; - regs->tf_rip = p->p_sysent->sv_sigcode_base; + regs->tf_rip = PROC_SIGCODE(p); regs->tf_rflags &= ~(PSL_T | PSL_D); regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; Index: sys/amd64/ia32/ia32_signal.c =================================================================== --- sys/amd64/ia32/ia32_signal.c +++ sys/amd64/ia32/ia32_signal.c @@ -535,7 +535,7 @@ } regs->tf_rsp = (uintptr_t)sfp; - regs->tf_rip = p->p_sysent->sv_sigcode_base + + regs->tf_rip = PROC_SIGCODE(p) + VDSO_FREEBSD4_IA32_SIGCODE_OFFSET - VDSO_IA32_SIGCODE_OFFSET; regs->tf_rflags &= ~(PSL_T | PSL_D); regs->tf_cs = _ucode32sel; @@ -670,7 +670,7 @@ fpstate_drop(td); regs->tf_rsp = (uintptr_t)sfp; - regs->tf_rip = p->p_sysent->sv_sigcode_base; + regs->tf_rip = PROC_SIGCODE(p); regs->tf_rflags &= ~(PSL_T | PSL_D); regs->tf_cs = _ucode32sel; regs->tf_ss = _udatasel; Index: sys/amd64/linux/linux_sysvec.c =================================================================== --- sys/amd64/linux/linux_sysvec.c +++ sys/amd64/linux/linux_sysvec.c @@ -772,7 +772,7 @@ tkoff = kern_timekeep_base - linux_vdso_base; ktimekeep_base = (l_uintptr_t *)(linux_vdso_mapping + tkoff); - *ktimekeep_base = sv->sv_timekeep_base; + *ktimekeep_base = sv->sv_shared_page_base + sv->sv_timekeep_offset; tkoff = kern_tsc_selector - linux_vdso_base; ktsc_selector = (l_uintptr_t *)(linux_vdso_mapping + tkoff); Index: sys/amd64/linux32/linux32_sysvec.c =================================================================== --- sys/amd64/linux32/linux32_sysvec.c +++ sys/amd64/linux32/linux32_sysvec.c @@ -924,7 +924,7 @@ tkoff = kern_timekeep_base - linux_vdso_base; ktimekeep_base = (l_uintptr_t *)(linux_vdso_mapping + tkoff); - *ktimekeep_base = sv->sv_timekeep_base; + *ktimekeep_base = sv->sv_shared_page_base + sv->sv_timekeep_offset; tkoff = kern_tsc_selector - linux_vdso_base; ktsc_selector = (l_uintptr_t *)(linux_vdso_mapping + tkoff); Index: sys/arm/arm/exec_machdep.c =================================================================== --- sys/arm/arm/exec_machdep.c +++ sys/arm/arm/exec_machdep.c @@ -346,8 +346,8 @@ tf->tf_pc = (register_t)catcher; tf->tf_usr_sp = (register_t)fp; sysent = p->p_sysent; - if (sysent->sv_sigcode_base != 0) - tf->tf_usr_lr = (register_t)sysent->sv_sigcode_base; + if (sysent->sv_shared_page_base != 0) + tf->tf_usr_lr = (register_t)PROC_SIGCODE(p); else tf->tf_usr_lr = (register_t)(PROC_PS_STRINGS(p) - *(sysent->sv_szsigcode)); Index: sys/arm64/arm64/exec_machdep.c =================================================================== --- sys/arm64/arm64/exec_machdep.c +++ sys/arm64/arm64/exec_machdep.c @@ -50,6 +50,8 @@ #include #include +#include +#include #include #include @@ -626,7 +628,7 @@ tf->tf_x[2] = (register_t)&fp->sf_uc; tf->tf_x[8] = (register_t)catcher; tf->tf_sp = (register_t)fp; - tf->tf_elr = (register_t)p->p_sysent->sv_sigcode_base; + tf->tf_elr = (register_t)PROC_SIGCODE(p); /* Clear the single step flag while in the signal handler */ if ((td->td_pcb->pcb_flags & PCB_SINGLE_STEP) != 0) { Index: sys/arm64/arm64/freebsd32_machdep.c =================================================================== --- sys/arm64/arm64/freebsd32_machdep.c +++ sys/arm64/arm64/freebsd32_machdep.c @@ -418,8 +418,8 @@ tf->tf_elr = (register_t)catcher; tf->tf_x[13] = (register_t)fp; sysent = p->p_sysent; - if (sysent->sv_sigcode_base != 0) - tf->tf_x[14] = (register_t)sysent->sv_sigcode_base; + if (sysent->sv_shared_page_base != 0) + tf->tf_x[14] = (register_t)PROC_SIGCODE(p); else tf->tf_x[14] = (register_t)(PROC_PS_STRINGS(p) - *(sysent->sv_szsigcode)); Index: sys/arm64/linux/linux_sysvec.c =================================================================== --- sys/arm64/linux/linux_sysvec.c +++ sys/arm64/linux/linux_sysvec.c @@ -619,7 +619,7 @@ tkoff = kern_timekeep_base - linux_vdso_base; ktimekeep_base = (l_uintptr_t *)(linux_vdso_mapping + tkoff); - *ktimekeep_base = sv->sv_timekeep_base; + *ktimekeep_base = sv->sv_shared_page_base + sv->sv_timekeep_offset; } SYSINIT(elf_linux_exec_sysvec_init, SI_SUB_EXEC + 1, SI_ORDER_ANY, linux_exec_sysvec_init, &elf_linux_sysvec); Index: sys/compat/freebsd32/freebsd32_misc.c =================================================================== --- sys/compat/freebsd32/freebsd32_misc.c +++ sys/compat/freebsd32/freebsd32_misc.c @@ -3525,7 +3525,7 @@ /* * Install sigcode. */ - if (sysent->sv_sigcode_base == 0) { + if (sysent->sv_shared_page_base == 0) { szsigcode = *sysent->sv_szsigcode; destp -= szsigcode; destp = rounddown2(destp, sizeof(uint32_t)); Index: sys/i386/i386/exec_machdep.c =================================================================== --- sys/i386/i386/exec_machdep.c +++ sys/i386/i386/exec_machdep.c @@ -237,8 +237,8 @@ } regs->tf_esp = (int)fp; - if (p->p_sysent->sv_sigcode_base != 0) { - regs->tf_eip = p->p_sysent->sv_sigcode_base + szsigcode - + if (p->p_sysent->sv_shared_page_base != 0) { + regs->tf_eip = PROC_SIGCODE(p) + szsigcode - szosigcode; } else { /* a.out sysentvec does not use shared page */ @@ -363,7 +363,7 @@ } regs->tf_esp = (int)sfp; - regs->tf_eip = p->p_sysent->sv_sigcode_base + szsigcode - + regs->tf_eip = PROC_SIGCODE(p) + szsigcode - szfreebsd4_sigcode; regs->tf_eflags &= ~(PSL_T | PSL_D); regs->tf_cs = _ucodesel; @@ -525,7 +525,7 @@ } regs->tf_esp = (int)sfp; - regs->tf_eip = p->p_sysent->sv_sigcode_base; + regs->tf_eip = PROC_SIGCODE(p); if (regs->tf_eip == 0) regs->tf_eip = PROC_PS_STRINGS(p) - szsigcode; regs->tf_eflags &= ~(PSL_T | PSL_D); Index: sys/i386/linux/linux_sysvec.c =================================================================== --- sys/i386/linux/linux_sysvec.c +++ sys/i386/linux/linux_sysvec.c @@ -866,7 +866,7 @@ tkoff = kern_timekeep_base - linux_vdso_base; ktimekeep_base = (l_uintptr_t *)(linux_vdso_mapping + tkoff); - *ktimekeep_base = sv->sv_timekeep_base; + *ktimekeep_base = sv->sv_shared_page_base + sv->sv_timekeep_offset; tkoff = kern_tsc_selector - linux_vdso_base; ktsc_selector = (l_uintptr_t *)(linux_vdso_mapping + tkoff); Index: sys/kern/imgact_elf.c =================================================================== --- sys/kern/imgact_elf.c +++ sys/kern/imgact_elf.c @@ -209,6 +209,12 @@ __XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE)) ": enable stack address randomization"); +static int __elfN(aslr_shared_page) = __ELF_WORD_SIZE == 64; +SYSCTL_INT(ASLR_NODE_OID, OID_AUTO, shared_page, CTLFLAG_RWTUN, + &__elfN(aslr_shared_page), 0, + __XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE)) + ": enable shared page address randomization"); + static int __elfN(sigfastblock) = 1; SYSCTL_INT(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO, sigfastblock, CTLFLAG_RWTUN, &__elfN(sigfastblock), 0, @@ -1305,6 +1311,8 @@ imgp->map_flags |= MAP_ASLR_IGNSTART; if (__elfN(aslr_stack)) imgp->map_flags |= MAP_ASLR_STACK; + if (__elfN(aslr_shared_page)) + imgp->map_flags |= MAP_ASLR_SHARED_PAGE; } if ((!__elfN(allow_wx) && (fctl0 & NT_FREEBSD_FCTL_WXNEEDED) == 0 && @@ -1433,11 +1441,14 @@ { Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs; Elf_Auxinfo *argarray, *pos; + struct vmspace *vmspace; int error; argarray = pos = malloc(AT_COUNT * sizeof(*pos), M_TEMP, M_WAITOK | M_ZERO); + vmspace = imgp->proc->p_vmspace; + if (args->execfd != -1) AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); @@ -1461,9 +1472,9 @@ AUXARGS_ENTRY_PTR(pos, AT_PAGESIZES, imgp->pagesizes); AUXARGS_ENTRY(pos, AT_PAGESIZESLEN, imgp->pagesizeslen); } - if (imgp->sysent->sv_timekeep_base != 0) { + if ((imgp->sysent->sv_flags & SV_TIMEKEEP) != 0) { AUXARGS_ENTRY(pos, AT_TIMEKEEP, - imgp->sysent->sv_timekeep_base); + vmspace->vm_sp_base + imgp->sysent->sv_timekeep_offset); } AUXARGS_ENTRY(pos, AT_STACKPROT, imgp->sysent->sv_shared_page_obj != NULL && imgp->stack_prot != 0 ? imgp->stack_prot : @@ -1479,10 +1490,16 @@ AUXARGS_ENTRY(pos, AT_ENVC, imgp->args->envc); AUXARGS_ENTRY_PTR(pos, AT_ENVV, imgp->envv); AUXARGS_ENTRY_PTR(pos, AT_PS_STRINGS, imgp->ps_strings); - if (imgp->sysent->sv_fxrng_gen_base != 0) - AUXARGS_ENTRY(pos, AT_FXRNG, imgp->sysent->sv_fxrng_gen_base); - if (imgp->sysent->sv_vdso_base != 0 && __elfN(vdso) != 0) - AUXARGS_ENTRY(pos, AT_KPRELOAD, imgp->sysent->sv_vdso_base); +#ifdef RANDOM_FENESTRASX + if ((imgp->sysent->sv_flags & SV_RNG_SEED_VER) != 0) { + AUXARGS_ENTRY(pos, AT_FXRNG, + vmspace->vm_sp_base + imgp->sysent->sv_fxrng_gen_offset); + } +#endif + if ((imgp->sysent->sv_flags & SV_DSO_SIG) != 0 && __elfN(vdso) != 0) { + AUXARGS_ENTRY(pos, AT_KPRELOAD, + vmspace->vm_sp_base + imgp->sysent->sv_vdso_offset); + } AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); Index: sys/kern/kern_exec.c =================================================================== --- sys/kern/kern_exec.c +++ sys/kern/kern_exec.c @@ -1107,13 +1107,12 @@ if (sv->sv_shared_page_obj == NULL) return; - pmap_remove(vmspace_pmap(vmspace), sv->sv_shared_page_base, - sv->sv_shared_page_base + sv->sv_shared_page_len); + pmap_remove(vmspace_pmap(vmspace), p->p_vmspace->vm_sp_base, + p->p_vmspace->vm_sp_base + sv->sv_shared_page_len); } /* - * Run down the current address space and install a new one. Map the shared - * page. + * Run down the current address space and install a new one. */ int exec_new_vmspace(struct image_params *imgp, struct sysentvec *sv) @@ -1122,7 +1121,6 @@ struct proc *p = imgp->proc; struct vmspace *vmspace = p->p_vmspace; struct thread *td = curthread; - vm_object_t obj; vm_offset_t sv_minuser; vm_map_t map; @@ -1159,7 +1157,8 @@ */ vm_map_lock(map); vm_map_modflags(map, 0, MAP_WIREFUTURE | MAP_ASLR | - MAP_ASLR_IGNSTART | MAP_ASLR_STACK | MAP_WXORX); + MAP_ASLR_IGNSTART | MAP_ASLR_STACK | MAP_ASLR_SHARED_PAGE | + MAP_WXORX); vm_map_unlock(map); } else { error = vmspace_exec(p, sv_minuser, sv->sv_maxuser); @@ -1170,21 +1169,6 @@ } map->flags |= imgp->map_flags; - /* Map a shared page */ - obj = sv->sv_shared_page_obj; - if (obj != NULL) { - vm_object_reference(obj); - error = vm_map_fixed(map, obj, 0, - sv->sv_shared_page_base, sv->sv_shared_page_len, - VM_PROT_READ | VM_PROT_EXECUTE, - VM_PROT_READ | VM_PROT_EXECUTE, - MAP_INHERIT_SHARE | MAP_ACC_NO_CHARGE); - if (error != KERN_SUCCESS) { - vm_object_deallocate(obj); - return (vm_mmap_to_errno(error)); - } - } - return (sv->sv_onexec != NULL ? sv->sv_onexec(p, imgp) : 0); } @@ -1200,9 +1184,11 @@ vm_map_t map; struct vmspace *vmspace; vm_offset_t stack_addr, stack_top; + vm_offset_t sharedpage_addr; u_long ssiz; int error, find_space, stack_off; vm_prot_t stack_prot; + vm_object_t obj; p = imgp->proc; sv = p->p_sysent; @@ -1254,6 +1240,43 @@ stack_top -= rounddown2(stack_off & PAGE_MASK, sizeof(void *)); } + /* Map a shared page */ + obj = sv->sv_shared_page_obj; + if (obj == NULL) { + /* + * No shared page is provided for this ABI, + * e.g. in case of a.out binaries. + */ + sharedpage_addr = 0; + goto out; + } + + /* + * If randomization is disabled the vm logic maps it exactly + * to the specific address (VMFS_NO_SPACE). + * Otherwise it can choose any address above .data section. + * Same logic is used for stack address randomization. + */ + if ((map->flags & MAP_ASLR_SHARED_PAGE) != 0) { + sharedpage_addr = round_page((vm_offset_t)p->p_vmspace->vm_daddr + + lim_max(curthread, RLIMIT_DATA)); + find_space = VMFS_ANY_SPACE; + } else { + sharedpage_addr = sv->sv_shared_page_base; + find_space = VMFS_NO_SPACE; + } + vm_object_reference(obj); + error = vm_map_find(map, obj, 0, + &sharedpage_addr, sv->sv_shared_page_len, + sv->sv_maxuser, find_space, + VM_PROT_READ | VM_PROT_EXECUTE, + VM_PROT_READ | VM_PROT_EXECUTE, + MAP_INHERIT_SHARE | MAP_ACC_NO_CHARGE); + if (error != KERN_SUCCESS) { + vm_object_deallocate(obj); + return (vm_mmap_to_errno(error)); + } +out: /* * vm_ssize and vm_maxsaddr are somewhat antiquated concepts, but they * are still used to enforce the stack rlimit on the process stack. @@ -1261,6 +1284,7 @@ vmspace->vm_maxsaddr = (char *)stack_addr; vmspace->vm_stacktop = stack_top; vmspace->vm_ssize = sgrowsiz >> PAGE_SHIFT; + vmspace->vm_sp_base = sharedpage_addr; return (0); } @@ -1624,7 +1648,7 @@ /* * Install sigcode. */ - if (sysent->sv_sigcode_base == 0 && sysent->sv_szsigcode != NULL) { + if (sysent->sv_shared_page_base == 0 && sysent->sv_szsigcode != NULL) { szsigcode = *(sysent->sv_szsigcode); destp -= szsigcode; destp = rounddown2(destp, sizeof(void *)); Index: sys/kern/kern_proc.c =================================================================== --- sys/kern/kern_proc.c +++ sys/kern/kern_proc.c @@ -3096,9 +3096,9 @@ if ((req->flags & SCTL_MASK32) != 0) { bzero(&kst32, sizeof(kst32)); if (SV_PROC_FLAG(p, SV_ILP32)) { - if (sv->sv_sigcode_base != 0) { - kst32.ksigtramp_start = sv->sv_sigcode_base; - kst32.ksigtramp_end = sv->sv_sigcode_base + + if (sv->sv_shared_page_base != 0) { + kst32.ksigtramp_start = PROC_SIGCODE(p); + kst32.ksigtramp_end = kst32.ksigtramp_start + ((sv->sv_flags & SV_DSO_SIG) == 0 ? *sv->sv_szsigcode : (uintptr_t)sv->sv_szsigcode); @@ -3114,9 +3114,9 @@ } #endif bzero(&kst, sizeof(kst)); - if (sv->sv_sigcode_base != 0) { - kst.ksigtramp_start = (char *)sv->sv_sigcode_base; - kst.ksigtramp_end = (char *)sv->sv_sigcode_base + + if (sv->sv_shared_page_base != 0) { + kst.ksigtramp_start = (char *)PROC_SIGCODE(p); + kst.ksigtramp_end = (char *)kst.ksigtramp_start + ((sv->sv_flags & SV_DSO_SIG) == 0 ? *sv->sv_szsigcode : (uintptr_t)sv->sv_szsigcode); } else { @@ -3245,6 +3245,8 @@ kvm.kvm_map_flags |= KMAP_FLAG_WXORX; if ((vmspace->vm_map.flags & MAP_ASLR_STACK) != 0) kvm.kvm_map_flags |= KMAP_FLAG_ASLR_STACK; + if ((vmspace->vm_map.flags & MAP_ASLR_SHARED_PAGE) != 0) + kvm.kvm_map_flags |= KMAP_FLAG_ASLR_SHARED_PAGE; #ifdef COMPAT_FREEBSD32 if (SV_CURPROC_FLAG(SV_ILP32)) { Index: sys/kern/kern_sharedpage.c =================================================================== --- sys/kern/kern_sharedpage.c +++ sys/kern/kern_sharedpage.c @@ -305,10 +305,6 @@ exec_sysvec_init(void *param) { struct sysentvec *sv; - vm_offset_t sb; -#ifdef RANDOM_FENESTRASX - ptrdiff_t base; -#endif u_int flags; int res; @@ -322,19 +318,18 @@ sv->sv_shared_page_obj = shared_page_obj; if ((flags & SV_ABI_MASK) == SV_ABI_FREEBSD) { if ((flags & SV_DSO_SIG) != 0) { - sb = sv->sv_shared_page_base; res = shared_page_fill((uintptr_t)sv->sv_szsigcode, 16, sv->sv_sigcode); if (res == -1) panic("copying sigtramp to shared page"); - sb += res; - sv->sv_vdso_base = sb; - sb += sv->sv_sigcodeoff; - sv->sv_sigcode_base = sb; + sv->sv_vdso_offset = res; + sv->sv_sigcode_offset = res + sv->sv_sigcodeoff; } else { - sv->sv_sigcode_base = sv->sv_shared_page_base + - shared_page_fill(*(sv->sv_szsigcode), 16, - sv->sv_sigcode); + res = shared_page_fill(*(sv->sv_szsigcode), + 16, sv->sv_sigcode); + if (res == -1) + panic("copying sigtramp to shared page"); + sv->sv_sigcode_offset = res; } } if ((flags & SV_TIMEKEEP) != 0) { @@ -348,8 +343,7 @@ KASSERT(compat32_svtk != NULL, ("Compat32 not registered")); } - sv->sv_timekeep_base = sv->sv_shared_page_base + - compat32_svtk->sv_timekeep_off; + sv->sv_timekeep_offset = compat32_svtk->sv_timekeep_off; } else { #endif if ((flags & SV_ABI_MASK) == SV_ABI_FREEBSD) { @@ -360,8 +354,7 @@ KASSERT(host_svtk != NULL, ("Host not registered")); } - sv->sv_timekeep_base = sv->sv_shared_page_base + - host_svtk->sv_timekeep_off; + sv->sv_timekeep_offset = host_svtk->sv_timekeep_off; #ifdef COMPAT_FREEBSD32 } #endif @@ -375,8 +368,8 @@ */ if (fxrng_shpage_mapping == NULL) alloc_sv_fxrng_generation(); - base = (char *)fxrng_shpage_mapping - shared_page_mapping; - sv->sv_fxrng_gen_base = sv->sv_shared_page_base + base; + sv->sv_fxrng_gen_offset = + (char *)fxrng_shpage_mapping - shared_page_mapping; } #endif } @@ -392,20 +385,13 @@ (sv->sv_flags & SV_RNG_SEED_VER)); sv2->sv_shared_page_obj = sv->sv_shared_page_obj; - sv2->sv_sigcode_base = sv2->sv_shared_page_base + - (sv->sv_sigcode_base - sv->sv_shared_page_base); - if ((sv2->sv_flags & SV_DSO_SIG) != 0) { - sv2->sv_vdso_base = sv2->sv_shared_page_base + - (sv->sv_vdso_base - sv->sv_shared_page_base); - } + sv2->sv_sigcode_offset = sv->sv_sigcode_offset; + if ((sv2->sv_flags & SV_DSO_SIG) != 0) + sv2->sv_vdso_offset = sv->sv_vdso_offset; if ((sv2->sv_flags & SV_ABI_MASK) != SV_ABI_FREEBSD) return; - if ((sv2->sv_flags & SV_TIMEKEEP) != 0) { - sv2->sv_timekeep_base = sv2->sv_shared_page_base + - (sv->sv_timekeep_base - sv->sv_shared_page_base); - } - if ((sv2->sv_flags & SV_RNG_SEED_VER) != 0) { - sv2->sv_fxrng_gen_base = sv2->sv_shared_page_base + - (sv->sv_fxrng_gen_base - sv->sv_shared_page_base); - } + if ((sv2->sv_flags & SV_TIMEKEEP) != 0) + sv2->sv_timekeep_offset = sv->sv_timekeep_offset; + if ((sv2->sv_flags & SV_RNG_SEED_VER) != 0) + sv2->sv_fxrng_gen_offset = sv->sv_fxrng_gen_offset; } Index: sys/powerpc/powerpc/elf32_machdep.c =================================================================== --- sys/powerpc/powerpc/elf32_machdep.c +++ sys/powerpc/powerpc/elf32_machdep.c @@ -52,6 +52,8 @@ #include #include +#include +#include #include #include Index: sys/powerpc/powerpc/elf64_machdep.c =================================================================== --- sys/powerpc/powerpc/elf64_machdep.c +++ sys/powerpc/powerpc/elf64_machdep.c @@ -49,6 +49,8 @@ #include #include +#include +#include #include #include @@ -216,10 +218,10 @@ * exec_sysvec_init_secondary() assumes secondary sysvecs use * identical signal code, and skips allocating a second copy. * Since the ELFv2 trampoline is a strict subset of the ELFv1 code, - * we can work around this by adjusting the base address. This also + * we can work around this by adjusting the offset. This also * avoids two copies of the trampoline code being allocated! */ - elf64_freebsd_sysvec_v2.sv_sigcode_base += + elf64_freebsd_sysvec_v2.sv_sigcode_offset += (uintptr_t)sigcode64_elfv2 - (uintptr_t)&sigcode64; elf64_freebsd_sysvec_v2.sv_szsigcode = &szsigcode64_elfv2; } Index: sys/powerpc/powerpc/elf_common.c =================================================================== --- sys/powerpc/powerpc/elf_common.c +++ sys/powerpc/powerpc/elf_common.c @@ -34,6 +34,7 @@ { Elf_Auxargs *args; Elf_Auxinfo *argarray, *pos; + struct vmspace *vmspace; int error; /* @@ -58,6 +59,8 @@ argarray = pos = malloc(AT_OLD_COUNT * sizeof(*pos), M_TEMP, M_WAITOK | M_ZERO); + vmspace = imgp->proc->p_vmspace; + if (args->execfd != -1) AUXARGS_ENTRY(pos, AT_OLD_EXECFD, args->execfd); AUXARGS_ENTRY(pos, AT_OLD_PHDR, args->phdr); @@ -81,9 +84,9 @@ AUXARGS_ENTRY_PTR(pos, AT_OLD_PAGESIZES, imgp->pagesizes); AUXARGS_ENTRY(pos, AT_OLD_PAGESIZESLEN, imgp->pagesizeslen); } - if (imgp->sysent->sv_timekeep_base != 0) { + if ((imgp->sysent->sv_flags & SV_TIMEKEEP) != 0) { AUXARGS_ENTRY(pos, AT_OLD_TIMEKEEP, - imgp->sysent->sv_timekeep_base); + vmspace->vm_sp_base + imgp->sysent->sv_timekeep_offset); } AUXARGS_ENTRY(pos, AT_OLD_STACKPROT, imgp->sysent->sv_shared_page_obj != NULL && imgp->stack_prot != 0 ? imgp->stack_prot : Index: sys/powerpc/powerpc/exec_machdep.c =================================================================== --- sys/powerpc/powerpc/exec_machdep.c +++ sys/powerpc/powerpc/exec_machdep.c @@ -94,7 +94,10 @@ #include #include +#include +#include #include +#include #ifdef FPU_EMU #include @@ -310,7 +313,7 @@ mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); - tf->srr0 = (register_t)p->p_sysent->sv_sigcode_base; + tf->srr0 = (register_t)PROC_SIGCODE(p); /* * copy the frame out to userland. Index: sys/riscv/riscv/exec_machdep.c =================================================================== --- sys/riscv/riscv/exec_machdep.c +++ sys/riscv/riscv/exec_machdep.c @@ -415,8 +415,8 @@ tf->tf_sp = (register_t)fp; sysent = p->p_sysent; - if (sysent->sv_sigcode_base != 0) - tf->tf_ra = (register_t)sysent->sv_sigcode_base; + if (sysent->sv_shared_page_base != 0) + tf->tf_ra = (register_t)PROC_SIGCODE(p); else tf->tf_ra = (register_t)(PROC_PS_STRINGS(p) - *(sysent->sv_szsigcode)); Index: sys/sys/exec.h =================================================================== --- sys/sys/exec.h +++ sys/sys/exec.h @@ -90,6 +90,14 @@ #define PROC_PS_STRINGS(p) \ ((p)->p_vmspace->vm_stacktop - (p)->p_sysent->sv_psstringssz) +/* + * Address of signal trampoline (in user space). + * This assumes that the sigcode resides in the shared page, which is true + * in all cases, except for a.out binaries. + */ +#define PROC_SIGCODE(p) \ + ((p)->p_vmspace->vm_sp_base + (p)->p_sysent->sv_sigcode_offset) + int exec_map_first_page(struct image_params *); void exec_unmap_first_page(struct image_params *); Index: sys/sys/imgact.h =================================================================== --- sys/sys/imgact.h +++ sys/sys/imgact.h @@ -91,7 +91,7 @@ bool vmspace_destroyed; /* we've blown away original vm space */ bool opened; /* we have opened executable vnode */ bool textset; - u_int map_flags; + vm_flags_t map_flags; }; #ifdef _KERNEL Index: sys/sys/sysent.h =================================================================== --- sys/sys/sysent.h +++ sys/sys/sysent.h @@ -137,19 +137,19 @@ void (*sv_set_syscall_retval)(struct thread *, int); int (*sv_fetch_syscall_args)(struct thread *); const char **sv_syscallnames; - vm_offset_t sv_timekeep_base; + vm_offset_t sv_timekeep_offset; vm_offset_t sv_shared_page_base; vm_offset_t sv_shared_page_len; - vm_offset_t sv_sigcode_base; + vm_offset_t sv_sigcode_offset; void *sv_shared_page_obj; - vm_offset_t sv_vdso_base; + vm_offset_t sv_vdso_offset; void (*sv_schedtail)(struct thread *); void (*sv_thread_detach)(struct thread *); int (*sv_trap)(struct thread *); u_long *sv_hwcap; /* Value passed in AT_HWCAP. */ u_long *sv_hwcap2; /* Value passed in AT_HWCAP2. */ const char *(*sv_machine_arch)(struct proc *); - vm_offset_t sv_fxrng_gen_base; + vm_offset_t sv_fxrng_gen_offset; void (*sv_onexec_old)(struct thread *td); int (*sv_onexec)(struct proc *, struct image_params *); void (*sv_onexit)(struct proc *); Index: sys/sys/user.h =================================================================== --- sys/sys/user.h +++ sys/sys/user.h @@ -625,6 +625,7 @@ #define KMAP_FLAG_ASLR_IGNSTART 0x04 /* ASLR may map into sbrk grow region */ #define KMAP_FLAG_WXORX 0x08 /* W^X mapping policy is enforced */ #define KMAP_FLAG_ASLR_STACK 0x10 /* the stack location is randomized */ +#define KMAP_FLAG_ASLR_SHARED_PAGE 0x20 /* the shared page location is randomized */ struct kinfo_vm_layout { uintptr_t kvm_min_user_addr; Index: sys/vm/vm.h =================================================================== --- sys/vm/vm.h +++ sys/vm/vm.h @@ -88,6 +88,8 @@ #define VM_PROT_RW (VM_PROT_READ|VM_PROT_WRITE) #define VM_PROT_DEFAULT VM_PROT_ALL +typedef uint16_t vm_flags_t; + enum obj_type { OBJT_DEFAULT, OBJT_SWAP, Index: sys/vm/vm_map.h =================================================================== --- sys/vm/vm_map.h +++ sys/vm/vm_map.h @@ -79,7 +79,6 @@ * vm_map_entry_t an entry in an address map. */ -typedef u_char vm_flags_t; typedef u_int vm_eflags_t; /* @@ -230,6 +229,7 @@ #define MAP_REPLENISH 0x20 /* kmapent zone needs to be refilled */ #define MAP_WXORX 0x40 /* enforce W^X */ #define MAP_ASLR_STACK 0x80 /* stack location is randomized */ +#define MAP_ASLR_SHARED_PAGE 0x100 /* shared page location is randomized */ #ifdef _KERNEL #if defined(KLD_MODULE) && !defined(KLD_TIED) @@ -295,6 +295,7 @@ caddr_t vm_daddr; /* (c) user virtual address of data */ caddr_t vm_maxsaddr; /* user VA at max stack growth */ vm_offset_t vm_stacktop; /* top of the stack, may not be page-aligned */ + vm_offset_t vm_sp_base; /* shared page address */ u_int vm_refcnt; /* number of references */ /* * Keep the PMAP last, so that CPU-specific variations of that Index: sys/vm/vm_map.c =================================================================== --- sys/vm/vm_map.c +++ sys/vm/vm_map.c @@ -4264,6 +4264,7 @@ vm2->vm_daddr = vm1->vm_daddr; vm2->vm_maxsaddr = vm1->vm_maxsaddr; vm2->vm_stacktop = vm1->vm_stacktop; + vm2->vm_sp_base = vm1->vm_sp_base; vm_map_lock(old_map); if (old_map->busy) vm_map_wait_busy(old_map); @@ -4282,7 +4283,7 @@ new_map->anon_loc = old_map->anon_loc; new_map->flags |= old_map->flags & (MAP_ASLR | MAP_ASLR_IGNSTART | - MAP_ASLR_STACK | MAP_WXORX); + MAP_ASLR_STACK | MAP_ASLR_SHARED_PAGE | MAP_WXORX); VM_MAP_ENTRY_FOREACH(old_entry, old_map) { if ((old_entry->eflags & MAP_ENTRY_IS_SUB_MAP) != 0) Index: tests/sys/kern/kern_copyin.c =================================================================== --- tests/sys/kern/kern_copyin.c +++ tests/sys/kern/kern_copyin.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -104,6 +105,8 @@ { char template[] = "copyin.XXXXXX"; uintptr_t maxuser; + size_t size; + void *addr; #if defined(__mips__) /* @@ -119,6 +122,16 @@ #else maxuser = VM_MAXUSER_ADDRESS; #endif + size = sysconf(_SC_PAGESIZE); + + /* + * Since the shared page address can be randomized we need to make + * sure that something is mapped at the top of the user address space. + * Otherwise reading bytes from maxuser-X will fail rendering this test + * useless. + */ + addr = mmap((void *)(maxuser - size), size, PROT_READ, + MAP_ANON | MAP_FIXED | MAP_EXCL, -1, 0); scratch_file = mkstemp(template); ATF_REQUIRE(scratch_file != -1); @@ -141,6 +154,9 @@ ATF_CHECK(copyin_checker(ADDR_SIGNED, 1) == EFAULT); ATF_CHECK(copyin_checker2(ADDR_SIGNED) == EFAULT); #endif + + if (addr != MAP_FAILED) + munmap(addr, PAGE_SIZE); } ATF_TP_ADD_TCS(tp)