[PATCH 10/10] userns: add support for readdir

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


Now ls works correctly inside a userns!

(but don't go doing some sort of setattr like 'chown'  :)

Signed-off-by: Serge Hallyn <serue at us.ibm.com>
---
 fs/ext3/file.c  |    4 ++++
 fs/ext3/inode.c |   22 ++++++++++++++++++++++
 fs/ext3/namei.c |    3 +++
 fs/ext3/xattr.c |    6 ++++++
 lib/fsuserns.c  |   42 +++++++++++++++++++++++++++++-------------
 5 files changed, 64 insertions(+), 13 deletions(-)

diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index acc4913..b259061 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -106,6 +106,9 @@ force_commit:
 	return ret;
 }
 
+extern int ext3_getattr(struct vfsmount *mnt, struct dentry *dentry,
+					struct kstat *stat);
+
 const struct file_operations ext3_file_operations = {
 	.llseek		= generic_file_llseek,
 	.read		= do_sync_read,
@@ -134,5 +137,6 @@ const struct inode_operations ext3_file_inode_operations = {
 	.removexattr	= generic_removexattr,
 #endif
 	.permission	= ext3_permission,
+	.getattr	= ext3_getattr,
 };
 
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 507d868..b252490 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -36,6 +36,7 @@
 #include <linux/mpage.h>
 #include <linux/uio.h>
 #include <linux/bio.h>
+#include <linux/security.h>
 #include "xattr.h"
 #include "acl.h"
 
@@ -3088,6 +3089,27 @@ err_out:
 	return error;
 }
 
+int ext3_getattr(struct vfsmount *mnt, struct dentry *dentry,
+					struct kstat *stat)
+{
+	struct inode *inode = dentry->d_inode;
+	int retval;
+	uid_t uid;
+	gid_t gid;
+
+	retval = security_inode_getattr(mnt, dentry);
+	if (retval)
+		return retval;
+
+	generic_fillattr(inode, stat);
+
+	retval = s_convert_uid_gid(inode, current->user->user_ns, &uid, &gid);
+	if (retval == 1) {
+		stat->uid = uid;
+		stat->gid = gid;
+	}
+	return 0;
+}
 
 /*
  * How many blocks doth make a writepage()?
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index e5be4bc..fe7350b 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -2410,6 +2410,8 @@ end_rename:
 	return retval;
 }
 
+extern int ext3_getattr(struct vfsmount *mnt, struct dentry *dentry,
+					struct kstat *stat);
 /*
  * directories can handle most operations...
  */
@@ -2431,6 +2433,7 @@ const struct inode_operations ext3_dir_inode_operations = {
 	.removexattr	= generic_removexattr,
 #endif
 	.permission	= ext3_permission,
+	.getattr	= ext3_getattr,
 };
 
 const struct inode_operations ext3_special_inode_operations = {
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 500fec7..cf7dc63 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -345,6 +345,7 @@ ext3_xattr_get_userns(struct inode *inode, void *value, size_t value_size)
 		error = ext3_xattr_block_get(inode, name_index, name, value,
 					     value_size);
 	up_read(&EXT3_I(inode)->xattr_sem);
+	printk(KERN_NOTICE "%s: returning %d for %lu\n", __func__, error, inode->i_ino);
 	return error;
 }
 
@@ -1102,7 +1103,12 @@ retry:
 		error = PTR_ERR(handle);
 	} else {
 		int error2;
+		char *buf;
+		int i;
 
+		printk(KERN_NOTICE "%s: writing %d bytes:\n", __func__, value_len);
+		for (i=0, buf = (char *)value; i<value_len; i++,buf++)
+			printk(KERN_NOTICE "%s: %d %x\n", __func__, i, (int)*buf);
 		error = ext3_xattr_set_handle(handle, inode, name_index, name,
 					      value, value_len, 0);
 		error2 = ext3_journal_stop(handle);
diff --git a/lib/fsuserns.c b/lib/fsuserns.c
index ac0ca99..f0be780 100644
--- a/lib/fsuserns.c
+++ b/lib/fsuserns.c
@@ -179,7 +179,7 @@ int fsuserns_convert_uid_gid(struct user_namespace *ns, struct inode *inode,
 	struct fsuserns_conversion_table *t;
 	struct fsuserns_table_entries *ep;
 	size_t valuelen;
-	struct unsstore *unsstore;
+	struct unsstore *unsstore = NULL;
 	int i, ret;
 
 	t = find_table(sb);
@@ -196,23 +196,33 @@ 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, NULL, 0);
+	if (ret <= 0)
+		goto notfound;
+	valuelen = ret;
+	unsstore = kzalloc(ret, GFP_KERNEL);
 	ret = xattrget(inode, unsstore, valuelen);
-	if (ret < 0)
-		return ret;
-	for (i=0; i<3; i++)
+	if (ret <= 0)
+		goto notfound;
+	for (i=0; i<(ret/sizeof(*unsstore)); i++) {
+		printk(KERN_NOTICE "%s: comparing unstore id %d to userns id %d\n",
+			__func__, unsstore[i].ns, ep->userns_id);
 		if (unsstore[i].ns == ep->userns_id)
-			break;
-	if (i==3)
-		goto out;
+			goto found;
+	}
+	goto notfound;
+
+found:
 	*retuid = unsstore[i].uid;
 	*retgid = unsstore[i].gid;
+	printk(KERN_NOTICE "%s: found a uid (%d) for nsid %d\n",
+			__func__, *retuid, ep->userns_id);
+	kfree(unsstore);
 	return 1;
 
-out:
+notfound:
+	kfree(unsstore);
+	printk(KERN_NOTICE "%s: no uid for my ns found\n", __func__);
 	/* The following is BAD CODE.  IT's for testing only */
 	if (current->uid == 0) {
 		if (inode->i_uid == ns->creator->uid) {
@@ -291,6 +301,12 @@ found:
 
 }
 
+/*
+ * Let's say uid 500 in the init_user_ns created (nsid=3), and uid 400
+ * there created (nsid=5).  Then root in nsid=5 creates a file.
+ * We want to store 500 as the inode->iuid.  In xattr security.userns
+ * we store (3,400) and (5,0)
+ */
 int fsuserns_store_creds(struct inode *inode, struct user_struct *user,
 	int (*xattrset)(struct inode *inode, const void *value, size_t value_len))
 {
@@ -327,7 +343,7 @@ int fsuserns_store_creds(struct inode *inode, struct user_struct *user,
 			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__,
+		printk(KERN_NOTICE "%s: setting xattr with ns=%d,uid=%d,gid=%d\n", __func__,
 				unsstore[i].ns, unsstore[i].uid, unsstore[i].gid);
 		user = ns->creator;
 		lastns = ns;
-- 
1.5.4.3



More information about the Containers mailing list