Commit 4a7215f13452bf2e8d271b2b9f09fddd990b4c04

Authored by Eric W. Biederman
Committed by Greg Kroah-Hartman
1 parent 54b8ced1ef

userns: Add a knob to disable setgroups on a per user namespace basis

commit 9cc46516ddf497ea16e8d7cb986ae03a0f6b92f8 upstream.

- Expose the knob to user space through a proc file /proc/<pid>/setgroups

  A value of "deny" means the setgroups system call is disabled in the
  current processes user namespace and can not be enabled in the
  future in this user namespace.

  A value of "allow" means the segtoups system call is enabled.

- Descendant user namespaces inherit the value of setgroups from
  their parents.

- A proc file is used (instead of a sysctl) as sysctls currently do
  not allow checking the permissions at open time.

- Writing to the proc file is restricted to before the gid_map
  for the user namespace is set.

  This ensures that disabling setgroups at a user namespace
  level will never remove the ability to call setgroups
  from a process that already has that ability.

  A process may opt in to the setgroups disable for itself by
  creating, entering and configuring a user namespace or by calling
  setns on an existing user namespace with setgroups disabled.
  Processes without privileges already can not call setgroups so this
  is a noop.  Prodcess with privilege become processes without
  privilege when entering a user namespace and as with any other path
  to dropping privilege they would not have the ability to call
  setgroups.  So this remains within the bounds of what is possible
  without a knob to disable setgroups permanently in a user namespace.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 4 changed files with 146 additions and 0 deletions Side-by-side Diff

... ... @@ -2464,6 +2464,57 @@
2464 2464 .llseek = seq_lseek,
2465 2465 .release = proc_id_map_release,
2466 2466 };
  2467 +
  2468 +static 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;
  2496 +err_put_ns:
  2497 + put_user_ns(ns);
  2498 +err:
  2499 + return ret;
  2500 +}
  2501 +
  2502 +static 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 +
  2511 +static 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 2518 #endif /* CONFIG_USER_NS */
2468 2519  
2469 2520 static int proc_pid_personality(struct seq_file *m, struct pid_namespace *ns,
... ... @@ -2572,6 +2623,7 @@
2572 2623 REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations),
2573 2624 REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations),
2574 2625 REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations),
  2626 + REG("setgroups", S_IRUGO|S_IWUSR, proc_setgroups_operations),
2575 2627 #endif
2576 2628 #ifdef CONFIG_CHECKPOINT_RESTORE
2577 2629 REG("timers", S_IRUGO, proc_timers_operations),
... ... @@ -2913,6 +2965,7 @@
2913 2965 REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations),
2914 2966 REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations),
2915 2967 REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations),
  2968 + REG("setgroups", S_IRUGO|S_IWUSR, proc_setgroups_operations),
2916 2969 #endif
2917 2970 };
2918 2971  
include/linux/user_namespace.h
... ... @@ -17,6 +17,10 @@
17 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 +
20 24 struct user_namespace {
21 25 struct uid_gid_map uid_map;
22 26 struct uid_gid_map gid_map;
... ... @@ -27,6 +31,7 @@
27 31 kuid_t owner;
28 32 kgid_t group;
29 33 unsigned int proc_inum;
  34 + unsigned long flags;
30 35  
31 36 /* Register of per-UID persistent keyrings for this namespace */
32 37 #ifdef CONFIG_PERSISTENT_KEYRINGS
... ... @@ -63,6 +68,8 @@
63 68 extern ssize_t proc_uid_map_write(struct file *, const char __user *, size_t, loff_t *);
64 69 extern ssize_t proc_gid_map_write(struct file *, const char __user *, size_t, loff_t *);
65 70 extern ssize_t proc_projid_map_write(struct file *, const char __user *, size_t, loff_t *);
  71 +extern ssize_t proc_setgroups_write(struct file *, const char __user *, size_t, loff_t *);
  72 +extern int proc_setgroups_show(struct seq_file *m, void *v);
66 73 extern bool userns_may_setgroups(const struct user_namespace *ns);
67 74 #else
68 75  
... ... @@ -51,6 +51,7 @@
51 51 .owner = GLOBAL_ROOT_UID,
52 52 .group = GLOBAL_ROOT_GID,
53 53 .proc_inum = PROC_USER_INIT_INO,
  54 + .flags = USERNS_INIT_FLAGS,
54 55 #ifdef CONFIG_PERSISTENT_KEYRINGS
55 56 .persistent_keyring_register_sem =
56 57 __RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem),
kernel/user_namespace.c
... ... @@ -100,6 +100,11 @@
100 100 ns->owner = owner;
101 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 108 set_cred_user_ns(new, ns);
104 109  
105 110 #ifdef CONFIG_PERSISTENT_KEYRINGS
... ... @@ -839,6 +844,84 @@
839 844 return false;
840 845 }
841 846  
  847 +int 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 +
  858 +ssize_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;
  918 +out:
  919 + return ret;
  920 +out_unlock:
  921 + mutex_unlock(&userns_state_mutex);
  922 + goto out;
  923 +}
  924 +
842 925 bool userns_may_setgroups(const struct user_namespace *ns)
843 926 {
844 927 bool allowed;
... ... @@ -848,6 +931,8 @@
848 931 * the user namespace has been established.
849 932 */
850 933 allowed = ns->gid_map.nr_extents != 0;
  934 + /* Is setgroups allowed? */
  935 + allowed = allowed && (ns->flags & USERNS_SETGROUPS_ALLOWED);
851 936 mutex_unlock(&userns_state_mutex);
852 937  
853 938 return allowed;