Hi Eric, Today's linux-next merge of the userns tree got a conflict in kernel/user_namespace.c between commits 3c0411846118 ("switch the rest of proc_ns_operations to working with &...->ns") and 64964528b24e ("make proc_ns_operations work with struct ns_common * instead of void *") from the vfs tree and commits 273d2c67c3e1 ("userns: Don't allow setgroups until a gid mapping has been setablished") and 9cc46516ddf4 ("userns: Add a knob to disable setgroups on a per user namespace basis") from the userns tree. I fixed it up (see below) and can carry the fix as necessary (no action is required). -- Cheers, Stephen Rothwell sfr@xxxxxxxxxxxxxxxx diff --cc kernel/user_namespace.c index 1491ad00388f,ad419b04c146..000000000000 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@@ -842,12 -849,101 +850,106 @@@ static bool new_idmap_permitted(const s return false; } +static inline struct user_namespace *to_user_ns(struct ns_common *ns) +{ + return container_of(ns, struct user_namespace, ns); +} + + int proc_setgroups_show(struct seq_file *seq, void *v) + { + struct user_namespace *ns = seq->private; + unsigned long userns_flags = ACCESS_ONCE(ns->flags); + + seq_printf(seq, "%s\n", + (userns_flags & USERNS_SETGROUPS_ALLOWED) ? + "allow" : "deny"); + return 0; + } + + ssize_t proc_setgroups_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) + { + struct seq_file *seq = file->private_data; + struct user_namespace *ns = seq->private; + char kbuf[8], *pos; + bool setgroups_allowed; + ssize_t ret; + + /* Only allow a very narrow range of strings to be written */ + ret = -EINVAL; + if ((*ppos != 0) || (count >= sizeof(kbuf))) + goto out; + + /* What was written? */ + ret = -EFAULT; + if (copy_from_user(kbuf, buf, count)) + goto out; + kbuf[count] = '\0'; + pos = kbuf; + + /* What is being requested? */ + ret = -EINVAL; + if (strncmp(pos, "allow", 5) == 0) { + pos += 5; + setgroups_allowed = true; + } + else if (strncmp(pos, "deny", 4) == 0) { + pos += 4; + setgroups_allowed = false; + } + else + goto out; + + /* Verify there is not trailing junk on the line */ + pos = skip_spaces(pos); + if (*pos != '\0') + goto out; + + ret = -EPERM; + mutex_lock(&userns_state_mutex); + if (setgroups_allowed) { + /* Enabling setgroups after setgroups has been disabled + * is not allowed. + */ + if (!(ns->flags & USERNS_SETGROUPS_ALLOWED)) + goto out_unlock; + } else { + /* Permanently disabling setgroups after setgroups has + * been enabled by writing the gid_map is not allowed. + */ + if (ns->gid_map.nr_extents != 0) + goto out_unlock; + ns->flags &= ~USERNS_SETGROUPS_ALLOWED; + } + mutex_unlock(&userns_state_mutex); + + /* Report a successful write */ + *ppos = count; + ret = count; + out: + return ret; + out_unlock: + mutex_unlock(&userns_state_mutex); + goto out; + } + + bool userns_may_setgroups(const struct user_namespace *ns) + { + bool allowed; + + mutex_lock(&userns_state_mutex); + /* It is not safe to use setgroups until a gid mapping in + * the user namespace has been established. + */ + allowed = ns->gid_map.nr_extents != 0; + /* Is setgroups allowed? */ + allowed = allowed && (ns->flags & USERNS_SETGROUPS_ALLOWED); + mutex_unlock(&userns_state_mutex); + + return allowed; + } + -static void *userns_get(struct task_struct *task) +static struct ns_common *userns_get(struct task_struct *task) { struct user_namespace *user_ns;
Attachment:
pgppOKUix5J0G.pgp
Description: OpenPGP digital signature