aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2014-12-02 13:27:26 -0500
committerEric W. Biederman <ebiederm@xmission.com>2014-12-11 19:06:36 -0500
commit9cc46516ddf497ea16e8d7cb986ae03a0f6b92f8 (patch)
treed996dd9c6d422e723af0da786add936bd7ec1c91
parentf0d62aec931e4ae3333c797d346dc4f188f454ba (diff)
userns: Add a knob to disable setgroups on a per user namespace basis
- 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. Cc: stable@vger.kernel.org Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
-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;