forked from Minki/linux
fs: port to iattr ownership update helpers
Earlier we introduced new helpers to abstract ownership update and remove code duplication. This converts all filesystems supporting idmapped mounts to make use of these new helpers. For now we always pass the initial idmapping which makes the idmapping functions these helpers call nops. This is done because we currently always pass the actual value to be written to i_{g,u}id via struct iattr. While this allowed us to treat the {g,u}id values in struct iattr as values that can be directly written to inode->i_{g,u}id it also increases the potential for confusion for filesystems. Now that we are have dedicated types to prevent this confusion we will ultimately only map the value from the idmapped mount into a filesystem value that can be written to inode->i_{g,u}id when the filesystem actually updates the inode. So pass down the initial idmapping until we finished that conversion at which point we pass down the mount's idmapping. No functional changes intended. Link: https://lore.kernel.org/r/20220621141454.2914719-6-brauner@kernel.org Cc: Seth Forshee <sforshee@digitalocean.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Aleksa Sarai <cyphar@cyphar.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Al Viro <viro@zeniv.linux.org.uk> CC: linux-fsdevel@vger.kernel.org Reviewed-by: Seth Forshee <sforshee@digitalocean.com> Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
This commit is contained in:
parent
1f36146a5a
commit
35faf3109a
@ -242,10 +242,8 @@ void setattr_copy(struct user_namespace *mnt_userns, struct inode *inode,
|
||||
{
|
||||
unsigned int ia_valid = attr->ia_valid;
|
||||
|
||||
if (ia_valid & ATTR_UID)
|
||||
inode->i_uid = attr->ia_uid;
|
||||
if (ia_valid & ATTR_GID)
|
||||
inode->i_gid = attr->ia_gid;
|
||||
i_uid_update(&init_user_ns, attr, inode);
|
||||
i_gid_update(&init_user_ns, attr, inode);
|
||||
if (ia_valid & ATTR_ATIME)
|
||||
inode->i_atime = attr->ia_atime;
|
||||
if (ia_valid & ATTR_MTIME)
|
||||
|
@ -1684,8 +1684,8 @@ int ext2_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
if ((iattr->ia_valid & ATTR_UID && !uid_eq(iattr->ia_uid, inode->i_uid)) ||
|
||||
(iattr->ia_valid & ATTR_GID && !gid_eq(iattr->ia_gid, inode->i_gid))) {
|
||||
if (i_uid_needs_update(&init_user_ns, iattr, inode) ||
|
||||
i_gid_needs_update(&init_user_ns, iattr, inode)) {
|
||||
error = dquot_transfer(inode, iattr);
|
||||
if (error)
|
||||
return error;
|
||||
|
@ -5356,8 +5356,8 @@ int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
|
||||
return error;
|
||||
}
|
||||
|
||||
if ((ia_valid & ATTR_UID && !uid_eq(attr->ia_uid, inode->i_uid)) ||
|
||||
(ia_valid & ATTR_GID && !gid_eq(attr->ia_gid, inode->i_gid))) {
|
||||
if (i_uid_needs_update(&init_user_ns, attr, inode) ||
|
||||
i_gid_needs_update(&init_user_ns, attr, inode)) {
|
||||
handle_t *handle;
|
||||
|
||||
/* (user+group)*(old+new) structure, inode write (sb,
|
||||
@ -5383,10 +5383,8 @@ int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
|
||||
}
|
||||
/* Update corresponding info in inode so that everything is in
|
||||
* one transaction */
|
||||
if (attr->ia_valid & ATTR_UID)
|
||||
inode->i_uid = attr->ia_uid;
|
||||
if (attr->ia_valid & ATTR_GID)
|
||||
inode->i_gid = attr->ia_gid;
|
||||
i_uid_update(&init_user_ns, attr, inode);
|
||||
i_gid_update(&init_user_ns, attr, inode);
|
||||
error = ext4_mark_inode_dirty(handle, inode);
|
||||
ext4_journal_stop(handle);
|
||||
if (unlikely(error)) {
|
||||
|
@ -861,10 +861,8 @@ static void __setattr_copy(struct user_namespace *mnt_userns,
|
||||
{
|
||||
unsigned int ia_valid = attr->ia_valid;
|
||||
|
||||
if (ia_valid & ATTR_UID)
|
||||
inode->i_uid = attr->ia_uid;
|
||||
if (ia_valid & ATTR_GID)
|
||||
inode->i_gid = attr->ia_gid;
|
||||
i_uid_update(&init_user_ns, attr, inode);
|
||||
i_gid_update(&init_user_ns, attr, inode);
|
||||
if (ia_valid & ATTR_ATIME)
|
||||
inode->i_atime = attr->ia_atime;
|
||||
if (ia_valid & ATTR_MTIME)
|
||||
@ -922,10 +920,8 @@ int f2fs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
if ((attr->ia_valid & ATTR_UID &&
|
||||
!uid_eq(attr->ia_uid, inode->i_uid)) ||
|
||||
(attr->ia_valid & ATTR_GID &&
|
||||
!gid_eq(attr->ia_gid, inode->i_gid))) {
|
||||
if (i_uid_needs_update(&init_user_ns, attr, inode) ||
|
||||
i_gid_needs_update(&init_user_ns, attr, inode)) {
|
||||
f2fs_lock_op(F2FS_I_SB(inode));
|
||||
err = dquot_transfer(inode, attr);
|
||||
if (err) {
|
||||
@ -938,10 +934,8 @@ int f2fs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
|
||||
* update uid/gid under lock_op(), so that dquot and inode can
|
||||
* be updated atomically.
|
||||
*/
|
||||
if (attr->ia_valid & ATTR_UID)
|
||||
inode->i_uid = attr->ia_uid;
|
||||
if (attr->ia_valid & ATTR_GID)
|
||||
inode->i_gid = attr->ia_gid;
|
||||
i_uid_update(&init_user_ns, attr, inode);
|
||||
i_gid_update(&init_user_ns, attr, inode);
|
||||
f2fs_mark_inode_dirty_sync(inode, true);
|
||||
f2fs_unlock_op(F2FS_I_SB(inode));
|
||||
}
|
||||
|
@ -2095,7 +2095,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
|
||||
if (!dquot_active(inode))
|
||||
return 0;
|
||||
|
||||
if (iattr->ia_valid & ATTR_UID && !uid_eq(iattr->ia_uid, inode->i_uid)){
|
||||
if (i_uid_needs_update(&init_user_ns, iattr, inode)) {
|
||||
dquot = dqget(sb, make_kqid_uid(iattr->ia_uid));
|
||||
if (IS_ERR(dquot)) {
|
||||
if (PTR_ERR(dquot) != -ESRCH) {
|
||||
@ -2106,7 +2106,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
|
||||
}
|
||||
transfer_to[USRQUOTA] = dquot;
|
||||
}
|
||||
if (iattr->ia_valid & ATTR_GID && !gid_eq(iattr->ia_gid, inode->i_gid)){
|
||||
if (i_gid_needs_update(&init_user_ns, iattr, inode)) {
|
||||
dquot = dqget(sb, make_kqid_gid(iattr->ia_gid));
|
||||
if (IS_ERR(dquot)) {
|
||||
if (PTR_ERR(dquot) != -ESRCH) {
|
||||
|
@ -704,13 +704,13 @@ xfs_setattr_nonsize(
|
||||
* didn't have the inode locked, inode's dquot(s) would have changed
|
||||
* also.
|
||||
*/
|
||||
if ((mask & ATTR_UID) && XFS_IS_UQUOTA_ON(mp) &&
|
||||
!uid_eq(inode->i_uid, iattr->ia_uid)) {
|
||||
if (XFS_IS_UQUOTA_ON(mp) &&
|
||||
i_uid_needs_update(&init_user_ns, iattr, inode)) {
|
||||
ASSERT(udqp);
|
||||
old_udqp = xfs_qm_vop_chown(tp, ip, &ip->i_udquot, udqp);
|
||||
}
|
||||
if ((mask & ATTR_GID) && XFS_IS_GQUOTA_ON(mp) &&
|
||||
!gid_eq(inode->i_gid, iattr->ia_gid)) {
|
||||
if (XFS_IS_GQUOTA_ON(mp) &&
|
||||
i_gid_needs_update(&init_user_ns, iattr, inode)) {
|
||||
ASSERT(xfs_has_pquotino(mp) || !XFS_IS_PQUOTA_ON(mp));
|
||||
ASSERT(gdqp);
|
||||
old_gdqp = xfs_qm_vop_chown(tp, ip, &ip->i_gdquot, gdqp);
|
||||
|
@ -22,9 +22,9 @@ static inline struct quota_info *sb_dqopt(struct super_block *sb)
|
||||
/* i_mutex must being held */
|
||||
static inline bool is_quota_modification(struct inode *inode, struct iattr *ia)
|
||||
{
|
||||
return (ia->ia_valid & ATTR_SIZE) ||
|
||||
(ia->ia_valid & ATTR_UID && !uid_eq(ia->ia_uid, inode->i_uid)) ||
|
||||
(ia->ia_valid & ATTR_GID && !gid_eq(ia->ia_gid, inode->i_gid));
|
||||
return ((ia->ia_valid & ATTR_SIZE) ||
|
||||
i_uid_needs_update(&init_user_ns, ia, inode) ||
|
||||
i_gid_needs_update(&init_user_ns, ia, inode));
|
||||
}
|
||||
|
||||
#if defined(CONFIG_QUOTA)
|
||||
|
@ -760,8 +760,8 @@ static int evm_attr_change(struct dentry *dentry, struct iattr *attr)
|
||||
struct inode *inode = d_backing_inode(dentry);
|
||||
unsigned int ia_valid = attr->ia_valid;
|
||||
|
||||
if ((!(ia_valid & ATTR_UID) || uid_eq(attr->ia_uid, inode->i_uid)) &&
|
||||
(!(ia_valid & ATTR_GID) || gid_eq(attr->ia_gid, inode->i_gid)) &&
|
||||
if (!i_uid_needs_update(&init_user_ns, attr, inode) &&
|
||||
!i_gid_needs_update(&init_user_ns, attr, inode) &&
|
||||
(!(ia_valid & ATTR_MODE) || attr->ia_mode == inode->i_mode))
|
||||
return 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user