diff options
author | 2012-06-21 00:56:59 +0000 | |
---|---|---|
committer | 2012-06-21 00:56:59 +0000 | |
commit | 16b62b6a0b93be6a70f097edd49f4c661f85cd4f (patch) | |
tree | b60ec958758bfe01ad491979d73feeea25c66228 /sys/kern/kern_fork.c | |
parent | fix strlcpy truncation check. from carsten at debian org, ok markus (diff) | |
download | wireguard-openbsd-16b62b6a0b93be6a70f097edd49f4c661f85cd4f.tar.xz wireguard-openbsd-16b62b6a0b93be6a70f097edd49f4c661f85cd4f.zip |
__tfork() needs to set the stack address of the new thread in the kernel,
so that it can't get a signal while still running on the parent thread's
stack. Also, pass in sizeof(struct __tfork) to provide forward compat
when more members are added. This is an ABI change, so switch syscall
numbers and bump lib majors this time.
ok deraadt@ matthew@
Diffstat (limited to 'sys/kern/kern_fork.c')
-rw-r--r-- | sys/kern/kern_fork.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 695cac4b619..7546a5f682d 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_fork.c,v 1.140 2012/05/10 05:01:23 guenther Exp $ */ +/* $OpenBSD: kern_fork.c,v 1.141 2012/06/21 00:56:59 guenther Exp $ */ /* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */ /* @@ -117,9 +117,38 @@ int sys___tfork(struct proc *p, void *v, register_t *retval) { struct sys___tfork_args /* { - syscallarg(struct __tfork) *param; + syscallarg(const struct __tfork) *param; + syscallarg(size_t) psize; } */ *uap = v; - struct __tfork param; + size_t psize = SCARG(uap, psize); + struct __tfork param = { 0 }; + int flags; + int error; + + if (psize == 0 || psize > sizeof(param)) + return (EINVAL); + if ((error = copyin(SCARG(uap, param), ¶m, psize))) + return (error); +#ifdef KTRACE + if (KTRPOINT(p, KTR_STRUCT)) + ktrstruct(p, "tfork", ¶m, sizeof(param)); +#endif + + flags = FORK_TFORK | FORK_THREAD | FORK_SIGHAND | FORK_SHAREVM + | FORK_NOZOMBIE | FORK_SHAREFILES; + + return (fork1(p, 0, flags, param.tf_stack, param.tf_tid, + tfork_child_return, param.tf_tcb, retval, NULL)); +} + +#ifdef COMPAT_O51 +int +compat_o51_sys___tfork(struct proc *p, void *v, register_t *retval) +{ + struct compat_o51_sys___tfork_args /* { + syscallarg(struct __tfork51) *param; + } */ *uap = v; + struct __tfork51 param; int flags; int error; @@ -135,6 +164,7 @@ sys___tfork(struct proc *p, void *v, register_t *retval) return (fork1(p, 0, flags, NULL, param.tf_tid, tfork_child_return, param.tf_tcb, retval, NULL)); } +#endif void tfork_child_return(void *arg) |