Commit 9b8ba0b8 authored by Luis Henriques's avatar Luis Henriques

Revert "(namespace) Revert "UBUNTU: SAUCE: fs: Allow superblock owner to...

Revert "(namespace) Revert "UBUNTU: SAUCE: fs: Allow superblock owner to change ownership of inodes with unmappable ids""

BugLink: https://bugs.launchpad.net/bugs/1644165

This reverts commit 65d51ade.

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

ac7f3f73 (namespace) vfs: Don't modify inodes with a uid or gid unknown to the vfs
ca52383a (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: default avatarLuis Henriques <luis.henriques@canonical.com>
parent f50c78ee
......@@ -16,6 +16,43 @@
#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. */
......
......@@ -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);
......
......@@ -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)
......
......@@ -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;
......
......@@ -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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment