diff options
-rw-r--r-- | include/linux/sched.h | 1 | ||||
-rw-r--r-- | include/linux/user_namespace.h | 4 | ||||
-rw-r--r-- | kernel/fork.c | 2 | ||||
-rw-r--r-- | kernel/nsproxy.c | 5 | ||||
-rw-r--r-- | kernel/user_namespace.c | 46 |
5 files changed, 54 insertions, 4 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h index c667255d70db..731edaca8ffd 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #define CLONE_STOPPED 0x02000000 /* Start in stopped state */ | 26 | #define CLONE_STOPPED 0x02000000 /* Start in stopped state */ |
27 | #define CLONE_NEWUTS 0x04000000 /* New utsname group? */ | 27 | #define CLONE_NEWUTS 0x04000000 /* New utsname group? */ |
28 | #define CLONE_NEWIPC 0x08000000 /* New ipcs */ | 28 | #define CLONE_NEWIPC 0x08000000 /* New ipcs */ |
29 | #define CLONE_NEWUSER 0x10000000 /* New user namespace */ | ||
29 | 30 | ||
30 | /* | 31 | /* |
31 | * Scheduling policies | 32 | * Scheduling policies |
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index 92a45867ecfb..bb320573bb9e 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/kref.h> | 4 | #include <linux/kref.h> |
5 | #include <linux/nsproxy.h> | 5 | #include <linux/nsproxy.h> |
6 | #include <linux/sched.h> | 6 | #include <linux/sched.h> |
7 | #include <linux/err.h> | ||
7 | 8 | ||
8 | #define UIDHASH_BITS (CONFIG_BASE_SMALL ? 3 : 8) | 9 | #define UIDHASH_BITS (CONFIG_BASE_SMALL ? 3 : 8) |
9 | #define UIDHASH_SZ (1 << UIDHASH_BITS) | 10 | #define UIDHASH_SZ (1 << UIDHASH_BITS) |
@@ -45,6 +46,9 @@ static inline struct user_namespace *get_user_ns(struct user_namespace *ns) | |||
45 | static inline struct user_namespace *copy_user_ns(int flags, | 46 | static inline struct user_namespace *copy_user_ns(int flags, |
46 | struct user_namespace *old_ns) | 47 | struct user_namespace *old_ns) |
47 | { | 48 | { |
49 | if (flags & CLONE_NEWUSER) | ||
50 | return ERR_PTR(-EINVAL); | ||
51 | |||
48 | return NULL; | 52 | return NULL; |
49 | } | 53 | } |
50 | 54 | ||
diff --git a/kernel/fork.c b/kernel/fork.c index 13cf0978780a..7c5c5888e00a 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -1606,7 +1606,7 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) | |||
1606 | err = -EINVAL; | 1606 | err = -EINVAL; |
1607 | if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND| | 1607 | if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND| |
1608 | CLONE_VM|CLONE_FILES|CLONE_SYSVSEM| | 1608 | CLONE_VM|CLONE_FILES|CLONE_SYSVSEM| |
1609 | CLONE_NEWUTS|CLONE_NEWIPC)) | 1609 | CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWUSER)) |
1610 | goto bad_unshare_out; | 1610 | goto bad_unshare_out; |
1611 | 1611 | ||
1612 | if ((err = unshare_thread(unshare_flags))) | 1612 | if ((err = unshare_thread(unshare_flags))) |
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index 895e3a3f2044..5aa28e219487 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c | |||
@@ -117,7 +117,7 @@ int copy_namespaces(int flags, struct task_struct *tsk) | |||
117 | 117 | ||
118 | get_nsproxy(old_ns); | 118 | get_nsproxy(old_ns); |
119 | 119 | ||
120 | if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC))) | 120 | if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER))) |
121 | return 0; | 121 | return 0; |
122 | 122 | ||
123 | if (!capable(CAP_SYS_ADMIN)) { | 123 | if (!capable(CAP_SYS_ADMIN)) { |
@@ -161,7 +161,8 @@ int unshare_nsproxy_namespaces(unsigned long unshare_flags, | |||
161 | { | 161 | { |
162 | int err = 0; | 162 | int err = 0; |
163 | 163 | ||
164 | if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC))) | 164 | if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | |
165 | CLONE_NEWUSER))) | ||
165 | return 0; | 166 | return 0; |
166 | 167 | ||
167 | if (!capable(CAP_SYS_ADMIN)) | 168 | if (!capable(CAP_SYS_ADMIN)) |
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 3d7964209774..89a27e8b17fb 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c | |||
@@ -21,6 +21,45 @@ EXPORT_SYMBOL_GPL(init_user_ns); | |||
21 | 21 | ||
22 | #ifdef CONFIG_USER_NS | 22 | #ifdef CONFIG_USER_NS |
23 | 23 | ||
24 | /* | ||
25 | * Clone a new ns copying an original user ns, setting refcount to 1 | ||
26 | * @old_ns: namespace to clone | ||
27 | * Return NULL on error (failure to kmalloc), new ns otherwise | ||
28 | */ | ||
29 | static struct user_namespace *clone_user_ns(struct user_namespace *old_ns) | ||
30 | { | ||
31 | struct user_namespace *ns; | ||
32 | struct user_struct *new_user; | ||
33 | int n; | ||
34 | |||
35 | ns = kmalloc(sizeof(struct user_namespace), GFP_KERNEL); | ||
36 | if (!ns) | ||
37 | return NULL; | ||
38 | |||
39 | kref_init(&ns->kref); | ||
40 | |||
41 | for (n = 0; n < UIDHASH_SZ; ++n) | ||
42 | INIT_LIST_HEAD(ns->uidhash_table + n); | ||
43 | |||
44 | /* Insert new root user. */ | ||
45 | ns->root_user = alloc_uid(ns, 0); | ||
46 | if (!ns->root_user) { | ||
47 | kfree(ns); | ||
48 | return NULL; | ||
49 | } | ||
50 | |||
51 | /* Reset current->user with a new one */ | ||
52 | new_user = alloc_uid(ns, current->uid); | ||
53 | if (!new_user) { | ||
54 | free_uid(ns->root_user); | ||
55 | kfree(ns); | ||
56 | return NULL; | ||
57 | } | ||
58 | |||
59 | switch_uid(new_user); | ||
60 | return ns; | ||
61 | } | ||
62 | |||
24 | struct user_namespace * copy_user_ns(int flags, struct user_namespace *old_ns) | 63 | struct user_namespace * copy_user_ns(int flags, struct user_namespace *old_ns) |
25 | { | 64 | { |
26 | struct user_namespace *new_ns; | 65 | struct user_namespace *new_ns; |
@@ -28,7 +67,12 @@ struct user_namespace * copy_user_ns(int flags, struct user_namespace *old_ns) | |||
28 | BUG_ON(!old_ns); | 67 | BUG_ON(!old_ns); |
29 | get_user_ns(old_ns); | 68 | get_user_ns(old_ns); |
30 | 69 | ||
31 | new_ns = old_ns; | 70 | if (!(flags & CLONE_NEWUSER)) |
71 | return old_ns; | ||
72 | |||
73 | new_ns = clone_user_ns(old_ns); | ||
74 | |||
75 | put_user_ns(old_ns); | ||
32 | return new_ns; | 76 | return new_ns; |
33 | } | 77 | } |
34 | 78 | ||