diff options
author | Philip Guenthe <guenther@cvs.openbsd.org> | 2009-12-28 02:54:25 +0000 |
---|---|---|
committer | Philip Guenthe <guenther@cvs.openbsd.org> | 2009-12-28 02:54:25 +0000 |
commit | fa5989e93dadf4c4259fb99782a792cfcfc04779 (patch) | |
tree | 5dc84ca656c7546c2a448365ab1ca29eb401eb97 /sys/compat/linux | |
parent | f270b9bbc87c6e6b700174af3bc6aed85a8f38bc (diff) |
Sanity check flags in fork1(), banning some combos we don't support
and catching FORK_THREAD when RTHREADS wasn't compiled in. Simplify
sys_rfork() based on that.
Flesh out the Linux clone support with more flags, but stricter
checks for missing support or bad combos. Still not enough for
NPTL to work, mind you.
ok kettenis@
Diffstat (limited to 'sys/compat/linux')
-rw-r--r-- | sys/compat/linux/linux_sched.c | 59 | ||||
-rw-r--r-- | sys/compat/linux/linux_sched.h | 15 |
2 files changed, 63 insertions, 11 deletions
diff --git a/sys/compat/linux/linux_sched.c b/sys/compat/linux/linux_sched.c index 4f208e06434..f2011ea95b2 100644 --- a/sys/compat/linux/linux_sched.c +++ b/sys/compat/linux/linux_sched.c @@ -1,4 +1,4 @@ -/* $OpenBSD: linux_sched.c,v 1.6 2008/06/26 05:42:14 ray Exp $ */ +/* $OpenBSD: linux_sched.c,v 1.7 2009/12/28 02:54:24 guenther Exp $ */ /* $NetBSD: linux_sched.c,v 1.6 2000/05/28 05:49:05 thorpej Exp $ */ /*- @@ -59,26 +59,67 @@ linux_sys_clone(p, v, retval) syscallarg(int) flags; syscallarg(void *) stack; } */ *uap = v; + int cflags = SCARG(uap, flags); int flags = FORK_RFORK, sig; /* - * We don't support the Linux CLONE_PID or CLONE_PTRACE flags. + * We only support certain bits. The Linux crew keep adding more, + * so let's test for anything outside of what we support and complain + * about them. Not everything in this list is completely supported, + * they just aren't _always_ an error. + * To make nptl threads work we need to add support for at least + * CLONE_SETTLS, CLONE_PARENT_SETTID, and CLONE_CHILD_CLEARTID. */ - if (SCARG(uap, flags) & (LINUX_CLONE_PID | LINUX_CLONE_PTRACE)) + if (cflags & ~(LINUX_CLONE_CSIGNAL | LINUX_CLONE_VM | LINUX_CLONE_FS | + LINUX_CLONE_FILES | LINUX_CLONE_SIGHAND | LINUX_CLONE_VFORK | + LINUX_CLONE_PARENT | LINUX_CLONE_THREAD | LINUX_CLONE_SYSVSEM | + LINUX_CLONE_UNTRACED)) return (EINVAL); - if (SCARG(uap, flags) & LINUX_CLONE_VM) + if (cflags & LINUX_CLONE_VM) flags |= FORK_SHAREVM; - /* XXX We pretend to support CLONE_FS for the moment. */ - if (SCARG(uap, flags) & LINUX_CLONE_FILES) + if (cflags & LINUX_CLONE_FILES) flags |= FORK_SHAREFILES; - if (SCARG(uap, flags) & LINUX_CLONE_SIGHAND) + if (cflags & LINUX_CLONE_SIGHAND) { + /* According to Linux, SIGHAND requires VM */ + if ((cflags & LINUX_CLONE_VM) == 0) + return (EINVAL); flags |= FORK_SIGHAND; - if (SCARG(uap, flags) & LINUX_CLONE_VFORK) { + } + if (cflags & LINUX_CLONE_VFORK) flags |= FORK_PPWAIT; + if (cflags & LINUX_CLONE_THREAD) { + /* + * Linux agrees with us: THREAD requires SIGHAND. + * Unlike Linux, we also also require FS and SYSVSEM. + * Also, we decree it to be incompatible with VFORK, as + * I don't want to work out whether that's 100% safe. + */ +#define REQUIRED \ + (LINUX_CLONE_SIGHAND | LINUX_CLONE_FS | LINUX_CLONE_SYSVSEM) +#define BANNED \ + LINUX_CLONE_VFORK + if ((cflags & (REQUIRED | BANNED)) != REQUIRED) + return (EINVAL); + /* + * Linux says that THREAD means no signal will be + * sent on exit (even if a non-standard signal is + * requested via LINUX_CLONE_CSIGNAL), so pass + * FORK_NOZOMBIE too. + */ + flags |= FORK_THREAD | FORK_NOZOMBIE; + } else { + /* only supported with THREAD */ + if (cflags & (LINUX_CLONE_FS | LINUX_CLONE_PARENT | + LINUX_CLONE_SYSVSEM)) + return (EINVAL); } + /* + * Since we don't support CLONE_PTRACE, the CLONE_UNTRACED + * flag can be silently ignored. + */ - sig = SCARG(uap, flags) & LINUX_CLONE_CSIGNAL; + sig = cflags & LINUX_CLONE_CSIGNAL; if (sig < 0 || sig >= LINUX__NSIG) return (EINVAL); sig = linux_to_bsd_sig[sig]; diff --git a/sys/compat/linux/linux_sched.h b/sys/compat/linux/linux_sched.h index 408ad8b8fb0..bfa9bc1a4fd 100644 --- a/sys/compat/linux/linux_sched.h +++ b/sys/compat/linux/linux_sched.h @@ -1,4 +1,4 @@ -/* $OpenBSD: linux_sched.h,v 1.2 2008/06/26 05:42:14 ray Exp $ */ +/* $OpenBSD: linux_sched.h,v 1.3 2009/12/28 02:54:24 guenther Exp $ */ /* $NetBSD: linux_sched.h,v 1.1 1999/05/12 19:49:09 thorpej Exp $ */ /*- @@ -42,11 +42,22 @@ #define LINUX_CLONE_FS 0x00000200 /* share "file system" info */ #define LINUX_CLONE_FILES 0x00000400 /* share file descriptors */ #define LINUX_CLONE_SIGHAND 0x00000800 /* share signal actions */ -#define LINUX_CLONE_PID 0x00001000 /* share process ID */ +#define LINUX_CLONE_PID 0x00001000 /* no longer supported */ #define LINUX_CLONE_PTRACE 0x00002000 /* ptrace(2) continues on child */ #define LINUX_CLONE_VFORK 0x00004000 /* parent blocks until child exits */ +#define LINUX_CLONE_PARENT 0x00008000 /* create sibling, not child */ +#define LINUX_CLONE_THREAD 0x00010000 /* new thread */ +#define LINUX_CLONE_NEWNS 0x00020000 /* don't share mount changes */ +#define LINUX_CLONE_SYSVSEM 0x00040000 /* share sysV SEM_UNDO */ +#define LINUX_CLONE_SETTLS 0x00080000 /* new thread-local-storage? */ +#define LINUX_CLONE_PARENT_SETTID 0x00100000 /* set the TID in the parent */ +#define LINUX_CLONE_CHILD_CLEARTID 0x00200000 /* clear the TID in the child */ +#define LINUX_CLONE_DETACHED 0x00400000 /* Unused, ignored */ +#define LINUX_CLONE_UNTRACED 0x00800000 /* undo LINUX_CLONE_PTRACE */ +#define LINUX_CLONE_CHILD_SETTID 0x01000000 /* set the TID in the child */ +#define LINUX_CLONE_STOPPED 0x02000000 /* Start in stopped state */ struct linux_sched_param { int sched_priority; |