Skip to content

Commit

Permalink
HBSD: Revert "MFC r343964, r344121, r344128, r344593, r344594:"
Browse files Browse the repository at this point in the history
This reverts commit a88991f, kib's MFC
of FreeBSD's Address Space Randomiation (ASR) implementation. This is a
direct commit to the hardened/12-stable/master branch.

Signed-off-by: Shawn Webb <shawn.webb@hardenedbsd.org>

Conflicts:
	sys/kern/imgact_elf.c (resolved)
	sys/sys/imgact.h (resolved)
  • Loading branch information
lattera committed Mar 14, 2019
1 parent 9b46f43 commit 9729cbe
Show file tree
Hide file tree
Showing 25 changed files with 28 additions and 568 deletions.
45 changes: 0 additions & 45 deletions lib/libc/sys/procctl.2
Expand Up @@ -72,46 +72,6 @@ The control request to perform is specified by the
argument.
The following commands are supported:
.Bl -tag -width PROC_TRAPCAP_STATUS
.It Dv PROC_ASLR_CTL
Controls the Address Space Layout Randomization (ASLR) in the program
images created
by
.Xr execve 2
in the specified process or its descendants that did not changed
the control nor modified it by other means.
The
.Va arg
parameter must point to the integer variable holding one of the following
values:
.Bl -tag -width PROC_ASLR_FORCE_DISABLE
.It Dv PROC_ASLR_FORCE_ENABLE
Request that ASLR is enabled after execution, even if it is disabled
system-wide.
The image flag and set-uid might prevent ASLR enablement still.
.It Dv PROC_ASLR_FORCE_DISABLE
Request that ASLR is disabled after execution.
Same notes as for
.Dv PROC_ASKR_FORCE_ENABLE
apply.
.It Dv PROC_ASLR_NOFORCE
Use system-wide configured policy for ASLR.
.El
.It Dv PROC_ASLR_STATUS
Returns the current status of ASLR enablement for the target process.
The
.Va arg
parameter must point to the integer variable, where one of the
following values is written:
.Bl -tag -width PROC_ASLR_FORCE_DISABLE
.It Dv PROC_ASLR_FORCE_ENABLE
.It Dv PROC_ASLR_FORCE_DISABLE
.It Dv PROC_ASLR_NOFORCE
.El
.Pp
If the currently executed image in the process itself has ASLR enabled,
the
.Dv PROC_ASLR_ACTIVE
flag is or-ed with the value listed above.
.It Dv PROC_SPROTECT
Set process protection state.
This is used to mark a process as protected from being killed if the system
Expand Down Expand Up @@ -583,16 +543,11 @@ The
.Fn procctl
function appeared in
.Fx 10.0 .
.Pp
The reaper facility is based on a similar feature of Linux and
DragonflyBSD, and first appeared in
.Fx 10.2 .
.Pp
The
.Dv PROC_PDEATHSIG_CTL
facility is based on the prctl(PR_SET_PDEATHSIG, ...) feature of Linux,
and first appeared in
.Fx 11.2 .
.Pp
The ASLR support was added to system for the checklists compliance in
.Fx 13.0 .
3 changes: 1 addition & 2 deletions sys/amd64/amd64/elf_machdep.c
Expand Up @@ -77,8 +77,7 @@ struct sysentvec elf64_freebsd_sysvec = {
.sv_setregs = exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
.sv_flags = SV_ABI_FREEBSD | SV_ASLR | SV_LP64 | SV_SHP |
SV_TIMEKEEP,
.sv_flags = SV_ABI_FREEBSD | SV_LP64 | SV_SHP | SV_TIMEKEEP,
.sv_set_syscall_retval = cpu_set_syscall_retval,
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
Expand Down
4 changes: 2 additions & 2 deletions sys/arm/arm/elf_machdep.c
Expand Up @@ -86,9 +86,9 @@ struct sysentvec elf32_freebsd_sysvec = {
.sv_maxssiz = NULL,
.sv_flags =
#if __ARM_ARCH >= 6
SV_ASLR | SV_SHP | SV_TIMEKEEP |
SV_SHP | SV_TIMEKEEP |
#endif
SV_ABI_FREEBSD | SV_ILP32 | SV_ASLR,
SV_ABI_FREEBSD | SV_ILP32,
.sv_set_syscall_retval = cpu_set_syscall_retval,
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
Expand Down
3 changes: 1 addition & 2 deletions sys/arm64/arm64/elf_machdep.c
Expand Up @@ -83,8 +83,7 @@ static struct sysentvec elf64_freebsd_sysvec = {
.sv_setregs = exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
.sv_flags = SV_SHP | SV_TIMEKEEP | SV_ABI_FREEBSD | SV_LP64 |
SV_ASLR,
.sv_flags = SV_SHP | SV_TIMEKEEP | SV_ABI_FREEBSD | SV_LP64,
.sv_set_syscall_retval = cpu_set_syscall_retval,
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
Expand Down
3 changes: 0 additions & 3 deletions sys/compat/freebsd32/freebsd32_misc.c
Expand Up @@ -3346,7 +3346,6 @@ freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap)
int error, error1, flags, signum;

switch (uap->com) {
case PROC_ASLR_CTL:
case PROC_SPROTECT:
case PROC_TRACE_CTL:
case PROC_TRAPCAP_CTL:
Expand Down Expand Up @@ -3378,7 +3377,6 @@ freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap)
return (error);
data = &x.rk;
break;
case PROC_ASLR_STATUS:
case PROC_TRACE_STATUS:
case PROC_TRAPCAP_STATUS:
data = &flags;
Expand Down Expand Up @@ -3407,7 +3405,6 @@ freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap)
if (error == 0)
error = error1;
break;
case PROC_ASLR_STATUS:
case PROC_TRACE_STATUS:
case PROC_TRAPCAP_STATUS:
if (error == 0)
Expand Down
2 changes: 1 addition & 1 deletion sys/compat/ia32/ia32_sysvec.c
Expand Up @@ -123,7 +123,7 @@ struct sysentvec ia32_freebsd_sysvec = {
.sv_setregs = ia32_setregs,
.sv_fixlimit = ia32_fixlimit,
.sv_maxssiz = &ia32_maxssiz,
.sv_flags = SV_ABI_FREEBSD | SV_ASLR | SV_IA32 | SV_ILP32 |
.sv_flags = SV_ABI_FREEBSD | SV_IA32 | SV_ILP32 |
SV_SHP | SV_TIMEKEEP,
.sv_set_syscall_retval = ia32_set_syscall_retval,
.sv_fetch_syscall_args = ia32_fetch_syscall_args,
Expand Down
4 changes: 2 additions & 2 deletions sys/i386/i386/elf_machdep.c
Expand Up @@ -78,8 +78,8 @@ struct sysentvec elf32_freebsd_sysvec = {
.sv_setregs = exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
.sv_flags = SV_ABI_FREEBSD | SV_ASLR | SV_IA32 | SV_ILP32 |
SV_SHP | SV_TIMEKEEP,
.sv_flags = SV_ABI_FREEBSD | SV_IA32 | SV_ILP32 | SV_SHP |
SV_TIMEKEEP,
.sv_set_syscall_retval = cpu_set_syscall_retval,
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
Expand Down
132 changes: 4 additions & 128 deletions sys/kern/imgact_elf.c
Expand Up @@ -132,27 +132,6 @@ SYSCTL_INT(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO,
nxstack, CTLFLAG_RW, &__elfN(nxstack), 0,
__XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE)) ": enable non-executable stack");

SYSCTL_NODE(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO, aslr, CTLFLAG_RW, 0,
"");
#define ASLR_NODE_OID __CONCAT(__CONCAT(_kern_elf, __ELF_WORD_SIZE), _aslr)

static int __elfN(aslr_enabled) = 0;
SYSCTL_INT(ASLR_NODE_OID, OID_AUTO, enable, CTLFLAG_RWTUN,
&__elfN(aslr_enabled), 0,
__XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE))
": enable address map randomization");

