aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/proc/base.c53
-rw-r--r--include/linux/user_namespace.h7
-rw-r--r--kernel/user.c1
-rw-r--r--kernel/user_namespace.c85
4 files changed, 146 insertions, 0 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 772efa45a452..7dc3ea89ef1a 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2464,6 +2464,57 @@ static const struct file_operations proc_projid_map_operations = {
2464 .llseek = seq_lseek, 2464 .llseek = seq_lseek,
2465 .release = proc_id_map_release, 2465 .release = proc_id_map_release,
2466}; 2466};
2467
2468static int proc_setgroups_open(struct inode *inode, struct file *file)
2469{
2470 struct user_namespace *ns = NULL;
2471 struct task_struct *task;
2472 int ret;
2473
2474 ret = -ESRCH;
2475 task = get_proc_task(inode);
2476 if (task) {
2477 rcu_read_lock();
2478 ns = get_user_ns(task_cred_xxx(task, user_ns));
2479 rcu_read_unlock();
2480 put_task_struct(task);
2481 }
2482 if (!ns)
2483 goto err;
2484
2485 if (file->f_mode & FMODE_WRITE) {
2486 ret = -EACCES;
2487 if (!ns_capable(ns, CAP_SYS_ADMIN))
2488 goto err_put_ns;
2489 }
2490
2491 ret = single_open(file, &proc_setgroups_show, ns);
2492 if (ret)
2493 goto err_put_ns;
2494
2495 return 0;
2496err_put_ns:
2497 put_user_ns(ns);
2498err:
2499 return ret;
2500}
2501
2502static int proc_setgroups_release(struct inode *inode, struct file *file)
2503{
2504 struct seq_file *seq = file->private_data;
2505 struct user_namespace *ns = seq->private;
2506 int ret = single_release(inode, file);
2507 put_user_ns(ns);
2508 return ret;
2509}
2510
2511static const struct file_operations proc_setgroups_operations = {
2512 .open = proc_setgroups_open,
2513 .write = proc_setgroups_write,
2514 .read = seq_read,
2515 .llseek = seq_lseek,
2516 .release = proc_setgroups_release,
2517};
2467#endif /* CONFIG_USER_NS */ 2518#endif /* CONFIG_USER_NS */
2468 2519
2469static int proc_pid_personality(struct seq_file *m, struct pid_namespace *ns, 2520static int proc_pid_personality(struct seq_file *m, struct pid_namespace *ns,
@@ -2572,6 +2623,7 @@ static const struct pid_entry tgid_base_stuff[] = {
2572 REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations), 2623 REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations),
2573 REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations), 2624 REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations),
2574 REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations), 2625 REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations),
2626 REG("setgroups", S_IRUGO|S_IWUSR, proc_setgroups_operations),
2575#endif 2627#endif
2576#ifdef CONFIG_CHECKPOINT_RESTORE 2628#ifdef CONFIG_CHECKPOINT_RESTORE
2577 REG("timers", S_IRUGO, proc_timers_operations), 2629 REG("timers", S_IRUGO, proc_timers_operations),
@@ -2913,6 +2965,7 @@ static const struct pid_entry tid_base_stuff[] = {
2913 REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations), 2965 REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations),
2914 REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations), 2966 REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations),
2915 REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations), 2967 REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations),
2968 REG("setgroups", S_IRUGO|S_IWUSR, proc_setgroups_operations),
2916#endif 2969#endif
2917}; 2970};
2918 2971
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 8d493083486a..9f3579ff543d 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -17,6 +17,10 @@ struct uid_gid_map { /* 64 bytes -- 1 cache line */
17 } extent[UID_GID_MAP_MAX_EXTENTS]; 17 } extent[UID_GID_MAP_MAX_EXTENTS];
18}; 18};
19 19
20#define USERNS_SETGROUPS_ALLOWED 1UL
21
22#define USERNS_INIT_FLAGS USERNS_SETGROUPS_ALLOWED
23
20struct user_namespace { 24struct user_namespace {
21 struct uid_gid_map uid_map; 25 struct uid_gid_map uid_map;
22 struct uid_gid_map gid_map; 26 struct uid_gid_map gid_map;
@@ -27,6 +31,7 @@ struct user_namespace {
27 kuid_t owner; 31 kuid_t owner;
28 kgid_t group; 32 kgid_t group;
29 unsigned int proc_inum; 33 unsigned int proc_inum;
34 unsigned long flags;
30 35
31 /* Register of per-UID persistent keyrings for this namespace */ 36 /* Register of per-UID persistent keyrings for this namespace */
32#ifdef CONFIG_PERSISTENT_KEYRINGS 37#ifdef CONFIG_PERSISTENT_KEYRINGS
@@ -63,6 +68,8 @@ extern const struct seq_operations proc_projid_seq_operations;
63extern ssize_t proc_uid_map_write(struct file *, const char __user *, size_t, loff_t *); 68extern ssize_t proc_uid_map_write(struct file *, const char __user *, size_t, loff_t *);
64extern ssize_t proc_gid_map_write(struct file *, const char __user *, size_t, loff_t *); 69extern ssize_t proc_gid_map_write(struct file *, const char __user *, size_t, loff_t *);
65extern ssize_t proc_projid_map_write(struct file *, const char __user *, size_t, loff_t *); 70extern ssize_t proc_projid_map_write(struct file *, const char __user *, size_t, loff_t *);
71extern ssize_t proc_setgroups_write(struct file *, const char __user *, size_t, loff_t *);
72extern int proc_setgroups_show(struct seq_file *m, void *v);
66extern bool userns_may_setgroups(const struct user_namespace *ns); 73extern bool userns_may_setgroups(const struct user_namespace *ns);
67#else 74#else
68 75
diff --git a/kernel/user.c b/kernel/user.c
index 4efa39350e44..2d09940c9632 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -51,6 +51,7 @@ struct user_namespace init_user_ns = {
51 .owner = GLOBAL_ROOT_UID, 51 .owner = GLOBAL_ROOT_UID,
52 .group = GLOBAL_ROOT_GID, 52 .group = GLOBAL_ROOT_GID,
53 .proc_inum = PROC_USER_INIT_INO, 53 .proc_inum = PROC_USER_INIT_INO,
54 .flags = USERNS_INIT_FLAGS,
54#ifdef CONFIG_PERSISTENT_KEYRINGS 55#ifdef CONFIG_PERSISTENT_KEYRINGS
55 .persistent_keyring_register_sem = 56 .persistent_keyring_register_sem =
56 __RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem), 57 __RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem),
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 44a555ac6104..6e80f4c1322b 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -100,6 +100,11 @@ int create_user_ns(struct cred *new)
100 ns->owner = owner; 100 ns->owner = owner;
101 ns->group = group; 101 ns->group = group;
102 102
103 /* Inherit USERNS_SETGROUPS_ALLOWED from our parent */
104 mutex_lock(&userns_state_mutex);
105 ns->flags = parent_ns->flags;
106 mutex_unlock(&userns_state_mutex);
107
103 set_cred_user_ns(new, ns); 108 set_cred_user_ns(new, ns);
104 109
105#ifdef CONFIG_PERSISTENT_KEYRINGS 110#ifdef CONFIG_PERSISTENT_KEYRINGS
@@ -839,6 +844,84 @@ static bool new_idmap_permitted(const struct file *file,
839 return false; 844 return false;
840} 845}
841 846
847int proc_setgroups_show(struct seq_file *seq, void *v)
848{
849 struct user_namespace *ns = seq->private;
850 unsigned long userns_flags = ACCESS_ONCE(ns->flags);
851
852 seq_printf(seq, "%s\n",
853 (userns_flags & USERNS_SETGROUPS_ALLOWED) ?
854 "allow" : "deny");
855 return 0;
856}
857
858ssize_t proc_setgroups_write(struct file *file, const char __user *buf,
859 size_t count, loff_t *ppos)
860{
861 struct seq_file *seq = file->private_data;
862 struct user_namespace *ns = seq->private;
863 char kbuf[8], *pos;
864 bool setgroups_allowed;
865 ssize_t ret;
866
867 /* Only allow a very narrow range of strings to be written */
868 ret = -EINVAL;
869 if ((*ppos != 0) || (count >= sizeof(kbuf)))
870 goto out;
871
872 /* What was written? */
873 ret = -EFAULT;
874 if (copy_from_user(kbuf, buf, count))
875 goto out;
876 kbuf[count] = '\0';
877 pos = kbuf;
878
879 /* What is being requested? */
880 ret = -EINVAL;
881 if (strncmp(pos, "allow", 5) == 0) {
882 pos += 5;
883 setgroups_allowed = true;
884 }
885 else if (strncmp(pos, "deny", 4) == 0) {
886 pos += 4;
887 setgroups_allowed = false;
888 }
889 else
890 goto out;
891
892 /* Verify there is not trailing junk on the line */
893 pos = skip_spaces(pos);
894 if (*pos != '\0')
895 goto out;
896
897 ret = -EPERM;
898 mutex_lock(&userns_state_mutex);
899 if (setgroups_allowed) {
900 /* Enabling setgroups after setgroups has been disabled
901 * is not allowed.
902 */
903 if (!(ns->flags & USERNS_SETGROUPS_ALLOWED))
904 goto out_unlock;
905 } else {
906 /* Permanently disabling setgroups after setgroups has
907 * been enabled by writing the gid_map is not allowed.
908 */
909 if (ns->gid_map.nr_extents != 0)
910 goto out_unlock;
911 ns->flags &= ~USERNS_SETGROUPS_ALLOWED;
912 }
913 mutex_unlock(&userns_state_mutex);
914
915 /* Report a successful write */
916 *ppos = count;
917 ret = count;
918out:
919 return ret;
920out_unlock:
921 mutex_unlock(&userns_state_mutex);
922 goto out;
923}
924
842bool userns_may_setgroups(const struct user_namespace *ns) 925bool userns_may_setgroups(const struct user_namespace *ns)
843{ 926{
844 bool allowed; 927 bool allowed;
@@ -848,6 +931,8 @@ bool userns_may_setgroups(const struct user_namespace *ns)
848 * the user namespace has been established. 931 * the user namespace has been established.
849 */ 932 */
850 allowed = ns->gid_map.nr_extents != 0; 933 allowed = ns->gid_map.nr_extents != 0;
934 /* Is setgroups allowed? */
935 allowed = allowed && (ns->flags & USERNS_SETGROUPS_ALLOWED);
851 mutex_unlock(&userns_state_mutex); 936 mutex_unlock(&userns_state_mutex);
852 937
853 return allowed; 938 return allowed;