diff options
Diffstat (limited to 'kernel/user_namespace.c')
| -rw-r--r-- | kernel/user_namespace.c | 46 |
1 files changed, 45 insertions, 1 deletions
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 | ||
