From nobody Thu Sep 24 12:09:31 2026 Received: from canpmsgout07.his.huawei.com (canpmsgout07.his.huawei.com [113.46.200.222]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E8CB5472F6D; Thu, 24 Sep 2026 10:22:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.222 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245353; cv=none; b=G9c9W1rHSrTXq4WlyZ8q6FMXndh0+TB645YwvSLEw3SMuF5c7Q8KKYIAhJInjU1sTu7D1DPKcNHPfK2YAZ22BrkVtiKmL7y/qnG4qX9srOUT3C0gTJquAQolpaQ9fQwPlNg03SbIQmO4fR0pqFFBtzj821h062SoTFjNXIqKDNo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245353; c=relaxed/simple; bh=+/K32wSGNGSAy0GrTSnSyHO9Gs60FXZ4iCxsm/7PpGQ=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Rri9rVgIJLlVzFxRXzLlUL5chdFW0xAa0a7Ee6JYtStMZwMrzyQJhoiW10MWNB+WCMeFHgetYQOWS6ZGzvHlMJYHtt7L8RcBtlgg/JLmUuS5Kqley/2ljT+grwUV42xJbhT5Oh+f7IoW9G+mIg97++vmAVaRBvGWlQyJvyl9rdU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=NISgf/f7; arc=none smtp.client-ip=113.46.200.222 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="NISgf/f7" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=GjTyQQ3XH1N9dXXvR9VUiYk5fhOnR7Gu5J01S1rOywY=; b=NISgf/f7+aB1wq2z+3DmTajbAV9wWbIWCsw8K8eK9NBCnecy/QAG9zdGh6pmlMd3DK8JuY5aC i+OEQkJJVc8YTbTFcjkgn3RUZ6tVF/30wAYVGMyw25pi7E6xZWCI+hJ5Mp0ZnFwHOAB0XfieInB aTpUEnrk9JfiBwo4EPQOApg= Received: from mail.maildlp.com (unknown [172.19.163.15]) by canpmsgout07.his.huawei.com (SkyGuard) with ESMTPS id 4hr8j80tCQzLlTm; Thu, 24 Sep 2026 18:10:20 +0800 (CST) Received: from whupemk100010.china.huawei.com (unknown [7.152.184.41]) by mail.maildlp.com (Postfix) with ESMTPS id 2286D40578; Thu, 24 Sep 2026 18:22:26 +0800 (CST) Received: from octopus.huawei.com (10.67.174.191) by whupemk100010.china.huawei.com (7.152.184.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45; Thu, 24 Sep 2026 18:22:21 +0800 From: Cai Xinchen To: , , , , , , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH RFC -next 01/12] fs: pass struct path to notify_change() Date: Thu, 24 Sep 2026 18:48:20 +0800 Message-ID: <20260924104831.1081137-2-caixinchen1@huawei.com> X-Mailer: git-send-email 2.18.0.huawei.25 In-Reply-To: <20260924104831.1081137-1-caixinchen1@huawei.com> References: <20260924104831.1081137-1-caixinchen1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To whupemk100010.china.huawei.com (7.152.184.41) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" notify_change() takes a struct mnt_idmap and a struct dentry even though all of its 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 the helper and its declaration to take a struct path instead and derive the idmap and dentry from it. This is a purely mechanical change with no behavior change. The security_inode_setattr() call within notify_change() keeps taking the idmap and dentry for now; it will be converted together with the LSM hook itself in a separate patch. Assisted-by: opencode: glm-5.3 Signed-off-by: Cai Xinchen --- drivers/base/devtmpfs.c | 6 ++++-- fs/attr.c | 18 +++++++++--------- fs/cachefiles/interface.c | 6 ++---- fs/coredump.c | 2 +- fs/ecryptfs/inode.c | 14 +++++++------- fs/inode.c | 7 +++---- fs/namei.c | 7 +++---- fs/nfsd/nfs4state.c | 14 ++++++++------ fs/nfsd/nfs4xdr.c | 2 +- fs/nfsd/state.h | 2 +- fs/nfsd/vfs.c | 14 ++++++++++---- fs/open.c | 18 +++++++++--------- fs/overlayfs/overlayfs.h | 7 ++++++- fs/smb/server/smb2pdu.c | 2 +- fs/smb/server/smbacl.c | 2 +- fs/utimes.c | 3 +-- include/linux/fs.h | 6 +++--- 17 files changed, 70 insertions(+), 60 deletions(-) diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 11c70888f38b..71da9235ed49 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -284,13 +284,14 @@ static int handle_create(const char *nodename, umode_= t mode, kuid_t uid, dev->devt, NULL); if (!err) { struct iattr newattrs; + struct path attr_path =3D { .mnt =3D path.mnt, .dentry =3D dentry }; =20 newattrs.ia_mode =3D mode; newattrs.ia_uid =3D uid; newattrs.ia_gid =3D gid; newattrs.ia_valid =3D ATTR_MODE|ATTR_UID|ATTR_GID; inode_lock(d_inode(dentry)); - notify_change(&nop_mnt_idmap, dentry, &newattrs, NULL); + notify_change(&attr_path, &newattrs, NULL); inode_unlock(d_inode(dentry)); =20 /* mark as kernel-created inode */ @@ -380,6 +381,7 @@ static int handle_remove(const char *nodename, struct d= evice *dev) inode =3D d_inode(dentry); if (dev_mynode(dev, inode)) { struct iattr newattrs; + struct path attr_path =3D { .mnt =3D parent.mnt, .dentry =3D dentry }; /* * before unlinking this node, reset permissions * of possible references like hardlinks @@ -390,7 +392,7 @@ static int handle_remove(const char *nodename, struct d= evice *dev) newattrs.ia_valid =3D ATTR_UID|ATTR_GID|ATTR_MODE; inode_lock(d_inode(dentry)); - notify_change(&nop_mnt_idmap, dentry, &newattrs, NULL); + notify_change(&attr_path, &newattrs, NULL); inode_unlock(d_inode(dentry)); err =3D vfs_unlink(&nop_mnt_idmap, d_inode(parent.dentry), dentry, NULL); diff --git a/fs/attr.c b/fs/attr.c index 71888ac903c2..ea91e4471faa 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -399,8 +399,7 @@ EXPORT_SYMBOL(may_setattr); =20 /** * notify_change - modify attributes of a filesystem object - * @idmap: idmap of the mount the inode was found from - * @dentry: object affected + * @path: object affected * @attr: new attributes * @delegated_inode: returns inode, if the inode is delegated * @@ -418,15 +417,16 @@ EXPORT_SYMBOL(may_setattr); * the file open for write, as there can be no conflicting delegation in * that case. * - * If the inode has been found through an idmapped mount the idmap of - * the vfsmount must be passed through @idmap. This function will then - * take care to map the inode according to @idmap before checking - * permissions. On non-idmapped mounts or if permission checking is to be - * performed on the raw inode simply pass @nop_mnt_idmap. + * If the inode has been found through an idmapped mount, permission + * checking is performed based on the idmap of @path->mnt. This function + * will take care to map the inode according to the idmap before + * checking permissions. */ -int notify_change(struct mnt_idmap *idmap, struct dentry *dentry, - struct iattr *attr, struct delegated_inode *delegated_inode) +int notify_change(const struct path *path, struct iattr *attr, + struct delegated_inode *delegated_inode) { + struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); + struct dentry *dentry =3D path->dentry; struct inode *inode =3D dentry->d_inode; umode_t mode =3D inode->i_mode; int error; diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index a160d5c3e74c..bbaba93015cd 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -138,8 +138,7 @@ static int cachefiles_adjust_size(struct cachefiles_obj= ect *object) newattrs.ia_size =3D oi_size & PAGE_MASK; ret =3D cachefiles_inject_remove_error(); if (ret =3D=3D 0) - ret =3D notify_change(&nop_mnt_idmap, file->f_path.dentry, - &newattrs, NULL); + ret =3D notify_change(&file->f_path, &newattrs, NULL); if (ret < 0) goto truncate_failed; } @@ -148,8 +147,7 @@ static int cachefiles_adjust_size(struct cachefiles_obj= ect *object) newattrs.ia_size =3D ni_size; ret =3D cachefiles_inject_write_error(); if (ret =3D=3D 0) - ret =3D notify_change(&nop_mnt_idmap, file->f_path.dentry, - &newattrs, NULL); + ret =3D notify_change(&file->f_path, &newattrs, NULL); =20 truncate_failed: inode_unlock(file_inode(file)); diff --git a/fs/coredump.c b/fs/coredump.c index f809e3fb4ba2..2e9903da7011 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -1049,7 +1049,7 @@ static bool coredump_file(struct core_name *cn, struc= t coredump_params *cprm, } if (!(file->f_mode & FMODE_CAN_WRITE)) return false; - if (do_truncate(idmap, file->f_path.dentry, 0, 0, file)) + if (do_truncate(&file->f_path, 0, 0, file)) return false; =20 cprm->file =3D no_free_ptr(file); diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 525297c7ebd8..627d456f9c38 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -732,7 +732,8 @@ upper_size_to_lower_size(struct ecryptfs_crypt_stat *cr= ypt_stat, */ static int __ecryptfs_truncate(struct dentry *dentry, const struct iattr *= ia) { - struct dentry *lower_dentry =3D ecryptfs_dentry_to_lower(dentry); + struct path lower_path =3D ecryptfs_lower_path(dentry); + struct dentry *lower_dentry =3D lower_path.dentry; struct inode *inode =3D d_inode(dentry); struct ecryptfs_crypt_stat *crypt_stat; loff_t i_size =3D i_size_read(inode); @@ -821,7 +822,7 @@ static int __ecryptfs_truncate(struct dentry *dentry, c= onst struct iattr *ia) set_size: lower_ia.ia_valid |=3D ATTR_SIZE; inode_lock(d_inode(lower_dentry)); - rc =3D notify_change(&nop_mnt_idmap, lower_dentry, &lower_ia, NULL); + rc =3D notify_change(&lower_path, &lower_ia, NULL); inode_unlock(d_inode(lower_dentry)); out: ecryptfs_put_lower_file(inode); @@ -873,7 +874,6 @@ static int ecryptfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *ia) { struct inode *inode =3D d_inode(dentry); - struct dentry *lower_dentry =3D ecryptfs_dentry_to_lower(dentry); struct inode *lower_inode =3D ecryptfs_inode_to_lower(inode); struct ecryptfs_crypt_stat *crypt_stat; int rc; @@ -925,14 +925,14 @@ static int ecryptfs_setattr(struct mnt_idmap *idmap, if (ia->ia_valid & ATTR_SIZE) { rc =3D __ecryptfs_truncate(dentry, ia); } else { + struct path lower_path =3D ecryptfs_lower_path(dentry); struct iattr lower_ia; =20 ecryptfs_iattr_to_lower(&lower_ia, ia); =20 - inode_lock(d_inode(lower_dentry)); - rc =3D notify_change(&nop_mnt_idmap, lower_dentry, &lower_ia, - NULL); - inode_unlock(d_inode(lower_dentry)); + inode_lock(d_inode(lower_path.dentry)); + rc =3D notify_change(&lower_path, &lower_ia, NULL); + inode_unlock(d_inode(lower_path.dentry)); } out: fsstack_copy_attr_all(inode, lower_inode); diff --git a/fs/inode.c b/fs/inode.c index 8cfbc11c2b1f..e1e9eb268803 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -2356,8 +2356,7 @@ int dentry_needs_remove_privs(struct mnt_idmap *idmap, return mask; } =20 -static int __remove_privs(struct mnt_idmap *idmap, - struct dentry *dentry, int kill) +static int __remove_privs(const struct path *path, int kill) { struct iattr newattrs; =20 @@ -2366,7 +2365,7 @@ static int __remove_privs(struct mnt_idmap *idmap, * Note we call this on write, so notify_change will not * encounter any conflicting delegations: */ - return notify_change(idmap, dentry, &newattrs, NULL); + return notify_change(path, &newattrs, NULL); } =20 static int file_remove_privs_flags(struct file *file, unsigned int flags) @@ -2387,7 +2386,7 @@ static int file_remove_privs_flags(struct file *file,= unsigned int flags) if (flags & IOCB_NOWAIT) return -EAGAIN; =20 - error =3D __remove_privs(file_mnt_idmap(file), dentry, kill); + error =3D __remove_privs(&file->f_path, kill); } =20 if (!error) diff --git a/fs/namei.c b/fs/namei.c index 1dd4ec7d0e62..909da4078eb7 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -4321,7 +4321,7 @@ static int may_open(struct mnt_idmap *idmap, const st= ruct path *path, return 0; } =20 -static int handle_truncate(struct mnt_idmap *idmap, struct file *filp) +static int handle_truncate(struct file *filp) { const struct path *path =3D &filp->f_path; struct inode *inode =3D path->dentry->d_inode; @@ -4331,8 +4331,7 @@ static int handle_truncate(struct mnt_idmap *idmap, s= truct file *filp) =20 error =3D security_file_truncate(filp); if (!error) { - error =3D do_truncate(idmap, path->dentry, 0, - ATTR_MTIME|ATTR_CTIME|ATTR_OPEN, + error =3D do_truncate(path, 0, ATTR_MTIME|ATTR_CTIME|ATTR_OPEN, filp); } put_write_access(inode); @@ -4914,7 +4913,7 @@ static int do_open(struct nameidata *nd, if (!error) error =3D security_file_post_open(file, op->acc_mode); if (!error && do_truncate) - error =3D handle_truncate(idmap, file); + error =3D handle_truncate(file); if (unlikely(error > 0)) { WARN_ON(1); error =3D -EINVAL; diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 1de6c6d757c3..400a42941879 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -10477,8 +10477,10 @@ bool nfsd4_vet_deleg_time(struct timespec64 *req, = const struct timespec64 *orig, return true; } =20 -static int cb_getattr_update_times(struct dentry *dentry, struct nfs4_dele= gation *dp) +static int cb_getattr_update_times(const struct path *path, + struct nfs4_delegation *dp) { + struct dentry *dentry =3D path->dentry; struct inode *inode =3D d_inode(dentry); struct nfs4_cb_fattr *ncf =3D &dp->dl_cb_fattr; struct iattr attrs =3D { }; @@ -10508,7 +10510,7 @@ static int cb_getattr_update_times(struct dentry *d= entry, struct nfs4_delegation =20 attrs.ia_valid |=3D ATTR_DELEG; inode_lock(inode); - ret =3D notify_change(&nop_mnt_idmap, dentry, &attrs, NULL); + ret =3D notify_change(path, &attrs, NULL); inode_unlock(inode); return ret; } @@ -10531,7 +10533,7 @@ static int cb_getattr_update_times(struct dentry *d= entry, struct nfs4_delegation * caller must put the reference. */ __be32 -nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct dentry *dentry, +nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, const struct path *pa= th, struct nfs4_delegation **pdp) { struct nfsd_thread_local_info *ntli =3D rqstp->rq_private; @@ -10539,7 +10541,7 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp= , struct dentry *dentry, struct nfs4_delegation *dp =3D NULL; struct file_lease *fl; struct nfs4_cb_fattr *ncf; - struct inode *inode =3D d_inode(dentry); + struct inode *inode =3D d_inode(path->dentry); __be32 status; =20 ctx =3D locks_inode_context(inode); @@ -10603,7 +10605,7 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp= , struct dentry *dentry, * not update the file's metadata with the client's * modified size */ - err =3D cb_getattr_update_times(dentry, dp); + err =3D cb_getattr_update_times(path, dp); if (err) { status =3D nfserrno(err); goto out_status; @@ -10789,7 +10791,7 @@ void nfsd_update_cmtime_attr(struct file *f, unsign= ed int flags) }; =20 inode_lock(inode); - ret =3D notify_change(&nop_mnt_idmap, f->f_path.dentry, &attr, NULL); + ret =3D notify_change(&f->f_path, &attr, NULL); inode_unlock(inode); if (ret) pr_notice_ratelimited("nfsd: Unable to update timestamps on " diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 00ddaac499c6..73bb099ec0f0 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -4096,7 +4096,7 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xd= r_stream *xdr, (attrmask[1] & (FATTR4_WORD1_TIME_ACCESS | FATTR4_WORD1_TIME_MODIFY | FATTR4_WORD1_TIME_METADATA))) { - status =3D nfsd4_deleg_getattr_conflict(rqstp, dentry, &dp); + status =3D nfsd4_deleg_getattr_conflict(rqstp, &path, &dp); if (status) goto out; } diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index cd9294f024bb..183123f0b91f 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -1018,7 +1018,7 @@ static inline bool try_to_expire_client(struct nfs4_c= lient *clp) } =20 extern __be32 nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, - struct dentry *dentry, struct nfs4_delegation **pdp); + const struct path *path, struct nfs4_delegation **pdp); =20 struct nfsd4_get_dir_delegation; struct nfs4_delegation *nfsd_get_dir_deleg(struct nfsd4_compound_state *cs= tate, diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 4789f2ec2078..ed8e04cc794e 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -455,7 +455,7 @@ nfsd_get_write_access(struct svc_fh *fhp) return nfserrno(get_write_access(d_inode(fhp->fh_dentry))); } =20 -static int __nfsd_setattr(struct dentry *dentry, struct iattr *iap) +static int __nfsd_setattr(const struct path *path, struct iattr *iap) { int host_err; =20 @@ -475,7 +475,7 @@ static int __nfsd_setattr(struct dentry *dentry, struct= iattr *iap) if (iap->ia_size < 0) return -EFBIG; =20 - host_err =3D notify_change(&nop_mnt_idmap, dentry, &size_attr, NULL); + host_err =3D notify_change(path, &size_attr, NULL); if (host_err) return host_err; iap->ia_valid &=3D ~ATTR_SIZE; @@ -501,7 +501,7 @@ static int __nfsd_setattr(struct dentry *dentry, struct= iattr *iap) if (!(iap->ia_valid & ATTR_DELEG)) iap->ia_valid |=3D ATTR_CTIME; =20 - return notify_change(&nop_mnt_idmap, dentry, iap, NULL); + return notify_change(path, iap, NULL); } =20 /** @@ -524,6 +524,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, { struct dentry *dentry; struct inode *inode; + struct path path; struct iattr *iap =3D attr->na_iattr; int accmode =3D NFSD_MAY_SATTR; umode_t ftype =3D 0; @@ -569,6 +570,11 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fh= p, dentry =3D fhp->fh_dentry; inode =3D d_inode(dentry); =20 + path =3D (struct path){ + .mnt =3D fhp->fh_export->ex_path.mnt, + .dentry =3D dentry, + }; + nfsd_sanitize_attrs(inode, iap); =20 /* @@ -612,7 +618,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, * copy for every loop iteration. */ attrs =3D *iap; - host_err =3D __nfsd_setattr(dentry, &attrs); + host_err =3D __nfsd_setattr(&path, &attrs); if (host_err !=3D -EAGAIN || !retries--) break; if (!nfsd_wait_for_delegreturn(rqstp, inode)) diff --git a/fs/open.c b/fs/open.c index 6069abe49664..41eb76798a23 100644 --- a/fs/open.c +++ b/fs/open.c @@ -36,10 +36,12 @@ =20 #include "internal.h" =20 -int do_truncate(struct mnt_idmap *idmap, struct dentry *dentry, - loff_t length, unsigned int time_attrs, struct file *filp) +int do_truncate(const struct path *path, loff_t length, + unsigned int time_attrs, struct file *filp) { int ret; + struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); + struct dentry *dentry =3D path->dentry; struct iattr newattrs; =20 /* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */ @@ -65,7 +67,7 @@ int do_truncate(struct mnt_idmap *idmap, struct dentry *d= entry, return ret; =20 /* Note any delegations or leases have already been broken: */ - ret =3D notify_change(idmap, dentry, &newattrs, NULL); + ret =3D notify_change(path, &newattrs, NULL); inode_unlock(dentry->d_inode); return ret; } @@ -115,7 +117,7 @@ int vfs_truncate(const struct path *path, loff_t length) =20 error =3D security_path_truncate(path); if (!error) - error =3D do_truncate(idmap, path->dentry, length, 0, NULL); + error =3D do_truncate(path, length, 0, NULL); =20 put_write_and_out: put_write_access(inode); @@ -191,7 +193,7 @@ int do_ftruncate(struct file *file, loff_t length, unsi= gned int flags) return error; =20 scoped_guard(super_write, inode->i_sb) - return do_truncate(file_mnt_idmap(file), dentry, length, + return do_truncate(&file->f_path, length, ATTR_MTIME | ATTR_CTIME, file); } =20 @@ -683,8 +685,7 @@ int chmod_common(const struct path *path, umode_t mode) goto out_unlock; newattrs.ia_mode =3D (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid =3D ATTR_MODE | ATTR_CTIME; - error =3D notify_change(mnt_idmap(path->mnt), path->dentry, - &newattrs, &delegated_inode); + error =3D notify_change(path, &newattrs, &delegated_inode); out_unlock: inode_unlock(inode); if (is_delegated(&delegated_inode)) { @@ -822,8 +823,7 @@ int chown_common(const struct path *path, uid_t user, g= id_t group) from_vfsuid(idmap, fs_userns, newattrs.ia_vfsuid), from_vfsgid(idmap, fs_userns, newattrs.ia_vfsgid)); if (!error) - error =3D notify_change(idmap, path->dentry, &newattrs, - &delegated_inode); + error =3D notify_change(path, &newattrs, &delegated_inode); inode_unlock(inode); if (is_delegated(&delegated_inode)) { error =3D break_deleg_wait(&delegated_inode); diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index e0d8c6152e9f..d915b87c0b06 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -206,7 +206,12 @@ static inline int ovl_do_notify_change(struct ovl_fs *= ofs, struct dentry *upperdentry, struct iattr *attr) { - return notify_change(ovl_upper_mnt_idmap(ofs), upperdentry, attr, NULL); + struct path path =3D { + .mnt =3D ovl_upper_mnt(ofs), + .dentry =3D upperdentry, + }; + + return notify_change(&path, attr, NULL); } =20 static inline int ovl_do_rmdir(struct ovl_fs *ofs, diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index 15e2801a8ce1..fb3ee170db3c 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -8243,7 +8243,7 @@ static int set_file_basic_info(struct ksmbd_file *fp, return -EACCES; =20 inode_lock(inode); - rc =3D notify_change(idmap, dentry, &attrs, NULL); + rc =3D notify_change(&filp->f_path, &attrs, NULL); inode_unlock(inode); } return rc; diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c index e75247915c87..fcace71b0a29 100644 --- a/fs/smb/server/smbacl.c +++ b/fs/smb/server/smbacl.c @@ -1721,7 +1721,7 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmb= d_tree_connect *tcon, } =20 inode_lock(inode); - rc =3D notify_change(idmap, path->dentry, &newattrs, NULL); + rc =3D notify_change(path, &newattrs, NULL); inode_unlock(inode); if (rc) goto out; diff --git a/fs/utimes.c b/fs/utimes.c index e22664e4115f..5de794587147 100644 --- a/fs/utimes.c +++ b/fs/utimes.c @@ -64,8 +64,7 @@ int vfs_utimes(const struct path *path, struct timespec64= *times) } retry_deleg: inode_lock(inode); - error =3D notify_change(mnt_idmap(path->mnt), path->dentry, &newattrs, - &delegated_inode); + error =3D notify_change(path, &newattrs, &delegated_inode); inode_unlock(inode); if (is_delegated(&delegated_inode)) { error =3D break_deleg_wait(&delegated_inode); diff --git a/include/linux/fs.h b/include/linux/fs.h index 05d05bb9c951..4087c45d88d5 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2483,7 +2483,7 @@ static inline bool is_idmapped_mnt(const struct vfsmo= unt *mnt) } =20 int vfs_truncate(const struct path *, loff_t); -int do_truncate(struct mnt_idmap *, struct dentry *, loff_t start, +int do_truncate(const struct path *path, loff_t length, unsigned int time_attrs, struct file *filp); extern int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len); @@ -2707,8 +2707,8 @@ static inline int bmap(struct inode *inode, sector_t= *block) } #endif =20 -int notify_change(struct mnt_idmap *, struct dentry *, - struct iattr *, struct delegated_inode *); +int notify_change(const struct path *path, struct iattr *attr, + struct delegated_inode *delegated_inode); int inode_permission(struct mnt_idmap *, struct inode *, int); int generic_permission(struct mnt_idmap *, struct inode *, int); static inline int file_permission(struct file *file, int mask) --=20 2.18.0.huawei.25 From nobody Thu Sep 24 12:09:31 2026 Received: from canpmsgout04.his.huawei.com (canpmsgout04.his.huawei.com [113.46.200.219]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 41A2E47798A; Thu, 24 Sep 2026 10:22:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.219 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245358; cv=none; b=GU8tCY87XwKF37fiORPkaLm8kk+UziTIpwCNlrabkfF/WieJuTpnsEF35fIJU+NknPsyTXMtNnd83N29V3P5OkZQzQUY8/6NyXuumBjmlt7sz9xgcOfdCpkISdVpK8lFKMfYrtB+RADlNeBMFUp797reBoPStjv6y9lUflYB49Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245358; c=relaxed/simple; bh=xMvFOKaxRGN6FGa6PSSXKKHP5V98CEeeE7KMOo+FrJw=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=pIgxLG1clqBRQN2aid8gSA+HrO8tjxMkP0eRn/QToRonYDc+ZCS3oVfoR4WJwLihQnNhB6Z8FLInKyRC+9mcUM2TWXfEV31P88SYwrZqtb8zSQlB4zRS7yVztVgo7yTxaFuZePjEYGF820vBnI2W+Z6911+3jHH97H+gLpsNYvE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=RG4Fy1P9; arc=none smtp.client-ip=113.46.200.219 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="RG4Fy1P9" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=scpxykvaJ6IR0KlcEgHZABm57FbZxqSwIYwnIN+9DX4=; b=RG4Fy1P9Pg5DYIVbIy0nl2VdXcQNa74ATc2Jcd+Zs88h1LrMMcvA69omrEFDvLsYjwCEQ1r/C Reu8+9doJVu3Ipnjl7gGbys5Q9k2e27W6y4afo7ii1c3JwpUPsLCo/L7Icpyvfl4U7+ZJcHeLQM DjZh8YvQO/MuLdRvgOB/00E= Received: from mail.maildlp.com (unknown [172.19.162.140]) by canpmsgout04.his.huawei.com (SkyGuard) with ESMTPS id 4hr8jD6QrRz1prM0; Thu, 24 Sep 2026 18:10:24 +0800 (CST) Received: from whupemk100010.china.huawei.com (unknown [7.152.184.41]) by mail.maildlp.com (Postfix) with ESMTPS id A27C2202E6; Thu, 24 Sep 2026 18:22:32 +0800 (CST) Received: from octopus.huawei.com (10.67.174.191) by whupemk100010.china.huawei.com (7.152.184.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45; Thu, 24 Sep 2026 18:22:28 +0800 From: Cai Xinchen To: , , , , , , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH RFC -next 02/12] LSM: pass struct path to the inode_setsecctx hook Date: Thu, 24 Sep 2026 18:48:21 +0800 Message-ID: <20260924104831.1081137-3-caixinchen1@huawei.com> X-Mailer: git-send-email 2.18.0.huawei.25 In-Reply-To: <20260924104831.1081137-1-caixinchen1@huawei.com> References: <20260924104831.1081137-1-caixinchen1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To whupemk100010.china.huawei.com (7.152.184.41) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The inode_setsecctx hook and its security_inode_setsecctx() caller in fs/nfsd operate on a dentry even though both have a struct path available. The SELinux and Smack implementations write the label through __vfs_setxattr_locked(), whose idmap argument they hardcode to &nop_mnt_idmap. Switch the hook to take a const struct path so that the upcoming conversion of the xattr helpers to struct path can be reflected directly in the implementations. For now the implementations keep passing &nop_mnt_idmap together with path->dentry to __vfs_setxattr_locked(), preserving the current behavior; they will be switched to pass the path itself once the xattr helpers take one. Assisted-by: opencode: glm-5.3 Signed-off-by: Cai Xinchen --- fs/nfsd/vfs.c | 2 +- include/linux/lsm_hook_defs.h | 2 +- include/linux/security.h | 4 ++-- security/security.c | 6 +++--- security/selinux/hooks.c | 6 +++--- security/smack/smack_lsm.c | 6 +++--- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index ed8e04cc794e..922337083fe9 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -625,7 +625,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, break; } if (attr->na_seclabel && attr->na_seclabel->len) - attr->na_labelerr =3D security_inode_setsecctx(dentry, + attr->na_labelerr =3D security_inode_setsecctx(&path, attr->na_seclabel->data, attr->na_seclabel->len); if (IS_ENABLED(CONFIG_FS_POSIX_ACL) && attr->na_dpacl) { if (!S_ISDIR(inode->i_mode)) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index f4939137e66b..b22f7928523e 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -314,7 +314,7 @@ LSM_HOOK(int, 0, secctx_to_secid, const char *secdata, = u32 seclen, u32 *secid) LSM_HOOK(void, LSM_RET_VOID, release_secctx, struct lsm_context *cp) LSM_HOOK(void, LSM_RET_VOID, inode_invalidate_secctx, struct inode *inode) LSM_HOOK(int, 0, inode_notifysecctx, struct inode *inode, void *ctx, u32 c= txlen) -LSM_HOOK(int, 0, inode_setsecctx, struct dentry *dentry, void *ctx, u32 ct= xlen) +LSM_HOOK(int, 0, inode_setsecctx, const struct path *path, void *ctx, u32 = ctxlen) LSM_HOOK(int, -EOPNOTSUPP, inode_getsecctx, struct inode *inode, struct lsm_context *cp) =20 diff --git a/include/linux/security.h b/include/linux/security.h index e3c8b4479a0a..6ac9fb634017 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -589,7 +589,7 @@ int security_secctx_to_secid(const char *secdata, u32 s= eclen, u32 *secid); void security_release_secctx(struct lsm_context *cp); void security_inode_invalidate_secctx(struct inode *inode); int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen= ); -int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); +int security_inode_setsecctx(const struct path *path, void *ctx, u32 ctxle= n); int security_inode_getsecctx(struct inode *inode, struct lsm_context *cp); int security_locked_down(enum lockdown_reason what); int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, u32 *uctx_len, @@ -1637,7 +1637,7 @@ static inline int security_inode_notifysecctx(struct = inode *inode, void *ctx, u3 { return -EOPNOTSUPP; } -static inline int security_inode_setsecctx(struct dentry *dentry, void *ct= x, u32 ctxlen) +static inline int security_inode_setsecctx(const struct path *path, void *= ctx, u32 ctxlen) { return -EOPNOTSUPP; } diff --git a/security/security.c b/security/security.c index bf0ec31f1047..de3ed5c18802 100644 --- a/security/security.c +++ b/security/security.c @@ -4134,7 +4134,7 @@ EXPORT_SYMBOL(security_inode_notifysecctx); =20 /** * security_inode_setsecctx() - Change the security label of an inode - * @dentry: inode + * @path: inode * @ctx: secctx * @ctxlen: length of secctx * @@ -4148,9 +4148,9 @@ EXPORT_SYMBOL(security_inode_notifysecctx); * * Return: Returns 0 on success, error on failure. */ -int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) +int security_inode_setsecctx(const struct path *path, void *ctx, u32 ctxle= n) { - return call_int_hook(inode_setsecctx, dentry, ctx, ctxlen); + return call_int_hook(inode_setsecctx, path, ctx, ctxlen); } EXPORT_SYMBOL(security_inode_setsecctx); =20 diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index f2394cf6646e..8af024fe4fb5 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -7166,10 +7166,10 @@ static int selinux_inode_notifysecctx(struct inode = *inode, void *ctx, u32 ctxlen /* * called with inode->i_mutex locked */ -static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 c= txlen) +static int selinux_inode_setsecctx(const struct path *path, void *ctx, u32= ctxlen) { - return __vfs_setxattr_locked(&nop_mnt_idmap, dentry, XATTR_NAME_SELINUX, - ctx, ctxlen, 0, NULL); + return __vfs_setxattr_locked(&nop_mnt_idmap, path->dentry, + XATTR_NAME_SELINUX, ctx, ctxlen, 0, NULL); } =20 static int selinux_inode_getsecctx(struct inode *inode, struct lsm_context= *cp) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 4439821a5e57..d9e9f4a52567 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4978,10 +4978,10 @@ static int smack_inode_notifysecctx(struct inode *i= node, void *ctx, u32 ctxlen) ctxlen, 0); } =20 -static int smack_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctx= len) +static int smack_inode_setsecctx(const struct path *path, void *ctx, u32 c= txlen) { - return __vfs_setxattr_locked(&nop_mnt_idmap, dentry, XATTR_NAME_SMACK, - ctx, ctxlen, 0, NULL); + return __vfs_setxattr_locked(&nop_mnt_idmap, path->dentry, + XATTR_NAME_SMACK, ctx, ctxlen, 0, NULL); } =20 static int smack_inode_getsecctx(struct inode *inode, struct lsm_context *= cp) --=20 2.18.0.huawei.25 From nobody Thu Sep 24 12:09:31 2026 Received: from canpmsgout08.his.huawei.com (canpmsgout08.his.huawei.com [113.46.200.223]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6B2ED4078D3; Thu, 24 Sep 2026 10:22:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.223 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245365; cv=none; b=bKqkHoqLXwJ8SKcwQMC8u6BivmQn/S4oe40Ih8RQrokHvptJSf5P6yEwiKKKsI97w7m8EG7xQVPEVgQ0+3mN+iyX6IdnlAofOa0QOHPmaoN6Smqkln99J6vQosnhNcg2Em3HFmUeSbSNVPU8vpZB1sN8S7yqWZqfqHX4EDPOCNI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245365; c=relaxed/simple; bh=b0GjL6EJO81BLSNOTvnisLDMEIrdtfZoIK9jv2JcgOc=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=YjnMXSfhgPGI0p5jiv916wGgTd0uldq4YXXCK6D4v0EbdShuDgEHLSsaUY04B5Fw6LpqaZA0yojk/RBgX691piaNFMRS5reke4FIyhwQTcb3CirtXiq2/p5aSZfm5YerYqdHndHgjVbUoZHSmdx3+6MRCIZMDy9S64ahYOZX7gs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=2aEnde+9; arc=none smtp.client-ip=113.46.200.223 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="2aEnde+9" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=D5Awij/QWh1PyOH7f2t2qpL214GBwE46RDMuaYGkhK0=; b=2aEnde+9KIJOjcQcyBud88F6DjKfvZbde6iMM2fbkDsu3vJfGqlqIxviOEI89Lv4Z/f+QykeX smQRYoEn2pmy+IoKoYuC50MmJAj5Sj4udxunF8yz8vUHky3a6AwGQ8hcT4O/fwcFdupZiiQg+nD sSHynKLkhTLAtl4CquytxVc= Received: from mail.maildlp.com (unknown [172.19.163.200]) by canpmsgout08.his.huawei.com (SkyGuard) with ESMTPS id 4hr8jN4bBjzmV8g; Thu, 24 Sep 2026 18:10:32 +0800 (CST) Received: from whupemk100010.china.huawei.com (unknown [7.152.184.41]) by mail.maildlp.com (Postfix) with ESMTPS id B8C904055B; Thu, 24 Sep 2026 18:22:37 +0800 (CST) Received: from octopus.huawei.com (10.67.174.191) by whupemk100010.china.huawei.com (7.152.184.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45; Thu, 24 Sep 2026 18:22:33 +0800 From: Cai Xinchen To: , , , , , , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH RFC -next 03/12] fs: pass struct path to xattr helpers Date: Thu, 24 Sep 2026 18:48:22 +0800 Message-ID: <20260924104831.1081137-4-caixinchen1@huawei.com> X-Mailer: git-send-email 2.18.0.huawei.25 In-Reply-To: <20260924104831.1081137-1-caixinchen1@huawei.com> References: <20260924104831.1081137-1-caixinchen1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To whupemk100010.china.huawei.com (7.152.184.41) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 --- 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(-) diff --git a/drivers/block/zloop.c b/drivers/block/zloop.c index f0ca221524db..d77b114d69fc 100644 --- a/drivers/block/zloop.c +++ b/drivers/block/zloop.c @@ -710,7 +710,7 @@ static int zloop_record_safe_wps(struct zloop_device *z= lo) =20 if (!zloop_zone_is_active(zone)) continue; - ret =3D vfs_setxattr(file_mnt_idmap(file), file_dentry(file), + ret =3D vfs_setxattr(&file->f_path, "user.zloop.wp", &zone->wp, sizeof(zone->wp), 0); if (ret) { pr_err("%pg: failed to record write pointer (%d)\n", @@ -1395,7 +1395,7 @@ static void zloop_forget_cache(struct zloop_device *z= lo) if (!zloop_zone_is_active(zone)) continue; =20 - ret =3D vfs_getxattr(file_mnt_idmap(file), file_dentry(file), + ret =3D vfs_getxattr(&file->f_path, "user.zloop.wp", &old_wp, sizeof(old_wp)); if (ret =3D=3D -ENODATA) { old_wp =3D 0; diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c index c70bf67e52b0..5a0b50bcfb73 100644 --- a/fs/cachefiles/xattr.c +++ b/fs/cachefiles/xattr.c @@ -40,14 +40,12 @@ struct cachefiles_vol_xattr { int cachefiles_set_object_xattr(struct cachefiles_object *object) { struct cachefiles_xattr *buf; - struct dentry *dentry; struct file *file =3D object->file; unsigned int len =3D object->cookie->aux_len; int ret; =20 if (!file) return -ESTALE; - dentry =3D file->f_path.dentry; =20 _enter("%x,#%d", object->debug_id, len); =20 @@ -69,7 +67,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object = *object) if (ret =3D=3D 0) { ret =3D mnt_want_write_file(file); if (ret =3D=3D 0) { - ret =3D vfs_setxattr(&nop_mnt_idmap, dentry, + ret =3D vfs_setxattr(&file->f_path, cachefiles_xattr_cache, buf, sizeof(struct cachefiles_xattr) + len, 0); mnt_drop_write_file(file); @@ -102,7 +100,6 @@ int cachefiles_set_object_xattr(struct cachefiles_objec= t *object) int cachefiles_check_auxdata(struct cachefiles_object *object, struct file= *file) { struct cachefiles_xattr *buf; - struct dentry *dentry =3D file->f_path.dentry; unsigned int len =3D object->cookie->aux_len, tlen; const void *p =3D fscache_get_aux(object->cookie); enum cachefiles_coherency_trace why; @@ -117,7 +114,7 @@ int cachefiles_check_auxdata(struct cachefiles_object *= object, struct file *file =20 xlen =3D cachefiles_inject_read_error(); if (xlen =3D=3D 0) - xlen =3D vfs_getxattr(&nop_mnt_idmap, dentry, cachefiles_xattr_cache, bu= f, tlen); + xlen =3D vfs_getxattr(&file->f_path, cachefiles_xattr_cache, buf, tlen); if (xlen !=3D tlen) { if (xlen < 0) { ret =3D xlen; @@ -161,14 +158,14 @@ int cachefiles_remove_object_xattr(struct cachefiles_= cache *cache, struct cachefiles_object *object, struct dentry *dentry) { + struct path path =3D { .mnt =3D cache->mnt, .dentry =3D dentry }; int ret; =20 ret =3D cachefiles_inject_remove_error(); if (ret =3D=3D 0) { ret =3D mnt_want_write(cache->mnt); if (ret =3D=3D 0) { - ret =3D vfs_removexattr(&nop_mnt_idmap, dentry, - cachefiles_xattr_cache); + ret =3D vfs_removexattr(&path, cachefiles_xattr_cache); mnt_drop_write(cache->mnt); } } @@ -214,7 +211,8 @@ bool cachefiles_set_volume_xattr(struct cachefiles_volu= me *volume) struct cachefiles_vol_xattr *buf; unsigned int len =3D volume->vcookie->coherency_len; const void *p =3D volume->vcookie->coherency; - struct dentry *dentry =3D volume->dentry; + struct path path =3D { .mnt =3D volume->cache->mnt, + .dentry =3D volume->dentry }; int ret; =20 _enter("%x,#%d", volume->vcookie->debug_id, len); @@ -230,22 +228,21 @@ bool cachefiles_set_volume_xattr(struct cachefiles_vo= lume *volume) if (ret =3D=3D 0) { ret =3D mnt_want_write(volume->cache->mnt); if (ret =3D=3D 0) { - ret =3D vfs_setxattr(&nop_mnt_idmap, dentry, - cachefiles_xattr_cache, + ret =3D vfs_setxattr(&path, cachefiles_xattr_cache, buf, len, 0); mnt_drop_write(volume->cache->mnt); } } if (ret < 0) { - trace_cachefiles_vfs_error(NULL, d_inode(dentry), ret, + trace_cachefiles_vfs_error(NULL, d_inode(path.dentry), ret, cachefiles_trace_setxattr_error); - trace_cachefiles_vol_coherency(volume, d_inode(dentry)->i_ino, + trace_cachefiles_vol_coherency(volume, d_inode(path.dentry)->i_ino, cachefiles_coherency_vol_set_fail); if (ret !=3D -ENOMEM) cachefiles_io_error( volume->cache, "Failed to set xattr with error %d", ret); } else { - trace_cachefiles_vol_coherency(volume, d_inode(dentry)->i_ino, + trace_cachefiles_vol_coherency(volume, d_inode(path.dentry)->i_ino, cachefiles_coherency_vol_set_ok); } =20 @@ -260,9 +257,10 @@ bool cachefiles_set_volume_xattr(struct cachefiles_vol= ume *volume) int cachefiles_check_volume_xattr(struct cachefiles_volume *volume) { struct cachefiles_vol_xattr *buf; - struct dentry *dentry =3D volume->dentry; unsigned int len =3D volume->vcookie->coherency_len; const void *p =3D volume->vcookie->coherency; + struct path path =3D { .mnt =3D volume->cache->mnt, + .dentry =3D volume->dentry }; enum cachefiles_coherency_trace why; ssize_t xlen; int ret =3D -ESTALE; @@ -276,11 +274,11 @@ int cachefiles_check_volume_xattr(struct cachefiles_v= olume *volume) =20 xlen =3D cachefiles_inject_read_error(); if (xlen =3D=3D 0) - xlen =3D vfs_getxattr(&nop_mnt_idmap, dentry, cachefiles_xattr_cache, bu= f, len); + xlen =3D vfs_getxattr(&path, cachefiles_xattr_cache, buf, len); if (xlen !=3D len) { if (xlen < 0) { ret =3D xlen; - trace_cachefiles_vfs_error(NULL, d_inode(dentry), xlen, + trace_cachefiles_vfs_error(NULL, d_inode(path.dentry), xlen, cachefiles_trace_getxattr_error); if (xlen =3D=3D -EIO) cachefiles_io_error( @@ -297,7 +295,7 @@ int cachefiles_check_volume_xattr(struct cachefiles_vol= ume *volume) ret =3D 0; } =20 - trace_cachefiles_vol_coherency(volume, d_inode(dentry)->i_ino, why); + trace_cachefiles_vol_coherency(volume, d_inode(path.dentry)->i_ino, why); kfree(buf); _leave(" =3D %d", ret); return ret; diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 627d456f9c38..3307cf13b5b4 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -991,17 +991,17 @@ ecryptfs_setxattr(struct dentry *dentry, struct inode= *inode, size_t size, int flags) { int rc; - struct dentry *lower_dentry; + struct path lower_path; struct inode *lower_inode; =20 - lower_dentry =3D ecryptfs_dentry_to_lower(dentry); - lower_inode =3D d_inode(lower_dentry); + lower_path =3D ecryptfs_lower_path(dentry); + lower_inode =3D d_inode(lower_path.dentry); if (!(lower_inode->i_opflags & IOP_XATTR)) { rc =3D -EOPNOTSUPP; goto out; } inode_lock(lower_inode); - rc =3D __vfs_setxattr_locked(&nop_mnt_idmap, lower_dentry, name, value, s= ize, flags, NULL); + rc =3D __vfs_setxattr_locked(&lower_path, name, value, size, flags, NULL); inode_unlock(lower_inode); if (!rc && inode) fsstack_copy_attr_all(inode, lower_inode); diff --git a/fs/nfsd/nfs4ctl.h b/fs/nfsd/nfs4ctl.h index bcec4c4ef1d5..97ab3d4212aa 100644 --- a/fs/nfsd/nfs4ctl.h +++ b/fs/nfsd/nfs4ctl.h @@ -38,7 +38,7 @@ int nfsd4_create_laundry_wq(void); void nfsd4_destroy_laundry_wq(void); bool nfsd_wait_for_delegreturn(struct svc_rqst *rqstp, struct inode *inode= ); =20 -extern int nfsd4_is_junction(struct dentry *dentry); +extern int nfsd4_is_junction(const struct path *path); extern int register_cld_notifier(void); extern void unregister_cld_notifier(void); #ifdef CONFIG_NFSD_V4_2_INTER_SSC @@ -68,7 +68,7 @@ static inline bool nfsd_wait_for_delegreturn(struct svc_r= qst *rqstp, return false; } =20 -static inline int nfsd4_is_junction(struct dentry *dentry) +static inline int nfsd4_is_junction(const struct path *path) { return 0; } diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 922337083fe9..a3b86fa60dca 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -233,11 +233,13 @@ static int nfsd_lookup_parent(struct svc_rqst *rqstp,= struct dentry *dparent, st */ int nfsd_mountpoint(struct dentry *dentry, struct svc_export *exp) { + struct path path =3D { .mnt =3D exp->ex_path.mnt, .dentry =3D dentry }; + if (!d_inode(dentry)) return 0; if (exp->ex_flags & NFSEXP_V4ROOT) return 1; - if (nfsd4_is_junction(dentry)) + if (nfsd4_is_junction(&path)) return 1; if (d_managed(dentry)) /* @@ -684,14 +686,14 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *f= hp, /** * nfsd4_is_junction - Test if an object could be an NFS junction * - * @dentry: object to test + * @path: object to test * - * Returns 1 if "dentry" appears to contain NFS junction information. + * Returns 1 if "path" appears to contain NFS junction information. * Otherwise 0 is returned. */ -int nfsd4_is_junction(struct dentry *dentry) +int nfsd4_is_junction(const struct path *path) { - struct inode *inode =3D d_inode(dentry); + struct inode *inode =3D d_inode(path->dentry); =20 if (inode =3D=3D NULL) return 0; @@ -699,8 +701,7 @@ int nfsd4_is_junction(struct dentry *dentry) return 0; if (!(inode->i_mode & S_ISVTX)) return 0; - if (vfs_getxattr(&nop_mnt_idmap, dentry, NFSD_JUNCTION_XATTR_NAME, - NULL, 0) <=3D 0) + if (vfs_getxattr(path, NFSD_JUNCTION_XATTR_NAME, NULL, 0) <=3D 0) return 0; return 1; } @@ -2619,19 +2620,20 @@ nfsd_getxattr(struct svc_rqst *rqstp, struct svc_fh= *fhp, char *name, __be32 err; char *buf; struct inode *inode; - struct dentry *dentry; + struct path path; =20 err =3D fh_verify(rqstp, fhp, 0, NFSD_MAY_READ); if (err) return err; =20 err =3D nfs_ok; - dentry =3D fhp->fh_dentry; - inode =3D d_inode(dentry); + path.mnt =3D fhp->fh_export->ex_path.mnt; + path.dentry =3D fhp->fh_dentry; + inode =3D d_inode(path.dentry); =20 inode_lock_shared(inode); =20 - len =3D vfs_getxattr(&nop_mnt_idmap, dentry, name, NULL, 0); + len =3D vfs_getxattr(&path, name, NULL, 0); =20 /* * Zero-length attribute, just return. @@ -2658,7 +2660,7 @@ nfsd_getxattr(struct svc_rqst *rqstp, struct svc_fh *= fhp, char *name, goto out; } =20 - len =3D vfs_getxattr(&nop_mnt_idmap, dentry, name, buf, len); + len =3D vfs_getxattr(&path, name, buf, len); if (len <=3D 0) { kvfree(buf); buf =3D NULL; @@ -2692,19 +2694,20 @@ nfsd_listxattr(struct svc_rqst *rqstp, struct svc_f= h *fhp, char **bufp, __be32 err; char *buf; struct inode *inode; - struct dentry *dentry; + struct path path; =20 err =3D fh_verify(rqstp, fhp, 0, NFSD_MAY_READ); if (err) return err; =20 - dentry =3D fhp->fh_dentry; - inode =3D d_inode(dentry); + path.mnt =3D fhp->fh_export->ex_path.mnt; + path.dentry =3D fhp->fh_dentry; + inode =3D d_inode(path.dentry); *lenp =3D 0; =20 inode_lock_shared(inode); =20 - len =3D vfs_listxattr(dentry, NULL, 0); + len =3D vfs_listxattr(&path, NULL, 0); if (len <=3D 0) { err =3D nfsd_xattr_errno(len); goto out; @@ -2721,7 +2724,7 @@ nfsd_listxattr(struct svc_rqst *rqstp, struct svc_fh = *fhp, char **bufp, goto out; } =20 - len =3D vfs_listxattr(dentry, buf, len); + len =3D vfs_listxattr(&path, buf, len); if (len <=3D 0) { kvfree(buf); err =3D nfsd_xattr_errno(len); @@ -2754,6 +2757,7 @@ nfsd_removexattr(struct svc_rqst *rqstp, struct svc_f= h *fhp, char *name) { __be32 err; int ret; + struct path path; =20 err =3D fh_verify(rqstp, fhp, 0, NFSD_MAY_WRITE); if (err) @@ -2763,16 +2767,17 @@ nfsd_removexattr(struct svc_rqst *rqstp, struct svc= _fh *fhp, char *name) if (ret) return nfserrno(ret); =20 - inode_lock(fhp->fh_dentry->d_inode); + path.mnt =3D fhp->fh_export->ex_path.mnt; + path.dentry =3D fhp->fh_dentry; + inode_lock(d_inode(path.dentry)); err =3D fh_fill_pre_attrs(fhp); if (err !=3D nfs_ok) goto out_unlock; - ret =3D __vfs_removexattr_locked(&nop_mnt_idmap, fhp->fh_dentry, - name, NULL); + ret =3D __vfs_removexattr_locked(&path, name, NULL); err =3D nfsd_xattr_errno(ret); fh_fill_post_attrs(fhp); out_unlock: - inode_unlock(fhp->fh_dentry->d_inode); + inode_unlock(d_inode(path.dentry)); fh_drop_write(fhp); =20 return err; @@ -2784,6 +2789,7 @@ nfsd_setxattr(struct svc_rqst *rqstp, struct svc_fh *= fhp, char *name, { __be32 err; int ret; + struct path path; =20 err =3D fh_verify(rqstp, fhp, 0, NFSD_MAY_WRITE); if (err) @@ -2792,16 +2798,17 @@ nfsd_setxattr(struct svc_rqst *rqstp, struct svc_fh= *fhp, char *name, ret =3D fh_want_write(fhp); if (ret) return nfserrno(ret); - inode_lock(fhp->fh_dentry->d_inode); + path.mnt =3D fhp->fh_export->ex_path.mnt; + path.dentry =3D fhp->fh_dentry; + inode_lock(d_inode(path.dentry)); err =3D fh_fill_pre_attrs(fhp); if (err !=3D nfs_ok) goto out_unlock; - ret =3D __vfs_setxattr_locked(&nop_mnt_idmap, fhp->fh_dentry, - name, buf, len, flags, NULL); + ret =3D __vfs_setxattr_locked(&path, name, buf, len, flags, NULL); fh_fill_post_attrs(fhp); err =3D nfsd_xattr_errno(ret); out_unlock: - inode_unlock(fhp->fh_dentry->d_inode); + inode_unlock(d_inode(path.dentry)); fh_drop_write(fhp); return err; } 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 p= ath *oldpath, struct de if (!old->d_inode->i_op->listxattr || !new->d_inode->i_op->listxattr) return 0; =20 - list_size =3D vfs_listxattr(old, NULL, 0); + list_size =3D vfs_listxattr(oldpath, NULL, 0); if (list_size <=3D 0) { if (list_size =3D=3D -EOPNOTSUPP) return 0; @@ -94,7 +94,7 @@ int ovl_copy_xattr(struct super_block *sb, const struct p= ath *oldpath, struct de if (!buf) return -ENOMEM; =20 - list_size =3D vfs_listxattr(old, buf, list_size); + list_size =3D vfs_listxattr(oldpath, buf, list_size); if (list_size <=3D 0) { error =3D 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, =20 WARN_ON(path->dentry->d_sb !=3D path->mnt->mnt_sb); =20 - err =3D vfs_getxattr(mnt_idmap(path->mnt), path->dentry, - name, value, size); + err =3D vfs_getxattr(path, name, value, size); len =3D (value && err > 0) ? err : 0; =20 pr_debug("getxattr(%pd2, \"%s\", \"%*pE\", %zu, 0) =3D %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 =3D { + .mnt =3D ovl_upper_mnt(ofs), + .dentry =3D dentry, + }; + /* Use vfs_setxattr(), not __vfs_setxattr(): it idmaps the security.capab= ility rootid. */ - int err =3D vfs_setxattr(ovl_upper_mnt_idmap(ofs), dentry, name, - value, size, flags); + int err =3D vfs_setxattr(&path, name, value, size, flags); =20 pr_debug("setxattr(%pd2, \"%s\", \"%*pE\", %zu, %d) =3D %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, str= uct dentry *dentry, static inline int ovl_do_removexattr(struct ovl_fs *ofs, struct dentry *de= ntry, const char *name) { - int err =3D vfs_removexattr(ovl_upper_mnt_idmap(ofs), dentry, name); + struct path path =3D { + .mnt =3D ovl_upper_mnt(ofs), + .dentry =3D dentry, + }; + + int err =3D vfs_removexattr(&path, name); pr_debug("removexattr(%pd2, \"%s\") =3D %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 in= ode *inode, const char if (!value && !upperdentry) { ovl_path_lower(dentry, &realpath); with_ovl_creds(dentry->d_sb) - err =3D vfs_getxattr(mnt_idmap(realpath.mnt), realdentry, name, NULL, 0= ); + err =3D vfs_getxattr(&realpath, name, NULL, 0); if (err < 0) goto out; } @@ -86,7 +86,7 @@ static int ovl_xattr_get(struct dentry *dentry, struct in= ode *inode, const char ovl_i_path_real(inode, &realpath); /* Use vfs_getxattr(), not __vfs_getxattr(): it idmaps the security.capab= ility rootid. */ with_ovl_creds(dentry->d_sb) - return vfs_getxattr(mnt_idmap(realpath.mnt), realpath.dentry, name, valu= e, size); + return vfs_getxattr(&realpath, name, value, size); } =20 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, cons= t char *s) =20 ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) { - struct dentry *realdentry =3D ovl_dentry_real(dentry); + struct path realpath; struct ovl_fs *ofs =3D OVL_FS(dentry->d_sb); ssize_t res; size_t len; char *s; size_t prefix_len, name_len; =20 + if (ovl_dentry_upper(dentry)) + ovl_path_upper(dentry, &realpath); + else + ovl_path_lower(dentry, &realpath); + with_ovl_creds(dentry->d_sb) - res =3D vfs_listxattr(realdentry, list, size); + res =3D vfs_listxattr(&realpath, list, size); if (res <=3D 0 || size =3D=3D 0) return res; =20 diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index fb3ee170db3c..b5db5f280701 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -3293,7 +3293,6 @@ static bool smb2_is_private_ea(const char *name, size= _t name_len) static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len, const struct path *path, bool get_write) { - struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); char *attr_name =3D NULL, *value; int rc =3D 0; unsigned int next =3D 0; @@ -3333,16 +3332,14 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, = unsigned int buf_len, value =3D (char *)&eabuf->name + eabuf->EaNameLength + 1; =20 if (!eabuf->EaValueLength) { - rc =3D ksmbd_vfs_casexattr_len(idmap, - path->dentry, + rc =3D ksmbd_vfs_casexattr_len(path, attr_name, XATTR_USER_PREFIX_LEN + eabuf->EaNameLength); =20 /* delete the EA only when it exits */ if (rc > 0) { - rc =3D ksmbd_vfs_remove_xattr(idmap, - path, + rc =3D ksmbd_vfs_remove_xattr(path, attr_name, get_write); =20 @@ -3357,7 +3354,7 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, un= signed int buf_len, /* if the EA doesn't exist, just do nothing. */ rc =3D 0; } else { - rc =3D ksmbd_vfs_setxattr(idmap, path, attr_name, value, + rc =3D ksmbd_vfs_setxattr(path, attr_name, value, le16_to_cpu(eabuf->EaValueLength), 0, get_write); if (rc < 0) { @@ -3394,7 +3391,6 @@ static noinline int smb2_set_stream_name_xattr(const = struct path *path, struct ksmbd_file *fp, char *stream_name, int s_type) { - struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); size_t xattr_stream_size; char *xattr_stream_name; int rc; @@ -3410,8 +3406,7 @@ static noinline int smb2_set_stream_name_xattr(const = struct path *path, fp->stream.size =3D xattr_stream_size; =20 /* Check if there is stream prefix in xattr space */ - rc =3D ksmbd_vfs_casexattr_len(idmap, - path->dentry, + rc =3D ksmbd_vfs_casexattr_len(path, xattr_stream_name, xattr_stream_size); if (rc >=3D 0) @@ -3438,7 +3433,7 @@ static noinline int smb2_set_stream_name_xattr(const = struct path *path, 0x00, 0x00, 0x01, 0x00, /* version */ [15] =3D 0x80, /* backup time */ }; - rc =3D ksmbd_vfs_setxattr(idmap, path, xattr_stream_name, + rc =3D ksmbd_vfs_setxattr(path, xattr_stream_name, (void *)afpinfo_empty, sizeof(afpinfo_empty), 0, false); return rc < 0 ? rc : 0; @@ -3447,7 +3442,7 @@ static noinline int smb2_set_stream_name_xattr(const = struct path *path, return -EBADF; } =20 - rc =3D ksmbd_vfs_setxattr(idmap, path, xattr_stream_name, NULL, 0, 0, fal= se); + rc =3D ksmbd_vfs_setxattr(path, xattr_stream_name, NULL, 0, 0, false); if (rc < 0) pr_err("Failed to store XATTR stream name :%d\n", rc); return 0; @@ -3462,8 +3457,7 @@ static noinline int smb2_set_stream_name_xattr(const = struct path *path, */ static loff_t ksmbd_stream_eof(struct ksmbd_file *fp) { - ssize_t slen =3D ksmbd_vfs_casexattr_len(file_mnt_idmap(fp->filp), - fp->filp->f_path.dentry, + ssize_t slen =3D ksmbd_vfs_casexattr_len(&fp->filp->f_path, fp->stream.name, fp->stream.size); return slen < 0 ? 0 : (loff_t)slen; @@ -3471,12 +3465,11 @@ static loff_t ksmbd_stream_eof(struct ksmbd_file *f= p) =20 static int smb2_remove_smb_xattrs(const struct path *path) { - struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); char *name, *xattr_list =3D NULL; ssize_t xattr_list_len; int err =3D 0; =20 - xattr_list_len =3D ksmbd_vfs_listxattr(path->dentry, &xattr_list); + xattr_list_len =3D ksmbd_vfs_listxattr(path, &xattr_list); if (xattr_list_len < 0) { goto out; } else if (!xattr_list_len) { @@ -3491,8 +3484,7 @@ static int smb2_remove_smb_xattrs(const struct path *= path) if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) && !strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX, STREAM_PREFIX_LEN)) { - err =3D ksmbd_vfs_remove_xattr(idmap, path, - name, true); + err =3D ksmbd_vfs_remove_xattr(path, name, true); if (err) ksmbd_debug(SMB, "remove xattr failed : %s\n", name); @@ -3538,7 +3530,7 @@ static void smb2_new_xattrs(struct ksmbd_tree_connect= *tcon, const struct path * da.flags =3D XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME | XATTR_DOSINFO_ITIME; =20 - rc =3D ksmbd_vfs_set_dos_attrib_xattr(mnt_idmap(path->mnt), path, &da, tr= ue); + rc =3D ksmbd_vfs_set_dos_attrib_xattr(path, &da, true); if (rc) ksmbd_debug(SMB, "failed to store file attribute into xattr\n"); } @@ -3547,6 +3539,7 @@ static bool smb2_parent_compressed(struct ksmbd_tree_= connect *tcon, const struct path *path) { struct dentry *parent =3D dget_parent(path->dentry); + struct path parent_path =3D { .mnt =3D path->mnt, .dentry =3D parent }; struct file_kattr fa =3D { .flags_valid =3D true }; struct xattr_dos_attrib da; bool compressed =3D false; @@ -3558,7 +3551,7 @@ static bool smb2_parent_compressed(struct ksmbd_tree_= connect *tcon, goto out; } =20 - rc =3D ksmbd_vfs_get_dos_attrib_xattr(mnt_idmap(path->mnt), parent, &da); + rc =3D ksmbd_vfs_get_dos_attrib_xattr(&parent_path, &da); if (rc > 0 && da.attr & FILE_ATTRIBUTE_COMPRESSED) compressed =3D true; =20 @@ -3578,8 +3571,7 @@ static void smb2_update_xattrs(struct ksmbd_tree_conn= ect *tcon, fp->f_ci->m_fattr &=3D ~(FILE_ATTRIBUTE_HIDDEN_LE | FILE_ATTRIBUTE_SYSTEM= _LE); =20 /* get FileAttributes from XATTR_NAME_DOS_ATTRIBUTE */ - rc =3D ksmbd_vfs_get_dos_attrib_xattr(mnt_idmap(path->mnt), - path->dentry, &da); + rc =3D ksmbd_vfs_get_dos_attrib_xattr(path, &da); if (rc > 0) { if (store_dos_attrs) { fp->f_ci->m_fattr =3D cpu_to_le32(da.attr); @@ -4524,8 +4516,7 @@ int smb2_open(struct ksmbd_work *work) =20 if (test_share_config_flag(tcon->share_conf, KSMBD_SHARE_FLAG_STORE_DOS_ATTRS) && - ksmbd_vfs_get_dos_attrib_xattr(mnt_idmap(path.mnt), - path.dentry, &da) > 0 && + ksmbd_vfs_get_dos_attrib_xattr(&path, &da) > 0 && da.attr & FILE_ATTRIBUTE_READONLY) { rsp->hdr.Status =3D STATUS_CANNOT_DELETE; rc =3D -EACCES; @@ -4863,7 +4854,6 @@ int smb2_open(struct ksmbd_work *work) } =20 rc =3D ksmbd_vfs_set_sd_xattr(conn, - idmap, &path, pntsd, pntsd_size, @@ -5886,7 +5876,6 @@ static int process_query_dir_entries(struct smb2_quer= y_dir_private *priv) ksmbd_kstat.kstat =3D &kstat; if (priv->info_level !=3D FILE_NAMES_INFORMATION) { rc =3D ksmbd_vfs_fill_dentry_attrs(priv->work, - idmap, dent, &ksmbd_kstat); if (rc) { @@ -6428,7 +6417,6 @@ static int smb2_get_ea(struct ksmbd_work *work, struc= t ksmbd_file *fp, ssize_t buf_free_len, alignment_bytes, next_offset, rsp_data_cnt =3D 0; struct smb2_ea_info_req *ea_req =3D NULL; const struct path *path; - struct mnt_idmap *idmap =3D file_mnt_idmap(fp->filp); =20 if (!(fp->daccess & FILE_READ_EA_LE)) { pr_err("Not permitted to read ext attr : 0x%x\n", @@ -6465,7 +6453,7 @@ static int smb2_get_ea(struct ksmbd_work *work, struc= t ksmbd_file *fp, if (buf_free_len < 0) return -EINVAL; =20 - rc =3D ksmbd_vfs_listxattr(path->dentry, &xattr_list); + rc =3D ksmbd_vfs_listxattr(path, &xattr_list); if (rc < 0) { rsp->hdr.Status =3D STATUS_INVALID_HANDLE; goto out; @@ -6511,8 +6499,7 @@ static int smb2_get_ea(struct ksmbd_work *work, struc= t ksmbd_file *fp, buf_free_len -=3D (offsetof(struct smb2_ea_info, name) + name_len + 1); /* bailout if xattr can't fit in buf_free_len */ - value_len =3D ksmbd_vfs_getxattr(idmap, path->dentry, - name, &buf); + value_len =3D ksmbd_vfs_getxattr(path, name, &buf); if (value_len <=3D 0) { rc =3D -ENOENT; rsp->hdr.Status =3D STATUS_INVALID_HANDLE; @@ -6802,7 +6789,7 @@ static char *smb2_get_normalized_stream_name(struct k= smbd_file *fp) if (!ksmbd_stream_fd(fp)) return NULL; =20 - xattr_list_len =3D ksmbd_vfs_listxattr(fp->filp->f_path.dentry, + xattr_list_len =3D ksmbd_vfs_listxattr(&fp->filp->f_path, &xattr_list); if (xattr_list_len <=3D 0) goto out; @@ -6905,7 +6892,7 @@ static int get_file_stream_info(struct ksmbd_work *wo= rk, if (buf_free_len < 0) goto out; =20 - xattr_list_len =3D ksmbd_vfs_listxattr(path->dentry, &xattr_list); + xattr_list_len =3D ksmbd_vfs_listxattr(path, &xattr_list); if (xattr_list_len < 0) { goto out; } else if (!xattr_list_len) { @@ -6950,8 +6937,7 @@ static int get_file_stream_info(struct ksmbd_work *wo= rk, streamlen *=3D 2; kfree(stream_buf); file_info->StreamNameLength =3D cpu_to_le32(streamlen); - slen =3D ksmbd_vfs_xattr_len(file_mnt_idmap(fp->filp), - path->dentry, stream_name); + slen =3D ksmbd_vfs_xattr_len(path, stream_name); ssize =3D slen < 0 ? 0 : (loff_t)slen; file_info->StreamSize =3D cpu_to_le64(ssize); file_info->StreamAllocationSize =3D cpu_to_le64(ssize); @@ -7689,8 +7675,8 @@ static int smb2_get_info_sec(struct ksmbd_work *work, =20 if (test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_ACL_XATTR)) - ppntsd_size =3D ksmbd_vfs_get_sd_xattr(work->conn, idmap, - fp->filp->f_path.dentry, + ppntsd_size =3D ksmbd_vfs_get_sd_xattr(work->conn, + &fp->filp->f_path, &ppntsd); =20 /* Check if sd buffer size exceeds response buffer size */ @@ -8051,8 +8037,7 @@ static int smb2_rename(struct ksmbd_work *work, goto out; } =20 - stream_buf_len =3D ksmbd_vfs_getcasexattr(file_mnt_idmap(fp->filp), - fp->filp->f_path.dentry, + stream_buf_len =3D ksmbd_vfs_getcasexattr(&fp->filp->f_path, fp->stream.name, fp->stream.size, &stream_buf); @@ -8063,8 +8048,7 @@ static int smb2_rename(struct ksmbd_work *work, } } =20 - rc =3D ksmbd_vfs_setxattr(file_mnt_idmap(fp->filp), - &fp->filp->f_path, + rc =3D ksmbd_vfs_setxattr(&fp->filp->f_path, xattr_stream_name, stream_buf, stream_buf_len, 0, true); kfree(stream_buf); @@ -8171,7 +8155,6 @@ static int set_file_basic_info(struct ksmbd_file *fp, struct iattr attrs; struct file *filp; struct inode *inode; - struct mnt_idmap *idmap; __le32 attrs_mask =3D FILE_ATTRIBUTE_DIRECTORY_LE | FILE_ATTRIBUTE_COMPRESSED_LE; int rc =3D 0; @@ -8182,7 +8165,6 @@ static int set_file_basic_info(struct ksmbd_file *fp, attrs.ia_valid =3D 0; filp =3D fp->filp; inode =3D file_inode(filp); - idmap =3D file_mnt_idmap(filp); =20 if (file_info->CreationTime) fp->create_time =3D le64_to_cpu(file_info->CreationTime); @@ -8227,7 +8209,7 @@ static int set_file_basic_info(struct ksmbd_file *fp, da.flags =3D XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME | XATTR_DOSINFO_ITIME; =20 - rc =3D ksmbd_vfs_set_dos_attrib_xattr(idmap, &filp->f_path, &da, + rc =3D ksmbd_vfs_set_dos_attrib_xattr(&filp->f_path, &da, true); if (rc) ksmbd_debug(SMB, @@ -10780,7 +10762,6 @@ static inline int fsctl_set_sparse(struct ksmbd_wor= k *work, u64 id, struct file_sparse *sparse) { struct ksmbd_file *fp; - struct mnt_idmap *idmap; int ret =3D 0; __le32 old_fattr; =20 @@ -10804,8 +10785,6 @@ static inline int fsctl_set_sparse(struct ksmbd_wor= k *work, u64 id, goto out; } =20 - idmap =3D file_mnt_idmap(fp->filp); - old_fattr =3D fp->f_ci->m_fattr; if (!sparse->SetSparse && (old_fattr & FILE_ATTRIBUTE_SPARSE_FILE_LE)) { @@ -10823,8 +10802,7 @@ static inline int fsctl_set_sparse(struct ksmbd_wor= k *work, u64 id, const struct cred *saved_cred; struct xattr_dos_attrib da =3D {0}; =20 - ret =3D ksmbd_vfs_get_dos_attrib_xattr(idmap, - fp->filp->f_path.dentry, &da); + ret =3D ksmbd_vfs_get_dos_attrib_xattr(&fp->filp->f_path, &da); if (ret <=3D 0) { da.version =3D 4; da.itime =3D fp->itime; @@ -10836,8 +10814,7 @@ static inline int fsctl_set_sparse(struct ksmbd_wor= k *work, u64 id, da.attr =3D le32_to_cpu(fp->f_ci->m_fattr); da.flags |=3D XATTR_DOSINFO_ATTRIB; saved_cred =3D override_creds(fp->filp->f_cred); - ret =3D ksmbd_vfs_set_dos_attrib_xattr(idmap, - &fp->filp->f_path, + ret =3D ksmbd_vfs_set_dos_attrib_xattr(&fp->filp->f_path, &da, true); revert_creds(saved_cred); if (ret) diff --git a/fs/smb/server/smb_common.c b/fs/smb/server/smb_common.c index 086a1b85e5f4..2cc8e24dcd6c 100644 --- a/fs/smb/server/smb_common.c +++ b/fs/smb/server/smb_common.c @@ -467,7 +467,6 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work= *work, int info_level, { int i, rc =3D 0; struct ksmbd_conn *conn =3D work->conn; - struct mnt_idmap *idmap =3D file_mnt_idmap(dir->filp); =20 for (i =3D 0; i < 2; i++) { struct kstat kstat; @@ -493,7 +492,6 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work= *work, int info_level, =20 ksmbd_kstat.kstat =3D &kstat; rc =3D ksmbd_vfs_fill_dentry_attrs(work, - idmap, dentry, &ksmbd_kstat); if (rc) diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c index fcace71b0a29..f81e06918cfb 100644 --- a/fs/smb/server/smbacl.c +++ b/fs/smb/server/smbacl.c @@ -1199,8 +1199,8 @@ int smb_inherit_dacl(struct ksmbd_conn *conn, struct smb_acl *parent_pdacl; struct smb_ntsd *parent_pntsd =3D NULL; struct smb_sid owner_sid, group_sid; - struct dentry *parent =3D path->dentry->d_parent; - struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); + struct path parent_path =3D { .mnt =3D path->mnt, + .dentry =3D path->dentry->d_parent }; int inherited_flags =3D 0, flags =3D 0, i, nt_size =3D 0, pdacl_size; int rc =3D 0, pntsd_type, ppntsd_size, acl_len, aces_size; unsigned int dacloffset; @@ -1209,8 +1209,8 @@ int smb_inherit_dacl(struct ksmbd_conn *conn, char *aces_base; bool is_dir =3D S_ISDIR(d_inode(path->dentry)->i_mode); =20 - ppntsd_size =3D ksmbd_vfs_get_sd_xattr(conn, idmap, - parent, &parent_pntsd); + ppntsd_size =3D ksmbd_vfs_get_sd_xattr(conn, &parent_path, + &parent_pntsd); if (ppntsd_size <=3D 0) return -ENOENT; =20 @@ -1427,7 +1427,7 @@ int smb_inherit_dacl(struct ksmbd_conn *conn, pntsd_size +=3D sizeof(struct smb_acl) + nt_size; } =20 - ksmbd_vfs_set_sd_xattr(conn, idmap, path, pntsd, pntsd_size, false); + ksmbd_vfs_set_sd_xattr(conn, path, pntsd, pntsd_size, false); kfree(pntsd); } =20 @@ -1476,8 +1476,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, cons= t struct path *path, vfsuid_t vfsuid; =20 ksmbd_debug(SMB, "check permission using windows acl\n"); - pntsd_size =3D ksmbd_vfs_get_sd_xattr(conn, idmap, - path->dentry, &pntsd); + pntsd_size =3D ksmbd_vfs_get_sd_xattr(conn, path, &pntsd); if (pntsd_size <=3D 0 || !pntsd) goto err_out; =20 @@ -1701,7 +1700,7 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmb= d_tree_connect *tcon, newattrs.ia_valid |=3D ATTR_MODE; newattrs.ia_mode =3D (inode->i_mode & ~0777) | (fattr.cf_mode & 0777); =20 - ksmbd_vfs_remove_acl_xattrs(idmap, path); + ksmbd_vfs_remove_acl_xattrs(path); /* Update posix acls */ if (IS_ENABLED(CONFIG_FS_POSIX_ACL) && fattr.cf_dacls) { rc =3D set_posix_acl(idmap, path->dentry, @@ -1732,8 +1731,8 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmb= d_tree_connect *tcon, =20 if (test_share_config_flag(tcon->share_conf, KSMBD_SHARE_FLAG_ACL_XATTR))= { /* Update WinACL in xattr */ - ksmbd_vfs_remove_sd_xattrs(idmap, path); - ksmbd_vfs_set_sd_xattr(conn, idmap, path, pntsd, ntsd_len, + ksmbd_vfs_remove_sd_xattrs(path); + ksmbd_vfs_set_sd_xattr(conn, path, pntsd, ntsd_len, get_write); } =20 diff --git a/fs/smb/server/tests/smbacl_kunit.c b/fs/smb/server/tests/smbac= l_kunit.c index 33496b4d31a3..0e918b72f94f 100644 --- a/fs/smb/server/tests/smbacl_kunit.c +++ b/fs/smb/server/tests/smbacl_kunit.c @@ -221,8 +221,7 @@ static void ksmbd_smb_check_perm_dacl_boundary_test(str= uct kunit *test) mk_vma_flags(VMA_NORESERVE_BIT)); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, file); =20 - rc =3D ksmbd_vfs_set_sd_xattr(NULL, mnt_idmap(file->f_path.mnt), - &file->f_path, pntsd, ntsd_size, + rc =3D ksmbd_vfs_set_sd_xattr(NULL, &file->f_path, pntsd, ntsd_size, false); KUNIT_EXPECT_EQ(test, 0, rc); if (rc) @@ -263,8 +262,7 @@ ksmbd_smb_check_perm_dacl_maximal_boundary_test(struct = kunit *test) mk_vma_flags(VMA_NORESERVE_BIT)); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, file); =20 - rc =3D ksmbd_vfs_set_sd_xattr(NULL, mnt_idmap(file->f_path.mnt), - &file->f_path, pntsd, ntsd_size, + rc =3D ksmbd_vfs_set_sd_xattr(NULL, &file->f_path, pntsd, ntsd_size, false); KUNIT_EXPECT_EQ(test, 0, rc); if (rc) diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c index db0f2de2bab3..eb904cf9ef2d 100644 --- a/fs/smb/server/vfs.c +++ b/fs/smb/server/vfs.c @@ -217,14 +217,14 @@ int ksmbd_vfs_mkdir(struct ksmbd_work *work, const ch= ar *name, umode_t mode) return err; } =20 -ssize_t ksmbd_vfs_getcasexattr(struct mnt_idmap *idmap, - struct dentry *dentry, char *attr_name, +ssize_t ksmbd_vfs_getcasexattr(const struct path *path, + char *attr_name, int attr_name_len, char **attr_value) { char *name, *xattr_list =3D NULL; ssize_t value_len =3D -ENOENT, xattr_list_len; =20 - xattr_list_len =3D ksmbd_vfs_listxattr(dentry, &xattr_list); + xattr_list_len =3D ksmbd_vfs_listxattr(path, &xattr_list); if (xattr_list_len <=3D 0) goto out; =20 @@ -234,8 +234,7 @@ ssize_t ksmbd_vfs_getcasexattr(struct mnt_idmap *idmap, if (strncasecmp(attr_name, name, attr_name_len)) continue; =20 - value_len =3D ksmbd_vfs_getxattr(idmap, - dentry, + value_len =3D ksmbd_vfs_getxattr(path, name, attr_value); if (value_len < 0) @@ -259,8 +258,7 @@ static int ksmbd_vfs_stream_read(struct ksmbd_file *fp,= char *buf, loff_t *pos, *pos, count); =20 saved_cred =3D override_creds(fp->filp->f_cred); - v_len =3D ksmbd_vfs_getcasexattr(file_mnt_idmap(fp->filp), - fp->filp->f_path.dentry, + v_len =3D ksmbd_vfs_getcasexattr(&fp->filp->f_path, fp->stream.name, fp->stream.size, &stream_buf); @@ -387,7 +385,6 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp= , char *buf, loff_t *pos, { const struct cred *saved_cred; char *stream_buf =3D NULL, *wbuf; - struct mnt_idmap *idmap =3D file_mnt_idmap(fp->filp); size_t size; ssize_t v_len; int err =3D 0; @@ -407,8 +404,7 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp= , char *buf, loff_t *pos, } =20 saved_cred =3D override_creds(fp->filp->f_cred); - v_len =3D ksmbd_vfs_getcasexattr(idmap, - fp->filp->f_path.dentry, + v_len =3D ksmbd_vfs_getcasexattr(&fp->filp->f_path, fp->stream.name, fp->stream.size, &stream_buf); @@ -433,8 +429,7 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp= , char *buf, loff_t *pos, =20 memcpy(&stream_buf[*pos], buf, count); =20 - err =3D ksmbd_vfs_setxattr(idmap, - &fp->filp->f_path, + err =3D ksmbd_vfs_setxattr(&fp->filp->f_path, fp->stream.name, (void *)stream_buf, size, @@ -813,17 +808,17 @@ int ksmbd_vfs_truncate(struct ksmbd_work *work, =20 /** * ksmbd_vfs_listxattr() - vfs helper for smb list extended attributes - * @dentry: dentry of file for listing xattrs + * @path: path of file for listing xattrs * @list: destination buffer * * Return: xattr list length on success, otherwise error */ -ssize_t ksmbd_vfs_listxattr(struct dentry *dentry, char **list) +ssize_t ksmbd_vfs_listxattr(const struct path *path, char **list) { ssize_t size; char *vlist =3D NULL; =20 - size =3D vfs_listxattr(dentry, NULL, 0); + size =3D vfs_listxattr(path, NULL, 0); if (size <=3D 0) return size; =20 @@ -832,7 +827,7 @@ ssize_t ksmbd_vfs_listxattr(struct dentry *dentry, char= **list) return -ENOMEM; =20 *list =3D vlist; - size =3D vfs_listxattr(dentry, vlist, size); + size =3D vfs_listxattr(path, vlist, size); if (size < 0) { ksmbd_debug(VFS, "listxattr failed\n"); kvfree(vlist); @@ -842,30 +837,27 @@ ssize_t ksmbd_vfs_listxattr(struct dentry *dentry, ch= ar **list) return size; } =20 -ssize_t ksmbd_vfs_xattr_len(struct mnt_idmap *idmap, - struct dentry *dentry, char *xattr_name) +ssize_t ksmbd_vfs_xattr_len(const struct path *path, char *xattr_name) { - return vfs_getxattr(idmap, dentry, xattr_name, NULL, 0); + return vfs_getxattr(path, xattr_name, NULL, 0); } =20 /** * ksmbd_vfs_getxattr() - vfs helper for smb get extended attributes value - * @idmap: idmap - * @dentry: dentry of file for getting xattrs + * @path: path of file for getting xattrs * @xattr_name: name of xattr name to query * @xattr_buf: destination buffer xattr value * * Return: read xattr value length on success, otherwise error */ -ssize_t ksmbd_vfs_getxattr(struct mnt_idmap *idmap, - struct dentry *dentry, +ssize_t ksmbd_vfs_getxattr(const struct path *path, char *xattr_name, char **xattr_buf) { ssize_t xattr_len; char *buf; =20 *xattr_buf =3D NULL; - xattr_len =3D ksmbd_vfs_xattr_len(idmap, dentry, xattr_name); + xattr_len =3D ksmbd_vfs_xattr_len(path, xattr_name); if (xattr_len < 0) return xattr_len; =20 @@ -873,8 +865,7 @@ ssize_t ksmbd_vfs_getxattr(struct mnt_idmap *idmap, if (!buf) return -ENOMEM; =20 - xattr_len =3D vfs_getxattr(idmap, dentry, xattr_name, - (void *)buf, xattr_len); + xattr_len =3D vfs_getxattr(path, xattr_name, (void *)buf, xattr_len); if (xattr_len > 0) *xattr_buf =3D buf; else @@ -884,7 +875,6 @@ ssize_t ksmbd_vfs_getxattr(struct mnt_idmap *idmap, =20 /** * ksmbd_vfs_setxattr() - vfs helper for smb set extended attributes value - * @idmap: idmap of the relevant mount * @path: path of dentry to set XATTR at * @attr_name: xattr name for setxattr * @attr_value: xattr value to set @@ -894,8 +884,7 @@ ssize_t ksmbd_vfs_getxattr(struct mnt_idmap *idmap, * * Return: 0 on success, otherwise error */ -int ksmbd_vfs_setxattr(struct mnt_idmap *idmap, - const struct path *path, const char *attr_name, +int ksmbd_vfs_setxattr(const struct path *path, const char *attr_name, void *attr_value, size_t attr_size, int flags, bool get_write) { @@ -907,8 +896,7 @@ int ksmbd_vfs_setxattr(struct mnt_idmap *idmap, return err; } =20 - err =3D vfs_setxattr(idmap, - path->dentry, + err =3D vfs_setxattr(path, attr_name, attr_value, attr_size, @@ -1178,8 +1166,7 @@ int ksmbd_vfs_query_allocated_ranges(struct ksmbd_fil= e *fp, loff_t start, return ret; } =20 -int ksmbd_vfs_remove_xattr(struct mnt_idmap *idmap, - const struct path *path, char *attr_name, +int ksmbd_vfs_remove_xattr(const struct path *path, char *attr_name, bool get_write) { int err; @@ -1190,7 +1177,7 @@ int ksmbd_vfs_remove_xattr(struct mnt_idmap *idmap, return err; } =20 - err =3D vfs_removexattr(idmap, path->dentry, attr_name); + err =3D vfs_removexattr(path, attr_name); =20 if (get_write =3D=3D true) mnt_drop_write(path->mnt); @@ -1472,14 +1459,13 @@ struct dentry *ksmbd_vfs_kern_path_create(struct ks= mbd_work *work, return dent; } =20 -int ksmbd_vfs_remove_acl_xattrs(struct mnt_idmap *idmap, - const struct path *path) +int ksmbd_vfs_remove_acl_xattrs(const struct path *path) { char *name, *xattr_list =3D NULL; ssize_t xattr_list_len; int err =3D 0; =20 - xattr_list_len =3D ksmbd_vfs_listxattr(path->dentry, &xattr_list); + xattr_list_len =3D ksmbd_vfs_listxattr(path, &xattr_list); if (xattr_list_len < 0) { goto out; } else if (!xattr_list_len) { @@ -1499,7 +1485,8 @@ int ksmbd_vfs_remove_acl_xattrs(struct mnt_idmap *idm= ap, sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1) || !strncmp(name, XATTR_NAME_POSIX_ACL_DEFAULT, sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1)) { - err =3D vfs_remove_acl(idmap, path->dentry, name); + err =3D vfs_remove_acl(mnt_idmap(path->mnt), + path->dentry, name); if (err) ksmbd_debug(SMB, "remove acl xattr failed : %s\n", name); @@ -1512,13 +1499,13 @@ int ksmbd_vfs_remove_acl_xattrs(struct mnt_idmap *i= dmap, return err; } =20 -int ksmbd_vfs_remove_sd_xattrs(struct mnt_idmap *idmap, const struct path = *path) +int ksmbd_vfs_remove_sd_xattrs(const struct path *path) { char *name, *xattr_list =3D NULL; ssize_t xattr_list_len; int err =3D 0; =20 - xattr_list_len =3D ksmbd_vfs_listxattr(path->dentry, &xattr_list); + xattr_list_len =3D ksmbd_vfs_listxattr(path, &xattr_list); if (xattr_list_len < 0) { goto out; } else if (!xattr_list_len) { @@ -1531,7 +1518,7 @@ int ksmbd_vfs_remove_sd_xattrs(struct mnt_idmap *idma= p, const struct path *path) ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name)); =20 if (!strncmp(name, XATTR_NAME_SD, XATTR_NAME_SD_LEN)) { - err =3D ksmbd_vfs_remove_xattr(idmap, path, name, true); + err =3D ksmbd_vfs_remove_xattr(path, name, true); if (err) ksmbd_debug(SMB, "remove xattr failed : %s\n", name); } @@ -1607,7 +1594,6 @@ static struct xattr_smb_acl *ksmbd_vfs_make_xattr_pos= ix_acl(struct mnt_idmap *id } =20 int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, - struct mnt_idmap *idmap, const struct path *path, struct smb_ntsd *pntsd, int len, bool get_write) @@ -1618,6 +1604,7 @@ int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, struct xattr_smb_acl *smb_acl, *def_smb_acl =3D NULL; struct dentry *dentry =3D path->dentry; struct inode *inode =3D d_inode(dentry); + struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); =20 acl.version =3D 4; acl.hash_type =3D XATTR_SD_HASH_TYPE_SHA256; @@ -1659,7 +1646,7 @@ int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, goto out; } =20 - rc =3D ksmbd_vfs_setxattr(idmap, path, + rc =3D ksmbd_vfs_setxattr(path, XATTR_NAME_SD, sd_ndr.data, sd_ndr.offset, 0, get_write); if (rc < 0) @@ -1675,19 +1662,19 @@ int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, EXPORT_SYMBOL_IF_KUNIT(ksmbd_vfs_set_sd_xattr); =20 int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn, - struct mnt_idmap *idmap, - struct dentry *dentry, + const struct path *path, struct smb_ntsd **pntsd) { int rc; struct ndr n; - struct inode *inode =3D d_inode(dentry); + struct inode *inode =3D d_inode(path->dentry); struct ndr acl_ndr =3D {0}; struct xattr_ntacl acl =3D {0}; struct xattr_smb_acl *smb_acl =3D NULL, *def_smb_acl =3D NULL; + struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); __u8 cmp_hash[XATTR_SD_HASH_SIZE] =3D {0}; =20 - rc =3D ksmbd_vfs_getxattr(idmap, dentry, XATTR_NAME_SD, &n.data); + rc =3D ksmbd_vfs_getxattr(path, XATTR_NAME_SD, &n.data); if (rc <=3D 0) return rc; =20 @@ -1744,8 +1731,7 @@ int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn, return rc; } =20 -int ksmbd_vfs_set_dos_attrib_xattr(struct mnt_idmap *idmap, - const struct path *path, +int ksmbd_vfs_set_dos_attrib_xattr(const struct path *path, struct xattr_dos_attrib *da, bool get_write) { @@ -1756,7 +1742,7 @@ int ksmbd_vfs_set_dos_attrib_xattr(struct mnt_idmap *= idmap, if (err) goto out; =20 - err =3D ksmbd_vfs_setxattr(idmap, path, XATTR_NAME_DOS_ATTRIBUTE, + err =3D ksmbd_vfs_setxattr(path, XATTR_NAME_DOS_ATTRIBUTE, (void *)n.data, n.offset, 0, get_write); if (err) ksmbd_debug(SMB, "failed to store dos attribute in xattr\n"); @@ -1766,14 +1752,13 @@ int ksmbd_vfs_set_dos_attrib_xattr(struct mnt_idmap= *idmap, return err; } =20 -int ksmbd_vfs_get_dos_attrib_xattr(struct mnt_idmap *idmap, - struct dentry *dentry, +int ksmbd_vfs_get_dos_attrib_xattr(const struct path *path, struct xattr_dos_attrib *da) { struct ndr n; int err; =20 - err =3D ksmbd_vfs_getxattr(idmap, dentry, XATTR_NAME_DOS_ATTRIBUTE, + err =3D ksmbd_vfs_getxattr(path, XATTR_NAME_DOS_ATTRIBUTE, (char **)&n.data); if (err > 0) { n.length =3D err; @@ -1822,7 +1807,6 @@ void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kst= at *ksmbd_kstat) } =20 int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work, - struct mnt_idmap *idmap, struct dentry *dentry, struct ksmbd_kstat *ksmbd_kstat) { @@ -1856,7 +1840,7 @@ int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *wo= rk, KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) { struct xattr_dos_attrib da; =20 - rc =3D ksmbd_vfs_get_dos_attrib_xattr(idmap, dentry, &da); + rc =3D ksmbd_vfs_get_dos_attrib_xattr(&path, &da); if (rc > 0) { ksmbd_kstat->file_attributes =3D cpu_to_le32(da.attr); ksmbd_kstat->create_time =3D da.create_time; @@ -1879,7 +1863,7 @@ int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *wo= rk, char *xattr_list =3D NULL, *name; ssize_t xattr_list_len; =20 - xattr_list_len =3D ksmbd_vfs_listxattr(dentry, &xattr_list); + xattr_list_len =3D ksmbd_vfs_listxattr(&path, &xattr_list); if (xattr_list_len > 0) { for (name =3D xattr_list; name - xattr_list < xattr_list_len; @@ -1897,14 +1881,14 @@ int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *= work, return 0; } =20 -ssize_t ksmbd_vfs_casexattr_len(struct mnt_idmap *idmap, - struct dentry *dentry, char *attr_name, +ssize_t ksmbd_vfs_casexattr_len(const struct path *path, + char *attr_name, int attr_name_len) { char *name, *xattr_list =3D NULL; ssize_t value_len =3D -ENOENT, xattr_list_len; =20 - xattr_list_len =3D ksmbd_vfs_listxattr(dentry, &xattr_list); + xattr_list_len =3D ksmbd_vfs_listxattr(path, &xattr_list); if (xattr_list_len <=3D 0) goto out; =20 @@ -1914,7 +1898,7 @@ ssize_t ksmbd_vfs_casexattr_len(struct mnt_idmap *idm= ap, if (strncasecmp(attr_name, name, attr_name_len)) continue; =20 - value_len =3D ksmbd_vfs_xattr_len(idmap, dentry, name); + value_len =3D ksmbd_vfs_xattr_len(path, name); break; } =20 @@ -2067,8 +2051,7 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *wor= k, =20 saved_cred =3D override_creds(src_fp->filp->f_cred); src_file_size =3D ksmbd_vfs_casexattr_len( - file_mnt_idmap(src_fp->filp), - src_fp->filp->f_path.dentry, + &src_fp->filp->f_path, src_fp->stream.name, src_fp->stream.size); revert_creds(saved_cred); if (src_file_size < 0) @@ -2386,7 +2369,7 @@ static int __ksmbd_vfs_set_compression(struct ksmbd_w= ork *work, if (fp->f_ci->m_fattr !=3D old_fattr) { struct xattr_dos_attrib da =3D {0}; =20 - rc =3D ksmbd_vfs_get_dos_attrib_xattr(idmap, dentry, &da); + rc =3D ksmbd_vfs_get_dos_attrib_xattr(&fp->filp->f_path, &da); if (rc <=3D 0) { da.version =3D 4; da.itime =3D fp->itime; @@ -2397,8 +2380,7 @@ static int __ksmbd_vfs_set_compression(struct ksmbd_w= ork *work, =20 da.attr =3D le32_to_cpu(fp->f_ci->m_fattr); da.flags |=3D XATTR_DOSINFO_ATTRIB; - rc =3D ksmbd_vfs_set_dos_attrib_xattr(idmap, - &fp->filp->f_path, + rc =3D ksmbd_vfs_set_dos_attrib_xattr(&fp->filp->f_path, &da, true); if (rc) rc =3D 0; diff --git a/fs/smb/server/vfs.h b/fs/smb/server/vfs.h index 566c670c90be..a0cf77a7a2c7 100644 --- a/fs/smb/server/vfs.h +++ b/fs/smb/server/vfs.h @@ -103,27 +103,24 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *wor= k, unsigned int *chunk_count_written, unsigned int *chunk_size_written, loff_t *total_size_written); -ssize_t ksmbd_vfs_listxattr(struct dentry *dentry, char **list); -ssize_t ksmbd_vfs_getxattr(struct mnt_idmap *idmap, - struct dentry *dentry, +ssize_t ksmbd_vfs_listxattr(const struct path *path, char **list); +ssize_t ksmbd_vfs_getxattr(const struct path *path, char *xattr_name, char **xattr_buf); -ssize_t ksmbd_vfs_xattr_len(struct mnt_idmap *idmap, - struct dentry *dentry, char *xattr_name); -ssize_t ksmbd_vfs_getcasexattr(struct mnt_idmap *idmap, - struct dentry *dentry, char *attr_name, +ssize_t ksmbd_vfs_xattr_len(const struct path *path, + char *xattr_name); +ssize_t ksmbd_vfs_getcasexattr(const struct path *path, + char *attr_name, int attr_name_len, char **attr_value); -ssize_t ksmbd_vfs_casexattr_len(struct mnt_idmap *idmap, - struct dentry *dentry, char *attr_name, +ssize_t ksmbd_vfs_casexattr_len(const struct path *path, + char *attr_name, int attr_name_len); -int ksmbd_vfs_setxattr(struct mnt_idmap *idmap, - const struct path *path, const char *attr_name, +int ksmbd_vfs_setxattr(const struct path *path, const char *attr_name, void *attr_value, size_t attr_size, int flags, bool get_write); int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_nam= e, size_t *xattr_stream_name_size, int s_type); -int ksmbd_vfs_remove_xattr(struct mnt_idmap *idmap, - const struct path *path, char *attr_name, +int ksmbd_vfs_remove_xattr(const struct path *path, char *attr_name, bool get_write); int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *name, unsigned int flags, @@ -152,29 +149,23 @@ int ksmbd_vfs_query_allocated_ranges(struct ksmbd_fil= e *fp, loff_t start, int ksmbd_vfs_unlink(struct file *filp); void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat); int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work, - struct mnt_idmap *idmap, struct dentry *dentry, struct ksmbd_kstat *ksmbd_kstat); void ksmbd_vfs_posix_lock_wait(struct file_lock *flock); void ksmbd_vfs_posix_lock_unblock(struct file_lock *flock); -int ksmbd_vfs_remove_acl_xattrs(struct mnt_idmap *idmap, - const struct path *path); -int ksmbd_vfs_remove_sd_xattrs(struct mnt_idmap *idmap, const struct path = *path); +int ksmbd_vfs_remove_acl_xattrs(const struct path *path); +int ksmbd_vfs_remove_sd_xattrs(const struct path *path); int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, - struct mnt_idmap *idmap, const struct path *path, struct smb_ntsd *pntsd, int len, bool get_write); int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn, - struct mnt_idmap *idmap, - struct dentry *dentry, + const struct path *path, struct smb_ntsd **pntsd); -int ksmbd_vfs_set_dos_attrib_xattr(struct mnt_idmap *idmap, - const struct path *path, +int ksmbd_vfs_set_dos_attrib_xattr(const struct path *path, struct xattr_dos_attrib *da, bool get_write); -int ksmbd_vfs_get_dos_attrib_xattr(struct mnt_idmap *idmap, - struct dentry *dentry, +int ksmbd_vfs_get_dos_attrib_xattr(const struct path *path, struct xattr_dos_attrib *da); int ksmbd_vfs_set_init_posix_acl(struct mnt_idmap *idmap, const struct path *path); diff --git a/fs/smb/server/vfs_cache.c b/fs/smb/server/vfs_cache.c index a96b764c4db5..b5700c6f096f 100644 --- a/fs/smb/server/vfs_cache.c +++ b/fs/smb/server/vfs_cache.c @@ -538,8 +538,7 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp) const struct cred *saved_cred; =20 saved_cred =3D override_creds(filp->f_cred); - err =3D ksmbd_vfs_remove_xattr(file_mnt_idmap(filp), - &filp->f_path, + err =3D ksmbd_vfs_remove_xattr(&filp->f_path, fp->stream.name, true); revert_creds(saved_cred); diff --git a/fs/xattr.c b/fs/xattr.c index d58979115200..818d6652b6d9 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -285,8 +285,7 @@ int __vfs_setxattr_noperm(struct mnt_idmap *idmap, * __vfs_setxattr_locked - set an extended attribute while holding the ino= de * lock * - * @idmap: idmap of the mount of the target inode - * @dentry: object to perform setxattr on + * @path: object to perform setxattr on * @name: xattr name to set * @value: value to set @name to * @size: size of @value @@ -295,10 +294,12 @@ int __vfs_setxattr_noperm(struct mnt_idmap *idmap, * a delegation was broken on, NULL if none. */ int -__vfs_setxattr_locked(struct mnt_idmap *idmap, struct dentry *dentry, - const char *name, const void *value, size_t size, - int flags, struct delegated_inode *delegated_inode) +__vfs_setxattr_locked(const struct path *path, const char *name, + const void *value, size_t size, int flags, + struct delegated_inode *delegated_inode) { + struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); + struct dentry *dentry =3D path->dentry; struct inode *inode =3D dentry->d_inode; int error; =20 @@ -324,9 +325,11 @@ __vfs_setxattr_locked(struct mnt_idmap *idmap, struct = dentry *dentry, EXPORT_SYMBOL_GPL(__vfs_setxattr_locked); =20 int -vfs_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, - const char *name, const void *value, size_t size, int flags) +vfs_setxattr(const struct path *path, const char *name, const void *value, + size_t size, int flags) { + struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); + struct dentry *dentry =3D path->dentry; struct inode *inode =3D dentry->d_inode; struct delegated_inode delegated_inode =3D { }; const void *orig_value =3D value; @@ -341,7 +344,7 @@ vfs_setxattr(struct mnt_idmap *idmap, struct dentry *de= ntry, =20 retry_deleg: inode_lock(inode); - error =3D __vfs_setxattr_locked(idmap, dentry, name, value, size, + error =3D __vfs_setxattr_locked(path, name, value, size, flags, &delegated_inode); inode_unlock(inode); =20 @@ -448,9 +451,11 @@ __vfs_getxattr(struct dentry *dentry, struct inode *in= ode, const char *name, EXPORT_SYMBOL(__vfs_getxattr); =20 ssize_t -vfs_getxattr(struct mnt_idmap *idmap, struct dentry *dentry, - const char *name, void *value, size_t size) +vfs_getxattr(const struct path *path, const char *name, void *value, + size_t size) { + struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); + struct dentry *dentry =3D path->dentry; struct inode *inode =3D dentry->d_inode; int error; =20 @@ -482,12 +487,12 @@ EXPORT_SYMBOL_GPL(vfs_getxattr); =20 /** * vfs_listxattr - retrieve \0 separated list of xattr names - * @dentry: the dentry from whose inode the xattr names are retrieved + * @path: the path from whose inode the xattr names are retrieved * @list: buffer to store xattr names into * @size: size of the buffer * * This function returns the names of all xattrs associated with the - * inode of @dentry. + * inode of @path->dentry. * * Note, for legacy reasons the vfs_listxattr() function lists POSIX * ACLs as well. Since POSIX ACLs are decoupled from IOP_XATTR the @@ -503,8 +508,9 @@ EXPORT_SYMBOL_GPL(vfs_getxattr); * negative error code. */ ssize_t -vfs_listxattr(struct dentry *dentry, char *list, size_t size) +vfs_listxattr(const struct path *path, char *list, size_t size) { + struct dentry *dentry =3D path->dentry; struct inode *inode =3D d_inode(dentry); ssize_t error; =20 @@ -550,17 +556,17 @@ EXPORT_SYMBOL(__vfs_removexattr); * __vfs_removexattr_locked - set an extended attribute while holding the = inode * lock * - * @idmap: idmap of the mount of the target inode - * @dentry: object to perform setxattr on + * @path: object to perform removexattr on * @name: name of xattr to remove * @delegated_inode: on return, will contain an inode pointer that * a delegation was broken on, NULL if none. */ int -__vfs_removexattr_locked(struct mnt_idmap *idmap, - struct dentry *dentry, const char *name, +__vfs_removexattr_locked(const struct path *path, const char *name, struct delegated_inode *delegated_inode) { + struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); + struct dentry *dentry =3D path->dentry; struct inode *inode =3D dentry->d_inode; int error; =20 @@ -589,17 +595,16 @@ __vfs_removexattr_locked(struct mnt_idmap *idmap, EXPORT_SYMBOL_GPL(__vfs_removexattr_locked); =20 int -vfs_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, - const char *name) +vfs_removexattr(const struct path *path, const char *name) { + struct dentry *dentry =3D path->dentry; struct inode *inode =3D dentry->d_inode; struct delegated_inode delegated_inode =3D { }; int error; =20 retry_deleg: inode_lock(inode); - error =3D __vfs_removexattr_locked(idmap, dentry, - name, &delegated_inode); + error =3D __vfs_removexattr_locked(path, name, &delegated_inode); inode_unlock(inode); =20 if (is_delegated(&delegated_inode)) { @@ -652,14 +657,13 @@ int setxattr_copy(const char __user *name, struct ker= nel_xattr_ctx *ctx) return error; } =20 -static int do_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, - struct kernel_xattr_ctx *ctx) +static int do_setxattr(const struct path *path, struct kernel_xattr_ctx *c= tx) { if (is_posix_acl_xattr(ctx->kname->name)) - return do_set_acl(idmap, dentry, ctx->kname->name, - ctx->kvalue, ctx->size); + return do_set_acl(mnt_idmap(path->mnt), path->dentry, + ctx->kname->name, ctx->kvalue, ctx->size); =20 - return vfs_setxattr(idmap, dentry, ctx->kname->name, + return vfs_setxattr(path, ctx->kname->name, ctx->kvalue, ctx->size, ctx->flags); } =20 @@ -669,7 +673,7 @@ int file_setxattr(struct file *f, struct kernel_xattr_c= tx *ctx) =20 if (!error) { audit_file(f); - error =3D do_setxattr(file_mnt_idmap(f), f->f_path.dentry, ctx); + error =3D do_setxattr(&f->f_path, ctx); mnt_drop_write_file(f); } return error; @@ -687,7 +691,7 @@ int filename_setxattr(int dfd, struct filename *filenam= e, return error; error =3D mnt_want_write(path.mnt); if (!error) { - error =3D do_setxattr(mnt_idmap(path.mnt), path.dentry, ctx); + error =3D do_setxattr(&path, ctx); mnt_drop_write(path.mnt); } path_put(&path); @@ -787,8 +791,7 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *= , name, * Extended attribute GET operations */ static ssize_t -do_getxattr(struct mnt_idmap *idmap, struct dentry *d, - struct kernel_xattr_ctx *ctx) +do_getxattr(const struct path *path, struct kernel_xattr_ctx *ctx) { ssize_t error; char *kname =3D ctx->kname->name; @@ -803,9 +806,10 @@ do_getxattr(struct mnt_idmap *idmap, struct dentry *d, } =20 if (is_posix_acl_xattr(kname)) - error =3D do_get_acl(idmap, d, kname, kvalue, ctx->size); + error =3D do_get_acl(mnt_idmap(path->mnt), path->dentry, + kname, kvalue, ctx->size); else - error =3D vfs_getxattr(idmap, d, kname, kvalue, ctx->size); + error =3D vfs_getxattr(path, kname, kvalue, ctx->size); if (error > 0) { if (ctx->size && copy_to_user(ctx->value, kvalue, error)) error =3D -EFAULT; @@ -822,7 +826,7 @@ do_getxattr(struct mnt_idmap *idmap, struct dentry *d, ssize_t file_getxattr(struct file *f, struct kernel_xattr_ctx *ctx) { audit_file(f); - return do_getxattr(file_mnt_idmap(f), f->f_path.dentry, ctx); + return do_getxattr(&f->f_path, ctx); } =20 ssize_t filename_getxattr(int dfd, struct filename *filename, @@ -834,7 +838,7 @@ ssize_t filename_getxattr(int dfd, struct filename *fil= ename, error =3D filename_lookup(dfd, filename, lookup_flags, &path, NULL); if (error) return error; - error =3D do_getxattr(mnt_idmap(path.mnt), path.dentry, ctx); + error =3D do_getxattr(&path, ctx); path_put(&path); if (retry_estale(error, lookup_flags)) { lookup_flags |=3D LOOKUP_REVAL; @@ -925,7 +929,7 @@ SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *= , name, * Extended attribute LIST operations */ static ssize_t -listxattr(struct dentry *d, char __user *list, size_t size) +listxattr(const struct path *path, char __user *list, size_t size) { ssize_t error; char *klist =3D NULL; @@ -938,7 +942,7 @@ listxattr(struct dentry *d, char __user *list, size_t s= ize) return -ENOMEM; } =20 - error =3D vfs_listxattr(d, klist, size); + error =3D vfs_listxattr(path, klist, size); if (error > 0) { if (size && copy_to_user(list, klist, error)) error =3D -EFAULT; @@ -957,7 +961,7 @@ static ssize_t file_listxattr(struct file *f, char __user *list, size_t size) { audit_file(f); - return listxattr(f->f_path.dentry, list, size); + return listxattr(&f->f_path, list, size); } =20 static @@ -971,7 +975,7 @@ ssize_t filename_listxattr(int dfd, struct filename *fi= lename, error =3D filename_lookup(dfd, filename, lookup_flags, &path, NULL); if (error) return error; - error =3D listxattr(path.dentry, list, size); + error =3D listxattr(&path, list, size); path_put(&path); if (retry_estale(error, lookup_flags)) { lookup_flags |=3D LOOKUP_REVAL; @@ -1029,11 +1033,12 @@ SYSCALL_DEFINE3(flistxattr, int, fd, char __user *,= list, size_t, size) * Extended attribute REMOVE operations */ static long -removexattr(struct mnt_idmap *idmap, struct dentry *d, const char *name) +removexattr(const struct path *path, const char *name) { if (is_posix_acl_xattr(name)) - return vfs_remove_acl(idmap, d, name); - return vfs_removexattr(idmap, d, name); + return vfs_remove_acl(mnt_idmap(path->mnt), path->dentry, + name); + return vfs_removexattr(path, name); } =20 static int file_removexattr(struct file *f, struct xattr_name *kname) @@ -1042,8 +1047,7 @@ static int file_removexattr(struct file *f, struct xa= ttr_name *kname) =20 if (!error) { audit_file(f); - error =3D removexattr(file_mnt_idmap(f), - f->f_path.dentry, kname->name); + error =3D removexattr(&f->f_path, kname->name); mnt_drop_write_file(f); } return error; @@ -1061,7 +1065,7 @@ static int filename_removexattr(int dfd, struct filen= ame *filename, return error; error =3D mnt_want_write(path.mnt); if (!error) { - error =3D removexattr(mnt_idmap(path.mnt), path.dentry, kname->name); + error =3D removexattr(&path, kname->name); mnt_drop_write(path.mnt); } path_put(&path); diff --git a/include/linux/xattr.h b/include/linux/xattr.h index 54ac3cbc133f..85042618fd81 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h @@ -77,22 +77,22 @@ struct xattr { }; =20 ssize_t __vfs_getxattr(struct dentry *, struct inode *, const char *, void= *, size_t); -ssize_t vfs_getxattr(struct mnt_idmap *, struct dentry *, const char *, - void *, size_t); -ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size); +ssize_t vfs_getxattr(const struct path *path, const char *name, void *valu= e, + size_t size); +ssize_t vfs_listxattr(const struct path *path, char *list, size_t size); int __vfs_setxattr(struct mnt_idmap *, struct dentry *, struct inode *, const char *, const void *, size_t, int); int __vfs_setxattr_noperm(struct mnt_idmap *, struct dentry *, const char *, const void *, size_t, int); -int __vfs_setxattr_locked(struct mnt_idmap *, struct dentry *, - const char *, const void *, size_t, int, - struct delegated_inode *); -int vfs_setxattr(struct mnt_idmap *, struct dentry *, const char *, - const void *, size_t, int); +int __vfs_setxattr_locked(const struct path *path, const char *name, + const void *value, size_t size, int flags, + struct delegated_inode *delegated_inode); +int vfs_setxattr(const struct path *path, const char *name, + const void *value, size_t size, int flags); int __vfs_removexattr(struct mnt_idmap *, struct dentry *, const char *); -int __vfs_removexattr_locked(struct mnt_idmap *, struct dentry *, - const char *, struct delegated_inode *); -int vfs_removexattr(struct mnt_idmap *, struct dentry *, const char *); +int __vfs_removexattr_locked(const struct path *path, const char *name, + struct delegated_inode *delegated_inode); +int vfs_removexattr(const struct path *path, const char *name); =20 ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buff= er_size); int vfs_getxattr_alloc(struct mnt_idmap *idmap, diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/e= vm_crypto.c index 1c41af2f91a6..3d759efd3c6c 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -237,7 +237,7 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry, size_t xattr_size =3D 0; char *xattr_value =3D NULL; int error; - int size, user_space_size; + int size; bool ima_present =3D false; u64 i_version =3D 0; =20 @@ -287,12 +287,6 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry, if (size < 0) continue; =20 - user_space_size =3D vfs_getxattr(&nop_mnt_idmap, dentry, - xattr->name, NULL, 0); - if (user_space_size !=3D size) - pr_debug("file %s: xattr %s size mismatch (kernel: %d, user: %d)\n", - dentry->d_name.name, xattr->name, size, - user_space_size); error =3D 0; xattr_size =3D size; crypto_shash_update(desc, (const u8 *)xattr_value, xattr_size); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8af024fe4fb5..1d06b08f3c41 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -7168,8 +7168,8 @@ static int selinux_inode_notifysecctx(struct inode *i= node, void *ctx, u32 ctxlen */ static int selinux_inode_setsecctx(const struct path *path, void *ctx, u32= ctxlen) { - return __vfs_setxattr_locked(&nop_mnt_idmap, path->dentry, - XATTR_NAME_SELINUX, ctx, ctxlen, 0, NULL); + return __vfs_setxattr_locked(path, XATTR_NAME_SELINUX, + ctx, ctxlen, 0, NULL); } =20 static int selinux_inode_getsecctx(struct inode *inode, struct lsm_context= *cp) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index d9e9f4a52567..e517809c230d 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4980,8 +4980,8 @@ static int smack_inode_notifysecctx(struct inode *ino= de, void *ctx, u32 ctxlen) =20 static int smack_inode_setsecctx(const struct path *path, void *ctx, u32 c= txlen) { - return __vfs_setxattr_locked(&nop_mnt_idmap, path->dentry, - XATTR_NAME_SMACK, ctx, ctxlen, 0, NULL); + return __vfs_setxattr_locked(path, XATTR_NAME_SMACK, + ctx, ctxlen, 0, NULL); } =20 static int smack_inode_getsecctx(struct inode *inode, struct lsm_context *= cp) --=20 2.18.0.huawei.25 From nobody Thu Sep 24 12:09:31 2026 Received: from canpmsgout10.his.huawei.com (canpmsgout10.his.huawei.com [113.46.200.225]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F0E5B46D570; Thu, 24 Sep 2026 10:22:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.225 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245374; cv=none; b=R4ciTNTeYdpCtPy4UB4Iawgn24fLdE+rXKpj/1vLuNHORmS5v4WHQsEVfdAsTDtLQHto6p90lovQozUKzJxVDOf01dktVKQ0nLDIOjDLbBvq5eKHnwWh/7zFiQp/ny7QVVq7uCdglvSyOqQIUxt4r1zV/lIDCHWQVqGB5yzxzig= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245374; c=relaxed/simple; bh=DFGXEJWaaD6Y8LCZ/3X3mwZXj4qQQE/weRspuNxP4VU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=YdZfMfu2SmURvP0DmsN3uJLFjx4rA2xEyTv1+lI9W6E0Ujom7TYpz5xFz+7dxlyOmPJnGnAawMojSnHSefjLh+zdgB7HlNr9SSTGeI75cNIIY4w4Th4OzLvlOv5DJOQFHH/UPn1bGTtPHJsKdJMNJ4rLekpDctSoA3B8IwybNds= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=gW1nrHpe; arc=none smtp.client-ip=113.46.200.225 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="gW1nrHpe" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=b0eYkrH8lAgXwtPuD9VgCirOAiEk4KJAmS03afZ5hRo=; b=gW1nrHpe+HHlau8VCHz/eJNHKdR2CWFxFFGdqv9bRO1VaS5z/zlVm1c7MQP0K2IQ7m1cxOdBk cXUxkkerJ+JmL9copgQTYCs/f3+ujTwj02gXeQ/0eOjzq69y2QZDLieds5cwo2QyLVhMVfG0her 5S3ioKo9Q6yHQWw8Pfndeuc= Received: from mail.maildlp.com (unknown [172.19.163.127]) by canpmsgout10.his.huawei.com (SkyGuard) with ESMTPS id 4hr8jW0s9Tz1K9WY; Thu, 24 Sep 2026 18:10:39 +0800 (CST) Received: from whupemk100010.china.huawei.com (unknown [7.152.184.41]) by mail.maildlp.com (Postfix) with ESMTPS id 4297A40561; Thu, 24 Sep 2026 18:22:45 +0800 (CST) Received: from octopus.huawei.com (10.67.174.191) by whupemk100010.china.huawei.com (7.152.184.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45; Thu, 24 Sep 2026 18:22:40 +0800 From: Cai Xinchen To: , , , , , , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH RFC -next 04/12] fs: pass struct path to POSIX ACL helpers Date: Thu, 24 Sep 2026 18:48:23 +0800 Message-ID: <20260924104831.1081137-5-caixinchen1@huawei.com> X-Mailer: git-send-email 2.18.0.huawei.25 In-Reply-To: <20260924104831.1081137-1-caixinchen1@huawei.com> References: <20260924104831.1081137-1-caixinchen1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To whupemk100010.china.huawei.com (7.152.184.41) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" vfs_set_acl(), vfs_get_acl() and vfs_remove_acl() together with the do_set_acl()/do_get_acl() syscall helpers take a struct mnt_idmap and a struct dentry even though their callers either already hold a struct path 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. set_posix_acl() keeps taking the idmap and dentry as it is called from inode_operations->set_acl, which operates on a bare dentry. The security_inode_*_acl() hooks invoked from fs/posix_acl.c keep taking the idmap and dentry for now; they will be converted together with the LSM hooks themselves in separate patches. Assisted-by: opencode: glm-5.3 Signed-off-by: Cai Xinchen --- fs/ecryptfs/inode.c | 12 ++++++------ fs/internal.h | 17 ++++++++--------- fs/overlayfs/inode.c | 4 ++-- fs/overlayfs/overlayfs.h | 14 ++++++++++++-- fs/posix_acl.c | 40 ++++++++++++++++++++------------------- fs/smb/server/vfs.c | 3 +-- fs/xattr.c | 10 ++++------ include/linux/posix_acl.h | 21 +++++++++----------- 8 files changed, 63 insertions(+), 58 deletions(-) diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 3307cf13b5b4..626341ef1a99 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -1093,8 +1093,9 @@ static int ecryptfs_fileattr_set(struct mnt_idmap *id= map, static struct posix_acl *ecryptfs_get_acl(struct mnt_idmap *idmap, struct dentry *dentry, int type) { - return vfs_get_acl(idmap, ecryptfs_dentry_to_lower(dentry), - posix_acl_xattr_name(type)); + struct path lower_path =3D ecryptfs_lower_path(dentry); + + return vfs_get_acl(&lower_path, posix_acl_xattr_name(type)); } =20 static int ecryptfs_set_acl(struct mnt_idmap *idmap, @@ -1102,11 +1103,10 @@ static int ecryptfs_set_acl(struct mnt_idmap *idmap, int type) { int rc; - struct dentry *lower_dentry =3D ecryptfs_dentry_to_lower(dentry); - struct inode *lower_inode =3D d_inode(lower_dentry); + struct path lower_path =3D ecryptfs_lower_path(dentry); + struct inode *lower_inode =3D d_inode(lower_path.dentry); =20 - rc =3D vfs_set_acl(&nop_mnt_idmap, lower_dentry, - posix_acl_xattr_name(type), acl); + rc =3D vfs_set_acl(&lower_path, posix_acl_xattr_name(type), acl); if (!rc) fsstack_copy_attr_all(d_inode(dentry), lower_inode); return rc; diff --git a/fs/internal.h b/fs/internal.h index 71211ef0859f..c2088345462c 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -304,20 +304,19 @@ int import_xattr_name(struct xattr_name *kname, const= char __user *name); int may_write_xattr(struct mnt_idmap *idmap, struct inode *inode); =20 #ifdef CONFIG_FS_POSIX_ACL -int do_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, - const char *acl_name, const void *kvalue, size_t size); -ssize_t do_get_acl(struct mnt_idmap *idmap, struct dentry *dentry, - const char *acl_name, void *kvalue, size_t size); +int do_set_acl(const struct path *path, const char *acl_name, + const void *kvalue, size_t size); +ssize_t do_get_acl(const struct path *path, const char *acl_name, + void *kvalue, size_t size); #else -static inline int do_set_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name, +static inline int do_set_acl(const struct path *path, const char *acl_name, const void *kvalue, size_t size) { return -EOPNOTSUPP; } -static inline ssize_t do_get_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name, - void *kvalue, size_t size) +static inline ssize_t do_get_acl(const struct path *path, + const char *acl_name, void *kvalue, + size_t size) { return -EOPNOTSUPP; } diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 401cb8c75520..f73556d17d65 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -414,7 +414,7 @@ struct posix_acl *ovl_get_acl_path(const struct path *p= ath, if (noperm) real_acl =3D get_inode_acl(realinode, posix_acl_type(acl_name)); else - real_acl =3D vfs_get_acl(idmap, path->dentry, acl_name); + real_acl =3D vfs_get_acl(path, acl_name); if (IS_ERR_OR_NULL(real_acl)) return real_acl; =20 @@ -502,7 +502,7 @@ static int ovl_set_or_remove_acl(struct dentry *dentry,= struct inode *inode, =20 ovl_path_lower(dentry, &realpath); with_ovl_creds(dentry->d_sb) - real_acl =3D vfs_get_acl(mnt_idmap(realpath.mnt), realdentry, acl_name); + real_acl =3D vfs_get_acl(&realpath, acl_name); if (IS_ERR(real_acl)) { err =3D PTR_ERR(real_acl); goto out; diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index c13f6b2c915c..5df2adfea13d 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -366,13 +366,23 @@ static inline int ovl_removexattr(struct ovl_fs *ofs,= struct dentry *dentry, static inline int ovl_do_set_acl(struct ovl_fs *ofs, struct dentry *dentry, const char *acl_name, struct posix_acl *acl) { - return vfs_set_acl(ovl_upper_mnt_idmap(ofs), dentry, acl_name, acl); + struct path path =3D { + .mnt =3D ovl_upper_mnt(ofs), + .dentry =3D dentry, + }; + + return vfs_set_acl(&path, acl_name, acl); } =20 static inline int ovl_do_remove_acl(struct ovl_fs *ofs, struct dentry *den= try, const char *acl_name) { - return vfs_remove_acl(ovl_upper_mnt_idmap(ofs), dentry, acl_name); + struct path path =3D { + .mnt =3D ovl_upper_mnt(ofs), + .dentry =3D dentry, + }; + + return vfs_remove_acl(&path, acl_name); } =20 static inline int ovl_do_rename_rd(struct renamedata *rd) diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 18b302f94174..be1643e18a6a 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -1081,8 +1081,7 @@ static int vfs_set_acl_idmapped_mnt(struct mnt_idmap = *idmap, =20 /** * vfs_set_acl - set posix acls - * @idmap: idmap of the mount - * @dentry: the dentry based on which to set the posix acls + * @path: the path based on which to set the posix acls * @acl_name: the name of the posix acl * @kacl: the posix acls in the appropriate VFS format * @@ -1091,9 +1090,11 @@ static int vfs_set_acl_idmapped_mnt(struct mnt_idmap= *idmap, * * Return: On success 0, on error negative errno. */ -int vfs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, - const char *acl_name, struct posix_acl *kacl) +int vfs_set_acl(const struct path *path, const char *acl_name, + struct posix_acl *kacl) { + struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); + struct dentry *dentry =3D path->dentry; int acl_type; int error; struct inode *inode =3D d_inode(dentry); @@ -1159,8 +1160,7 @@ EXPORT_SYMBOL_GPL(vfs_set_acl); =20 /** * vfs_get_acl - get posix acls - * @idmap: idmap of the mount - * @dentry: the dentry based on which to retrieve the posix acls + * @path: the path based on which to retrieve the posix acls * @acl_name: the name of the posix acl * * This function retrieves @kacl from the filesystem. The caller must all @@ -1168,9 +1168,10 @@ EXPORT_SYMBOL_GPL(vfs_set_acl); * * Return: On success POSIX ACLs in VFS format, on error negative errno. */ -struct posix_acl *vfs_get_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name) +struct posix_acl *vfs_get_acl(const struct path *path, const char *acl_nam= e) { + struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); + struct dentry *dentry =3D path->dentry; struct inode *inode =3D d_inode(dentry); struct posix_acl *acl; int acl_type, error; @@ -1204,17 +1205,17 @@ EXPORT_SYMBOL_GPL(vfs_get_acl); =20 /** * vfs_remove_acl - remove posix acls - * @idmap: idmap of the mount - * @dentry: the dentry based on which to retrieve the posix acls + * @path: the path based on which to retrieve the posix acls * @acl_name: the name of the posix acl * * This function removes posix acls. * * Return: On success 0, on error negative errno. */ -int vfs_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry, - const char *acl_name) +int vfs_remove_acl(const struct path *path, const char *acl_name) { + struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); + struct dentry *dentry =3D path->dentry; int acl_type; int error; struct inode *inode =3D d_inode(dentry); @@ -1265,8 +1266,8 @@ int vfs_remove_acl(struct mnt_idmap *idmap, struct de= ntry *dentry, } EXPORT_SYMBOL_GPL(vfs_remove_acl); =20 -int do_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, - const char *acl_name, const void *kvalue, size_t size) +int do_set_acl(const struct path *path, const char *acl_name, + const void *kvalue, size_t size) { int error; struct posix_acl *acl =3D NULL; @@ -1281,22 +1282,23 @@ int do_set_acl(struct mnt_idmap *idmap, struct dent= ry *dentry, return PTR_ERR(acl); } =20 - error =3D vfs_set_acl(idmap, dentry, acl_name, acl); + error =3D vfs_set_acl(path, acl_name, acl); posix_acl_release(acl); return error; } =20 -ssize_t do_get_acl(struct mnt_idmap *idmap, struct dentry *dentry, - const char *acl_name, void *kvalue, size_t size) +ssize_t do_get_acl(const struct path *path, const char *acl_name, + void *kvalue, size_t size) { ssize_t error; struct posix_acl *acl; =20 - acl =3D vfs_get_acl(idmap, dentry, acl_name); + acl =3D vfs_get_acl(path, acl_name); if (IS_ERR(acl)) return PTR_ERR(acl); =20 - error =3D vfs_posix_acl_to_xattr(idmap, d_inode(dentry), + error =3D vfs_posix_acl_to_xattr(mnt_idmap(path->mnt), + d_inode(path->dentry), acl, kvalue, size); posix_acl_release(acl); return error; diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c index eb904cf9ef2d..97497e72fbe9 100644 --- a/fs/smb/server/vfs.c +++ b/fs/smb/server/vfs.c @@ -1485,8 +1485,7 @@ int ksmbd_vfs_remove_acl_xattrs(const struct path *pa= th) sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1) || !strncmp(name, XATTR_NAME_POSIX_ACL_DEFAULT, sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1)) { - err =3D vfs_remove_acl(mnt_idmap(path->mnt), - path->dentry, name); + err =3D vfs_remove_acl(path, name); if (err) ksmbd_debug(SMB, "remove acl xattr failed : %s\n", name); diff --git a/fs/xattr.c b/fs/xattr.c index 818d6652b6d9..ee4a5f6d7ef3 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -660,8 +660,8 @@ int setxattr_copy(const char __user *name, struct kerne= l_xattr_ctx *ctx) static int do_setxattr(const struct path *path, struct kernel_xattr_ctx *c= tx) { if (is_posix_acl_xattr(ctx->kname->name)) - return do_set_acl(mnt_idmap(path->mnt), path->dentry, - ctx->kname->name, ctx->kvalue, ctx->size); + return do_set_acl(path, ctx->kname->name, + ctx->kvalue, ctx->size); =20 return vfs_setxattr(path, ctx->kname->name, ctx->kvalue, ctx->size, ctx->flags); @@ -806,8 +806,7 @@ do_getxattr(const struct path *path, struct kernel_xatt= r_ctx *ctx) } =20 if (is_posix_acl_xattr(kname)) - error =3D do_get_acl(mnt_idmap(path->mnt), path->dentry, - kname, kvalue, ctx->size); + error =3D do_get_acl(path, kname, kvalue, ctx->size); else error =3D vfs_getxattr(path, kname, kvalue, ctx->size); if (error > 0) { @@ -1036,8 +1035,7 @@ static long removexattr(const struct path *path, const char *name) { if (is_posix_acl_xattr(name)) - return vfs_remove_acl(mnt_idmap(path->mnt), path->dentry, - name); + return vfs_remove_acl(path, name); return vfs_removexattr(path, name); } =20 diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h index 62d497763e25..384111cb6673 100644 --- a/include/linux/posix_acl.h +++ b/include/linux/posix_acl.h @@ -105,12 +105,11 @@ static inline void cache_no_acl(struct inode *inode) inode->i_default_acl =3D NULL; } =20 -int vfs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, - const char *acl_name, struct posix_acl *kacl); -struct posix_acl *vfs_get_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name); -int vfs_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry, - const char *acl_name); +int vfs_set_acl(const struct path *path, const char *acl_name, + struct posix_acl *kacl); +struct posix_acl *vfs_get_acl(const struct path *path, + const char *acl_name); +int vfs_remove_acl(const struct path *path, const char *acl_name); int posix_acl_listxattr(struct inode *inode, char **buffer, ssize_t *remaining_size); #else @@ -141,22 +140,20 @@ static inline void forget_all_cached_acls(struct inod= e *inode) { } =20 -static inline int vfs_set_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *name, +static inline int vfs_set_acl(const struct path *path, const char *name, struct posix_acl *acl) { return -EOPNOTSUPP; } =20 -static inline struct posix_acl *vfs_get_acl(struct mnt_idmap *idmap, - struct dentry *dentry, +static inline struct posix_acl *vfs_get_acl(const struct path *path, const char *acl_name) { return ERR_PTR(-EOPNOTSUPP); } =20 -static inline int vfs_remove_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name) +static inline int vfs_remove_acl(const struct path *path, + const char *acl_name) { return -EOPNOTSUPP; } --=20 2.18.0.huawei.25 From nobody Thu Sep 24 12:09:31 2026 Received: from canpmsgout10.his.huawei.com (canpmsgout10.his.huawei.com [113.46.200.225]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 97A7447276D; Thu, 24 Sep 2026 10:22:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.225 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245374; cv=none; b=PWY3HjsCLQy/j0HpuAaiBag9255gCWurhrSF3sAClj8gXo66D+j71KxT2HLigVJcKkzXBYehWpAJh8/Zu8KGxRfWncBfsrOYmLSRnXT/IwaeS2FeFLyAOKE21WWUEzhch5hRagnDf8OwClSl+iKCYyFh9pHWoVd2QI3yyumYSc0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245374; c=relaxed/simple; bh=yIWk2z7Kn6KDAbnNXADHaqW8/grBunxlSozSsJw0ERQ=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=eu1XlPez9fQV+KgxytW1fuxAY24uTaowDE6sodkqgZ8wZ0Ou+xc6SRjetgiyv6P1ESPX885Atv5OxCq+LjWc4sFLCS35/Yoq9gUFOSfZO52RNkXC0cXvQDpx0NEhAnBd7XYxcS4+TLRagUt/BI0YoHcdNw8Z2cyD+h0TxF1lQ5w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=CJb1ZQJ7; arc=none smtp.client-ip=113.46.200.225 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="CJb1ZQJ7" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=uGzOy/v4wYJC3Hqw93vd9Z+a0m25IVeEcUNy9USeD5Q=; b=CJb1ZQJ78rVItwYnP0OSDKYg2fUFIEaxqOho+5xaDHvSaWnDatSjLwQeRiPggUx2YBwlafp34 w1p7rxUxrdhqzAkFSpCHWKYk3ILyVFBQgjOXQrAMbSZYc/XK/mHVV4Y5gJKL5OX4vmAmzqQIS0m AICaIIYZxhKNs6sMLXgRXVU= Received: from mail.maildlp.com (unknown [172.19.163.214]) by canpmsgout10.his.huawei.com (SkyGuard) with ESMTPS id 4hr8jb1tRXz1K9D2; Thu, 24 Sep 2026 18:10:43 +0800 (CST) Received: from whupemk100010.china.huawei.com (unknown [7.152.184.41]) by mail.maildlp.com (Postfix) with ESMTPS id 68D0A4057C; Thu, 24 Sep 2026 18:22:49 +0800 (CST) Received: from octopus.huawei.com (10.67.174.191) by whupemk100010.china.huawei.com (7.152.184.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45; Thu, 24 Sep 2026 18:22:44 +0800 From: Cai Xinchen To: , , , , , , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH RFC -next 05/12] LSM: pass struct path to the inode_setattr hook Date: Thu, 24 Sep 2026 18:48:24 +0800 Message-ID: <20260924104831.1081137-6-caixinchen1@huawei.com> X-Mailer: git-send-email 2.18.0.huawei.25 In-Reply-To: <20260924104831.1081137-1-caixinchen1@huawei.com> References: <20260924104831.1081137-1-caixinchen1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To whupemk100010.china.huawei.com (7.152.184.41) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The inode_setattr hook is called from notify_change(), which now holds a struct path and used to derive the idmap and dentry from it just for the hook. The other in-kernel caller, the fat and exfat attribute ioctls, already holds a struct file and can pass its f_path directly. Convert the hook and its SELinux, Smack and EVM implementations to take a const struct path. The implementations derive the idmap and dentry they still need from the path, so this is a purely mechanical change with no behavior change. Assisted-by: opencode: glm-5.3 Signed-off-by: Cai Xinchen --- fs/attr.c | 2 +- fs/exfat/file.c | 3 +-- fs/fat/file.c | 3 +-- include/linux/lsm_hook_defs.h | 2 +- include/linux/security.h | 6 ++---- security/integrity/evm/evm_main.c | 7 ++++--- security/security.c | 10 ++++------ security/selinux/hooks.c | 3 ++- security/smack/smack_lsm.c | 3 ++- 9 files changed, 18 insertions(+), 21 deletions(-) diff --git a/fs/attr.c b/fs/attr.c index ea91e4471faa..f0eb4be496fc 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -537,7 +537,7 @@ int notify_change(const struct path *path, struct iattr= *attr, !vfsgid_valid(i_gid_into_vfsgid(idmap, inode))) return -EOVERFLOW; =20 - error =3D security_inode_setattr(idmap, dentry, attr); + error =3D security_inode_setattr(path, attr); if (error) return error; =20 diff --git a/fs/exfat/file.c b/fs/exfat/file.c index a2a9ee1a2004..db62a8c85d64 100644 --- a/fs/exfat/file.c +++ b/fs/exfat/file.c @@ -493,8 +493,7 @@ static int exfat_ioctl_set_attributes(struct file *file= , u32 __user *user_attr) * out the RO attribute for checking by the security * module, just because it maps to a file mode. */ - err =3D security_inode_setattr(file_mnt_idmap(file), - file->f_path.dentry, &ia); + err =3D security_inode_setattr(&file->f_path, &ia); if (err) goto out_unlock_inode; =20 diff --git a/fs/fat/file.c b/fs/fat/file.c index 6c475c53334c..c0ec05825517 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -92,8 +92,7 @@ static int fat_ioctl_set_attributes(struct file *file, u3= 2 __user *user_attr) * out the RO attribute for checking by the security * module, just because it maps to a file mode. */ - err =3D security_inode_setattr(file_mnt_idmap(file), - file->f_path.dentry, &ia); + err =3D security_inode_setattr(&file->f_path, &ia); if (err) goto out_unlock_inode; =20 diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index b22f7928523e..b54fdf7d32e8 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -142,7 +142,7 @@ LSM_HOOK(int, 0, inode_follow_link, struct dentry *dent= ry, struct inode *inode, bool rcu) LSM_HOOK(int, 0, inode_permission, struct mnt_idmap *idmap, struct inode *inode, int mask) -LSM_HOOK(int, 0, inode_setattr, struct mnt_idmap *idmap, struct dentry *de= ntry, +LSM_HOOK(int, 0, inode_setattr, const struct path *path, struct iattr *attr) LSM_HOOK(void, LSM_RET_VOID, inode_post_setattr, struct mnt_idmap *idmap, struct dentry *dentry, int ia_valid) diff --git a/include/linux/security.h b/include/linux/security.h index 6ac9fb634017..09c14c83e58f 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -429,8 +429,7 @@ int security_inode_follow_link(struct dentry *dentry, s= truct inode *inode, bool rcu); int security_inode_permission(struct mnt_idmap *idmap, struct inode *inode, int mask); -int security_inode_setattr(struct mnt_idmap *idmap, - struct dentry *dentry, struct iattr *attr); +int security_inode_setattr(const struct path *path, struct iattr *attr); void security_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *d= entry, int ia_valid); int security_inode_getattr(const struct path *path); @@ -1001,8 +1000,7 @@ static inline int security_inode_permission(struct mn= t_idmap *idmap, return 0; } =20 -static inline int security_inode_setattr(struct mnt_idmap *idmap, - struct dentry *dentry, +static inline int security_inode_setattr(const struct path *path, struct iattr *attr) { return 0; diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm= _main.c index b59e3f121b8a..b0af1bf86ab5 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -949,18 +949,19 @@ static int evm_attr_change(struct mnt_idmap *idmap, =20 /** * evm_inode_setattr - prevent updating an invalid EVM extended attribute - * @idmap: idmap of the mount - * @dentry: pointer to the affected dentry + * @path: pointer to the affected object * @attr: iattr structure containing the new file attributes * * Permit update of file attributes when files have a valid EVM signature, * except in the case of them having an immutable portable signature. */ -static int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentr= y, +static int evm_inode_setattr(const struct path *path, struct iattr *attr) { unsigned int ia_valid =3D attr->ia_valid; enum integrity_status evm_status; + struct dentry *dentry =3D path->dentry; + struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); =20 /* Policy permits modification of the protected attrs even though * there's no HMAC key loaded diff --git a/security/security.c b/security/security.c index de3ed5c18802..ce74b9f1d110 100644 --- a/security/security.c +++ b/security/security.c @@ -1891,8 +1891,7 @@ int security_inode_permission(struct mnt_idmap *idmap= , struct inode *inode, =20 /** * security_inode_setattr() - Check if setting file attributes is allowed - * @idmap: idmap of the mount - * @dentry: file + * @path: file * @attr: new attributes * * Check permission before setting file attributes. Note that the kernel = call @@ -1902,12 +1901,11 @@ int security_inode_permission(struct mnt_idmap *idm= ap, struct inode *inode, * * Return: Returns 0 if permission is granted. */ -int security_inode_setattr(struct mnt_idmap *idmap, - struct dentry *dentry, struct iattr *attr) +int security_inode_setattr(const struct path *path, struct iattr *attr) { - if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; - return call_int_hook(inode_setattr, idmap, dentry, attr); + return call_int_hook(inode_setattr, path, attr); } EXPORT_SYMBOL_GPL(security_inode_setattr); =20 diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 1d06b08f3c41..49785dd62df4 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3339,10 +3339,11 @@ static int selinux_inode_permission(struct mnt_idma= p *idmap, return rc; } =20 -static int selinux_inode_setattr(struct mnt_idmap *idmap, struct dentry *d= entry, +static int selinux_inode_setattr(const struct path *path, struct iattr *iattr) { const struct cred *cred =3D current_cred(); + struct dentry *dentry =3D path->dentry; struct inode *inode =3D d_backing_inode(dentry); unsigned int ia_valid =3D iattr->ia_valid; u32 av =3D FILE__WRITE; diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index e517809c230d..991b967c4c4e 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1272,10 +1272,11 @@ static int smack_inode_permission(struct mnt_idmap = *idmap, struct inode *inode, * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_setattr(struct mnt_idmap *idmap, struct dentry *den= try, +static int smack_inode_setattr(const struct path *path, struct iattr *iattr) { struct smk_audit_info ad; + struct dentry *dentry =3D path->dentry; int rc; =20 /* --=20 2.18.0.huawei.25 From nobody Thu Sep 24 12:09:31 2026 Received: from canpmsgout12.his.huawei.com (canpmsgout12.his.huawei.com [113.46.200.227]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 268B34734EE; Thu, 24 Sep 2026 10:22:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.227 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245379; cv=none; b=loDVoCKvn9es3EPvl1pK7dc5uiC/vHOf5cpahAKXveRdq+Z8QwecceZT2H29HDmu9dLWMpIGRmx6cbvbCsapmN7J7sn6Qo82n/SM343euUfxoor8w78LlNE1dFhJbslNwr0U7ps9DPUmgT/qjA9ABD7RUvmrATJYS08q8mcpZjk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245379; c=relaxed/simple; bh=HFIeNbCDQvHOZUpb97fVJuTD5Xfvj0xr/vLW1HLndgU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=H2yS0XM5R7CVs1MwzTIuzE3X3sbFnalDrwKPg3C1NnCVhCrsga2zvtLhU2eaGypucII5UuY+xqZ+AeDLZ16bZoaRYPQ4B7WdZL70tnVsIxiifCKRNr7pfkY9lYYyVBf0IwzMaeOFHUKto1KSwrqL+md0T3B6NwSsdw7qmLSdtrw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=izv1kzjI; arc=none smtp.client-ip=113.46.200.227 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="izv1kzjI" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=UBErxReQP/m4dnSx4/Ks3qpJsicn/oLlYlbYKKe9S+k=; b=izv1kzjIiGJXxTPwJBhi2JyZnREsN1wNLfMFHTPYK+XZt8nzP/VYr6DunF0XLIXF/P5eNOn6m G4Tel+7GUzBoANwsfB6l50yA3Eql/d3sAjTeGiX9xhYvWQDTmAaP+MMQOT6nQ38/FOAMIwtwhCE Az5bCnDi7rVBPBEl/M2fRCs= Received: from mail.maildlp.com (unknown [172.19.163.214]) by canpmsgout12.his.huawei.com (SkyGuard) with ESMTPS id 4hr8jj6BBYznTyW; Thu, 24 Sep 2026 18:10:49 +0800 (CST) Received: from whupemk100010.china.huawei.com (unknown [7.152.184.41]) by mail.maildlp.com (Postfix) with ESMTPS id 9C4354057C; Thu, 24 Sep 2026 18:22:53 +0800 (CST) Received: from octopus.huawei.com (10.67.174.191) by whupemk100010.china.huawei.com (7.152.184.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45; Thu, 24 Sep 2026 18:22:49 +0800 From: Cai Xinchen To: , , , , , , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH RFC -next 06/12] LSM: pass struct path to the inode xattr hooks Date: Thu, 24 Sep 2026 18:48:25 +0800 Message-ID: <20260924104831.1081137-7-caixinchen1@huawei.com> X-Mailer: git-send-email 2.18.0.huawei.25 In-Reply-To: <20260924104831.1081137-1-caixinchen1@huawei.com> References: <20260924104831.1081137-1-caixinchen1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To whupemk100010.china.huawei.com (7.152.184.41) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The inode_setxattr, inode_getxattr, inode_listxattr and inode_removexattr hooks are called from fs/xattr.c, whose helpers now hold a struct path and used to derive the idmap and dentry from it just for the hook calls. Convert the hooks and their commoncap, SELinux, Smack, EVM and IMA implementations to take a const struct path. The implementations derive the idmap and dentry they still need from the path, so this is a purely mechanical change with no behavior change. Assisted-by: opencode: glm-5.3 Signed-off-by: Cai Xinchen --- fs/xattr.c | 8 ++--- include/linux/lsm_hook_defs.h | 13 ++++--- include/linux/security.h | 35 +++++++++--------- security/commoncap.c | 22 +++++------- security/integrity/evm/evm_main.c | 15 ++++---- security/integrity/ima/ima_appraise.c | 9 ++--- security/security.c | 51 +++++++++++++-------------- security/selinux/hooks.c | 23 ++++++------ security/smack/smack_lsm.c | 18 +++++----- 9 files changed, 96 insertions(+), 98 deletions(-) diff --git a/fs/xattr.c b/fs/xattr.c index ee4a5f6d7ef3..7f09307d6845 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -307,7 +307,7 @@ __vfs_setxattr_locked(const struct path *path, const ch= ar *name, if (error) return error; =20 - error =3D security_inode_setxattr(idmap, dentry, name, value, size, + error =3D security_inode_setxattr(path, name, value, size, flags); if (error) goto out; @@ -463,7 +463,7 @@ vfs_getxattr(const struct path *path, const char *name,= void *value, if (error) return error; =20 - error =3D security_inode_getxattr(dentry, name); + error =3D security_inode_getxattr(path, name); if (error) return error; =20 @@ -514,7 +514,7 @@ vfs_listxattr(const struct path *path, char *list, size= _t size) struct inode *inode =3D d_inode(dentry); ssize_t error; =20 - error =3D security_inode_listxattr(dentry); + error =3D security_inode_listxattr(path); if (error) return error; =20 @@ -574,7 +574,7 @@ __vfs_removexattr_locked(const struct path *path, const= char *name, if (error) return error; =20 - error =3D security_inode_removexattr(idmap, dentry, name); + error =3D security_inode_removexattr(path, name); if (error) goto out; =20 diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index b54fdf7d32e8..3a3512a3ee91 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -148,15 +148,14 @@ LSM_HOOK(void, LSM_RET_VOID, inode_post_setattr, stru= ct mnt_idmap *idmap, struct dentry *dentry, int ia_valid) LSM_HOOK(int, 0, inode_getattr, const struct path *path) LSM_HOOK(int, 0, inode_xattr_skipcap, const char *name) -LSM_HOOK(int, 0, inode_setxattr, struct mnt_idmap *idmap, - struct dentry *dentry, const char *name, const void *value, - size_t size, int flags) +LSM_HOOK(int, 0, inode_setxattr, const struct path *path, + const char *name, const void *value, size_t size, int flags) LSM_HOOK(void, LSM_RET_VOID, inode_post_setxattr, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) -LSM_HOOK(int, 0, inode_getxattr, struct dentry *dentry, const char *name) -LSM_HOOK(int, 0, inode_listxattr, struct dentry *dentry) -LSM_HOOK(int, 0, inode_removexattr, struct mnt_idmap *idmap, - struct dentry *dentry, const char *name) +LSM_HOOK(int, 0, inode_getxattr, const struct path *path, const char *name) +LSM_HOOK(int, 0, inode_listxattr, const struct path *path) +LSM_HOOK(int, 0, inode_removexattr, const struct path *path, + const char *name) LSM_HOOK(void, LSM_RET_VOID, inode_post_removexattr, struct dentry *dentry, const char *name) LSM_HOOK(int, 0, inode_file_setattr, struct dentry *dentry, struct file_ka= ttr *fa) diff --git a/include/linux/security.h b/include/linux/security.h index 09c14c83e58f..f5dc67a937bd 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -185,10 +185,9 @@ extern int cap_capset(struct cred *new, const struct c= red *old, const kernel_cap_t *inheritable, const kernel_cap_t *permitted); extern int cap_bprm_creds_from_file(struct linux_binprm *bprm, const struc= t file *file); -int cap_inode_setxattr(struct dentry *dentry, const char *name, +int cap_inode_setxattr(const struct path *path, const char *name, const void *value, size_t size, int flags); -int cap_inode_removexattr(struct mnt_idmap *idmap, - struct dentry *dentry, const char *name); +int cap_inode_removexattr(const struct path *path, const char *name); int cap_inode_need_killpriv(struct dentry *dentry); int cap_inode_killpriv(struct mnt_idmap *idmap, struct dentry *dentry); int cap_inode_getsecurity(struct mnt_idmap *idmap, @@ -433,9 +432,9 @@ int security_inode_setattr(const struct path *path, str= uct iattr *attr); void security_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *d= entry, int ia_valid); int security_inode_getattr(const struct path *path); -int security_inode_setxattr(struct mnt_idmap *idmap, - struct dentry *dentry, const char *name, - const void *value, size_t size, int flags); +int security_inode_setxattr(const struct path *path, + const char *name, const void *value, + size_t size, int flags); int security_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name, struct posix_acl *kacl); @@ -450,10 +449,10 @@ void security_inode_post_remove_acl(struct mnt_idmap = *idmap, const char *acl_name); void security_inode_post_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); -int security_inode_getxattr(struct dentry *dentry, const char *name); -int security_inode_listxattr(struct dentry *dentry); -int security_inode_removexattr(struct mnt_idmap *idmap, - struct dentry *dentry, const char *name); +int security_inode_getxattr(const struct path *path, const char *name); +int security_inode_listxattr(const struct path *path); +int security_inode_removexattr(const struct path *path, + const char *name); void security_inode_post_removexattr(struct dentry *dentry, const char *na= me); int security_inode_file_setattr(struct dentry *dentry, struct file_kattr *fa); @@ -1016,11 +1015,10 @@ static inline int security_inode_getattr(const stru= ct path *path) return 0; } =20 -static inline int security_inode_setxattr(struct mnt_idmap *idmap, - struct dentry *dentry, const char *name, const void *value, - size_t size, int flags) +static inline int security_inode_setxattr(const struct path *path, + const char *name, const void *value, size_t size, int flags) { - return cap_inode_setxattr(dentry, name, value, size, flags); + return cap_inode_setxattr(path, name, value, size, flags); } =20 static inline int security_inode_set_acl(struct mnt_idmap *idmap, @@ -1059,22 +1057,21 @@ static inline void security_inode_post_setxattr(str= uct dentry *dentry, const char *name, const void *value, size_t size, int flags) { } =20 -static inline int security_inode_getxattr(struct dentry *dentry, +static inline int security_inode_getxattr(const struct path *path, const char *name) { return 0; } =20 -static inline int security_inode_listxattr(struct dentry *dentry) +static inline int security_inode_listxattr(const struct path *path) { return 0; } =20 -static inline int security_inode_removexattr(struct mnt_idmap *idmap, - struct dentry *dentry, +static inline int security_inode_removexattr(const struct path *path, const char *name) { - return cap_inode_removexattr(idmap, dentry, name); + return cap_inode_removexattr(path, name); } =20 static inline void security_inode_post_removexattr(struct dentry *dentry, diff --git a/security/commoncap.c b/security/commoncap.c index c5d2f263d75b..9a185a6036af 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -1007,7 +1008,7 @@ int cap_bprm_creds_from_file(struct linux_binprm *bpr= m, const struct file *file) =20 /** * cap_inode_setxattr - Determine whether an xattr may be altered - * @dentry: The inode/dentry being altered + * @path: The inode/path being altered * @name: The name of the xattr to be changed * @value: The value that the xattr will be changed to * @size: The size of value @@ -1019,9 +1020,10 @@ int cap_bprm_creds_from_file(struct linux_binprm *bp= rm, const struct file *file) * This is used to make sure security xattrs don't get updated or set by t= hose * who aren't privileged to do so. */ -int cap_inode_setxattr(struct dentry *dentry, const char *name, +int cap_inode_setxattr(const struct path *path, const char *name, const void *value, size_t size, int flags) { + struct dentry *dentry =3D path->dentry; struct user_namespace *user_ns =3D dentry->d_sb->s_user_ns; =20 /* Ignore non-security xattrs */ @@ -1044,25 +1046,18 @@ int cap_inode_setxattr(struct dentry *dentry, const= char *name, /** * cap_inode_removexattr - Determine whether an xattr may be removed * - * @idmap: idmap of the mount the inode was found from - * @dentry: The inode/dentry being altered + * @path: The inode/path being altered * @name: The name of the xattr to be changed * * Determine whether an xattr may be removed from an inode, returning 0 if * permission is granted, -ve if denied. * - * If the inode has been found through an idmapped mount the idmap of - * the vfsmount must be passed through @idmap. This function will then - * take care to map the inode according to @idmap before checking - * permissions. On non-idmapped mounts or if permission checking is to be - * performed on the raw inode simply pass @nop_mnt_idmap. - * * This is used to make sure security xattrs don't get removed by those who * aren't privileged to remove them. */ -int cap_inode_removexattr(struct mnt_idmap *idmap, - struct dentry *dentry, const char *name) +int cap_inode_removexattr(const struct path *path, const char *name) { + struct dentry *dentry =3D path->dentry; struct user_namespace *user_ns =3D dentry->d_sb->s_user_ns; =20 /* Ignore non-security xattrs */ @@ -1075,7 +1070,8 @@ int cap_inode_removexattr(struct mnt_idmap *idmap, struct inode *inode =3D d_backing_inode(dentry); if (!inode) return -EINVAL; - if (!capable_wrt_inode_uidgid(idmap, inode, CAP_SETFCAP)) + if (!capable_wrt_inode_uidgid(mnt_idmap(path->mnt), inode, + CAP_SETFCAP)) return -EPERM; return 0; } diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm= _main.c index b0af1bf86ab5..47ad39d64c76 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -594,8 +594,7 @@ static int evm_protect_xattr(struct mnt_idmap *idmap, =20 /** * evm_inode_setxattr - protect the EVM extended attribute - * @idmap: idmap of the mount - * @dentry: pointer to the affected dentry + * @path: pointer to the affected object * @xattr_name: pointer to the affected extended attribute name * @xattr_value: pointer to the new extended attribute value * @xattr_value_len: pointer to the new extended attribute value length @@ -607,11 +606,13 @@ static int evm_protect_xattr(struct mnt_idmap *idmap, * userspace from writing HMAC value. Writing 'security.evm' requires * requires CAP_SYS_ADMIN privileges. */ -static int evm_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dent= ry, +static int evm_inode_setxattr(const struct path *path, const char *xattr_name, const void *xattr_value, size_t xattr_value_len, int flags) { const struct evm_ima_xattr_data *xattr_data =3D xattr_value; + struct dentry *dentry =3D path->dentry; + struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); =20 /* Policy permits modification of the protected xattrs even though * there's no HMAC key loaded @@ -632,16 +633,18 @@ static int evm_inode_setxattr(struct mnt_idmap *idmap= , struct dentry *dentry, =20 /** * evm_inode_removexattr - protect the EVM extended attribute - * @idmap: idmap of the mount - * @dentry: pointer to the affected dentry + * @path: pointer to the affected object * @xattr_name: pointer to the affected extended attribute name * * Removing 'security.evm' requires CAP_SYS_ADMIN privileges and that * the current value is valid. */ -static int evm_inode_removexattr(struct mnt_idmap *idmap, struct dentry *d= entry, +static int evm_inode_removexattr(const struct path *path, const char *xattr_name) { + struct dentry *dentry =3D path->dentry; + struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); + /* Policy permits modification of the protected xattrs even though * there's no HMAC key loaded */ diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima= /ima_appraise.c index b280488e15fc..58ba674bc172 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -759,11 +759,12 @@ static int validate_hash_algo(struct dentry *dentry, return -EACCES; } =20 -static int ima_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dent= ry, +static int ima_inode_setxattr(const struct path *path, const char *xattr_name, const void *xattr_value, size_t xattr_value_len, int flags) { const struct evm_ima_xattr_data *xvalue =3D xattr_value; + struct dentry *dentry =3D path->dentry; int digsig =3D 0; int result; int err; @@ -801,16 +802,16 @@ static int ima_inode_set_acl(struct mnt_idmap *idmap,= struct dentry *dentry, return 0; } =20 -static int ima_inode_removexattr(struct mnt_idmap *idmap, struct dentry *d= entry, +static int ima_inode_removexattr(const struct path *path, const char *xattr_name) { int result, digsig =3D -1; =20 - result =3D ima_protect_xattr(dentry, xattr_name, NULL, 0); + result =3D ima_protect_xattr(path->dentry, xattr_name, NULL, 0); if (result =3D=3D 1 || evm_revalidate_status(xattr_name)) { if (!strcmp(xattr_name, XATTR_NAME_IMA)) digsig =3D 0; - ima_reset_appraise_flags(d_backing_inode(dentry), digsig); + ima_reset_appraise_flags(d_backing_inode(path->dentry), digsig); if (result =3D=3D 1) result =3D 0; } diff --git a/security/security.c b/security/security.c index ce74b9f1d110..3a8892d8ca5c 100644 --- a/security/security.c +++ b/security/security.c @@ -1942,15 +1942,14 @@ int security_inode_getattr(const struct path *path) =20 /** * security_inode_setxattr() - Check if setting file xattrs is allowed - * @idmap: idmap of the mount - * @dentry: file + * @path: file * @name: xattr name * @value: xattr value * @size: size of xattr value * @flags: flags * * This hook performs the desired permission checks before setting the ext= ended - * attributes (xattrs) on @dentry. It is important to note that we have s= ome + * attributes (xattrs) on @path. It is important to note that we have some * additional logic before the main LSM implementation calls to detect if = we * need to perform an additional capability check at the LSM layer. * @@ -1966,23 +1965,23 @@ int security_inode_getattr(const struct path *path) * * Return: Returns 0 if permission is granted. */ -int security_inode_setxattr(struct mnt_idmap *idmap, - struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) +int security_inode_setxattr(const struct path *path, + const char *name, const void *value, + size_t size, int flags) { int rc; =20 - if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; =20 /* enforce the capability checks at the lsm layer, if needed */ if (!call_int_hook(inode_xattr_skipcap, name)) { - rc =3D cap_inode_setxattr(dentry, name, value, size, flags); + rc =3D cap_inode_setxattr(path, name, value, size, flags); if (rc) return rc; } =20 - return call_int_hook(inode_setxattr, idmap, dentry, name, value, size, + return call_int_hook(inode_setxattr, path, name, value, size, flags); } =20 @@ -2099,45 +2098,44 @@ void security_inode_post_setxattr(struct dentry *de= ntry, const char *name, =20 /** * security_inode_getxattr() - Check if xattr access is allowed - * @dentry: file + * @path: file * @name: xattr name * * Check permission before obtaining the extended attributes identified by - * @name for @dentry. + * @name for @path. * * Return: Returns 0 if permission is granted. */ -int security_inode_getxattr(struct dentry *dentry, const char *name) +int security_inode_getxattr(const struct path *path, const char *name) { - if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; - return call_int_hook(inode_getxattr, dentry, name); + return call_int_hook(inode_getxattr, path, name); } =20 /** * security_inode_listxattr() - Check if listing xattrs is allowed - * @dentry: file + * @path: file * * Check permission before obtaining the list of extended attribute names = for - * @dentry. + * @path. * * Return: Returns 0 if permission is granted. */ -int security_inode_listxattr(struct dentry *dentry) +int security_inode_listxattr(const struct path *path) { - if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; - return call_int_hook(inode_listxattr, dentry); + return call_int_hook(inode_listxattr, path); } =20 /** * security_inode_removexattr() - Check if removing an xattr is allowed - * @idmap: idmap of the mount - * @dentry: file + * @path: file * @name: xattr name * * This hook performs the desired permission checks before setting the ext= ended - * attributes (xattrs) on @dentry. It is important to note that we have s= ome + * attributes (xattrs) on @path. It is important to note that we have some * additional logic before the main LSM implementation calls to detect if = we * need to perform an additional capability check at the LSM layer. * @@ -2153,22 +2151,21 @@ int security_inode_listxattr(struct dentry *dentry) * * Return: Returns 0 if permission is granted. */ -int security_inode_removexattr(struct mnt_idmap *idmap, - struct dentry *dentry, const char *name) +int security_inode_removexattr(const struct path *path, const char *name) { int rc; =20 - if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; =20 /* enforce the capability checks at the lsm layer, if needed */ if (!call_int_hook(inode_xattr_skipcap, name)) { - rc =3D cap_inode_removexattr(idmap, dentry, name); + rc =3D cap_inode_removexattr(path, name); if (rc) return rc; } =20 - return call_int_hook(inode_removexattr, idmap, dentry, name); + return call_int_hook(inode_removexattr, path, name); } =20 /** diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 49785dd62df4..5d98ec73df9f 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3410,10 +3410,12 @@ static int selinux_inode_xattr_skipcap(const char *= name) return !strcmp(name, XATTR_NAME_SELINUX); } =20 -static int selinux_inode_setxattr(struct mnt_idmap *idmap, - struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) +static int selinux_inode_setxattr(const struct path *path, + const char *name, const void *value, + size_t size, int flags) { + struct dentry *dentry =3D path->dentry; + struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); struct inode *inode =3D d_backing_inode(dentry); struct inode_security_struct *isec; struct superblock_security_struct *sbsec; @@ -3555,26 +3557,27 @@ static void selinux_inode_post_setxattr(struct dent= ry *dentry, const char *name, spin_unlock(&isec->lock); } =20 -static int selinux_inode_getxattr(struct dentry *dentry, const char *name) +static int selinux_inode_getxattr(const struct path *path, const char *nam= e) { const struct cred *cred =3D current_cred(); =20 - return dentry_has_perm(cred, dentry, FILE__GETATTR); + return dentry_has_perm(cred, path->dentry, FILE__GETATTR); } =20 -static int selinux_inode_listxattr(struct dentry *dentry) +static int selinux_inode_listxattr(const struct path *path) { const struct cred *cred =3D current_cred(); =20 - return dentry_has_perm(cred, dentry, FILE__GETATTR); + return dentry_has_perm(cred, path->dentry, FILE__GETATTR); } =20 -static int selinux_inode_removexattr(struct mnt_idmap *idmap, - struct dentry *dentry, const char *name) +static int selinux_inode_removexattr(const struct path *path, + const char *name) { /* if not a selinux xattr, only check the ordinary setattr perm */ if (strcmp(name, XATTR_NAME_SELINUX)) - return dentry_has_perm(current_cred(), dentry, FILE__SETATTR); + return dentry_has_perm(current_cred(), path->dentry, + FILE__SETATTR); =20 if (!selinux_initialized()) return 0; diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 991b967c4c4e..4adb2fd9cf70 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1351,11 +1351,12 @@ static int smack_inode_xattr_skipcap(const char *na= me) * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_setxattr(struct mnt_idmap *idmap, - struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) +static int smack_inode_setxattr(const struct path *path, + const char *name, const void *value, + size_t size, int flags) { struct smk_audit_info ad; + struct dentry *dentry =3D path->dentry; struct smack_known *skp; int check_priv =3D 0; int check_import =3D 0; @@ -1462,9 +1463,10 @@ static void smack_inode_post_setxattr(struct dentry = *dentry, const char *name, * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_getxattr(struct dentry *dentry, const char *name) +static int smack_inode_getxattr(const struct path *path, const char *name) { struct smk_audit_info ad; + struct dentry *dentry =3D path->dentry; int rc; =20 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); @@ -1477,19 +1479,19 @@ static int smack_inode_getxattr(struct dentry *dent= ry, const char *name) =20 /** * smack_inode_removexattr - Smack check on removexattr - * @idmap: idmap of the mount - * @dentry: the object + * @path: the object * @name: name of the attribute * * Removing the Smack attribute requires CAP_MAC_ADMIN * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_removexattr(struct mnt_idmap *idmap, - struct dentry *dentry, const char *name) +static int smack_inode_removexattr(const struct path *path, + const char *name) { struct inode_smack *isp; struct smk_audit_info ad; + struct dentry *dentry =3D path->dentry; int rc =3D 0; =20 if (strcmp(name, XATTR_NAME_SMACK) =3D=3D 0 || --=20 2.18.0.huawei.25 From nobody Thu Sep 24 12:09:31 2026 Received: from canpmsgout01.his.huawei.com (canpmsgout01.his.huawei.com [113.46.200.216]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 428DC47F3A7; Thu, 24 Sep 2026 10:23:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.216 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245390; cv=none; b=nHomG3hlNT/Sso0GzSPyOGafQsaYkMU6VcWIwp3v9qZPs+LO+/QZkel3xBIQN02W9T4fdSn9aUa/SHcCjld92PQihHbxBVowFU26AFr8AghjyjSOrGPtDhkKFYcvHi7jX0N6j9DjdU43ZBTXQ7csD0P8anHvrr93zxWjdUa2lEU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245390; c=relaxed/simple; bh=Fqwyei3Ztjb0aI6NUPVzla5NbVpe5rVaVOA85skp3wU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=kTnv+VZP43YFuuWLqehtMsd9bLbBzONlPC48THBH1XcFOov/Mo/7DMzKLzluLW9I0Zor9qxbUX7Avfc6OYmzttXN3fv7s8kHBMQHBRujaHDcGwV8k+QS4zsOt0SUlTN41mjCfMQSdaYdqwfkjvaxVk7116iIgMcjHsW8Bu3hxDE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=eCXAGTPs; arc=none smtp.client-ip=113.46.200.216 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="eCXAGTPs" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=osRFNmOAHmWZaaweGsL8Oy4pTHYwimhSKRVBH90rkrU=; b=eCXAGTPsBRQ02NpoWhxGYJ53Ht36PjuV82XOFGXjjIyISP0xwS6HUcXTy7V9AUGBZlF1c1Kil 1zT8+N0G6wxphpgD4uNM5mUuousyW4M2kkiniumyghvOF7Xcqtkge36lvYfLBzkK/e3RgwLf0a6 8v0jkoXvTtClwk4Ur0qphkE= Received: from mail.maildlp.com (unknown [172.19.162.223]) by canpmsgout01.his.huawei.com (SkyGuard) with ESMTPS id 4hr8k06RLdz1T4MG; Thu, 24 Sep 2026 18:11:04 +0800 (CST) Received: from whupemk100010.china.huawei.com (unknown [7.152.184.41]) by mail.maildlp.com (Postfix) with ESMTPS id CB17140561; Thu, 24 Sep 2026 18:22:57 +0800 (CST) Received: from octopus.huawei.com (10.67.174.191) by whupemk100010.china.huawei.com (7.152.184.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45; Thu, 24 Sep 2026 18:22:53 +0800 From: Cai Xinchen To: , , , , , , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH RFC -next 07/12] LSM: pass struct path to the inode posix acl hooks Date: Thu, 24 Sep 2026 18:48:26 +0800 Message-ID: <20260924104831.1081137-8-caixinchen1@huawei.com> X-Mailer: git-send-email 2.18.0.huawei.25 In-Reply-To: <20260924104831.1081137-1-caixinchen1@huawei.com> References: <20260924104831.1081137-1-caixinchen1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To whupemk100010.china.huawei.com (7.152.184.41) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The inode_set_acl, inode_get_acl and inode_remove_acl hooks are called from fs/posix_acl.c, whose helpers now hold a struct path and used to derive the idmap and dentry from it just for the hook calls. Convert the hooks and their SELinux, Smack, EVM and IMA implementations to take a const struct path. The implementations derive the idmap and dentry they still need from the path, so this is a purely mechanical change with no behavior change. Assisted-by: opencode: glm-5.3 Signed-off-by: Cai Xinchen --- fs/posix_acl.c | 6 ++--- include/linux/lsm_hook_defs.h | 12 ++++----- include/linux/security.h | 20 +++++---------- security/integrity/evm/evm_main.c | 14 +++++----- security/integrity/ima/ima_appraise.c | 8 +++--- security/security.c | 32 ++++++++++------------- security/selinux/hooks.c | 19 +++++++------- security/smack/smack_lsm.c | 37 ++++++++++++--------------- 8 files changed, 66 insertions(+), 82 deletions(-) diff --git a/fs/posix_acl.c b/fs/posix_acl.c index be1643e18a6a..72e77540a0e9 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -1128,7 +1128,7 @@ int vfs_set_acl(const struct path *path, const char *= acl_name, if (error) goto out_inode_unlock; =20 - error =3D security_inode_set_acl(idmap, dentry, acl_name, kacl); + error =3D security_inode_set_acl(path, acl_name, kacl); if (error) goto out_inode_unlock; =20 @@ -1184,7 +1184,7 @@ struct posix_acl *vfs_get_acl(const struct path *path= , const char *acl_name) * The VFS has no restrictions on reading POSIX ACLs so calling * something like xattr_permission() isn't needed. Only LSMs get a say. */ - error =3D security_inode_get_acl(idmap, dentry, acl_name); + error =3D security_inode_get_acl(path, acl_name); if (error) return ERR_PTR(error); =20 @@ -1236,7 +1236,7 @@ int vfs_remove_acl(const struct path *path, const cha= r *acl_name) if (error) goto out_inode_unlock; =20 - error =3D security_inode_remove_acl(idmap, dentry, acl_name); + error =3D security_inode_remove_acl(path, acl_name); if (error) goto out_inode_unlock; =20 diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 3a3512a3ee91..45cf0ca24260 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -160,14 +160,14 @@ LSM_HOOK(void, LSM_RET_VOID, inode_post_removexattr, = struct dentry *dentry, const char *name) LSM_HOOK(int, 0, inode_file_setattr, struct dentry *dentry, struct file_ka= ttr *fa) LSM_HOOK(int, 0, inode_file_getattr, struct dentry *dentry, struct file_ka= ttr *fa) -LSM_HOOK(int, 0, inode_set_acl, struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name, struct posix_acl *kacl) +LSM_HOOK(int, 0, inode_set_acl, const struct path *path, + const char *acl_name, struct posix_acl *kacl) LSM_HOOK(void, LSM_RET_VOID, inode_post_set_acl, struct dentry *dentry, const char *acl_name, struct posix_acl *kacl) -LSM_HOOK(int, 0, inode_get_acl, struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name) -LSM_HOOK(int, 0, inode_remove_acl, struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name) +LSM_HOOK(int, 0, inode_get_acl, const struct path *path, + const char *acl_name) +LSM_HOOK(int, 0, inode_remove_acl, const struct path *path, + const char *acl_name) LSM_HOOK(void, LSM_RET_VOID, inode_post_remove_acl, struct mnt_idmap *idma= p, struct dentry *dentry, const char *acl_name) LSM_HOOK(int, 0, inode_need_killpriv, struct dentry *dentry) diff --git a/include/linux/security.h b/include/linux/security.h index f5dc67a937bd..8b02b3bfe46d 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -435,15 +435,12 @@ int security_inode_getattr(const struct path *path); int security_inode_setxattr(const struct path *path, const char *name, const void *value, size_t size, int flags); -int security_inode_set_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name, - struct posix_acl *kacl); +int security_inode_set_acl(const struct path *path, + const char *acl_name, struct posix_acl *kacl); void security_inode_post_set_acl(struct dentry *dentry, const char *acl_na= me, struct posix_acl *kacl); -int security_inode_get_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name); -int security_inode_remove_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name); +int security_inode_get_acl(const struct path *path, const char *acl_name); +int security_inode_remove_acl(const struct path *path, const char *acl_nam= e); void security_inode_post_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name); @@ -1021,8 +1018,7 @@ static inline int security_inode_setxattr(const struc= t path *path, return cap_inode_setxattr(path, name, value, size, flags); } =20 -static inline int security_inode_set_acl(struct mnt_idmap *idmap, - struct dentry *dentry, +static inline int security_inode_set_acl(const struct path *path, const char *acl_name, struct posix_acl *kacl) { @@ -1034,15 +1030,13 @@ static inline void security_inode_post_set_acl(stru= ct dentry *dentry, struct posix_acl *kacl) { } =20 -static inline int security_inode_get_acl(struct mnt_idmap *idmap, - struct dentry *dentry, +static inline int security_inode_get_acl(const struct path *path, const char *acl_name) { return 0; } =20 -static inline int security_inode_remove_acl(struct mnt_idmap *idmap, - struct dentry *dentry, +static inline int security_inode_remove_acl(const struct path *path, const char *acl_name) { return 0; diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm= _main.c index 47ad39d64c76..c83befd32e99 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -685,8 +685,7 @@ static inline int evm_inode_set_acl_change(struct mnt_i= dmap *idmap, =20 /** * evm_inode_set_acl - protect the EVM extended attribute from posix acls - * @idmap: idmap of the idmapped mount - * @dentry: pointer to the affected dentry + * @path: pointer to the affected object * @acl_name: name of the posix acl * @kacl: pointer to the posix acls * @@ -696,10 +695,12 @@ static inline int evm_inode_set_acl_change(struct mnt= _idmap *idmap, * * Return: zero on success, -EPERM on failure. */ -static int evm_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentr= y, +static int evm_inode_set_acl(const struct path *path, const char *acl_name, struct posix_acl *kacl) { enum integrity_status evm_status; + struct dentry *dentry =3D path->dentry; + struct mnt_idmap *idmap =3D mnt_idmap(path->mnt); =20 /* Policy permits modification of the protected xattrs even though * there's no HMAC key loaded @@ -738,8 +739,7 @@ static int evm_inode_set_acl(struct mnt_idmap *idmap, s= truct dentry *dentry, =20 /** * evm_inode_remove_acl - Protect the EVM extended attribute from posix ac= ls - * @idmap: idmap of the mount - * @dentry: pointer to the affected dentry + * @path: pointer to the affected object * @acl_name: name of the posix acl * * Prevent removing posix acls causing the EVM HMAC to be re-calculated @@ -748,10 +748,10 @@ static int evm_inode_set_acl(struct mnt_idmap *idmap,= struct dentry *dentry, * * Return: zero on success, -EPERM on failure. */ -static int evm_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *de= ntry, +static int evm_inode_remove_acl(const struct path *path, const char *acl_name) { - return evm_inode_set_acl(idmap, dentry, acl_name, NULL); + return evm_inode_set_acl(path, acl_name, NULL); } =20 static void evm_reset_status(struct inode *inode) diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima= /ima_appraise.c index 58ba674bc172..518faf04ddde 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -793,11 +793,11 @@ static int ima_inode_setxattr(const struct path *path, return result; } =20 -static int ima_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentr= y, +static int ima_inode_set_acl(const struct path *path, const char *acl_name, struct posix_acl *kacl) { if (evm_revalidate_status(acl_name)) - ima_reset_appraise_flags(d_backing_inode(dentry), -1); + ima_reset_appraise_flags(d_backing_inode(path->dentry), -1); =20 return 0; } @@ -818,10 +818,10 @@ static int ima_inode_removexattr(const struct path *p= ath, return result; } =20 -static int ima_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *de= ntry, +static int ima_inode_remove_acl(const struct path *path, const char *acl_name) { - return ima_inode_set_acl(idmap, dentry, acl_name, NULL); + return ima_inode_set_acl(path, acl_name, NULL); } =20 static struct security_hook_list ima_appraise_hooks[] __ro_after_init =3D { diff --git a/security/security.c b/security/security.c index 3a8892d8ca5c..74bcd8c0502c 100644 --- a/security/security.c +++ b/security/security.c @@ -1987,8 +1987,7 @@ int security_inode_setxattr(const struct path *path, =20 /** * security_inode_set_acl() - Check if setting posix acls is allowed - * @idmap: idmap of the mount - * @dentry: file + * @path: file * @acl_name: acl name * @kacl: acl struct * @@ -1997,13 +1996,12 @@ int security_inode_setxattr(const struct path *path, * * Return: Returns 0 if permission is granted. */ -int security_inode_set_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name, - struct posix_acl *kacl) +int security_inode_set_acl(const struct path *path, + const char *acl_name, struct posix_acl *kacl) { - if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; - return call_int_hook(inode_set_acl, idmap, dentry, acl_name, kacl); + return call_int_hook(inode_set_acl, path, acl_name, kacl); } =20 /** @@ -2025,8 +2023,7 @@ void security_inode_post_set_acl(struct dentry *dentr= y, const char *acl_name, =20 /** * security_inode_get_acl() - Check if reading posix acls is allowed - * @idmap: idmap of the mount - * @dentry: file + * @path: file * @acl_name: acl name * * Check permission before getting osix acls, the posix acls are identifie= d by @@ -2034,18 +2031,16 @@ void security_inode_post_set_acl(struct dentry *den= try, const char *acl_name, * * Return: Returns 0 if permission is granted. */ -int security_inode_get_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name) +int security_inode_get_acl(const struct path *path, const char *acl_name) { - if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; - return call_int_hook(inode_get_acl, idmap, dentry, acl_name); + return call_int_hook(inode_get_acl, path, acl_name); } =20 /** * security_inode_remove_acl() - Check if removing a posix acl is allowed - * @idmap: idmap of the mount - * @dentry: file + * @path: file * @acl_name: acl name * * Check permission before removing posix acls, the posix acls are identif= ied @@ -2053,12 +2048,11 @@ int security_inode_get_acl(struct mnt_idmap *idmap, * * Return: Returns 0 if permission is granted. */ -int security_inode_remove_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name) +int security_inode_remove_acl(const struct path *path, const char *acl_nam= e) { - if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; - return call_int_hook(inode_remove_acl, idmap, dentry, acl_name); + return call_int_hook(inode_remove_acl, path, acl_name); } =20 /** diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5d98ec73df9f..45ece734463e 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3498,23 +3498,22 @@ static int selinux_inode_setxattr(const struct path= *path, &ad); } =20 -static int selinux_inode_set_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name, - struct posix_acl *kacl) +static int selinux_inode_set_acl(const struct path *path, + const char *acl_name, struct posix_acl *kacl) { - return dentry_has_perm(current_cred(), dentry, FILE__SETATTR); + return dentry_has_perm(current_cred(), path->dentry, FILE__SETATTR); } =20 -static int selinux_inode_get_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name) +static int selinux_inode_get_acl(const struct path *path, + const char *acl_name) { - return dentry_has_perm(current_cred(), dentry, FILE__GETATTR); + return dentry_has_perm(current_cred(), path->dentry, FILE__GETATTR); } =20 -static int selinux_inode_remove_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name) +static int selinux_inode_remove_acl(const struct path *path, + const char *acl_name) { - return dentry_has_perm(current_cred(), dentry, FILE__SETATTR); + return dentry_has_perm(current_cred(), path->dentry, FILE__SETATTR); } =20 static void selinux_inode_post_setxattr(struct dentry *dentry, const char = *name, diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 4adb2fd9cf70..7889f63ec739 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1548,62 +1548,59 @@ static int smack_inode_removexattr(const struct pat= h *path, * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_set_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name, - struct posix_acl *kacl) +static int smack_inode_set_acl(const struct path *path, + const char *acl_name, struct posix_acl *kacl) { struct smk_audit_info ad; int rc; =20 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); - smk_ad_setfield_u_fs_path_dentry(&ad, dentry); + smk_ad_setfield_u_fs_path_dentry(&ad, path->dentry); =20 - rc =3D smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_WRITE, &ad); - rc =3D smk_bu_inode(d_backing_inode(dentry), MAY_WRITE, rc); + rc =3D smk_curacc(smk_of_inode(d_backing_inode(path->dentry)), MAY_WRITE,= &ad); + rc =3D smk_bu_inode(d_backing_inode(path->dentry), MAY_WRITE, rc); return rc; } =20 /** * smack_inode_get_acl - Smack check for getting posix acls - * @idmap: idmap of the mnt this request came from - * @dentry: the object + * @path: the object * @acl_name: name of the posix acl * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_get_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name) +static int smack_inode_get_acl(const struct path *path, + const char *acl_name) { struct smk_audit_info ad; int rc; =20 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); - smk_ad_setfield_u_fs_path_dentry(&ad, dentry); + smk_ad_setfield_u_fs_path_dentry(&ad, path->dentry); =20 - rc =3D smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_READ, &ad); - rc =3D smk_bu_inode(d_backing_inode(dentry), MAY_READ, rc); + rc =3D smk_curacc(smk_of_inode(d_backing_inode(path->dentry)), MAY_READ, = &ad); + rc =3D smk_bu_inode(d_backing_inode(path->dentry), MAY_READ, rc); return rc; } =20 /** * smack_inode_remove_acl - Smack check for getting posix acls - * @idmap: idmap of the mnt this request came from - * @dentry: the object + * @path: the object * @acl_name: name of the posix acl * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_remove_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name) +static int smack_inode_remove_acl(const struct path *path, + const char *acl_name) { struct smk_audit_info ad; int rc; =20 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); - smk_ad_setfield_u_fs_path_dentry(&ad, dentry); + smk_ad_setfield_u_fs_path_dentry(&ad, path->dentry); =20 - rc =3D smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_WRITE, &ad); - rc =3D smk_bu_inode(d_backing_inode(dentry), MAY_WRITE, rc); + rc =3D smk_curacc(smk_of_inode(d_backing_inode(path->dentry)), MAY_WRITE,= &ad); + rc =3D smk_bu_inode(d_backing_inode(path->dentry), MAY_WRITE, rc); return rc; } =20 --=20 2.18.0.huawei.25 From nobody Thu Sep 24 12:09:31 2026 Received: from canpmsgout11.his.huawei.com (canpmsgout11.his.huawei.com [113.46.200.226]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1F6A74749CB; Thu, 24 Sep 2026 10:23:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.226 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245393; cv=none; b=EzgLuf+5nLKbHEGKWqVjzr56LyWek0FACYpMgAeFgNfp5N2FB6fqRsxxk9m6viXmX5VTqTnOrre/HAdBvTvqECyDeYwxXLLiICVDJip1oSzbl40PypaGWc/lELlz82gcT3MNnXaD96/ih4Z/LfDEOZcWAHd4Qj9f5P1gFyaXndI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245393; c=relaxed/simple; bh=VeWUWRSnBxHKKDcRUQ550bHJrpkTNvy2BtO+ZCcCH18=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=IjqwZKFZeWtMKlCWAms/ByKzM0NC6yM/L2EKEKsnAf8TwN9kSsHpuGEEtrjrBbksJQwP8mTrUjWxn+ywkINGtKc8eel+6XHTh/gpXSysGEy3msS6AuglKei8T3ySHfP74VOF+iBix5xKrALWi9MwKSjZvKBwf70L+1t3KyoJEuE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=gBApezkF; arc=none smtp.client-ip=113.46.200.226 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="gBApezkF" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=ZwaDNZNV6bX2xJkx/JZuqpyIL+4SAOfyAuv9CJN8pY0=; b=gBApezkF4n1I6Dvzs8V8RqXpFsrsvYgGFheQ98U34b/kt9tSLvkq4jWjWQJbWwqbp7Yh3cOph kqRtXNnJ3WC4k4JSC7BD7geHHNFNr5BpMcdo2yotihr9e7FPze9onTj4wN85fCps7+/pFJLRW/d FENCCFz1puiVjql+cAWaoBI= Received: from mail.maildlp.com (unknown [172.19.163.163]) by canpmsgout11.his.huawei.com (SkyGuard) with ESMTPS id 4hr8ky578lzKm5t; Thu, 24 Sep 2026 18:11:54 +0800 (CST) Received: from whupemk100010.china.huawei.com (unknown [7.152.184.41]) by mail.maildlp.com (Postfix) with ESMTPS id 0468D4048B; Thu, 24 Sep 2026 18:23:02 +0800 (CST) Received: from octopus.huawei.com (10.67.174.191) by whupemk100010.china.huawei.com (7.152.184.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45; Thu, 24 Sep 2026 18:22:57 +0800 From: Cai Xinchen To: , , , , , , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH RFC -next 08/12] landlock: Add READ_METADATA and WRITE_METADATA access rights Date: Thu, 24 Sep 2026 18:48:27 +0800 Message-ID: <20260924104831.1081137-9-caixinchen1@huawei.com> X-Mailer: git-send-email 2.18.0.huawei.25 In-Reply-To: <20260924104831.1081137-1-caixinchen1@huawei.com> References: <20260924104831.1081137-1-caixinchen1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To whupemk100010.china.huawei.com (7.152.184.41) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add two new filesystem access rights to control file metadata access: - LANDLOCK_ACCESS_FS_READ_METADATA: Read file or directory metadata (e.g. inode attributes, extended attributes and POSIX ACLs) through stat(2), fstat(2), lstat(2), newfstatat(2), getxattr(2) and friends, listxattr(2) and friends, and the POSIX ACL read operations. - LANDLOCK_ACCESS_FS_WRITE_METADATA: Change file or directory metadata through chmod(2) and friends, chown(2) and friends, utimensat(2) and friends, setxattr(2) and friends, removexattr(2) and friends, and the POSIX ACL set and remove operations. This follows the coarse-grained grouping approach discussed in the mailing list [1], where file metadata operations are grouped by security relevance rather than by individual syscall. Remove stat(2), chmod(2), chown(2), setxattr(2) and utime(2) from the list of file-related actions that cannot be restricted yet, and add the names of the new rights to _LANDLOCK_ACCESS_FS_NAMES in include/linux/landlock.h, which is shared by audit records and trace events, so that denied accesses can be reported with a human-readable name and the static assertion on fs_access_strings in security/landlock/audit.c stays valid. Increment the Landlock ABI version from 11 to 12, and update the ABI version check in tools/testing/selftests/landlock/base_test.c accordingly. [1] https://lore.kernel.org/all/abc960a1-e66e-792e-6869-cfd201c29dbe@digikod.ne= t/ Assisted-by: opencode: glm-5.3 Signed-off-by: Cai Xinchen --- include/linux/landlock.h | 4 ++- include/uapi/linux/landlock.h | 26 +++++++++++++++++--- security/landlock/limits.h | 2 +- security/landlock/syscalls.c | 2 +- tools/testing/selftests/landlock/base_test.c | 2 +- 5 files changed, 28 insertions(+), 8 deletions(-) diff --git a/include/linux/landlock.h b/include/linux/landlock.h index 004cbd0b9298..86fc2181ab24 100644 --- a/include/linux/landlock.h +++ b/include/linux/landlock.h @@ -39,7 +39,9 @@ _LANDLOCK_NAME_ENTRY(LANDLOCK_ACCESS_FS_REFER, "refer"), \ _LANDLOCK_NAME_ENTRY(LANDLOCK_ACCESS_FS_TRUNCATE, "truncate"), \ _LANDLOCK_NAME_ENTRY(LANDLOCK_ACCESS_FS_IOCTL_DEV, "ioctl_dev"), \ - _LANDLOCK_NAME_ENTRY(LANDLOCK_ACCESS_FS_RESOLVE_UNIX, "resolve_unix") + _LANDLOCK_NAME_ENTRY(LANDLOCK_ACCESS_FS_RESOLVE_UNIX, "resolve_unix"), \ + _LANDLOCK_NAME_ENTRY(LANDLOCK_ACCESS_FS_READ_METADATA, "read_metadata"), \ + _LANDLOCK_NAME_ENTRY(LANDLOCK_ACCESS_FS_WRITE_METADATA, "write_metadata") =20 #define _LANDLOCK_ACCESS_NET_NAMES \ _LANDLOCK_NAME_ENTRY(LANDLOCK_ACCESS_NET_BIND_TCP, "bind_tcp"), \ diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h index cceda3b3b961..40d64e8b5e2d 100644 --- a/include/uapi/linux/landlock.h +++ b/include/uapi/linux/landlock.h @@ -343,6 +343,24 @@ struct landlock_net_port_attr { * * The rationale for this design is described in * :ref:`Documentation/security/landlock.rst `. + * - %LANDLOCK_ACCESS_FS_READ_METADATA: Read file or directory metadata (e= .g. + * inode attributes, extended attributes, and POSIX ACLs) through + * :manpage:`stat(2)`, :manpage:`fstat(2)`, :manpage:`lstat(2)`, + * :manpage:`newfstatat(2)`, :manpage:`getxattr(2)`, and + * :manpage:`listxattr(2)`. + * + * This access right is available since the twelfth version of the Landl= ock + * ABI. + * - %LANDLOCK_ACCESS_FS_WRITE_METADATA: Change file or directory metadata + * (e.g. inode attributes, extended attributes, and POSIX ACLs) through + * :manpage:`chmod(2)`, :manpage:`chown(2)`, :manpage:`utimensat(2)`, + * :manpage:`setxattr(2)`, and :manpage:`removexattr(2)`, as well as rel= ated + * system calls. Implicit metadata changes performed by the kernel (e.g. + * timestamp updates with :manpage:`write(2)`) are not restricted by this + * access right. + * + * This access right is available since the twelfth version of the Landl= ock + * ABI. * * Whether an opened file can be truncated with :manpage:`ftruncate(2)` or= used * with `ioctl(2)` is determined during :manpage:`open(2)`, in the same wa= y as @@ -406,10 +424,8 @@ struct landlock_net_port_attr { * .. warning:: * * It is currently not possible to restrict some file-related actions - * accessible through these syscall families: :manpage:`chdir(2)`, - * :manpage:`stat(2)`, :manpage:`flock(2)`, :manpage:`chmod(2)`, - * :manpage:`chown(2)`, :manpage:`setxattr(2)`, :manpage:`utime(2)`, - * :manpage:`fcntl(2)`, :manpage:`access(2)`. + * accessible through these syscall families: :manpage:`chdir(2)', + * :manpage:`flock(2)', :manpage:`fcntl(2)', :manpage:`access(2)'. * Future Landlock evolutions will enable to restrict them. */ /* clang-format off */ @@ -430,6 +446,8 @@ struct landlock_net_port_attr { #define LANDLOCK_ACCESS_FS_TRUNCATE (1ULL << 14) #define LANDLOCK_ACCESS_FS_IOCTL_DEV (1ULL << 15) #define LANDLOCK_ACCESS_FS_RESOLVE_UNIX (1ULL << 16) +#define LANDLOCK_ACCESS_FS_READ_METADATA (1ULL << 17) +#define LANDLOCK_ACCESS_FS_WRITE_METADATA (1ULL << 18) /* clang-format on */ =20 /** diff --git a/security/landlock/limits.h b/security/landlock/limits.h index 1a7c5fb8f6fd..665ff238bd27 100644 --- a/security/landlock/limits.h +++ b/security/landlock/limits.h @@ -19,7 +19,7 @@ #define LANDLOCK_MAX_NUM_LAYERS 16 #define LANDLOCK_MAX_NUM_RULES U32_MAX =20 -#define LANDLOCK_LAST_ACCESS_FS LANDLOCK_ACCESS_FS_RESOLVE_UNIX +#define LANDLOCK_LAST_ACCESS_FS LANDLOCK_ACCESS_FS_WRITE_METADATA #define LANDLOCK_MASK_ACCESS_FS ((LANDLOCK_LAST_ACCESS_FS << 1) - 1) #define LANDLOCK_NUM_ACCESS_FS __const_hweight64(LANDLOCK_MASK_ACCESS_FS) =20 diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c index 400a2f928de3..205d64c534d7 100644 --- a/security/landlock/syscalls.c +++ b/security/landlock/syscalls.c @@ -172,7 +172,7 @@ static const struct file_operations ruleset_fops =3D { * If the change involves a fix that requires userspace awareness, also up= date * the errata documentation in Documentation/userspace-api/landlock.rst . */ -const int landlock_abi_version =3D 11; +const int landlock_abi_version =3D 12; =20 /** * sys_landlock_create_ruleset - Create a new ruleset diff --git a/tools/testing/selftests/landlock/base_test.c b/tools/testing/s= elftests/landlock/base_test.c index d20ab8f0862c..58fe322d8637 100644 --- a/tools/testing/selftests/landlock/base_test.c +++ b/tools/testing/selftests/landlock/base_test.c @@ -76,7 +76,7 @@ TEST(abi_version) const struct landlock_ruleset_attr ruleset_attr =3D { .handled_access_fs =3D LANDLOCK_ACCESS_FS_READ_FILE, }; - ASSERT_EQ(11, landlock_create_ruleset(NULL, 0, + ASSERT_EQ(12, landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION)); =20 ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0, --=20 2.18.0.huawei.25 From nobody Thu Sep 24 12:09:31 2026 Received: from canpmsgout12.his.huawei.com (canpmsgout12.his.huawei.com [113.46.200.227]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B294A47F3C8; Thu, 24 Sep 2026 10:23:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.227 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245391; cv=none; b=CV5uDKGTf21FK0Wo2lgEIs0oOBKhC3eCOryMOIhvOCEqZE8Bist+ew2LGkZjvmmT8Nm+CvBW1cnQa1+UOS76vdk6ArqVkT3EUnBCUNvsbujOvZMMhCdHH52xd3gb88MERIqAWpTjops2FaLZ+lUw5GEpuP/aZmKsAnGA+vYUpNM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245391; c=relaxed/simple; bh=kPZ7kSV7h3PbnyJjDNNBC436auNtiwgx9wgf/yL9eBo=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=MU/5PQyA+mUf80KUpmf3Ses/QJqyKteEFmaBcRODcwbEWgD1pKJYavTfOSS0D3Dp/lRFgeIP/QS52CkM7dAERIRzLku7B4dzpIHfnWBLfPWjC1NXMkOxLlO3cxfBvDp3Pn1Jr9Tf3HHzJjXSp+06g+9Qg+qFR6mX0zfFzTpvMV4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=bdk57RtK; arc=none smtp.client-ip=113.46.200.227 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="bdk57RtK" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=MZ1uULpIvXaxZi3vnTnjSUlgREhcBScDIx/J/VNziJE=; b=bdk57RtKGpe9cc8Vfy/o2gf5H3AWR8a+RFsoHm5d5onmfgOclSgOsrhdppbEitCUN6xgu8ge6 DQeuQ4gFZ4HrCpMrIuI3gn0gBtlCeW2M/DmCuPVoGCU1taKQuI8DSUpd5WFkfC62yoSSNVFUPzW Pj3wUTGhX9E3HOZpaTHWrBo= Received: from mail.maildlp.com (unknown [172.19.163.127]) by canpmsgout12.his.huawei.com (SkyGuard) with ESMTPS id 4hr8jy2yXtznTWP; Thu, 24 Sep 2026 18:11:02 +0800 (CST) Received: from whupemk100010.china.huawei.com (unknown [7.152.184.41]) by mail.maildlp.com (Postfix) with ESMTPS id 375CC40561; Thu, 24 Sep 2026 18:23:06 +0800 (CST) Received: from octopus.huawei.com (10.67.174.191) by whupemk100010.china.huawei.com (7.152.184.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45; Thu, 24 Sep 2026 18:23:01 +0800 From: Cai Xinchen To: , , , , , , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH RFC -next 09/12] landlock: Implement metadata access hooks Date: Thu, 24 Sep 2026 18:48:28 +0800 Message-ID: <20260924104831.1081137-10-caixinchen1@huawei.com> X-Mailer: git-send-email 2.18.0.huawei.25 In-Reply-To: <20260924104831.1081137-1-caixinchen1@huawei.com> References: <20260924104831.1081137-1-caixinchen1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To whupemk100010.china.huawei.com (7.152.184.41) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement the LANDLOCK_ACCESS_FS_READ_METADATA and LANDLOCK_ACCESS_FS_WRITE_METADATA access rights by hooking the inode_getattr, inode_setattr, inode_setxattr, inode_getxattr, inode_listxattr, inode_removexattr, inode_set_acl, inode_get_acl and inode_remove_acl LSM hooks, which now receive a struct path thanks to the preceding VFS and LSM refactoring. The following system calls are now controlled: - stat(2), fstat(2), lstat(2), newfstatat(2), getxattr(2) and friends, listxattr(2) and friends, and POSIX ACL reads via inode_getattr, inode_getxattr, inode_listxattr and inode_get_acl (READ_METADATA) - chmod(2), fchmod(2), fchmodat(2), fchmodat2(2), chown(2), fchown(2), lchown(2), fchownat(2), chgrp(2), utimensat(2), futimens(2), utime(2), setxattr(2) and friends, removexattr(2) and friends, and POSIX ACL set and remove via inode_setattr, inode_setxattr, inode_removexattr, inode_set_acl and inode_remove_acl (WRITE_METADATA) Both new rights are added to ACCESS_FILE as they apply to both files and directories. hook_inode_setattr only restricts explicit metadata changes, i.e. it checks WRITE_METADATA only when the ia_valid mask contains ATTR_MODE, ATTR_UID, ATTR_GID, ATTR_TIMES_SET or ATTR_TOUCH. Metadata changes that the kernel performs implicitly, such as timestamp updates on write(2) or size changes on truncate(2), are therefore not restricted, and neither are chmod(2)/chown(2) calls that do not change any attribute (e.g. chown(2) with -1/-1, which is a no-op that never reaches the hook), matching the behavior of the SELinux inode_setattr hook. Kernel-internal accesses performed with override_creds() (e.g. overlayfs and cachefiles) are not affected because Landlock domains are attached to credentials, and kernel threads without a Landlock domain (e.g. nfsd and ksmbd) are not restricted either. Assisted-by: opencode: glm-5.3 Signed-off-by: Cai Xinchen --- security/landlock/fs.c | 86 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/security/landlock/fs.c b/security/landlock/fs.c index cab43892ec2f..e58b2aa0da65 100644 --- a/security/landlock/fs.c +++ b/security/landlock/fs.c @@ -318,6 +318,8 @@ static struct landlock_object *get_inode_object(struct = inode *const inode) LANDLOCK_ACCESS_FS_EXECUTE | \ LANDLOCK_ACCESS_FS_WRITE_FILE | \ LANDLOCK_ACCESS_FS_READ_FILE | \ + LANDLOCK_ACCESS_FS_READ_METADATA | \ + LANDLOCK_ACCESS_FS_WRITE_METADATA | \ LANDLOCK_ACCESS_FS_TRUNCATE | \ LANDLOCK_ACCESS_FS_IOCTL_DEV | \ LANDLOCK_ACCESS_FS_RESOLVE_UNIX) @@ -1676,6 +1678,81 @@ static int hook_path_truncate(const struct path *con= st path) return current_check_access_path(path, LANDLOCK_ACCESS_FS_TRUNCATE); } =20 +static int hook_inode_getattr(const struct path *const path) +{ + return current_check_access_path(path, + LANDLOCK_ACCESS_FS_READ_METADATA); +} + +static int hook_inode_setattr(const struct path *const path, + struct iattr *const attr) +{ + /* + * Explicit metadata changes (i.e. mode, ownership, and timestamps + * set with utimes() and friends) require + * LANDLOCK_ACCESS_FS_WRITE_METADATA. Implicit timestamp updates + * (e.g. ATTR_CTIME set for a write) and size changes (handled by + * the truncate hooks) are not restricted. + */ + if (!(attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | + ATTR_TIMES_SET | ATTR_TOUCH))) + return 0; + + return current_check_access_path(path, + LANDLOCK_ACCESS_FS_WRITE_METADATA); +} + +static int hook_inode_setxattr(const struct path *const path, + const char *const name, + const void *const value, const size_t size, + const int flags) +{ + return current_check_access_path(path, + LANDLOCK_ACCESS_FS_WRITE_METADATA); +} + +static int hook_inode_getxattr(const struct path *const path, + const char *const name) +{ + return current_check_access_path(path, + LANDLOCK_ACCESS_FS_READ_METADATA); +} + +static int hook_inode_listxattr(const struct path *const path) +{ + return current_check_access_path(path, + LANDLOCK_ACCESS_FS_READ_METADATA); +} + +static int hook_inode_removexattr(const struct path *const path, + const char *const name) +{ + return current_check_access_path(path, + LANDLOCK_ACCESS_FS_WRITE_METADATA); +} + +static int hook_inode_set_acl(const struct path *const path, + const char *const acl_name, + struct posix_acl *const kacl) +{ + return current_check_access_path(path, + LANDLOCK_ACCESS_FS_WRITE_METADATA); +} + +static int hook_inode_get_acl(const struct path *const path, + const char *const acl_name) +{ + return current_check_access_path(path, + LANDLOCK_ACCESS_FS_READ_METADATA); +} + +static int hook_inode_remove_acl(const struct path *const path, + const char *const acl_name) +{ + return current_check_access_path(path, + LANDLOCK_ACCESS_FS_WRITE_METADATA); +} + /** * unmask_scoped_access - Remove access right bits in @masks in all layers * where @client and @server have the same domain @@ -2100,6 +2177,15 @@ static struct security_hook_list landlock_hooks[] __= ro_after_init =3D { LSM_HOOK_INIT(path_unlink, hook_path_unlink), LSM_HOOK_INIT(path_rmdir, hook_path_rmdir), LSM_HOOK_INIT(path_truncate, hook_path_truncate), + LSM_HOOK_INIT(inode_getattr, hook_inode_getattr), + LSM_HOOK_INIT(inode_setattr, hook_inode_setattr), + LSM_HOOK_INIT(inode_setxattr, hook_inode_setxattr), + LSM_HOOK_INIT(inode_getxattr, hook_inode_getxattr), + LSM_HOOK_INIT(inode_listxattr, hook_inode_listxattr), + LSM_HOOK_INIT(inode_removexattr, hook_inode_removexattr), + LSM_HOOK_INIT(inode_set_acl, hook_inode_set_acl), + LSM_HOOK_INIT(inode_get_acl, hook_inode_get_acl), + LSM_HOOK_INIT(inode_remove_acl, hook_inode_remove_acl), LSM_HOOK_INIT(unix_find, hook_unix_find), =20 LSM_HOOK_INIT(file_alloc_security, hook_file_alloc_security), --=20 2.18.0.huawei.25 From nobody Thu Sep 24 12:09:31 2026 Received: from canpmsgout01.his.huawei.com (canpmsgout01.his.huawei.com [113.46.200.216]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C8803480DD3; Thu, 24 Sep 2026 10:23:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.216 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245397; cv=none; b=CzDs1upO7rQbc/wTVngj//7BIaZi8QhFCuuGvwQwdb3bmc3yL7LdHx+EMyxQWiFz99bLEO6RHqcQINviBJqPP6Eg2naZl96kF6Dbq8XWWWYXmaCLKGbxBho/I8LmHGrEJszE1L2Oc7ltkgeJwDqxj3FMJAgGBEm6sNpiWc7a5XM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245397; c=relaxed/simple; bh=+J9wF9Lwfej7v+EFr/M72Wad5q0IN8ZD20vz7sYauA8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=AI9NvB9Xjl6TRngeyP2sba5eSda0INmkXIeUv8Ldym4cYuhC/2nEojGjAO68ZJQeaM/7uyvqfbJSusWdpHRvVWo1lC/0jMWQLZ1S6mfGe4SxR++zwU/JvDKl0jtATxYlDmUZe+tnBglYE+3RBYe/7yHQuPXY6yxHajeecwmHQWU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=OSEgd3wT; arc=none smtp.client-ip=113.46.200.216 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="OSEgd3wT" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=8DKf2xUAPJdFv62WusOE155ZXr5hz4ClWmqJjmuEvrM=; b=OSEgd3wTTC9H3Bg/fwH6mgbUPq7QleGKyp7CnGhY5pEPAsAzLMw+cpov82lIQpBgTgdOAExFM W27uMrhIIRBmXzModDQeGZ0M8zORvTlCpf4H5oXTbGvlQeuu+fuqhc8/UWePrvpcPkV2JfmLZcX loEouL1qBf21RS7PXeeVZ6I= Received: from mail.maildlp.com (unknown [172.19.163.104]) by canpmsgout01.his.huawei.com (SkyGuard) with ESMTPS id 4hr8kF3MwKz1T4MQ; Thu, 24 Sep 2026 18:11:17 +0800 (CST) Received: from whupemk100010.china.huawei.com (unknown [7.152.184.41]) by mail.maildlp.com (Postfix) with ESMTPS id 68CE34057F; Thu, 24 Sep 2026 18:23:10 +0800 (CST) Received: from octopus.huawei.com (10.67.174.191) by whupemk100010.china.huawei.com (7.152.184.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45; Thu, 24 Sep 2026 18:23:05 +0800 From: Cai Xinchen To: , , , , , , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH RFC -next 10/12] selftests/landlock: Add tests for metadata access rights Date: Thu, 24 Sep 2026 18:48:29 +0800 Message-ID: <20260924104831.1081137-11-caixinchen1@huawei.com> X-Mailer: git-send-email 2.18.0.huawei.25 In-Reply-To: <20260924104831.1081137-1-caixinchen1@huawei.com> References: <20260924104831.1081137-1-caixinchen1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To whupemk100010.china.huawei.com (7.152.184.41) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add layout1 tests for the LANDLOCK_ACCESS_FS_READ_METADATA and LANDLOCK_ACCESS_FS_WRITE_METADATA access rights: - unhandled_metadata: metadata access is allowed when the new rights are not handled by the ruleset; - write_metadata: chmod(2), fchmod(2), chown(2), fchown(2), lchown(2), utimensat(2) (both with explicit times and with UTIME_NOW), setxattr(2), and removexattr(2) are denied with EACCES without WRITE_METADATA, and allowed with it. Writing to a file (which triggers implicit timestamp updates) stays allowed without WRITE_METADATA; - read_metadata: stat(2), fstat(2), getxattr(2), and listxattr(2) are denied with EACCES without READ_METADATA, and allowed with it. Rule enforcement is checked per file and per directory. chown(2) is tested with a group change because chown(2) with (-1, -1) is a no-op that is not visible to the inode_setattr hook. Update the ACCESS_FILE and ACCESS_LAST definitions to include the new rights. Assisted-by: opencode: glm-5.3 Signed-off-by: Cai Xinchen --- tools/testing/selftests/landlock/fs_test.c | 309 ++++++++++++++++++++- 1 file changed, 308 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/sel= ftests/landlock/fs_test.c index fd20a2b3c0a5..a3e764cc56d5 100644 --- a/tools/testing/selftests/landlock/fs_test.c +++ b/tools/testing/selftests/landlock/fs_test.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include =20 @@ -578,11 +579,13 @@ TEST_F_FORK(layout1, inval) LANDLOCK_ACCESS_FS_EXECUTE | \ LANDLOCK_ACCESS_FS_WRITE_FILE | \ LANDLOCK_ACCESS_FS_READ_FILE | \ + LANDLOCK_ACCESS_FS_READ_METADATA | \ + LANDLOCK_ACCESS_FS_WRITE_METADATA | \ LANDLOCK_ACCESS_FS_TRUNCATE | \ LANDLOCK_ACCESS_FS_IOCTL_DEV | \ LANDLOCK_ACCESS_FS_RESOLVE_UNIX) =20 -#define ACCESS_LAST LANDLOCK_ACCESS_FS_RESOLVE_UNIX +#define ACCESS_LAST LANDLOCK_ACCESS_FS_WRITE_METADATA =20 #define ACCESS_ALL ( \ ACCESS_FILE | \ @@ -10923,4 +10926,308 @@ TEST_F(trace_layout1, check_rule_fs_empty_grant) free(buf); } =20 +/* Invokes chmod(2) and returns its errno or 0. */ +static int test_chmod(const char *const path, mode_t mode) +{ + if (chmod(path, mode) < 0) + return errno; + return 0; +} + +/* Invokes fchmod(2) and returns its errno or 0. */ +static int test_fchmod(int fd, mode_t mode) +{ + if (fchmod(fd, mode) < 0) + return errno; + return 0; +} + +/* Invokes chown(2) and returns its errno or 0. */ +static int test_chown(const char *const path, uid_t uid, gid_t gid) +{ + if (chown(path, uid, gid) < 0) + return errno; + return 0; +} + +/* Invokes fchown(2) and returns its errno or 0. */ +static int test_fchown(int fd, uid_t uid, gid_t gid) +{ + if (fchown(fd, uid, gid) < 0) + return errno; + return 0; +} + +/* Invokes lchown(2) and returns its errno or 0. */ +static int test_lchown(const char *const path, uid_t uid, gid_t gid) +{ + if (lchown(path, uid, gid) < 0) + return errno; + return 0; +} + +/* Invokes utimensat(2) with explicit times and returns its errno or 0. */ +static int test_utimensat(const char *const path) +{ + const struct timespec times[] =3D { + { + .tv_sec =3D 0, + .tv_nsec =3D UTIME_OMIT, + }, + { + .tv_sec =3D 1, + .tv_nsec =3D 0, + }, + }; + + if (utimensat(AT_FDCWD, path, times, 0) < 0) + return errno; + return 0; +} + +/* Invokes utimensat(2) with UTIME_NOW and returns its errno or 0. */ +static int test_utimensat_now(const char *const path) +{ + if (utimensat(AT_FDCWD, path, NULL, 0) < 0) + return errno; + return 0; +} + +/* Invokes setxattr(2) and returns its errno or 0. */ +static int test_setxattr(const char *const path, const char *const name, + const void *const value, const size_t size) +{ + if (setxattr(path, name, value, size, 0) < 0) + return errno; + return 0; +} + +/* Invokes getxattr(2) and returns its errno or 0. */ +static int test_getxattr(const char *const path, const char *const name, + void *const value, const size_t size) +{ + if (getxattr(path, name, value, size) < 0) + return errno; + return 0; +} + +/* Invokes listxattr(2) and returns its errno or 0. */ +static int test_listxattr(const char *const path, void *const list, + const size_t size) +{ + if (listxattr(path, list, size) < 0) + return errno; + return 0; +} + +/* Invokes removexattr(2) and returns its errno or 0. */ +static int test_removexattr(const char *const path, const char *const name) +{ + if (removexattr(path, name) < 0) + return errno; + return 0; +} + +/* Invokes stat(2) and returns its errno or 0. */ +static int test_stat(const char *const path, struct stat *statbuf) +{ + if (stat(path, statbuf) < 0) + return errno; + return 0; +} + +/* Invokes fstat(2) and returns its errno or 0. */ +static int test_fstat(int fd, struct stat *statbuf) +{ + if (fstat(fd, statbuf) < 0) + return errno; + return 0; +} + +TEST_F_FORK(layout1, unhandled_metadata) +{ + int file_fd; + int ruleset_fd; + const char *const file1 =3D file1_s1d1; + const char *const file2 =3D file2_s1d1; + const char *const dir1 =3D dir_s1d1; + struct stat statbuf; + const struct rule rules[] =3D { + { + .path =3D file1, + .access =3D LANDLOCK_ACCESS_FS_WRITE_FILE, + }, + { + .path =3D file2, + .access =3D LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE, + }, + { + .path =3D dir1, + .access =3D ACCESS_RW, + }, + {}, + }; + + /* + * READ_METADATA and WRITE_METADATA are not handled, so metadata + * access should be allowed. + */ + ruleset_fd =3D create_ruleset(_metadata, ACCESS_RW, rules); + ASSERT_LE(0, ruleset_fd); + file_fd =3D open(file1, O_WRONLY | O_CLOEXEC); + ASSERT_LE(0, file_fd); + + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + EXPECT_EQ(0, test_chmod(file1, 0644)); + EXPECT_EQ(0, test_fchmod(file_fd, 0644)); + EXPECT_EQ(0, test_chmod(file2, 0400)); + EXPECT_EQ(0, test_chmod(dir1, 0700)); + + EXPECT_EQ(0, test_chown(file1, -1, 0)); + EXPECT_EQ(0, test_fchown(file_fd, -1, 0)); + EXPECT_EQ(0, test_lchown(file1, -1, 0)); + + EXPECT_EQ(0, test_utimensat(file1)); + EXPECT_EQ(0, test_utimensat_now(file1)); + + EXPECT_EQ(0, test_setxattr(file1, "user.test", "a", 1)); + EXPECT_EQ(0, test_getxattr(file1, "user.test", NULL, 0)); + EXPECT_EQ(0, test_listxattr(file1, NULL, 0)); + EXPECT_EQ(0, test_removexattr(file1, "user.test")); + + EXPECT_EQ(0, test_stat(file1, &statbuf)); + EXPECT_EQ(0, test_fstat(file_fd, &statbuf)); + EXPECT_EQ(0, test_stat(dir1, &statbuf)); + + ASSERT_EQ(0, close(file_fd)); +} + +TEST_F_FORK(layout1, write_metadata) +{ + int file_fd, file2_fd; + int ruleset_fd; + const char *const file1 =3D file1_s1d1; + const char *const file2 =3D file2_s1d1; + const char *const dir1 =3D dir_s1d1; + const struct rule rules[] =3D { + { + .path =3D file1, + .access =3D LANDLOCK_ACCESS_FS_WRITE_FILE | + LANDLOCK_ACCESS_FS_WRITE_METADATA, + }, + { + .path =3D file2, + .access =3D LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE, + }, + { + .path =3D dir1, + .access =3D ACCESS_RW, + }, + {}, + }; + + ruleset_fd =3D create_ruleset(_metadata, ACCESS_RW | + LANDLOCK_ACCESS_FS_WRITE_METADATA, rules); + ASSERT_LE(0, ruleset_fd); + file_fd =3D open(file1, O_WRONLY | O_CLOEXEC); + ASSERT_LE(0, file_fd); + file2_fd =3D open(file2, O_WRONLY | O_CLOEXEC); + ASSERT_LE(0, file2_fd); + + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + /* file1 has WRITE_METADATA: allowed */ + EXPECT_EQ(0, test_chmod(file1, 0644)); + EXPECT_EQ(0, test_fchmod(file_fd, 0644)); + EXPECT_EQ(0, test_chown(file1, -1, 0)); + EXPECT_EQ(0, test_fchown(file_fd, -1, 0)); + EXPECT_EQ(0, test_lchown(file1, -1, 0)); + EXPECT_EQ(0, test_utimensat(file1)); + EXPECT_EQ(0, test_utimensat_now(file1)); + EXPECT_EQ(0, test_setxattr(file1, "user.test", "a", 1)); + EXPECT_EQ(0, test_removexattr(file1, "user.test")); + + /* + * Writing is not an explicit metadata change: implicit timestamp + * updates are allowed without WRITE_METADATA. + */ + EXPECT_EQ(1, write(file2_fd, "a", 1)); + + /* file2 does not have WRITE_METADATA: denied */ + EXPECT_EQ(EACCES, test_chmod(file2, 0400)); + EXPECT_EQ(EACCES, test_chown(file2, -1, 0)); + EXPECT_EQ(EACCES, test_lchown(file2, -1, 0)); + EXPECT_EQ(EACCES, test_utimensat(file2)); + EXPECT_EQ(EACCES, test_utimensat_now(file2)); + EXPECT_EQ(EACCES, test_setxattr(file2, "user.test", "a", 1)); + EXPECT_EQ(EACCES, test_removexattr(file2, "user.test")); + + /* dir1 does not have WRITE_METADATA: denied */ + EXPECT_EQ(EACCES, test_chmod(dir1, 0700)); + EXPECT_EQ(EACCES, test_chown(dir1, -1, 0)); + + ASSERT_EQ(0, close(file_fd)); + ASSERT_EQ(0, close(file2_fd)); +} + +TEST_F_FORK(layout1, read_metadata) +{ + int file_fd; + int ruleset_fd; + const char *const file1 =3D file1_s1d1; + const char *const file2 =3D file2_s1d1; + const char *const dir1 =3D dir_s1d1; + struct stat statbuf; + const struct rule rules[] =3D { + { + .path =3D file1, + .access =3D LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_READ_METADATA, + }, + { + .path =3D file2, + .access =3D LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE, + }, + { + .path =3D dir1, + .access =3D ACCESS_RW, + }, + {}, + }; + + ruleset_fd =3D create_ruleset(_metadata, ACCESS_RW | + LANDLOCK_ACCESS_FS_READ_METADATA, rules); + ASSERT_LE(0, ruleset_fd); + + ASSERT_EQ(0, setxattr(file1, "user.test", "a", 1, 0)); + ASSERT_EQ(0, setxattr(file2, "user.test", "a", 1, 0)); + + file_fd =3D open(file1, O_RDONLY | O_CLOEXEC); + ASSERT_LE(0, file_fd); + + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + /* file1 has READ_METADATA: allowed */ + EXPECT_EQ(0, test_stat(file1, &statbuf)); + EXPECT_EQ(0, test_fstat(file_fd, &statbuf)); + EXPECT_EQ(0, test_getxattr(file1, "user.test", NULL, 0)); + EXPECT_EQ(0, test_listxattr(file1, NULL, 0)); + + /* file2 does not have READ_METADATA: denied */ + EXPECT_EQ(EACCES, test_stat(file2, &statbuf)); + EXPECT_EQ(EACCES, test_getxattr(file2, "user.test", NULL, 0)); + EXPECT_EQ(EACCES, test_listxattr(file2, NULL, 0)); + /* dir1 does not have READ_METADATA: denied */ + EXPECT_EQ(EACCES, test_stat(dir1, &statbuf)); + + ASSERT_EQ(0, close(file_fd)); +} + TEST_HARNESS_MAIN --=20 2.18.0.huawei.25 From nobody Thu Sep 24 12:09:31 2026 Received: from canpmsgout09.his.huawei.com (canpmsgout09.his.huawei.com [113.46.200.224]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E6C55483823; Thu, 24 Sep 2026 10:23:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.224 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245406; cv=none; b=OpZuNxumm8ZX/jY88Ce9KFZTE76mnv8v0BJbcq8n1P6VJm1+5izeQKsJDfpyXK5DjhTzTQ3xs90RTztpbjQy6s+Md/ZQb8OIBHGL4o6LdBX2wk0+vXOTa/TabH8/qkBbS3ARkfa0FM0Cng0JGOJfobTB+YqKcCaCb65C2aPa7ro= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245406; c=relaxed/simple; bh=Ma+7vQ49a/OV6U+OzRcoEE2UvhGUYJLDvCh/irabEzA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=H6ENKPumIsdz8rG2F/uogr4K1d9+wq1TDkcUC6q1fJ3h5GumXoPi9YjUjUcK8KqyNz1tGthMjIxEQycq23Zq9Rb1wBOMOjMrX3DWYkEYdt6scH9R0+4v+4PJ9D9MyGVH2QC8Es8ej8G6JzZoXf8k0JGb9gSUesC5CEmX3NaFsV8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=3G0G2bcn; arc=none smtp.client-ip=113.46.200.224 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="3G0G2bcn" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=s454HcCeb+dSDfnoAkpf7M/xsIsKD5YvOJGrwmLEfrI=; b=3G0G2bcnL+mWyuOQ4kleYffDy7gL7uqE8/bVI772g7BFvep7BMkvVhmGU+42CLzJ8b5AULFs4 TPEBJ1wZWwHng+pNUNprsSIT0TO9rBlEU+YGOTXKbKcnruSDqmXfNld+v+Eto6U6FVfxjheUXkS 9ZOMdH13EA6QSRkos5mOux4= Received: from mail.maildlp.com (unknown [172.19.163.214]) by canpmsgout09.his.huawei.com (SkyGuard) with ESMTPS id 4hr8lH4XQmz1cyVb; Thu, 24 Sep 2026 18:12:11 +0800 (CST) Received: from whupemk100010.china.huawei.com (unknown [7.152.184.41]) by mail.maildlp.com (Postfix) with ESMTPS id 94BE04057C; Thu, 24 Sep 2026 18:23:14 +0800 (CST) Received: from octopus.huawei.com (10.67.174.191) by whupemk100010.china.huawei.com (7.152.184.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45; Thu, 24 Sep 2026 18:23:10 +0800 From: Cai Xinchen To: , , , , , , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH RFC -next 11/12] samples/landlock: Add metadata rights to sandboxer Date: Thu, 24 Sep 2026 18:48:30 +0800 Message-ID: <20260924104831.1081137-12-caixinchen1@huawei.com> X-Mailer: git-send-email 2.18.0.huawei.25 In-Reply-To: <20260924104831.1081137-1-caixinchen1@huawei.com> References: <20260924104831.1081137-1-caixinchen1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To whupemk100010.china.huawei.com (7.152.184.41) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Handle the new LANDLOCK_ACCESS_FS_READ_METADATA and LANDLOCK_ACCESS_FS_WRITE_METADATA access rights in the sandboxer: READ_METADATA is added to the read-only set, WRITE_METADATA to the read-write set, and both to ACCESS_FILE. Update the ABI version fallback switch to remove the metadata rights for ABI < 12, and bump LANDLOCK_ABI_LAST to 12. Assisted-by: opencode: glm-5.3 Signed-off-by: Cai Xinchen --- samples/landlock/sandboxer.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/samples/landlock/sandboxer.c b/samples/landlock/sandboxer.c index 030583273f3f..1a77a675f654 100644 --- a/samples/landlock/sandboxer.c +++ b/samples/landlock/sandboxer.c @@ -115,6 +115,8 @@ static int parse_path(char *env_path, const char ***con= st path_list) LANDLOCK_ACCESS_FS_EXECUTE | \ LANDLOCK_ACCESS_FS_WRITE_FILE | \ LANDLOCK_ACCESS_FS_READ_FILE | \ + LANDLOCK_ACCESS_FS_READ_METADATA | \ + LANDLOCK_ACCESS_FS_WRITE_METADATA | \ LANDLOCK_ACCESS_FS_TRUNCATE | \ LANDLOCK_ACCESS_FS_IOCTL_DEV | \ LANDLOCK_ACCESS_FS_RESOLVE_UNIX) @@ -286,7 +288,8 @@ static bool check_ruleset_scope(const char *const env_v= ar, #define ACCESS_FS_ROUGHLY_READ ( \ LANDLOCK_ACCESS_FS_EXECUTE | \ LANDLOCK_ACCESS_FS_READ_FILE | \ - LANDLOCK_ACCESS_FS_READ_DIR) + LANDLOCK_ACCESS_FS_READ_DIR | \ + LANDLOCK_ACCESS_FS_READ_METADATA) =20 #define ACCESS_FS_ROUGHLY_WRITE ( \ LANDLOCK_ACCESS_FS_WRITE_FILE | \ @@ -302,7 +305,8 @@ static bool check_ruleset_scope(const char *const env_v= ar, LANDLOCK_ACCESS_FS_REFER | \ LANDLOCK_ACCESS_FS_TRUNCATE | \ LANDLOCK_ACCESS_FS_IOCTL_DEV | \ - LANDLOCK_ACCESS_FS_RESOLVE_UNIX) + LANDLOCK_ACCESS_FS_RESOLVE_UNIX | \ + LANDLOCK_ACCESS_FS_WRITE_METADATA) =20 /* clang-format on */ =20 @@ -369,7 +373,7 @@ static int add_quiet_access(const char *const env_var, return 0; } =20 -#define LANDLOCK_ABI_LAST 11 +#define LANDLOCK_ABI_LAST 12 =20 #define XSTR(s) #s #define STR(s) XSTR(s) @@ -552,7 +556,12 @@ int main(const int argc, char *const argv[], char *con= st *const envp) supported_restrict_flags &=3D ~LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS; set_restrict_flags &=3D ~LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS; - + __attribute__((fallthrough)); + case 11: + /* Removes metadata rights for ABI < 12 */ + ruleset_attr.handled_access_fs &=3D + ~(LANDLOCK_ACCESS_FS_READ_METADATA | + LANDLOCK_ACCESS_FS_WRITE_METADATA); /* Must be printed for any ABI < LANDLOCK_ABI_LAST. */ fprintf(stderr, "Hint: You should update the running kernel " --=20 2.18.0.huawei.25 From nobody Thu Sep 24 12:09:31 2026 Received: from canpmsgout09.his.huawei.com (canpmsgout09.his.huawei.com [113.46.200.224]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C861D471408; Thu, 24 Sep 2026 10:23:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.224 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245410; cv=none; b=LTgZPvkeN30iMar9Af9nLKyjrXU5eH1JtmU0w9d0ub0wFiC42DB2R+KOgAR3p3PF8gThJJkUXlGdg/+QQqLJgFN27vRXa91Rp1rzS3UveM21pVh8FOhALQQwiYgk6gJHT7paOwVQqHfJBqx1AQ5Nh4E1AL74wSgBN2ua3+GufCg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790245410; c=relaxed/simple; bh=N9GNT5Gr77tnZpa1DIFKdP6tlc1V/iDCYmqnSrwJd4M=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ZBdF5QZ4BvHzjcyQFfMtjg4F9ch2JTA/RYD6T8xrgPwaLG5W78hl/GpRBquLhG8jTcHAGSmZDXGjTd8im3bp2yvt1ElkYAkpe1OzTHUa2AVnaabvCvvv61UN6IvQGg+rEILcF02v7RBPrKXVJXIt5Bjz0XO2xmhUTaFnXRmVmYw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=KojgF+/C; arc=none smtp.client-ip=113.46.200.224 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="KojgF+/C" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=WplCFr0Ls1VpRS9r4EdhOkQGGZvquUDe0yNKbhY/NCY=; b=KojgF+/CS9kWlkRdNlF4xuRQ5V2F3k2F35yAWV4kuAlG5XZVUZIVOkLhqZC9+Fw+ibeb6Xuxz wFGRVGNp/ebDt4Ncc3JLEUvjx1y/flsc3RltibM0z6jU4VDvmIsIlJFHfoHKT7GXRM3IWlraVyc pHCciaYm2G1G4Z9Sf1aw0Mo= Received: from mail.maildlp.com (unknown [172.19.163.214]) by canpmsgout09.his.huawei.com (SkyGuard) with ESMTPS id 4hr8lM6LmWz1cyPY; Thu, 24 Sep 2026 18:12:15 +0800 (CST) Received: from whupemk100010.china.huawei.com (unknown [7.152.184.41]) by mail.maildlp.com (Postfix) with ESMTPS id D49BB4057C; Thu, 24 Sep 2026 18:23:18 +0800 (CST) Received: from octopus.huawei.com (10.67.174.191) by whupemk100010.china.huawei.com (7.152.184.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45; Thu, 24 Sep 2026 18:23:14 +0800 From: Cai Xinchen To: , , , , , , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH RFC -next 12/12] Documentation: Update landlock doc for metadata rights Date: Thu, 24 Sep 2026 18:48:31 +0800 Message-ID: <20260924104831.1081137-13-caixinchen1@huawei.com> X-Mailer: git-send-email 2.18.0.huawei.25 In-Reply-To: <20260924104831.1081137-1-caixinchen1@huawei.com> References: <20260924104831.1081137-1-caixinchen1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To whupemk100010.china.huawei.com (7.152.184.41) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Update the user space documentation to include the new LANDLOCK_ACCESS_FS_READ_METADATA and LANDLOCK_ACCESS_FS_WRITE_METADATA access rights in the example ruleset attributes, and extend the ABI version fallback switch to remove them for ABI < 12. Assisted-by: opencode: glm-5.3 Signed-off-by: Cai Xinchen --- Documentation/userspace-api/landlock.rst | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Documentation/userspace-api/landlock.rst b/Documentation/users= pace-api/landlock.rst index 84cb7bf6b3ed..f6389b9668b4 100644 --- a/Documentation/userspace-api/landlock.rst +++ b/Documentation/userspace-api/landlock.rst @@ -78,7 +78,9 @@ to be explicit about the denied-by-default access rights. LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_TRUNCATE | LANDLOCK_ACCESS_FS_IOCTL_DEV | - LANDLOCK_ACCESS_FS_RESOLVE_UNIX, + LANDLOCK_ACCESS_FS_RESOLVE_UNIX | + LANDLOCK_ACCESS_FS_READ_METADATA | + LANDLOCK_ACCESS_FS_WRITE_METADATA, .handled_access_net =3D LANDLOCK_ACCESS_NET_BIND_TCP | LANDLOCK_ACCESS_NET_CONNECT_TCP | @@ -140,6 +142,13 @@ version, and only use the available subset of access r= ights: ruleset_attr.handled_access_net &=3D ~(LANDLOCK_ACCESS_NET_BIND_UDP | LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP); + __attribute__((fallthrough)); + case 10: + case 11: + /* Removes metadata rights for ABI < 12 */ + ruleset_attr.handled_access_fs &=3D + ~(LANDLOCK_ACCESS_FS_READ_METADATA | + LANDLOCK_ACCESS_FS_WRITE_METADATA); } =20 This enables the creation of an inclusive ruleset that will contain our ru= les. --=20 2.18.0.huawei.25