Don't open-code the checks and instead move them into a clean little helper we can call. This also reduces the risk that if we ever change something we forget to change all locations. Inspired-by: Vivek Goyal <vgoyal@xxxxxxxxxx> Cc: Christoph Hellwig <hch@xxxxxx> Cc: Al Viro <viro@xxxxxxxxxxxxxxxxxx> Cc: linux-fsdevel@xxxxxxxxxxxxxxx Signed-off-by: Christian Brauner <christian.brauner@xxxxxxxxxx> --- fs/namei.c | 11 +++-------- include/linux/fs.h | 11 +++++++++++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 216f16e74351..bc03cbc37ba7 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2823,16 +2823,14 @@ static int may_delete(struct user_namespace *mnt_userns, struct inode *dir, static inline int may_create(struct user_namespace *mnt_userns, struct inode *dir, struct dentry *child) { - struct user_namespace *s_user_ns; audit_inode_child(dir, child, AUDIT_TYPE_CHILD_CREATE); if (child->d_inode) return -EEXIST; if (IS_DEADDIR(dir)) return -ENOENT; - s_user_ns = dir->i_sb->s_user_ns; - if (!kuid_has_mapping(s_user_ns, fsuid_into_mnt(mnt_userns)) || - !kgid_has_mapping(s_user_ns, fsgid_into_mnt(mnt_userns))) + if (!fsuidgid_has_mapping(dir->i_sb, mnt_userns)) return -EOVERFLOW; + return inode_permission(mnt_userns, dir, MAY_WRITE | MAY_EXEC); } @@ -3034,14 +3032,11 @@ static int may_o_create(struct user_namespace *mnt_userns, const struct path *dir, struct dentry *dentry, umode_t mode) { - struct user_namespace *s_user_ns; int error = security_path_mknod(dir, dentry, mode, 0); if (error) return error; - s_user_ns = dir->dentry->d_sb->s_user_ns; - if (!kuid_has_mapping(s_user_ns, fsuid_into_mnt(mnt_userns)) || - !kgid_has_mapping(s_user_ns, fsgid_into_mnt(mnt_userns))) + if (!fsuidgid_has_mapping(dir->dentry->d_sb, mnt_userns)) return -EOVERFLOW; error = inode_permission(mnt_userns, dir->dentry->d_inode, diff --git a/include/linux/fs.h b/include/linux/fs.h index ec8f3ddf4a6a..edcb1aa99fd6 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1620,6 +1620,17 @@ static inline kgid_t fsgid_into_mnt(struct user_namespace *mnt_userns) return kgid_from_mnt(mnt_userns, current_fsgid()); } +static inline bool fsuidgid_has_mapping(struct super_block *sb, + struct user_namespace *mnt_userns) +{ + struct user_namespace *s_user_ns = sb->s_user_ns; + + return kuid_has_mapping(s_user_ns, + kuid_from_mnt(mnt_userns, current_fsuid())) && + kgid_has_mapping(s_user_ns, + kgid_from_mnt(mnt_userns, current_fsgid())); +} + extern struct timespec64 current_time(struct inode *inode); /* -- 2.27.0