summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Layton <jlayton@kernel.org>2023-05-17 12:26:44 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-06-21 14:54:14 +0200
commit8157832461bdae946485a17f7701c1215b85fd77 (patch)
tree65816e50336a8bee4be0e0b481ecd3a98ceb7bee
parent05f45f3981d392f9f3ced9bd5302ad981bb55499 (diff)
downloadlinux-stable-8157832461bdae946485a17f7701c1215b85fd77.tar.gz
linux-stable-8157832461bdae946485a17f7701c1215b85fd77.tar.bz2
linux-stable-8157832461bdae946485a17f7701c1215b85fd77.zip
nfsd: make a copy of struct iattr before calling notify_change
[ Upstream commit d53d70084d27f56bcdf5074328f2c9ec861be596 ] notify_change can modify the iattr structure. In particular it can end up setting ATTR_MODE when ATTR_KILL_SUID is already set, causing a BUG() if the same iattr is passed to notify_change more than once. Make a copy of the struct iattr before calling notify_change. Reported-by: Zhi Li <yieli@redhat.com> Link: https://bugzilla.redhat.com/show_bug.cgi?id=2207969 Tested-by: Zhi Li <yieli@redhat.com> Fixes: 34b91dda7124 ("NFSD: Make nfsd4_setattr() wait before returning NFS4ERR_DELAY") Signed-off-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--fs/nfsd/vfs.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index abc682854507..542a1adbbf2a 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -545,7 +545,15 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
inode_lock(inode);
for (retries = 1;;) {
- host_err = __nfsd_setattr(dentry, iap);
+ struct iattr attrs;
+
+ /*
+ * notify_change() can alter its iattr argument, making
+ * @iap unsuitable for submission multiple times. Make a
+ * copy for every loop iteration.
+ */
+ attrs = *iap;
+ host_err = __nfsd_setattr(dentry, &attrs);
if (host_err != -EAGAIN || !retries--)
break;
if (!nfsd_wait_for_delegreturn(rqstp, inode))