aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/kern/imgact_elf.c5
-rw-r--r--sys/kern/kern_exec.c11
-rw-r--r--sys/kern/kern_resource.c3
-rw-r--r--sys/sys/imgact_elf.h2
-rw-r--r--sys/sys/sysent.h2
-rw-r--r--sys/vm/vm_map.c2
-rw-r--r--sys/vm/vm_map.h1
7 files changed, 19 insertions, 7 deletions
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index ef1edfcabaf0..898f0f66a532 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -2684,7 +2684,7 @@ __elfN(untrans_prot)(vm_prot_t prot)
return (flags);
}
-void
+vm_size_t
__elfN(stackgap)(struct image_params *imgp, uintptr_t *stack_base)
{
uintptr_t range, rbase, gap;
@@ -2692,7 +2692,7 @@ __elfN(stackgap)(struct image_params *imgp, uintptr_t *stack_base)
pct = __elfN(aslr_stack_gap);
if (pct == 0)
- return;
+ return (0);
if (pct > 50)
pct = 50;
range = imgp->eff_stack_sz * pct / 100;
@@ -2700,4 +2700,5 @@ __elfN(stackgap)(struct image_params *imgp, uintptr_t *stack_base)
gap = rbase % range;
gap &= ~(sizeof(u_long) - 1);
*stack_base -= gap;
+ return (gap);
}
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 50e75fda6cfb..9dceebdd8441 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -1148,6 +1148,7 @@ exec_new_vmspace(struct image_params *imgp, struct sysentvec *sv)
stack_prot, error, vm_mmap_to_errno(error));
return (vm_mmap_to_errno(error));
}
+ vmspace->vm_stkgap = 0;
/*
* vm_ssize and vm_maxsaddr are somewhat antiquated concepts, but they
@@ -1493,12 +1494,16 @@ exec_args_get_begin_envv(struct image_args *args)
void
exec_stackgap(struct image_params *imgp, uintptr_t *dp)
{
+ struct proc *p = imgp->proc;
+
if (imgp->sysent->sv_stackgap == NULL ||
- (imgp->proc->p_fctl0 & (NT_FREEBSD_FCTL_ASLR_DISABLE |
+ (p->p_fctl0 & (NT_FREEBSD_FCTL_ASLR_DISABLE |
NT_FREEBSD_FCTL_ASG_DISABLE)) != 0 ||
- (imgp->map_flags & MAP_ASLR) == 0)
+ (imgp->map_flags & MAP_ASLR) == 0) {
+ p->p_vmspace->vm_stkgap = 0;
return;
- imgp->sysent->sv_stackgap(imgp, dp);
+ }
+ p->p_vmspace->vm_stkgap = imgp->sysent->sv_stackgap(imgp, dp);
}
/*
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
index 4c62961e1bc4..b556d4fded51 100644
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -671,6 +671,9 @@ kern_proc_setrlimit(struct thread *td, struct proc *p, u_int which,
if (limp->rlim_max < 0)
limp->rlim_max = RLIM_INFINITY;
+ if (which == RLIMIT_STACK && limp->rlim_cur != RLIM_INFINITY)
+ limp->rlim_cur += p->p_vmspace->vm_stkgap;
+
oldssiz.rlim_cur = 0;
newlim = lim_alloc();
PROC_LOCK(p);
diff --git a/sys/sys/imgact_elf.h b/sys/sys/imgact_elf.h
index 97383c6eeeb8..294f17c87b6f 100644
--- a/sys/sys/imgact_elf.h
+++ b/sys/sys/imgact_elf.h
@@ -118,7 +118,7 @@ int __elfN(remove_brand_entry)(Elf_Brandinfo *entry);
int __elfN(freebsd_fixup)(uintptr_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 *, uintptr_t *);
+vm_size_t __elfN(stackgap)(struct image_params *, uintptr_t *);
int __elfN(freebsd_copyout_auxargs)(struct image_params *, uintptr_t);
void __elfN(puthdr)(struct thread *, void *, size_t, int, size_t, int);
void __elfN(prepare_notes)(struct thread *, struct note_info_list *,
diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h
index ad50bf56e87d..ea96c87a79af 100644
--- a/sys/sys/sysent.h
+++ b/sys/sys/sysent.h
@@ -119,7 +119,7 @@ struct sysentvec {
void (*sv_elf_core_prepare_notes)(struct thread *,
struct note_info_list *, size_t *);
int (*sv_imgact_try)(struct image_params *);
- void (*sv_stackgap)(struct image_params *, uintptr_t *);
+ vm_size_t (*sv_stackgap)(struct image_params *, uintptr_t *);
int (*sv_copyout_auxargs)(struct image_params *,
uintptr_t);
int sv_minsigstksz; /* minimum signal stack size */
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 1ac4ccf72f11..87a290b998b9 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -343,6 +343,7 @@ vmspace_alloc(vm_offset_t min, vm_offset_t max, pmap_pinit_t pinit)
vm->vm_taddr = 0;
vm->vm_daddr = 0;
vm->vm_maxsaddr = 0;
+ vm->vm_stkgap = 0;
return (vm);
}
@@ -4265,6 +4266,7 @@ vmspace_fork(struct vmspace *vm1, vm_ooffset_t *fork_charge)
vm2->vm_taddr = vm1->vm_taddr;
vm2->vm_daddr = vm1->vm_daddr;
vm2->vm_maxsaddr = vm1->vm_maxsaddr;
+ vm2->vm_stkgap = vm1->vm_stkgap;
vm_map_lock(old_map);
if (old_map->busy)
vm_map_wait_busy(old_map);
diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h
index ace205b21b42..873ff62eec4a 100644
--- a/sys/vm/vm_map.h
+++ b/sys/vm/vm_map.h
@@ -293,6 +293,7 @@ struct vmspace {
caddr_t vm_taddr; /* (c) user virtual address of text */
caddr_t vm_daddr; /* (c) user virtual address of data */
caddr_t vm_maxsaddr; /* user VA at max stack growth */
+ vm_size_t vm_stkgap; /* stack gap size in bytes */
u_int vm_refcnt; /* number of references */
/*
* Keep the PMAP last, so that CPU-specific variations of that