Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

smb: client: fix compound alignment with encryption

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>

authored by

Paulo Alcantara and committed by
Steve French
90f7c100 76eeb9b8

+25 -3
+25 -3
fs/smb/client/smb2ops.c
··· 2640 2640 } 2641 2641 2642 2642 /* SMB headers in a compound are 8 byte aligned. */ 2643 - if (!IS_ALIGNED(len, 8)) { 2644 - num_padding = 8 - (len & 7); 2643 + if (IS_ALIGNED(len, 8)) 2644 + goto out; 2645 + 2646 + num_padding = 8 - (len & 7); 2647 + if (smb3_encryption_required(tcon)) { 2648 + int i; 2649 + 2650 + /* 2651 + * Flatten request into a single buffer with required padding as 2652 + * the encryption layer can't handle the padding iovs. 2653 + */ 2654 + for (i = 1; i < rqst->rq_nvec; i++) { 2655 + memcpy(rqst->rq_iov[0].iov_base + 2656 + rqst->rq_iov[0].iov_len, 2657 + rqst->rq_iov[i].iov_base, 2658 + rqst->rq_iov[i].iov_len); 2659 + rqst->rq_iov[0].iov_len += rqst->rq_iov[i].iov_len; 2660 + } 2661 + memset(rqst->rq_iov[0].iov_base + rqst->rq_iov[0].iov_len, 2662 + 0, num_padding); 2663 + rqst->rq_iov[0].iov_len += num_padding; 2664 + rqst->rq_nvec = 1; 2665 + } else { 2645 2666 rqst->rq_iov[rqst->rq_nvec].iov_base = smb2_padding; 2646 2667 rqst->rq_iov[rqst->rq_nvec].iov_len = num_padding; 2647 2668 rqst->rq_nvec++; 2648 - len += num_padding; 2649 2669 } 2670 + len += num_padding; 2671 + out: 2650 2672 shdr->NextCommand = cpu_to_le32(len); 2651 2673 } 2652 2674