Re: [PATCH RFC -next 03/12] fs: pass struct path to xattr helpers
flat view
From: Amir Goldstein <amir73il@gmail.com>
Date: 2026-09-24 11:12:58
Also in:
driver-core, linux-block, linux-cifs, linux-doc, linux-fsdevel, linux-integrity, linux-kselftest, linux-nfs, linux-unionfs, lkml, netfs, selinux
On Thu, Sep 24, 2026 at 12:22 PM Cai Xinchen [off-list ref] wrote:
vfs_setxattr(), vfs_getxattr(), vfs_listxattr() and vfs_removexattr() along with their __vfs_setxattr_locked()/__vfs_removexattr_locked() counterparts and the do_setxattr()/do_getxattr()/listxattr()/ removexattr() syscall helpers take a struct mnt_idmap and a struct dentry even though callers either already hold a struct path (or a struct file) or have to pass &nop_mnt_idmap because no idmapped mount is involved. Switch them all to take a struct path instead and derive the idmap and dentry from it where needed. __vfs_setxattr_noperm(), __vfs_getxattr(), __vfs_setxattr(), __vfs_removexattr() and vfs_getxattr_alloc() keep taking the idmap and dentry as they are only called from contexts that operate on bare dentries such as LSM internals. The SELinux and Smack inode_setsecctx implementations now pass the path they got from the previous patch straight through. The security_inode_*xattr() hooks invoked from fs/xattr.c keep taking the idmap and dentry for now; they will be converted together with the LSM hooks themselves in separate patches. evm_calc_hmac_or_hash() contains a redundant xattr size sanity check which calls vfs_getxattr() only to emit a debug message when the kernel-side and user-space-side xattr sizes differ, without ever influencing the result. Because that function only has a dentry, the call cannot be migrated to the new path-based signature; drop the check and the now unused user_space_size variable instead. Assisted-by: opencode: glm-5.3 Signed-off-by: Cai Xinchen <redacted> --- drivers/block/zloop.c | 4 +- fs/cachefiles/xattr.c | 32 ++++---- fs/ecryptfs/inode.c | 8 +- fs/nfsd/nfs4ctl.h | 4 +- fs/nfsd/vfs.c | 57 +++++++------- fs/overlayfs/copy_up.c | 4 +- fs/overlayfs/overlayfs.h | 18 +++-- fs/overlayfs/xattrs.c | 13 +++- fs/smb/server/smb2pdu.c | 75 +++++++------------ fs/smb/server/smb_common.c | 2 - fs/smb/server/smbacl.c | 19 +++-- fs/smb/server/tests/smbacl_kunit.c | 6 +- fs/smb/server/vfs.c | 112 ++++++++++++---------------- fs/smb/server/vfs.h | 39 ++++------ fs/smb/server/vfs_cache.c | 3 +- fs/xattr.c | 92 ++++++++++++----------- include/linux/xattr.h | 22 +++--- security/integrity/evm/evm_crypto.c | 8 +- security/selinux/hooks.c | 4 +- security/smack/smack_lsm.c | 4 +- 20 files changed, 243 insertions(+), 283 deletions(-)
[...]
quoted hunk ↗ jump to hunk
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index e963701b4c87..6dc241f195a6 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c@@ -83,7 +83,7 @@ int ovl_copy_xattr(struct super_block *sb, const struct path *oldpath, struct de if (!old->d_inode->i_op->listxattr || !new->d_inode->i_op->listxattr) return 0; - list_size = vfs_listxattr(old, NULL, 0); + list_size = vfs_listxattr(oldpath, NULL, 0); if (list_size <= 0) { if (list_size == -EOPNOTSUPP) return 0;@@ -94,7 +94,7 @@ int ovl_copy_xattr(struct super_block *sb, const struct path *oldpath, struct de if (!buf) return -ENOMEM; - list_size = vfs_listxattr(old, buf, list_size); + list_size = vfs_listxattr(oldpath, buf, list_size); if (list_size <= 0) { error = list_size; goto out;diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index d915b87c0b06..c13f6b2c915c 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h@@ -291,8 +291,7 @@ static inline ssize_t ovl_do_getxattr(const struct path *path, const char *name, WARN_ON(path->dentry->d_sb != path->mnt->mnt_sb); - err = vfs_getxattr(mnt_idmap(path->mnt), path->dentry, - name, value, size); + err = vfs_getxattr(path, name, value, size); len = (value && err > 0) ? err : 0; pr_debug("getxattr(%pd2, \"%s\", \"%*pE\", %zu, 0) = %i\n",@@ -325,9 +324,13 @@ static inline int ovl_do_setxattr(struct ovl_fs *ofs, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { + struct path path = { + .mnt = ovl_upper_mnt(ofs), + .dentry = dentry, + }; + /* Use vfs_setxattr(), not __vfs_setxattr(): it idmaps the security.capability rootid. */ - int err = vfs_setxattr(ovl_upper_mnt_idmap(ofs), dentry, name, - value, size, flags); + int err = vfs_setxattr(&path, name, value, size, flags); pr_debug("setxattr(%pd2, \"%s\", \"%*pE\", %zu, %d) = %i\n", dentry, name, min((int)size, 48), value, size, flags, err);@@ -344,7 +347,12 @@ static inline int ovl_setxattr(struct ovl_fs *ofs, struct dentry *dentry, static inline int ovl_do_removexattr(struct ovl_fs *ofs, struct dentry *dentry, const char *name) { - int err = vfs_removexattr(ovl_upper_mnt_idmap(ofs), dentry, name); + struct path path = { + .mnt = ovl_upper_mnt(ofs), + .dentry = dentry, + }; + + int err = vfs_removexattr(&path, name); pr_debug("removexattr(%pd2, \"%s\") = %i\n", dentry, name, err); return err; }diff --git a/fs/overlayfs/xattrs.c b/fs/overlayfs/xattrs.c index 5ae44b9c8790..b4658324b9f3 100644 --- a/fs/overlayfs/xattrs.c +++ b/fs/overlayfs/xattrs.c@@ -45,7 +45,7 @@ static int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char if (!value && !upperdentry) { ovl_path_lower(dentry, &realpath); with_ovl_creds(dentry->d_sb) - err = vfs_getxattr(mnt_idmap(realpath.mnt), realdentry, name, NULL, 0); + err = vfs_getxattr(&realpath, name, NULL, 0); if (err < 0) goto out; }@@ -86,7 +86,7 @@ static int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char ovl_i_path_real(inode, &realpath); /* Use vfs_getxattr(), not __vfs_getxattr(): it idmaps the security.capability rootid. */ with_ovl_creds(dentry->d_sb) - return vfs_getxattr(mnt_idmap(realpath.mnt), realpath.dentry, name, value, size); + return vfs_getxattr(&realpath, name, value, size); } static bool ovl_can_list(struct super_block *sb, const char *s)@@ -105,15 +105,20 @@ static bool ovl_can_list(struct super_block *sb, const char *s) ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) { - struct dentry *realdentry = ovl_dentry_real(dentry); + struct path realpath; struct ovl_fs *ofs = OVL_FS(dentry->d_sb); ssize_t res; size_t len; char *s; size_t prefix_len, name_len; + if (ovl_dentry_upper(dentry)) + ovl_path_upper(dentry, &realpath); + else + ovl_path_lower(dentry, &realpath); +
that's ovl_path_real() I have no technical issue with the ovl patch bits in this series. Anyway, I guess landlock is not going to enforce anything on the private mnt with ovl_creds anyway? Thanks, Amir.