Make randomized stack gap between strings and pointers to argv/envs.
This effectively makes the stack base on the csu _start entry randomized. The gap is enabled if ASLR is for the ABI is enabled, and then kern.elf{64,32}.aslr.stack_gap specify the max percentage of the initial stack size that can be wasted for gap. Setting it to zero disables the gap, and max is capped at 50%. Only amd64 for now. Reviewed by: cem, markj Discussed with: emaste MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential revision: https://reviews.freebsd.org/D21081
This commit is contained in:
parent
3638455c92
commit
fc83c5a7d0
@ -82,6 +82,7 @@ struct sysentvec elf64_freebsd_sysvec = {
|
||||
.sv_schedtail = NULL,
|
||||
.sv_thread_detach = NULL,
|
||||
.sv_trap = NULL,
|
||||
.sv_stackgap = elf64_stackgap,
|
||||
};
|
||||
INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
|
||||
|
||||
|
@ -3166,6 +3166,9 @@ freebsd32_copyout_strings(struct image_params *imgp)
|
||||
destp = rounddown2(destp, sizeof(uint32_t));
|
||||
|
||||
vectp = (uint32_t *)destp;
|
||||
if (imgp->sysent->sv_stackgap != NULL)
|
||||
imgp->sysent->sv_stackgap(imgp, (u_long *)&vectp);
|
||||
|
||||
if (imgp->auxargs) {
|
||||
/*
|
||||
* Allocate room on the stack for the ELF auxargs
|
||||
|
@ -128,6 +128,7 @@ struct sysentvec ia32_freebsd_sysvec = {
|
||||
.sv_schedtail = NULL,
|
||||
.sv_thread_detach = NULL,
|
||||
.sv_trap = NULL,
|
||||
.sv_stackgap = elf32_stackgap,
|
||||
};
|
||||
INIT_SYSENTVEC(elf_ia32_sysvec, &ia32_freebsd_sysvec);
|
||||
|
||||
|
@ -156,6 +156,12 @@ 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 int __elfN(aslr_stack_gap) = 3;
|
||||
SYSCTL_INT(ASLR_NODE_OID, OID_AUTO, stack_gap, CTLFLAG_RW,
|
||||
&__elfN(aslr_stack_gap), 0,
|
||||
__XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE))
|
||||
": maximum percentage of main stack to waste on a random gap");
|
||||
|
||||
static Elf_Brandinfo *elf_brand_list[MAX_BRANDS];
|
||||
|
||||
#define aligned(a, t) (rounddown2((u_long)(a), sizeof(t)) == (u_long)(a))
|
||||
@ -2720,3 +2726,24 @@ __elfN(untrans_prot)(vm_prot_t prot)
|
||||
flags |= PF_W;
|
||||
return (flags);
|
||||
}
|
||||
|
||||
void
|
||||
__elfN(stackgap)(struct image_params *imgp, u_long *stack_base)
|
||||
{
|
||||
u_long range, rbase, gap;
|
||||
int pct;
|
||||
|
||||
if ((imgp->map_flags & MAP_ASLR) == 0)
|
||||
return;
|
||||
pct = __elfN(aslr_stack_gap);
|
||||
if (pct == 0)
|
||||
return;
|
||||
if (pct > 50)
|
||||
pct = 50;
|
||||
range = imgp->eff_stack_sz * pct / 100;
|
||||
range *= pct;
|
||||
arc4rand(&rbase, sizeof(rbase), 0);
|
||||
gap = rbase % range;
|
||||
gap &= ~(sizeof(u_long) - 1);
|
||||
*stack_base -= gap;
|
||||
}
|
||||
|
@ -1128,6 +1128,7 @@ exec_new_vmspace(struct image_params *imgp, struct sysentvec *sv)
|
||||
} else {
|
||||
ssiz = maxssiz;
|
||||
}
|
||||
imgp->eff_stack_sz = ssiz;
|
||||
stack_addr = sv->sv_usrstack - ssiz;
|
||||
error = vm_map_stack(map, stack_addr, (vm_size_t)ssiz,
|
||||
obj != NULL && imgp->stack_prot != 0 ? imgp->stack_prot :
|
||||
@ -1615,6 +1616,9 @@ exec_copyout_strings(struct image_params *imgp)
|
||||
destp = rounddown2(destp, sizeof(void *));
|
||||
|
||||
vectp = (char **)destp;
|
||||
if (imgp->sysent->sv_stackgap != NULL)
|
||||
imgp->sysent->sv_stackgap(imgp, (u_long *)&vectp);
|
||||
|
||||
if (imgp->auxargs) {
|
||||
/*
|
||||
* Allocate room on the stack for the ELF auxargs
|
||||
|
@ -87,6 +87,7 @@ struct image_params {
|
||||
int pagesizeslen;
|
||||
vm_prot_t stack_prot;
|
||||
u_long stack_sz;
|
||||
u_long eff_stack_sz;
|
||||
struct ucred *newcred; /* new credentials if changing */
|
||||
bool credential_setid; /* true if becoming setid */
|
||||
bool textset;
|
||||
|
@ -98,6 +98,7 @@ int __elfN(remove_brand_entry)(Elf_Brandinfo *entry);
|
||||
int __elfN(freebsd_fixup)(register_t **, struct image_params *);
|
||||
int __elfN(coredump)(struct thread *, struct vnode *, off_t, int);
|
||||
size_t __elfN(populate_note)(int, void *, void *, size_t, void **);
|
||||
void __elfN(stackgap)(struct image_params *, u_long *);
|
||||
|
||||
/* Machine specific function to dump per-thread information. */
|
||||
void __elfN(dump_thread)(struct thread *, void *, size_t *);
|
||||
|
@ -109,6 +109,7 @@ struct sysentvec {
|
||||
int (*sv_coredump)(struct thread *, struct vnode *, off_t, int);
|
||||
/* function to dump core, or NULL */
|
||||
int (*sv_imgact_try)(struct image_params *);
|
||||
void (*sv_stackgap)(struct image_params *, u_long *);
|
||||
int sv_minsigstksz; /* minimum signal stack size */
|
||||
vm_offset_t sv_minuser; /* VM_MIN_ADDRESS */
|
||||
vm_offset_t sv_maxuser; /* VM_MAXUSER_ADDRESS */
|
||||
|
Loading…
x
Reference in New Issue
Block a user