diff options
author | Philip Guenthe <guenther@cvs.openbsd.org> | 2010-01-04 19:27:22 +0000 |
---|---|---|
committer | Philip Guenthe <guenther@cvs.openbsd.org> | 2010-01-04 19:27:22 +0000 |
commit | a26f38ecb5333a71a35ddf489a8da5ccfeba3c7c (patch) | |
tree | bf47e6c25b80e40705eb620930c68e8f232da381 /sys | |
parent | 0cd9308f43d1309399f86f68a1eb1e1957e1eb5b (diff) |
Previous commit was too restrictive: just ignore the CLONE_FS flag
when not doing CLONE_THREAD, like we did before, instead of treating
it as an error. This unbreaks Opera running in linux compat.
Also, Linux completely ignores CLONE_DETACHED, so do that too, and
consistently refer to the flags in comment via their Linux names
without trying to abbreviate them further.
Problem found and fix confirmed by sturm@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/compat/linux/linux_sched.c | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/sys/compat/linux/linux_sched.c b/sys/compat/linux/linux_sched.c index f2011ea95b2..7500d978231 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.7 2009/12/28 02:54:24 guenther Exp $ */ +/* $OpenBSD: linux_sched.c,v 1.8 2010/01/04 19:27:21 guenther Exp $ */ /* $NetBSD: linux_sched.c,v 1.6 2000/05/28 05:49:05 thorpej Exp $ */ /*- @@ -73,7 +73,7 @@ linux_sys_clone(p, v, retval) 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)) + LINUX_CLONE_DETACHED | LINUX_CLONE_UNTRACED)) return (EINVAL); if (cflags & LINUX_CLONE_VM) @@ -81,7 +81,7 @@ linux_sys_clone(p, v, retval) if (cflags & LINUX_CLONE_FILES) flags |= FORK_SHAREFILES; if (cflags & LINUX_CLONE_SIGHAND) { - /* According to Linux, SIGHAND requires VM */ + /* According to Linux, CLONE_SIGHAND requires CLONE_VM */ if ((cflags & LINUX_CLONE_VM) == 0) return (EINVAL); flags |= FORK_SIGHAND; @@ -90,10 +90,11 @@ linux_sys_clone(p, v, retval) 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. + * Linux agrees with us: CLONE_THREAD requires + * CLONE_SIGHAND. Unlike Linux, we also also require + * CLONE_FS and CLONE_SYSVSEM. Also, we decree it + * to be incompatible with CLONE_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) @@ -102,21 +103,36 @@ linux_sys_clone(p, v, retval) 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 + * Linux says that CLONE_THREAD means no signal + * will be sent on exit (even if a non-standard + * signal is requested via 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)) + /* + * These are only supported with CLONE_THREAD. Arguably, + * CLONE_FS should be in this list, because we don't + * support sharing of working directory and root directory + * (chdir + chroot) except via threads. On the other + * hand, we tie the sharing of umask to the sharing of + * files, so a process that doesn't request CLONE_FS but + * does ask for CLONE_FILES is going to get some of the + * former's effect. Some programs (e.g., Opera) at least + * _seem_ to work if we let it through, so we'll just + * cross our fingers for now and silently ignore it if + * CLONE_FILES was also requested. + */ + if (cflags & (LINUX_CLONE_PARENT | LINUX_CLONE_SYSVSEM)) + return (EINVAL); + if ((cflags & (LINUX_CLONE_FS | LINUX_CLONE_FILES)) == + LINUX_CLONE_FS) return (EINVAL); } /* * Since we don't support CLONE_PTRACE, the CLONE_UNTRACED - * flag can be silently ignored. + * flag can be silently ignored. CLONE_DETACHED is always + * ignored by Linux. */ sig = cflags & LINUX_CLONE_CSIGNAL; |