diff options
author | 2002-07-20 19:24:55 +0000 | |
---|---|---|
committer | 2002-07-20 19:24:55 +0000 | |
commit | 4a5480fe18b84efa6a06b21bf545eb9124282da7 (patch) | |
tree | 1ae6886fef3407c1df68824801d7de5f46ff2d31 /sys/kern/kern_exec.c | |
parent | properly split yacc and lex use (diff) | |
download | wireguard-openbsd-4a5480fe18b84efa6a06b21bf545eb9124282da7.tar.xz wireguard-openbsd-4a5480fe18b84efa6a06b21bf545eb9124282da7.zip |
Instead of copying out the signal trampoline on top of the stack, create
an uvm aobj, copy out the signal trampoline into it and share that page
among all processes for the same emulation.
This also requires us to actually be able to tell signal code where the
trampoline is located, so introduce a new field in struct proc - p_sigcode
that is a pointer to sigcode. This allows us to remove all the ugly
calculations of the signal trampoline address done in every sendsig
function in the tree (that's why so many files are changed).
Tested by various people. ok deraadt@
Diffstat (limited to 'sys/kern/kern_exec.c')
-rw-r--r-- | sys/kern/kern_exec.c | 81 |
1 files changed, 62 insertions, 19 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index fd12717ce6a..7fb2276bb39 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_exec.c,v 1.67 2002/05/02 00:36:04 millert Exp $ */ +/* $OpenBSD: kern_exec.c,v 1.68 2002/07/20 19:24:57 art Exp $ */ /* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */ /*- @@ -66,6 +66,11 @@ #include <dev/rndvar.h> /* + * Map the shared signal code. + */ +int exec_sigcode_map(struct proc *, struct emul *); + +/* * stackgap_random specifies if the stackgap should have a random size added * to it. Must be a n^2. If non-zero, the stack gap will be calculated as: * (arc4random() * ALIGNBYTES) & (stackgap_random - 1) + STACKGAPLEN. @@ -246,7 +251,6 @@ sys_execve(p, v, retval) struct ps_strings arginfo; struct vmspace *vm = p->p_vmspace; char **tmpfap; - int szsigcode; extern struct emul emul_native; /* @@ -365,15 +369,12 @@ sys_execve(p, v, retval) dp = (char *)ALIGN(dp); - szsigcode = pack.ep_emul->e_esigcode - pack.ep_emul->e_sigcode; - sgap = STACKGAPLEN; if (stackgap_random != 0) sgap += (arc4random() * ALIGNBYTES) & (stackgap_random - 1); /* Now check if args & environ fit into new stack */ len = ((argc + envc + 2 + pack.ep_emul->e_arglen) * sizeof(char *) + - sizeof(long) + dp + sgap + szsigcode + - sizeof(struct ps_strings)) - argp; + sizeof(long) + dp + sgap + sizeof(struct ps_strings)) - argp; len = ALIGN(len); /* make the stack "safely" aligned */ @@ -424,8 +425,8 @@ sys_execve(p, v, retval) arginfo.ps_nenvstr = envc; #ifdef MACHINE_STACK_GROWS_UP - stack = (char *)USRSTACK + sizeof(arginfo) + szsigcode; - slen = len - sizeof(arginfo) - szsigcode; + stack = (char *)USRSTACK + sizeof(arginfo); + slen = len - sizeof(arginfo); #else stack = (char *)(USRSTACK - len); #endif @@ -437,17 +438,6 @@ sys_execve(p, v, retval) if (copyout(&arginfo, (char *)PS_STRINGS, sizeof(arginfo))) goto exec_abort; - /* copy out the process's signal trampoline code */ -#ifdef MACHINE_STACK_GROWS_UP - if (szsigcode && copyout((char *)pack.ep_emul->e_sigcode, - ((char *)PS_STRINGS) + sizeof(arginfo), szsigcode)) - goto exec_abort; -#else - if (szsigcode && copyout((char *)pack.ep_emul->e_sigcode, - ((char *)PS_STRINGS) - szsigcode, szsigcode)) - goto exec_abort; -#endif - stopprofclock(p); /* stop profiling */ fdcloseexec(p); /* handle close on exec */ execsigs(p); /* reset catched signals */ @@ -607,6 +597,10 @@ sys_execve(p, v, retval) (*pack.ep_emul->e_setregs)(p, &pack, (u_long)stack, retval); #endif + /* map the process's signal trampoline code */ + if (exec_sigcode_map(p, pack.ep_emul)) + goto exec_abort; + if (p->p_flag & P_TRACED) psignal(p, SIGTRAP); @@ -708,3 +702,52 @@ copyargs(pack, arginfo, stack, argp) return (cpp); } + +int +exec_sigcode_map(struct proc *p, struct emul *e) +{ + vsize_t sz; + + sz = (vaddr_t)e->e_esigcode - (vaddr_t)e->e_sigcode; + + /* + * If we don't have a sigobject for this emulation, create one. + * + * sigobject is an anonymous memory object (just like SYSV shared + * memory) that we keep a permanent reference to and that we map + * in all processes that need this sigcode. The creation is simple, + * we create an object, add a permanent reference to it, map it in + * kernel space, copy out the sigcode to it and unmap it. + * The we map it with PROT_READ|PROT_EXEC into the process just + * the way sys_mmap would map it. + */ + if (e->e_sigobject == NULL) { + vaddr_t va; + int r; + + e->e_sigobject = uao_create(sz, 0); + uao_reference(e->e_sigobject); /* permanent reference */ + + va = vm_map_min(kernel_map); /* hint */ + if ((r = uvm_map(kernel_map, &va, round_page(sz), e->e_sigobject, + 0, 0, UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_RW, + UVM_INH_SHARE, UVM_ADV_RANDOM, 0)))) { + printf("kernel mapping failed %d\n", r); + return (ENOMEM); + } + memcpy((void *)va, e->e_sigcode, sz); + uvm_unmap(kernel_map, va, va + round_page(sz)); + } + + /* Just a hint to uvm_mmap where to put it. */ + p->p_sigcode = round_page((vaddr_t)p->p_vmspace->vm_daddr + MAXDSIZ); + uao_reference(e->e_sigobject); + if (uvm_map(&p->p_vmspace->vm_map, &p->p_sigcode, round_page(sz), + e->e_sigobject, 0, 0, UVM_MAPFLAG(UVM_PROT_RX, UVM_PROT_RX, + UVM_INH_SHARE, UVM_ADV_RANDOM, 0))) { + printf("user mapping failed\n"); + return (ENOMEM); + } + + return (0); +} |