]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
Revert "(namespace) Revert "UBUNTU: SAUCE: fs: Allow superblock owner to change owner...
authorLuis Henriques <luis.henriques@canonical.com>
Wed, 23 Nov 2016 10:00:15 +0000 (10:00 +0000)
committerLuis Henriques <luis.henriques@canonical.com>
Wed, 23 Nov 2016 10:13:57 +0000 (10:13 +0000)
BugLink: https://bugs.launchpad.net/bugs/1644165
This reverts commit 65d51ade0eb256f763adbd8b7a237c04056084e6.

The kernel fix for bug #1634964 breaks LXD userspace, in particular the
following commits:

ac7f3f73cb39 (namespace) vfs: Don't modify inodes with a uid or gid unknown to the vfs
ca52383ad6a6 (namespace) vfs: Don't create inodes with a uid or gid unknown to the vfs

LXD 2.0.6 will include changes to support these kernel changes, but it isn't
available yet on xenial, so for now we just revert these commits.

Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
fs/attr.c
fs/kernfs/inode.c
fs/proc/base.c
fs/proc/generic.c
fs/proc/proc_sysctl.c

index 820d570fee0b5ee70098160f0e10a35483031d55..df79af91c4cf4afbb88582edf48cc03ce4e7b767 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
 #include <linux/evm.h>
 #include <linux/ima.h>
 
+static bool chown_ok(const struct inode *inode, kuid_t uid)
+{
+       struct user_namespace *user_ns;
+
+       if (uid_eq(current_fsuid(), inode->i_uid) && uid_eq(uid, inode->i_uid))
+               return true;
+       if (capable_wrt_inode_uidgid(inode, CAP_CHOWN))
+               return true;
+
+       user_ns = inode->i_sb->s_user_ns;
+       if (!uid_valid(inode->i_uid) &&
+           (!gid_valid(inode->i_gid) || kgid_has_mapping(user_ns, inode->i_gid)) &&
+           ns_capable(user_ns, CAP_CHOWN))
+               return true;
+
+       return false;
+}
+
+static bool chgrp_ok(const struct inode *inode, kgid_t gid)
+{
+       struct user_namespace *user_ns;
+
+       if (uid_eq(current_fsuid(), inode->i_uid) &&
+           (in_group_p(gid) || gid_eq(gid, inode->i_gid)))
+               return true;
+       if (capable_wrt_inode_uidgid(inode, CAP_CHOWN))
+               return true;
+
+       user_ns = inode->i_sb->s_user_ns;
+       if (!gid_valid(inode->i_gid) &&
+           (!uid_valid(inode->i_uid) || kuid_has_mapping(user_ns, inode->i_uid)) &&
+           ns_capable(user_ns, CAP_CHOWN))
+               return true;
+
+       return false;
+}
+
 /**
  * inode_change_ok - check if attribute changes to an inode are allowed
  * @inode:     inode to check
@@ -47,17 +84,11 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr)
                return 0;
 
        /* Make sure a caller can chown. */
-       if ((ia_valid & ATTR_UID) &&
-           (!uid_eq(current_fsuid(), inode->i_uid) ||
-            !uid_eq(attr->ia_uid, inode->i_uid)) &&
-           !capable_wrt_inode_uidgid(inode, CAP_CHOWN))
+       if ((ia_valid & ATTR_UID) && !chown_ok(inode, attr->ia_uid))
                return -EPERM;
 
        /* Make sure caller can chgrp. */
-       if ((ia_valid & ATTR_GID) &&
-           (!uid_eq(current_fsuid(), inode->i_uid) ||
-           (!in_group_p(attr->ia_gid) && !gid_eq(attr->ia_gid, inode->i_gid))) &&
-           !capable_wrt_inode_uidgid(inode, CAP_CHOWN))
+       if ((ia_valid & ATTR_GID) && !chgrp_ok(inode, attr->ia_gid))
                return -EPERM;
 
        /* Make sure a caller can chmod. */
index 756dd56aaf60acd337fb251fb287cbd382d57740..2f8ef6d2256287896d4d4a5b47e213b874e6162b 100644 (file)
@@ -117,6 +117,8 @@ int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr)
 
        if (!kn)
                return -EINVAL;
+       if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid))
+               return -EPERM;
 
        mutex_lock(&kernfs_mutex);
        error = inode_change_ok(inode, iattr);
index 29ed193b62b21f5c163c9683cd87e5d09bc752d6..56999b51838f4ca732f1cdc6299bbea5535651de 100644 (file)
@@ -711,6 +711,8 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr)
 
        if (attr->ia_valid & ATTR_MODE)
                return -EPERM;
+       if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid))
+               return -EPERM;
 
        error = inode_change_ok(inode, attr);
        if (error)
index 14e3b82090a6a13082761322ceec5bebed816e5a..6e618e49911e7ff3c3369ebbfcd57819b7a940d0 100644 (file)
@@ -105,6 +105,9 @@ static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
        struct proc_dir_entry *de = PDE(inode);
        int error;
 
+       if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid))
+               return -EPERM;
+
        error = inode_change_ok(inode, iattr);
        if (error)
                return error;
index fe5b6e6c46719a79de1d808de782ccfd20bf67a8..f5d57515719415131d6054082f5b879b633658df 100644 (file)
@@ -752,6 +752,8 @@ static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr)
 
        if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
                return -EPERM;
+       if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid))
+               return -EPERM;
 
        error = inode_change_ok(inode, attr);
        if (error)