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

CIFS: Fix signing for SMB2/3

It seems Ronnie's preamble removal broke signing.

the signing functions are called when:

A) we send a request (to sign it)
B) when we recv a response (to check the signature).

On code path A, the smb2 header is in iov[1] but on code path B, the
smb2 header is in iov[0] (and there's only one vector).

So we have different iov indexes for the smb2 header but the signing
function always use index 1. Fix this by checking the nb of io vectors
in the signing function as a hint.

Signed-off-by: Aurelien Aptel <aaptel@suse.com>
Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>

authored by

Aurelien Aptel and committed by
Steve French
57f933ce 93e95fa5

+12 -10
+3 -5
fs/cifs/cifsencrypt.c
··· 37 37 #include <crypto/aead.h> 38 38 39 39 int __cifs_calc_signature(struct smb_rqst *rqst, 40 + int start, 40 41 struct TCP_Server_Info *server, char *signature, 41 42 struct shash_desc *shash) 42 43 { ··· 46 45 struct kvec *iov = rqst->rq_iov; 47 46 int n_vec = rqst->rq_nvec; 48 47 49 - if (n_vec < 2 || iov[0].iov_len != 4) 50 - return -EIO; 51 - 52 - for (i = 1; i < n_vec; i++) { 48 + for (i = start; i < n_vec; i++) { 53 49 if (iov[i].iov_len == 0) 54 50 continue; 55 51 if (iov[i].iov_base == NULL) { ··· 117 119 return rc; 118 120 } 119 121 120 - return __cifs_calc_signature(rqst, server, signature, 122 + return __cifs_calc_signature(rqst, 1, server, signature, 121 123 &server->secmech.sdescmd5->shash); 122 124 } 123 125
+1 -1
fs/cifs/cifsproto.h
··· 544 544 struct cifs_sb_info *cifs_sb, 545 545 const unsigned char *path, char *pbuf, 546 546 unsigned int *pbytes_written); 547 - int __cifs_calc_signature(struct smb_rqst *rqst, 547 + int __cifs_calc_signature(struct smb_rqst *rqst, int start, 548 548 struct TCP_Server_Info *server, char *signature, 549 549 struct shash_desc *shash); 550 550 enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
+8 -4
fs/cifs/smb2transport.c
··· 171 171 unsigned char smb2_signature[SMB2_HMACSHA256_SIZE]; 172 172 unsigned char *sigptr = smb2_signature; 173 173 struct kvec *iov = rqst->rq_iov; 174 - struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base; 174 + int iov_hdr_index = rqst->rq_nvec > 1 ? 1 : 0; 175 + struct smb2_sync_hdr *shdr = 176 + (struct smb2_sync_hdr *)iov[iov_hdr_index].iov_base; 175 177 struct cifs_ses *ses; 176 178 177 179 ses = smb2_find_smb_ses(server, shdr->SessionId); ··· 204 202 return rc; 205 203 } 206 204 207 - rc = __cifs_calc_signature(rqst, server, sigptr, 205 + rc = __cifs_calc_signature(rqst, iov_hdr_index, server, sigptr, 208 206 &server->secmech.sdeschmacsha256->shash); 209 207 210 208 if (!rc) ··· 414 412 unsigned char smb3_signature[SMB2_CMACAES_SIZE]; 415 413 unsigned char *sigptr = smb3_signature; 416 414 struct kvec *iov = rqst->rq_iov; 417 - struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base; 415 + int iov_hdr_index = rqst->rq_nvec > 1 ? 1 : 0; 416 + struct smb2_sync_hdr *shdr = 417 + (struct smb2_sync_hdr *)iov[iov_hdr_index].iov_base; 418 418 struct cifs_ses *ses; 419 419 420 420 ses = smb2_find_smb_ses(server, shdr->SessionId); ··· 447 443 return rc; 448 444 } 449 445 450 - rc = __cifs_calc_signature(rqst, server, sigptr, 446 + rc = __cifs_calc_signature(rqst, iov_hdr_index, server, sigptr, 451 447 &server->secmech.sdesccmacaes->shash); 452 448 453 449 if (!rc)