@@ -4416,69 +4416,82 @@ fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
44164416 memcpy (& tr_hdr -> SessionId , & shdr -> SessionId , 8 );
44174417}
44184418
4419- /* We can not use the normal sg_set_buf() as we will sometimes pass a
4420- * stack object as buf.
4421- */
4422- static inline void smb2_sg_set_buf (struct scatterlist * sg , const void * buf ,
4423- unsigned int buflen )
4419+ static void * smb2_aead_req_alloc (struct crypto_aead * tfm , const struct smb_rqst * rqst ,
4420+ int num_rqst , const u8 * sig , u8 * * iv ,
4421+ struct aead_request * * req , struct scatterlist * * sgl ,
4422+ unsigned int * num_sgs )
44244423{
4425- void * addr ;
4426- /*
4427- * VMAP_STACK (at least) puts stack into the vmalloc address space
4428- */
4429- if (is_vmalloc_addr (buf ))
4430- addr = vmalloc_to_page (buf );
4431- else
4432- addr = virt_to_page (buf );
4433- sg_set_page (sg , addr , buflen , offset_in_page (buf ));
4424+ unsigned int req_size = sizeof (* * req ) + crypto_aead_reqsize (tfm );
4425+ unsigned int iv_size = crypto_aead_ivsize (tfm );
4426+ unsigned int len ;
4427+ u8 * p ;
4428+
4429+ * num_sgs = cifs_get_num_sgs (rqst , num_rqst , sig );
4430+
4431+ len = iv_size ;
4432+ len += crypto_aead_alignmask (tfm ) & ~(crypto_tfm_ctx_alignment () - 1 );
4433+ len = ALIGN (len , crypto_tfm_ctx_alignment ());
4434+ len += req_size ;
4435+ len = ALIGN (len , __alignof__(struct scatterlist ));
4436+ len += * num_sgs * sizeof (* * sgl );
4437+
4438+ p = kmalloc (len , GFP_ATOMIC );
4439+ if (!p )
4440+ return NULL ;
4441+
4442+ * iv = (u8 * )PTR_ALIGN (p , crypto_aead_alignmask (tfm ) + 1 );
4443+ * req = (struct aead_request * )PTR_ALIGN (* iv + iv_size ,
4444+ crypto_tfm_ctx_alignment ());
4445+ * sgl = (struct scatterlist * )PTR_ALIGN ((u8 * )* req + req_size ,
4446+ __alignof__(struct scatterlist ));
4447+ return p ;
44344448}
44354449
4436- /* Assumes the first rqst has a transform header as the first iov.
4437- * I.e.
4438- * rqst[0].rq_iov[0] is transform header
4439- * rqst[0].rq_iov[1+] data to be encrypted/decrypted
4440- * rqst[1+].rq_iov[0+] data to be encrypted/decrypted
4441- */
4442- static struct scatterlist *
4443- init_sg (int num_rqst , struct smb_rqst * rqst , u8 * sign )
4450+ static void * smb2_get_aead_req (struct crypto_aead * tfm , const struct smb_rqst * rqst ,
4451+ int num_rqst , const u8 * sig , u8 * * iv ,
4452+ struct aead_request * * req , struct scatterlist * * sgl )
44444453{
4445- unsigned int sg_len ;
4454+ unsigned int off , len , skip ;
44464455 struct scatterlist * sg ;
4447- unsigned int i ;
4448- unsigned int j ;
4449- unsigned int idx = 0 ;
4450- int skip ;
4451-
4452- sg_len = 1 ;
4453- for (i = 0 ; i < num_rqst ; i ++ )
4454- sg_len += rqst [i ].rq_nvec + rqst [i ].rq_npages ;
4456+ unsigned int num_sgs ;
4457+ unsigned long addr ;
4458+ int i , j ;
4459+ void * p ;
44554460
4456- sg = kmalloc_array ( sg_len , sizeof ( struct scatterlist ), GFP_KERNEL );
4457- if (!sg )
4461+ p = smb2_aead_req_alloc ( tfm , rqst , num_rqst , sig , iv , req , sgl , & num_sgs );
4462+ if (!p )
44584463 return NULL ;
44594464
4460- sg_init_table (sg , sg_len );
4465+ sg_init_table (* sgl , num_sgs );
4466+ sg = * sgl ;
4467+
4468+ /* Assumes the first rqst has a transform header as the first iov.
4469+ * I.e.
4470+ * rqst[0].rq_iov[0] is transform header
4471+ * rqst[0].rq_iov[1+] data to be encrypted/decrypted
4472+ * rqst[1+].rq_iov[0+] data to be encrypted/decrypted
4473+ */
44614474 for (i = 0 ; i < num_rqst ; i ++ ) {
4475+ /*
4476+ * The first rqst has a transform header where the
4477+ * first 20 bytes are not part of the encrypted blob.
4478+ */
44624479 for (j = 0 ; j < rqst [i ].rq_nvec ; j ++ ) {
4463- /*
4464- * The first rqst has a transform header where the
4465- * first 20 bytes are not part of the encrypted blob
4466- */
4467- skip = (i == 0 ) && (j == 0 ) ? 20 : 0 ;
4468- smb2_sg_set_buf (& sg [idx ++ ],
4469- rqst [i ].rq_iov [j ].iov_base + skip ,
4470- rqst [i ].rq_iov [j ].iov_len - skip );
4471- }
4480+ struct kvec * iov = & rqst [i ].rq_iov [j ];
44724481
4482+ skip = (i == 0 ) && (j == 0 ) ? 20 : 0 ;
4483+ addr = (unsigned long )iov -> iov_base + skip ;
4484+ len = iov -> iov_len - skip ;
4485+ sg = cifs_sg_set_buf (sg , (void * )addr , len );
4486+ }
44734487 for (j = 0 ; j < rqst [i ].rq_npages ; j ++ ) {
4474- unsigned int len , offset ;
4475-
4476- rqst_page_get_length (& rqst [i ], j , & len , & offset );
4477- sg_set_page (& sg [idx ++ ], rqst [i ].rq_pages [j ], len , offset );
4488+ rqst_page_get_length (& rqst [i ], j , & len , & off );
4489+ sg_set_page (sg ++ , rqst [i ].rq_pages [j ], len , off );
44784490 }
44794491 }
4480- smb2_sg_set_buf (& sg [idx ], sign , SMB2_SIGNATURE_SIZE );
4481- return sg ;
4492+ cifs_sg_set_buf (sg , sig , SMB2_SIGNATURE_SIZE );
4493+
4494+ return p ;
44824495}
44834496
44844497static int
@@ -4522,11 +4535,11 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
45224535 u8 sign [SMB2_SIGNATURE_SIZE ] = {};
45234536 u8 key [SMB3_ENC_DEC_KEY_SIZE ];
45244537 struct aead_request * req ;
4525- char * iv ;
4526- unsigned int iv_len ;
4538+ u8 * iv ;
45274539 DECLARE_CRYPTO_WAIT (wait );
45284540 struct crypto_aead * tfm ;
45294541 unsigned int crypt_len = le32_to_cpu (tr_hdr -> OriginalMessageSize );
4542+ void * creq ;
45304543
45314544 rc = smb2_get_enc_key (server , tr_hdr -> SessionId , enc , key );
45324545 if (rc ) {
@@ -4561,32 +4574,15 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
45614574 return rc ;
45624575 }
45634576
4564- req = aead_request_alloc (tfm , GFP_KERNEL );
4565- if (!req ) {
4566- cifs_server_dbg (VFS , "%s: Failed to alloc aead request\n" , __func__ );
4577+ creq = smb2_get_aead_req (tfm , rqst , num_rqst , sign , & iv , & req , & sg );
4578+ if (unlikely (!creq ))
45674579 return - ENOMEM ;
4568- }
45694580
45704581 if (!enc ) {
45714582 memcpy (sign , & tr_hdr -> Signature , SMB2_SIGNATURE_SIZE );
45724583 crypt_len += SMB2_SIGNATURE_SIZE ;
45734584 }
45744585
4575- sg = init_sg (num_rqst , rqst , sign );
4576- if (!sg ) {
4577- cifs_server_dbg (VFS , "%s: Failed to init sg\n" , __func__ );
4578- rc = - ENOMEM ;
4579- goto free_req ;
4580- }
4581-
4582- iv_len = crypto_aead_ivsize (tfm );
4583- iv = kzalloc (iv_len , GFP_KERNEL );
4584- if (!iv ) {
4585- cifs_server_dbg (VFS , "%s: Failed to alloc iv\n" , __func__ );
4586- rc = - ENOMEM ;
4587- goto free_sg ;
4588- }
4589-
45904586 if ((server -> cipher_type == SMB2_ENCRYPTION_AES128_GCM ) ||
45914587 (server -> cipher_type == SMB2_ENCRYPTION_AES256_GCM ))
45924588 memcpy (iv , (char * )tr_hdr -> Nonce , SMB3_AES_GCM_NONCE );
@@ -4595,6 +4591,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
45954591 memcpy (iv + 1 , (char * )tr_hdr -> Nonce , SMB3_AES_CCM_NONCE );
45964592 }
45974593
4594+ aead_request_set_tfm (req , tfm );
45984595 aead_request_set_crypt (req , sg , sg , crypt_len , iv );
45994596 aead_request_set_ad (req , assoc_data_len );
46004597
@@ -4607,11 +4604,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
46074604 if (!rc && enc )
46084605 memcpy (& tr_hdr -> Signature , sign , SMB2_SIGNATURE_SIZE );
46094606
4610- kfree (iv );
4611- free_sg :
4612- kfree (sg );
4613- free_req :
4614- kfree (req );
4607+ kfree_sensitive (creq );
46154608 return rc ;
46164609}
46174610
0 commit comments