[PATCH 09/10] userns: have ext3 use fsuserns to read userns xattrs, and add groups to userns

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


userns: have ext3 use fsuserns to read userns xattrs, and add groups to userns

Signed-off-by: Serge Hallyn <serue at us.ibm.com>
---
 fs/ext3/super.c    |   11 +++++++++--
 fs/ext3/xattr.c    |   19 ++++++++++++++++++-
 fs/ext3/xattr.h    |    3 ++-
 include/linux/fs.h |    2 +-
 lib/fsuserns.c     |   48 +++++++++++++++++++++++++++++++++++++++++-------
 5 files changed, 71 insertions(+), 12 deletions(-)

diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 3458d25..37c8404 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -723,11 +723,18 @@ static struct quotactl_ops ext3_qctl_operations = {
 extern int fsuserns_add_userns(struct super_block *sb,
                 struct user *user, void *data);
 extern int fsuserns_convert_uid_gid(struct user_namespace *ns,
-		struct inode *inode, uid_t *retuid, gid_t *retgid);
+		struct inode *inode, uid_t *retuid, gid_t *retgid,
+		int (*xattrget)(struct inode *, const void *, size_t));
 extern int fsuserns_is_capable(struct user_namespace *ns,
 		struct inode *inode, int cap);
 #endif
 
+int ext3_convert_uid_gid(struct user_namespace *ns, struct inode *inode,
+                        uid_t *retuid, gid_t *retgid)
+{
+	return fsuserns_convert_uid_gid(ns, inode, retuid, retgid, ext3_xattr_get_userns);
+}
+
 static const struct super_operations ext3_sops = {
 	.alloc_inode	= ext3_alloc_inode,
 	.destroy_inode	= ext3_destroy_inode,
@@ -750,7 +757,7 @@ static const struct super_operations ext3_sops = {
 #ifdef CONFIG_USER_NS
 	.add_userns	= fsuserns_add_userns,
 	.is_capable	= fsuserns_is_capable,
-	.convert_uid_gid = fsuserns_convert_uid_gid,
+	.convert_uid_gid = ext3_convert_uid_gid,
 #endif
 };
 
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index da47c35..500fec7 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -331,6 +331,23 @@ ext3_xattr_get(struct inode *inode, int name_index, const char *name,
 	return error;
 }
 
+int
+ext3_xattr_get_userns(struct inode *inode, void *value, size_t value_size)
+{
+	int error;
+	int name_index = EXT3_XATTR_INDEX_SECURITY;
+	char *name = "userns";
+
+	down_read(&EXT3_I(inode)->xattr_sem);
+	error = ext3_xattr_ibody_get(inode, name_index, name, value,
+				     value_size);
+	if (error == -ENODATA)
+		error = ext3_xattr_block_get(inode, name_index, name, value,
+					     value_size);
+	up_read(&EXT3_I(inode)->xattr_sem);
+	return error;
+}
+
 static int
 ext3_xattr_list_entries(struct inode *inode, struct ext3_xattr_entry *entry,
 			char *buffer, size_t buffer_size)
@@ -1087,7 +1104,7 @@ retry:
 		int error2;
 
 		error = ext3_xattr_set_handle(handle, inode, name_index, name,
-					      value, value_len, flags);
+					      value, value_len, 0);
 		error2 = ext3_journal_stop(handle);
 		if (error == -ENOSPC &&
 		    ext3_should_retry_alloc(inode->i_sb, &retries))
diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h
index 8a523de..8c5b982 100644
--- a/fs/ext3/xattr.h
+++ b/fs/ext3/xattr.h
@@ -70,7 +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 int ext3_xattr_get_userns(struct inode *inode, void *value, size_t value_len);
+extern int ext3_xattr_set_userns(struct inode *inode, const void *value, size_t value_len);
 
 extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
 extern void ext3_xattr_put_super(struct super_block *);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 492abef..9ec6dac 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1329,7 +1329,7 @@ struct super_operations {
 	void (*umount_begin) (struct super_block *);
 	int (*add_userns) (struct super_block *, struct user_struct *, void *);
 	int (*is_capable) (struct user_namespace *, struct inode *, int);
-	uid_t (*convert_uid_gid)(struct user_namespace *, struct inode *,
+	int (*convert_uid_gid)(struct user_namespace *, struct inode *,
 						uid_t *, gid_t *);
 
 	int (*show_options)(struct seq_file *, struct vfsmount *);
diff --git a/lib/fsuserns.c b/lib/fsuserns.c
index db70970..ac0ca99 100644
--- a/lib/fsuserns.c
+++ b/lib/fsuserns.c
@@ -59,6 +59,12 @@ struct fsuserns_conversion_table {
 
 LIST_HEAD(fsuserns_tables);
 
+struct unsstore {
+	int ns;
+	uid_t uid;
+	gid_t gid;
+};
+
 struct fsuserns_conversion_table *find_table_locked(
 				struct super_block *sb)
 {
@@ -166,11 +172,15 @@ skip:
  * return 1 if we got a translation, 0 otherwise
  */
 int fsuserns_convert_uid_gid(struct user_namespace *ns, struct inode *inode,
-                                                uid_t *retuid, gid_t *retgid)
+			uid_t *retuid, gid_t *retgid,
+			int (*xattrget)(struct inode *inode, void *value, size_t value_len))
 {
 	struct super_block *sb = inode->i_sb;
 	struct fsuserns_conversion_table *t;
 	struct fsuserns_table_entries *ep;
+	size_t valuelen;
+	struct unsstore *unsstore;
+	int i, ret;
 
 	t = find_table(sb);
 	if (!t)
@@ -186,6 +196,23 @@ int fsuserns_convert_uid_gid(struct user_namespace *ns, struct inode *inode,
 convert:
 	mutex_unlock(&fsuserns_table_mutex);
 
+	/* look for an xattr */
+	/* yes, 3 needs to be made adjustable */
+	valuelen = 3;
+	unsstore = kzalloc(3*sizeof(struct unsstore), GFP_KERNEL);
+	ret = xattrget(inode, unsstore, valuelen);
+	if (ret < 0)
+		return ret;
+	for (i=0; i<3; i++)
+		if (unsstore[i].ns == ep->userns_id)
+			break;
+	if (i==3)
+		goto out;
+	*retuid = unsstore[i].uid;
+	*retgid = unsstore[i].gid;
+	return 1;
+
+out:
 	/* The following is BAD CODE.  IT's for testing only */
 	if (current->uid == 0) {
 		if (inode->i_uid == ns->creator->uid) {
@@ -264,11 +291,6 @@ found:
 
 }
 
-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))
 {
@@ -290,11 +312,23 @@ int fsuserns_store_creds(struct inode *inode, struct user_struct *user,
 	size = depth * sizeof(struct unsstore);
 	unsstore = kmalloc(size, GFP_KERNEL);
 	ns = user->user_ns;
+	lastns = NULL;
 	for (i=0; ns != &init_user_ns; i++) {
 		unsstore[i].ns = find_ns_id(inode, ns);
 		unsstore[i].uid = user->uid;
+		/*
+		 * this is too bad.  But putting grp on user_struct wouldn't work
+		 * (think about if i do
+		* 		clone(CLONE_NEWUSER);
+		 * 		change grp,
+		 * 		clone(CLONE_NEWUSER)
+		 * */
+		if (!lastns)  
+			unsstore[i].gid = current->gid;
+		else
+			unsstore[i].gid = lastns->creator_grp;
 		printk(KERN_NOTICE "%s: setting xattr with ns=%d,uid=%d\n", __func__,
-				unsstore[i].ns, unsstore[i].uid);
+				unsstore[i].ns, unsstore[i].uid, unsstore[i].gid);
 		user = ns->creator;
 		lastns = ns;
 		ns = user->user_ns;
-- 
1.5.4.3



More information about the Containers mailing list