Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153331200
D35349.id106468.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D35349.id106468.diff
View Options
Index: sys/amd64/amd64/exec_machdep.c
===================================================================
--- sys/amd64/amd64/exec_machdep.c
+++ sys/amd64/amd64/exec_machdep.c
@@ -77,6 +77,7 @@
#include <vm/vm_param.h>
#include <vm/vm_extern.h>
#include <vm/pmap.h>
+#include <vm/vm_map.h>
#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/arm/arm/exec_machdep.c
===================================================================
--- sys/arm/arm/exec_machdep.c
+++ sys/arm/arm/exec_machdep.c
@@ -347,7 +347,7 @@
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;
+ tf->tf_usr_lr = 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 <vm/vm.h>
#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
#include <machine/armreg.h>
#include <machine/kdb.h>
@@ -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
@@ -419,7 +419,7 @@
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;
+ 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/i386/i386/exec_machdep.c
===================================================================
--- sys/i386/i386/exec_machdep.c
+++ sys/i386/i386/exec_machdep.c
@@ -238,7 +238,7 @@
regs->tf_esp = (int)fp;
if (p->p_sysent->sv_sigcode_base != 0) {
- regs->tf_eip = p->p_sysent->sv_sigcode_base + szsigcode -
+ 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/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);
@@ -1463,7 +1474,7 @@
}
if (imgp->sysent->sv_timekeep_base != 0) {
AUXARGS_ENTRY(pos, AT_TIMEKEEP,
- imgp->sysent->sv_timekeep_base);
+ imgp->sysent->sv_timekeep_base - vmspace->vm_sp_offset);
}
AUXARGS_ENTRY(pos, AT_STACKPROT, imgp->sysent->sv_shared_page_obj
!= NULL && imgp->stack_prot != 0 ? imgp->stack_prot :
@@ -1480,9 +1491,11 @@
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);
+ AUXARGS_ENTRY(pos, AT_FXRNG,
+ imgp->sysent->sv_fxrng_gen_base - vmspace->vm_sp_offset);
if (imgp->sysent->sv_vdso_base != 0 && __elfN(vdso) != 0)
- AUXARGS_ENTRY(pos, AT_KPRELOAD, imgp->sysent->sv_vdso_base);
+ AUXARGS_ENTRY(pos, AT_KPRELOAD,
+ imgp->sysent->sv_vdso_base - vmspace->vm_sp_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
@@ -1098,6 +1098,7 @@
{
struct vmspace *vmspace;
struct sysentvec *sv;
+ vm_offset_t base;
vmspace = p->p_vmspace;
if (refcount_load(&vmspace->vm_refcnt) != 1)
@@ -1107,13 +1108,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);
+ base = sv->sv_shared_page_base - p->p_vmspace->vm_sp_offset;
+ pmap_remove(vmspace_pmap(vmspace), base, 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 +1122,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 +1158,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 +1170,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 +1185,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 +1241,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.
@@ -1262,6 +1286,15 @@
vmspace->vm_stacktop = stack_top;
vmspace->vm_ssize = sgrowsiz >> PAGE_SHIFT;
+ /*
+ * It's assumed here that the default location of shared page
+ * is at the top of the user address space.
+ * Therefore the (possibly) randomized address has to be smaller.
+ * This should be true for all architectures.
+ */
+ MPASS(sharedpage_addr <= sv->sv_shared_page_base);
+ vmspace->vm_sp_offset = sv->sv_shared_page_base - sharedpage_addr;
+
return (0);
}
Index: sys/kern/kern_proc.c
===================================================================
--- sys/kern/kern_proc.c
+++ sys/kern/kern_proc.c
@@ -3097,8 +3097,8 @@
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 +
+ 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);
@@ -3115,8 +3115,8 @@
#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 +
+ 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/powerpc/powerpc/exec_machdep.c
===================================================================
--- sys/powerpc/powerpc/exec_machdep.c
+++ sys/powerpc/powerpc/exec_machdep.c
@@ -94,7 +94,10 @@
#include <machine/trap.h>
#include <machine/vmparam.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
#include <vm/pmap.h>
+#include <vm/vm_map.h>
#ifdef FPU_EMU
#include <powerpc/fpu/fpu_extern.h>
@@ -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
@@ -416,7 +416,7 @@
sysent = p->p_sysent;
if (sysent->sv_sigcode_base != 0)
- tf->tf_ra = (register_t)sysent->sv_sigcode_base;
+ 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 sv_sigcode_base != 0, which should true for all cases,
+ * except for a.out binaries.
+ */
+#define PROC_SIGCODE(p) \
+ ((p)->p_sysent->sv_sigcode_base - (p)->p_vmspace->vm_sp_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/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_offset; /* shared page offset from the usual location */
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_offset = vm1->vm_sp_offset;
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 <sys/exec.h>
#include <sys/sysctl.h>
#include <sys/user.h>
+#include <sys/mman.h>
#include <errno.h>
#include <fcntl.h>
@@ -104,6 +105,7 @@
{
char template[] = "copyin.XXXXXX";
uintptr_t maxuser;
+ void *addr;
#if defined(__mips__)
/*
@@ -120,6 +122,15 @@
maxuser = VM_MAXUSER_ADDRESS;
#endif
+ /*
+ * Since the shared page address can now 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 - PAGE_SIZE), PAGE_SIZE, PROT_READ,
+ MAP_ANON | MAP_FIXED | MAP_EXCL, -1, 0);
+
scratch_file = mkstemp(template);
ATF_REQUIRE(scratch_file != -1);
unlink(template);
@@ -141,6 +152,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)
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Apr 21, 12:55 PM (1 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31911711
Default Alt Text
D35349.id106468.diff (16 KB)
Attached To
Mode
D35349: [RFC] Shared page address randomization
Attached
Detach File
Event Timeline
Log In to Comment