static int __elfN(pie_aslr_enabled) = 0;
SYSCTL_INT(ASLR_NODE_OID, OID_AUTO, pie_enable, CTLFLAG_RWTUN,
&__elfN(pie_aslr_enabled), 0,
__XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE))
": enable address map randomization for PIE binaries");

static int __elfN(aslr_honor_sbrk) = 1;
SYSCTL_INT(ASLR_NODE_OID, OID_AUTO, honor_sbrk, CTLFLAG_RW,
&__elfN(aslr_honor_sbrk), 0,
__XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE)) ": assume sbrk is used");

static Elf_Brandinfo *elf_brand_list[MAX_BRANDS];

#define trunc_page_ps(va, ps) rounddown2(va, ps)
Expand Down Expand Up @@ -798,36 +777,6 @@ __elfN(load_file)(struct proc *p, const char *file, u_long *addr,
return (error);
}

static u_long
__CONCAT(rnd_, __elfN(base))(vm_map_t map __unused, u_long minv, u_long maxv,
u_int align)
{
u_long rbase, res;

MPASS(vm_map_min(map) <= minv);
MPASS(maxv <= vm_map_max(map));
MPASS(minv < maxv);
MPASS(minv + align < maxv);
arc4rand(&rbase, sizeof(rbase), 0);
res = roundup(minv, (u_long)align) + rbase % (maxv - minv);
res &= ~((u_long)align - 1);
if (res >= maxv)
res -= align;
KASSERT(res >= minv,
("res %#lx < minv %#lx, maxv %#lx rbase %#lx",
res, minv, maxv, rbase));
KASSERT(res < maxv,
("res %#lx > maxv %#lx, minv %#lx rbase %#lx",
res, maxv, minv, rbase));
return (res);
}

