linux-next: manual merge of the userns tree with the vfs tree

From: Stephen Rothwell
Date: Mon Dec 15 2014 - 22:21:31 EST


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: pgpodBJrbr0rg.pgp
Description: OpenPGP digital signature