summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBharath SM <bharathsm@microsoft.com>2026-03-09 16:00:49 +0530
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-03-19 16:08:45 +0100
commit92e64f1852f455f57d0850989e57c30d7fac7d95 (patch)
tree436ed0d97dc6dd9795b416c2abd03e3d390ca6b2
parent9509b659ca7ebe52752b5c3d805c24f9df8fa570 (diff)
smb: client: fix in-place encryption corruption in SMB2_write()
commit d78840a6a38d312dc1a51a65317bb67e46f0b929 upstream. SMB2_write() places write payload in iov[1..n] as part of rq_iov. smb3_init_transform_rq() pointer-shares rq_iov, so crypt_message() encrypts iov[1] in-place, replacing the original plaintext with ciphertext. On a replayable error, the retry sends the same iov[1] which now contains ciphertext instead of the original data, resulting in corruption. The corruption is most likely to be observed when connections are unstable, as reconnects trigger write retries that re-send the already-encrypted data. This affects SFU mknod, MF symlinks, etc. On kernels before 6.10 (prior to the netfs conversion), sync writes also used this path and were similarly affected. The async write path wasn't unaffected as it uses rq_iter which gets deep-copied. Fix by moving the write payload into rq_iter via iov_iter_kvec(), so smb3_init_transform_rq() deep-copies it before encryption. Cc: stable@vger.kernel.org #6.3+ Acked-by: Henrique Carvalho <henrique.carvalho@suse.com> Acked-by: Shyam Prasad N <sprasad@microsoft.com> Acked-by: Paulo Alcantara (Red Hat) <pc@manguebit.org> Signed-off-by: Bharath SM <bharathsm@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/smb/client/smb2pdu.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
index 309e2fcabc08..3e49c5b396b5 100644
--- a/fs/smb/client/smb2pdu.c
+++ b/fs/smb/client/smb2pdu.c
@@ -5172,7 +5172,10 @@ replay_again:
memset(&rqst, 0, sizeof(struct smb_rqst));
rqst.rq_iov = iov;
- rqst.rq_nvec = n_vec + 1;
+ /* iov[0] is the SMB header; move payload to rq_iter for encryption safety */
+ rqst.rq_nvec = 1;
+ iov_iter_kvec(&rqst.rq_iter, ITER_SOURCE, &iov[1], n_vec,
+ io_parms->length);
if (retries)
smb2_set_replay(server, &rqst);