| From 90f7c100d2dd99d5cd5be950d553edd2647e6cc8 Mon Sep 17 00:00:00 2001 |
| From: Paulo Alcantara <pc@manguebit.org> |
| Date: Sat, 6 Sep 2025 21:19:29 -0300 |
| Subject: smb: client: fix compound alignment with encryption |
| |
| From: Paulo Alcantara <pc@manguebit.org> |
| |
| commit 90f7c100d2dd99d5cd5be950d553edd2647e6cc8 upstream. |
| |
| The encryption layer can't handle the padding iovs, so flatten the |
| compound request into a single buffer with required padding to prevent |
| the server from dropping the connection when finding unaligned |
| compound requests. |
| |
| Fixes: bc925c1216f0 ("smb: client: improve compound padding in encryption") |
| Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.org> |
| Reviewed-by: David Howells <dhowells@redhat.com> |
| Cc: linux-cifs@vger.kernel.org |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Steve French <stfrench@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/smb/client/smb2ops.c | 28 +++++++++++++++++++++++++--- |
| 1 file changed, 25 insertions(+), 3 deletions(-) |
| |
| --- a/fs/smb/client/smb2ops.c |
| +++ b/fs/smb/client/smb2ops.c |
| @@ -2640,13 +2640,35 @@ smb2_set_next_command(struct cifs_tcon * |
| } |
| |
| /* SMB headers in a compound are 8 byte aligned. */ |
| - if (!IS_ALIGNED(len, 8)) { |
| - num_padding = 8 - (len & 7); |
| + if (IS_ALIGNED(len, 8)) |
| + goto out; |
| + |
| + num_padding = 8 - (len & 7); |
| + if (smb3_encryption_required(tcon)) { |
| + int i; |
| + |
| + /* |
| + * Flatten request into a single buffer with required padding as |
| + * the encryption layer can't handle the padding iovs. |
| + */ |
| + for (i = 1; i < rqst->rq_nvec; i++) { |
| + memcpy(rqst->rq_iov[0].iov_base + |
| + rqst->rq_iov[0].iov_len, |
| + rqst->rq_iov[i].iov_base, |
| + rqst->rq_iov[i].iov_len); |
| + rqst->rq_iov[0].iov_len += rqst->rq_iov[i].iov_len; |
| + } |
| + memset(rqst->rq_iov[0].iov_base + rqst->rq_iov[0].iov_len, |
| + 0, num_padding); |
| + rqst->rq_iov[0].iov_len += num_padding; |
| + rqst->rq_nvec = 1; |
| + } else { |
| rqst->rq_iov[rqst->rq_nvec].iov_base = smb2_padding; |
| rqst->rq_iov[rqst->rq_nvec].iov_len = num_padding; |
| rqst->rq_nvec++; |
| - len += num_padding; |
| } |
| + len += num_padding; |
| +out: |
| shdr->NextCommand = cpu_to_le32(len); |
| } |
| |