/*
* Impossible et_dyn_addr initial value indicating that the real base
* must be calculated later with some randomization applied.
*/
#define ET_DYN_ADDR_RAND 1

static int
__CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
{
Expand All @@ -836,15 +785,13 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
const Elf_Phdr *phdr;
Elf_Auxargs *elf_auxargs;
struct vmspace *vmspace;
vm_map_t map;
const char *err_str, *newinterp;
char *interp, *interp_buf, *path;
Elf_Brandinfo *brand_info;
struct sysentvec *sv;
vm_prot_t prot;
u_long text_size, data_size, total_size, text_addr, data_addr;
u_long seg_size, seg_addr, addr, baddr, et_dyn_addr, entry, proghdr;
u_long maxalign, mapsz, maxv, maxv1;
uint32_t fctl0;
int32_t osrel;
int error, i, n, interp_name_len, have_interp;
Expand Down Expand Up @@ -888,17 +835,12 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
err_str = newinterp = NULL;
interp = interp_buf = NULL;
td = curthread;
maxalign = PAGE_SIZE;
mapsz = 0;

for (i = 0; i < hdr->e_phnum; i++) {
switch (phdr[i].p_type) {
case PT_LOAD:
if (n == 0)
baddr = phdr[i].p_vaddr;
if (phdr[i].p_align > maxalign)
maxalign = phdr[i].p_align;
mapsz += phdr[i].p_memsz;
n++;
break;
case PT_INTERP:
Expand Down Expand Up @@ -959,7 +901,6 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
error = ENOEXEC;
goto ret;
}
sv = brand_info->sysvec;
et_dyn_addr = 0;
if (hdr->e_type == ET_DYN) {
if ((brand_info->flags & BI_CAN_EXEC_DYN) == 0) {
Expand All @@ -971,18 +912,10 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
* Honour the base load address from the dso if it is
* non-zero for some reason.
*/
if (baddr == 0) {
if ((sv->sv_flags & SV_ASLR) == 0 ||
(fctl0 & NT_FREEBSD_FCTL_ASLR_DISABLE) != 0)
et_dyn_addr = ET_DYN_LOAD_ADDR;
else if ((__elfN(pie_aslr_enabled) &&
(imgp->proc->p_flag2 & P2_ASLR_DISABLE) == 0) ||
(imgp->proc->p_flag2 & P2_ASLR_ENABLE) != 0)
et_dyn_addr = ET_DYN_ADDR_RAND;
else
et_dyn_addr = ET_DYN_LOAD_ADDR;
}
if (baddr == 0)
et_dyn_addr = ET_DYN_LOAD_ADDR;
}
sv = brand_info->sysvec;
if (interp != NULL && brand_info->interp_newpath != NULL)
newinterp = brand_info->interp_newpath;

Expand All @@ -999,42 +932,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
*/
VOP_UNLOCK(imgp->vp, 0);

/*
* Decide whether to enable randomization of user mappings.
* First, reset user preferences for the setid binaries.
* Then, account for the support of the randomization by the
* ABI, by user preferences, and make special treatment for
* PIE binaries.
*/
if (imgp->credential_setid) {
PROC_LOCK(imgp->proc);
imgp->proc->p_flag2 &= ~(P2_ASLR_ENABLE | P2_ASLR_DISABLE);
PROC_UNLOCK(imgp->proc);
}
if ((sv->sv_flags & SV_ASLR) == 0 ||
(imgp->proc->p_flag2 & P2_ASLR_DISABLE) != 0 ||
(fctl0 & NT_FREEBSD_FCTL_ASLR_DISABLE) != 0) {
KASSERT(et_dyn_addr != ET_DYN_ADDR_RAND,
("et_dyn_addr == RAND and !ASLR"));
} else if ((imgp->proc->p_flag2 & P2_ASLR_ENABLE) != 0 ||
(__elfN(aslr_enabled) && hdr->e_type == ET_EXEC) ||
et_dyn_addr == ET_DYN_ADDR_RAND) {
imgp->map_flags |= MAP_ASLR;
/*
* If user does not care about sbrk, utilize the bss
* grow region for mappings as well. We can select
* the base for the image anywere and still not suffer
* from the fragmentation.
*/
if (!__elfN(aslr_honor_sbrk) ||
(imgp->proc->p_flag2 & P2_ASLR_IGNSTART) != 0)
imgp->map_flags |= MAP_ASLR_IGNSTART;
}

error = exec_new_vmspace(imgp, sv);
vmspace = imgp->proc->p_vmspace;
map = &vmspace->vm_map;

imgp->proc->p_sysent = sv;

et_dyn_addr = 0;
Expand All @@ -1054,14 +952,6 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
pax_aslr_execbase(imgp->proc, &et_dyn_addr);
#endif
}
maxv = vm_map_max(map) - lim_max(td, RLIMIT_STACK);
if (et_dyn_addr == ET_DYN_ADDR_RAND) {
KASSERT((map->flags & MAP_ASLR) != 0,
("ET_DYN_ADDR_RAND but !MAP_ASLR"));
et_dyn_addr = __CONCAT(rnd_, __elfN(base))(map,
vm_map_min(map) + mapsz + lim_max(td, RLIMIT_DATA),
/* reserve half of the address space to interpreter */
maxv / 2, 1UL << flsl(maxalign));
}

vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
Expand Down Expand Up @@ -1155,6 +1045,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
goto ret;
}

vmspace = imgp->proc->p_vmspace;
vmspace->vm_tsize = text_size >> PAGE_SHIFT;
vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr;
vmspace->vm_dsize = data_size >> PAGE_SHIFT;
Expand All @@ -1171,28 +1062,13 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
#ifdef PAX_ASLR
pax_aslr_rtld(imgp->proc, &addr);
#endif
if ((map->flags & MAP_ASLR) != 0) {
maxv1 = maxv / 2 + addr / 2;
MPASS(maxv1 >= addr); /* No overflow */
map->anon_loc = __CONCAT(rnd_, __elfN(base))(map, addr, maxv1,
MAXPAGESIZES > 1 ? pagesizes[1] : pagesizes[0]);
} else {
map->anon_loc = addr;
}
PROC_UNLOCK(imgp->proc);

imgp->entry_addr = entry;

if (interp != NULL) {
have_interp = FALSE;
VOP_UNLOCK(imgp->vp, 0);
if ((map->flags & MAP_ASLR) != 0) {
/* Assume that interpeter fits into 1/4 of AS */
maxv1 = maxv / 2 + addr / 2;
MPASS(maxv1 >= addr); /* No overflow */
addr = __CONCAT(rnd_, __elfN(base))(map, addr,
maxv1, PAGE_SIZE);
}
if (brand_info->emul_path != NULL &&
brand_info->emul_path[0] != '\0') {
path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
Expand Down
9 changes: 2 additions & 7 deletions sys/kern/kern_exec.c
Expand Up @@ -1129,13 +1129,9 @@ exec_new_vmspace(struct image_params *imgp, struct sysentvec *sv)
shmexit(vmspace);
pmap_remove_pages(vmspace_pmap(vmspace));
vm_map_remove(map, vm_map_min(map), vm_map_max(map));
/*
* An exec terminates mlockall(MCL_FUTURE), ASLR state
* must be re-evaluated.
*/
/* An exec terminates mlockall(MCL_FUTURE). */
vm_map_lock(map);
vm_map_modflags(map, 0, MAP_WIREFUTURE | MAP_ASLR |
MAP_ASLR_IGNSTART);
vm_map_modflags(map, 0, MAP_WIREFUTURE);
vm_map_unlock(map);
} else {
error = vmspace_exec(p, sv_minuser, sv->sv_maxuser);
Expand All @@ -1144,7 +1140,6 @@ exec_new_vmspace(struct image_params *imgp, struct sysentvec *sv)
vmspace = p->p_vmspace;
map = &vmspace->vm_map;
}
map->flags |= imgp->map_flags;

#ifdef PAX_ASLR
PROC_LOCK(imgp->proc);
Expand Down
3 changes: 1 addition & 2 deletions sys/kern/kern_fork.c
Expand Up @@ -515,8 +515,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *
* Increase reference counts on shared objects.
*/
p2->p_flag = P_INMEM;
p2->p_flag2 = p1->p_flag2 & (P2_ASLR_DISABLE | P2_ASLR_ENABLE |
P2_ASLR_IGNSTART | P2_NOTRACE | P2_NOTRACE_EXEC | P2_TRAPCAP);
p2->p_flag2 = p1->p_flag2 & (P2_NOTRACE | P2_NOTRACE_EXEC | P2_TRAPCAP);
p2->p_swtick = ticks;
if (p1->p_flag & P_PROFIL)
startprofclock(p2);
Expand Down

0 comments on commit 9729cbe

Please sign in to comment.