[Devel] [PATCH 08/10] userns: store child userns uids as xattrs in ext3 using lib/fsuserns

Serge E. Hallyn serue at us.ibm.com
Fri Aug 22 12:47:05 PDT 2008


userns: store child userns uids as xattrs in ext3 using lib/fsuserns

Signed-off-by: Serge Hallyn <serue at us.ibm.com>
---
 fs/ext3/namei.c                |    7 +++-
 fs/ext3/xattr.c                |   29 +++++++++++++++
 fs/ext3/xattr.h                |    2 +
 include/linux/user_namespace.h |    1 +
 kernel/user_namespace.c        |    1 +
 lib/fsuserns.c                 |   74 ++++++++++++++++++++++++++++++++++++++++
 6 files changed, 113 insertions(+), 1 deletions(-)

diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index de13e91..e5be4bc 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1676,6 +1676,9 @@ static int ext3_add_nondir(handle_t *handle,
 	return err;
 }
 
+int fsuserns_store_creds(struct inode *inode, struct user_struct *user,
+	int (*)(struct inode *inode, const void *value, size_t value_len));
+
 /*
  * By the time this is called, we already have created
  * the directory cache entry for the new file, but it
@@ -1707,7 +1710,9 @@ retry:
 		inode->i_op = &ext3_file_inode_operations;
 		inode->i_fop = &ext3_file_operations;
 		ext3_set_aops(inode);
-		err = ext3_add_nondir(handle, dentry, inode);
+		err = fsuserns_store_creds(inode, current->user, ext3_xattr_set_userns);
+		if (!err)
+			err = ext3_add_nondir(handle, dentry, inode);
 	}
 	ext3_journal_stop(handle);
 	if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 175414a..da47c35 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -1070,6 +1070,35 @@ retry:
 	return error;
 }
 
+int
+ext3_xattr_set_userns(struct inode *inode,
+	       const void *value, size_t value_len)
+{
+	int name_index = EXT3_XATTR_INDEX_SECURITY;
+	handle_t *handle;
+	int error, retries = 0;
+	char *name = "userns";
+
+retry:
+	handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
+	if (IS_ERR(handle)) {
+		error = PTR_ERR(handle);
+	} else {
+		int error2;
+
+		error = ext3_xattr_set_handle(handle, inode, name_index, name,
+					      value, value_len, flags);
+		error2 = ext3_journal_stop(handle);
+		if (error == -ENOSPC &&
+		    ext3_should_retry_alloc(inode->i_sb, &retries))
+			goto retry;
+		if (error == 0)
+			error = error2;
+	}
+
+	return error;
+}
+
 /*
  * ext3_xattr_delete_inode()
  *
diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h
index 148a4df..8a523de 100644
--- a/fs/ext3/xattr.h
+++ b/fs/ext3/xattr.h
@@ -70,6 +70,8 @@ extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
 extern int ext3_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
 extern int ext3_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int);
 
+extern int ext3_xattr_set_userns(struct inode *inode, const void *value, size_t value_len, int flags);
+
 extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
 extern void ext3_xattr_put_super(struct super_block *);
 
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 1b4959d..a793263 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -14,6 +14,7 @@ struct user_namespace {
 	struct hlist_head	uidhash_table[UIDHASH_SZ];
 	struct user_struct	*root_user;
 	struct user_struct	*creator;
+	gid_t			creator_grp;
 };
 
 extern struct user_namespace init_user_ns;
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 39aea7b..879693a 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -51,6 +51,7 @@ int create_new_userns(int flags, struct task_struct *tsk)
 	put_user_ns(ns);
 
 	task_switch_uid(tsk, ns->root_user);
+	ns->creator_grp = tsk->gid;
 	tsk->uid = tsk->euid = tsk->suid = tsk->fsuid = 0;
 	tsk->gid = tsk->egid = tsk->sgid = tsk->fsgid = 0;
 
diff --git a/lib/fsuserns.c b/lib/fsuserns.c
index c237d1d..db70970 100644
--- a/lib/fsuserns.c
+++ b/lib/fsuserns.c
@@ -5,6 +5,7 @@
 #include <linux/fs.h>
 #include <linux/user.h>
 #include <linux/user_namespace.h>
+#include <linux/xattr.h>
 
 /*
  * Ok, eventually I'll want some policy loaded which looks as follows:
@@ -233,3 +234,76 @@ convert:
 	printk(KERN_NOTICE "%s: oh, but I wasn't capable(%d)\n", __func__, cap);
 	return 0;
 }
+
+/*
+ * when a user_namespace is registered with an fs, we store the
+ * nsid.  This next fn will need to retreive an nsid for a
+ * given fs (inode->i_sb, that is) and user_namespace
+ *
+ * I don't want to do that bookkeeping yet, so i just return 1 :)
+ */
+int find_ns_id(struct inode *inode, struct user_namespace *ns)
+{
+	struct fsuserns_conversion_table *t;
+	struct fsuserns_table_entries *ep;
+
+	t = find_table(inode->i_sb);
+	mutex_lock(&fsuserns_table_mutex);
+	list_for_each_entry(ep, &t->entries, entries) {
+		if (ep->ns == ns)
+			goto found;
+	}
+	ep = NULL;
+found:
+	mutex_unlock(&fsuserns_table_mutex);
+
+	if (!ep)
+		return -1;
+	return ep->userns_id;
+
+
+}
+
+struct unsstore {
+	int ns;
+	uid_t uid;
+};
+
+int fsuserns_store_creds(struct inode *inode, struct user_struct *user,
+	int (*xattrset)(struct inode *inode, const void *value, size_t value_len))
+{
+	struct user_namespace *ns = user->user_ns, *lastns;
+	size_t size;
+	int i, depth, ret;
+	struct unsstore *unsstore;
+	struct user_struct *creator = user;
+	
+	if (ns == &init_user_ns)
+		return 0;
+
+	depth = 0;
+	while (ns != &init_user_ns) {
+		depth++;
+		creator = ns->creator;
+		ns = creator->user_ns;
+	}
+	size = depth * sizeof(struct unsstore);
+	unsstore = kmalloc(size, GFP_KERNEL);
+	ns = user->user_ns;
+	for (i=0; ns != &init_user_ns; i++) {
+		unsstore[i].ns = find_ns_id(inode, ns);
+		unsstore[i].uid = user->uid;
+		printk(KERN_NOTICE "%s: setting xattr with ns=%d,uid=%d\n", __func__,
+				unsstore[i].ns, unsstore[i].uid);
+		user = ns->creator;
+		lastns = ns;
+		ns = user->user_ns;
+	}
+
+	inode->i_uid = creator->uid;
+	inode->i_gid = lastns->creator_grp;
+
+	ret = xattrset(inode, unsstore, size);
+	kfree(unsstore);
+	return ret;
+}
-- 
1.5.4.3

_______________________________________________
Containers mailing list
Containers at lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers




More information about the Devel mailing list