[PATCH 06/10] user namespaces: hook fs/attr.c

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


Hook fs/attr.c so things like chown are properly handled.  Note this is only
for permission checks.  We'll need to hook ext3_setattr to get the right
uids updated.

Signed-off-by: Serge Hallyn <serue at us.ibm.com>
---
 fs/attr.c             |   28 +++++++++++++++++++---------
 include/linux/sched.h |    1 +
 2 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/fs/attr.c b/fs/attr.c
index 26c71ba..072d367 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -22,6 +22,11 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)
 {
 	int retval = -EPERM;
 	unsigned int ia_valid = attr->ia_valid;
+	uid_t iuid;
+	gid_t igid;
+
+	if (!s_convert_uid_gid(inode, current_userns(), &iuid, &igid))
+		return -EPERM;
 
 	/* If force is set do it anyway. */
 	if (ia_valid & ATTR_FORCE)
@@ -29,30 +34,30 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)
 
 	/* Make sure a caller can chown. */
 	if ((ia_valid & ATTR_UID) &&
-	    (current->fsuid != inode->i_uid ||
-	     attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN))
+	    (current->fsuid != iuid ||
+	     attr->ia_uid != iuid) && !s_is_capable(inode, current_userns(), CAP_CHOWN))
 		goto error;
 
 	/* Make sure caller can chgrp. */
 	if ((ia_valid & ATTR_GID) &&
-	    (current->fsuid != inode->i_uid ||
-	    (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid)) &&
-	    !capable(CAP_CHOWN))
+	    (current->fsuid != iuid ||
+	    (!in_group_p(attr->ia_gid) && attr->ia_gid != igid)) &&
+	    !s_is_capable(inode, current_userns(), CAP_CHOWN))
 		goto error;
 
 	/* Make sure a caller can chmod. */
 	if (ia_valid & ATTR_MODE) {
-		if (!is_owner_or_cap(inode))
+		if (current->fsuid != iuid || !s_is_capable(inode, current_userns(), CAP_FOWNER))
 			goto error;
 		/* Also check the setgid bit! */
 		if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
-				inode->i_gid) && !capable(CAP_FSETID))
+				igid) && !s_is_capable(inode, current_userns(), CAP_FSETID))
 			attr->ia_mode &= ~S_ISGID;
 	}
 
 	/* Check for setting the inode time. */
 	if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) {
-		if (!is_owner_or_cap(inode))
+		if (current->fsuid != iuid || !s_is_capable(inode, current_userns(), CAP_FOWNER))
 			goto error;
 	}
 fine:
@@ -66,6 +71,11 @@ EXPORT_SYMBOL(inode_change_ok);
 int inode_setattr(struct inode * inode, struct iattr * attr)
 {
 	unsigned int ia_valid = attr->ia_valid;
+	uid_t iuid;
+	gid_t igid;
+
+	if (!s_convert_uid_gid(inode, current_userns(), &iuid, &igid))
+		return -EPERM;
 
 	if (ia_valid & ATTR_SIZE &&
 	    attr->ia_size != i_size_read(inode)) {
@@ -90,7 +100,7 @@ int inode_setattr(struct inode * inode, struct iattr * attr)
 	if (ia_valid & ATTR_MODE) {
 		umode_t mode = attr->ia_mode;
 
-		if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+		if (!in_group_p(igid) && !s_is_capable(inode, current_userns(), CAP_FSETID))
 			mode &= ~S_ISGID;
 		inode->i_mode = mode;
 	}
diff --git a/include/linux/sched.h b/include/linux/sched.h
index a2f1356..f557535 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -611,6 +611,7 @@ struct user_struct {
 #endif
 };
 
+#define current_userns() (current->user->user_ns)
 extern int uids_sysfs_init(void);
 
 extern struct user_struct *find_user(uid_t);
-- 
1.5.4.3



More information about the Containers mailing list