| From e66eded8309ebf679d3d3c1f5820d1f2ca332c71 Mon Sep 17 00:00:00 2001 |
| From: "Eric W. Biederman" <ebiederm@xmission.com> |
| Date: Wed, 13 Mar 2013 11:51:49 -0700 |
| Subject: userns: Don't allow CLONE_NEWUSER | CLONE_FS |
| |
| From: "Eric W. Biederman" <ebiederm@xmission.com> |
| |
| commit e66eded8309ebf679d3d3c1f5820d1f2ca332c71 upstream. |
| |
| Don't allowing sharing the root directory with processes in a |
| different user namespace. There doesn't seem to be any point, and to |
| allow it would require the overhead of putting a user namespace |
| reference in fs_struct (for permission checks) and incrementing that |
| reference count on practically every call to fork. |
| |
| So just perform the inexpensive test of forbidding sharing fs_struct |
| acrosss processes in different user namespaces. We already disallow |
| other forms of threading when unsharing a user namespace so this |
| should be no real burden in practice. |
| |
| This updates setns, clone, and unshare to disallow multiple user |
| namespaces sharing an fs_struct. |
| |
| Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| kernel/fork.c | 5 ++++- |
| kernel/user_namespace.c | 4 ++++ |
| 2 files changed, 8 insertions(+), 1 deletion(-) |
| |
| --- a/kernel/fork.c |
| +++ b/kernel/fork.c |
| @@ -1141,6 +1141,9 @@ static struct task_struct *copy_process( |
| if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) |
| return ERR_PTR(-EINVAL); |
| |
| + if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS)) |
| + return ERR_PTR(-EINVAL); |
| + |
| /* |
| * Thread groups must share signals as well, and detached threads |
| * can only be started up within the thread group. |
| @@ -1801,7 +1804,7 @@ SYSCALL_DEFINE1(unshare, unsigned long, |
| * If unsharing a user namespace must also unshare the thread. |
| */ |
| if (unshare_flags & CLONE_NEWUSER) |
| - unshare_flags |= CLONE_THREAD; |
| + unshare_flags |= CLONE_THREAD | CLONE_FS; |
| /* |
| * If unsharing a pid namespace must also unshare the thread. |
| */ |
| --- a/kernel/user_namespace.c |
| +++ b/kernel/user_namespace.c |
| @@ -21,6 +21,7 @@ |
| #include <linux/uaccess.h> |
| #include <linux/ctype.h> |
| #include <linux/projid.h> |
| +#include <linux/fs_struct.h> |
| |
| static struct kmem_cache *user_ns_cachep __read_mostly; |
| |
| @@ -803,6 +804,9 @@ static int userns_install(struct nsproxy |
| if (atomic_read(¤t->mm->mm_users) > 1) |
| return -EINVAL; |
| |
| + if (current->fs->users != 1) |
| + return -EINVAL; |
| + |
| if (!ns_capable(user_ns, CAP_SYS_ADMIN)) |
| return -EPERM; |
| |