@@ -4197,69 +4197,82 @@ fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
41974197 memcpy (& tr_hdr -> SessionId , & shdr -> SessionId , 8 );
41984198}
41994199
4200- /* We can not use the normal sg_set_buf() as we will sometimes pass a
4201- * stack object as buf.
4202- */
4203- static inline void smb2_sg_set_buf (struct scatterlist * sg , const void * buf ,
4204- unsigned int buflen )
4200+ static void * smb2_aead_req_alloc (struct crypto_aead * tfm , const struct smb_rqst * rqst ,
4201+ int num_rqst , const u8 * sig , u8 * * iv ,
4202+ struct aead_request * * req , struct scatterlist * * sgl ,
4203+ unsigned int * num_sgs )
42054204{
4206- void * addr ;
4207- /*
4208- * VMAP_STACK (at least) puts stack into the vmalloc address space
4209- */
4210- if (is_vmalloc_addr (buf ))
4211- addr = vmalloc_to_page (buf );
4212- else
4213- addr = virt_to_page (buf );
4214- sg_set_page (sg , addr , buflen , offset_in_page (buf ));
4205+ unsigned int req_size = sizeof (* * req ) + crypto_aead_reqsize (tfm );
4206+ unsigned int iv_size = crypto_aead_ivsize (tfm );
4207+ unsigned int len ;
4208+ u8 * p ;
4209+
4210+ * num_sgs = cifs_get_num_sgs (rqst , num_rqst , sig );
4211+
4212+ len = iv_size ;
4213+ len += crypto_aead_alignmask (tfm ) & ~(crypto_tfm_ctx_alignment () - 1 );
4214+ len = ALIGN (len , crypto_tfm_ctx_alignment ());
4215+ len += req_size ;
4216+ len = ALIGN (len , __alignof__(struct scatterlist ));
4217+ len += * num_sgs * sizeof (* * sgl );
4218+
4219+ p = kmalloc (len , GFP_ATOMIC );
4220+ if (!p )
4221+ return NULL ;
4222+
4223+ * iv = (u8 * )PTR_ALIGN (p , crypto_aead_alignmask (tfm ) + 1 );
4224+ * req = (struct aead_request * )PTR_ALIGN (* iv + iv_size ,
4225+ crypto_tfm_ctx_alignment ());
4226+ * sgl = (struct scatterlist * )PTR_ALIGN ((u8 * )* req + req_size ,
4227+ __alignof__(struct scatterlist ));
4228+ return p ;
42154229}
42164230
4217- /* Assumes the first rqst has a transform header as the first iov.
4218- * I.e.
4219- * rqst[0].rq_iov[0] is transform header
4220- * rqst[0].rq_iov[1+] data to be encrypted/decrypted
4221- * rqst[1+].rq_iov[0+] data to be encrypted/decrypted
4222- */
4223- static struct scatterlist *
4224- init_sg (int num_rqst , struct smb_rqst * rqst , u8 * sign )
4231+ static void * smb2_get_aead_req (struct crypto_aead * tfm , const struct smb_rqst * rqst ,
4232+ int num_rqst , const u8 * sig , u8 * * iv ,
4233+ struct aead_request * * req , struct scatterlist * * sgl )
42254234{
4226- unsigned int sg_len ;
4235+ unsigned int off , len , skip ;
42274236 struct scatterlist * sg ;
4228- unsigned int i ;
4229- unsigned int j ;
4230- unsigned int idx = 0 ;
4231- int skip ;
4232-
4233- sg_len = 1 ;
4234- for (i = 0 ; i < num_rqst ; i ++ )
4235- sg_len += rqst [i ].rq_nvec + rqst [i ].rq_npages ;
4237+ unsigned int num_sgs ;
4238+ unsigned long addr ;
4239+ int i , j ;
4240+ void * p ;
42364241
4237- sg = kmalloc_array ( sg_len , sizeof ( struct scatterlist ), GFP_KERNEL );
4238- if (!sg )
4242+ p = smb2_aead_req_alloc ( tfm , rqst , num_rqst , sig , iv , req , sgl , & num_sgs );
4243+ if (!p )
42394244 return NULL ;
42404245
4241- sg_init_table (sg , sg_len );
4246+ sg_init_table (* sgl , num_sgs );
4247+ sg = * sgl ;
4248+
4249+ /* Assumes the first rqst has a transform header as the first iov.
4250+ * I.e.
4251+ * rqst[0].rq_iov[0] is transform header
4252+ * rqst[0].rq_iov[1+] data to be encrypted/decrypted
4253+ * rqst[1+].rq_iov[0+] data to be encrypted/decrypted
4254+ */
42424255 for (i = 0 ; i < num_rqst ; i ++ ) {
4256+ /*
4257+ * The first rqst has a transform header where the
4258+ * first 20 bytes are not part of the encrypted blob.
4259+ */
42434260 for (j = 0 ; j < rqst [i ].rq_nvec ; j ++ ) {
4244- /*
4245- * The first rqst has a transform header where the
4246- * first 20 bytes are not part of the encrypted blob
4247- */
4248- skip = (i == 0 ) && (j == 0 ) ? 20 : 0 ;
4249- smb2_sg_set_buf (& sg [idx ++ ],
4250- rqst [i ].rq_iov [j ].iov_base + skip ,
4251- rqst [i ].rq_iov [j ].iov_len - skip );
4252- }
4261+ struct kvec * iov = & rqst [i ].rq_iov [j ];
42534262
4263+ skip = (i == 0 ) && (j == 0 ) ? 20 : 0 ;
4264+ addr = (unsigned long )iov -> iov_base + skip ;
4265+ len = iov -> iov_len - skip ;
4266+ sg = cifs_sg_set_buf (sg , (void * )addr , len );
4267+ }
42544268 for (j = 0 ; j < rqst [i ].rq_npages ; j ++ ) {
4255- unsigned int len , offset ;
4256-
4257- rqst_page_get_length (& rqst [i ], j , & len , & offset );
4258- sg_set_page (& sg [idx ++ ], rqst [i ].rq_pages [j ], len , offset );
4269+ rqst_page_get_length (& rqst [i ], j , & len , & off );
4270+ sg_set_page (sg ++ , rqst [i ].rq_pages [j ], len , off );
42594271 }
42604272 }
4261- smb2_sg_set_buf (& sg [idx ], sign , SMB2_SIGNATURE_SIZE );
4262- return sg ;
4273+ cifs_sg_set_buf (sg , sig , SMB2_SIGNATURE_SIZE );
4274+
4275+ return p ;
42634276}
42644277
42654278static int
@@ -4305,11 +4318,11 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
43054318 u8 sign [SMB2_SIGNATURE_SIZE ] = {};
43064319 u8 key [SMB3_ENC_DEC_KEY_SIZE ];
43074320 struct aead_request * req ;
4308- char * iv ;
4309- unsigned int iv_len ;
4321+ u8 * iv ;
43104322 DECLARE_CRYPTO_WAIT (wait );
43114323 struct crypto_aead * tfm ;
43124324 unsigned int crypt_len = le32_to_cpu (tr_hdr -> OriginalMessageSize );
4325+ void * creq ;
43134326
43144327 rc = smb2_get_enc_key (server , le64_to_cpu (tr_hdr -> SessionId ), enc , key );
43154328 if (rc ) {
@@ -4344,32 +4357,15 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
43444357 return rc ;
43454358 }
43464359
4347- req = aead_request_alloc (tfm , GFP_KERNEL );
4348- if (!req ) {
4349- cifs_server_dbg (VFS , "%s: Failed to alloc aead request\n" , __func__ );
4360+ creq = smb2_get_aead_req (tfm , rqst , num_rqst , sign , & iv , & req , & sg );
4361+ if (unlikely (!creq ))
43504362 return - ENOMEM ;
4351- }
43524363
43534364 if (!enc ) {
43544365 memcpy (sign , & tr_hdr -> Signature , SMB2_SIGNATURE_SIZE );
43554366 crypt_len += SMB2_SIGNATURE_SIZE ;
43564367 }
43574368
4358- sg = init_sg (num_rqst , rqst , sign );
4359- if (!sg ) {
4360- cifs_server_dbg (VFS , "%s: Failed to init sg\n" , __func__ );
4361- rc = - ENOMEM ;
4362- goto free_req ;
4363- }
4364-
4365- iv_len = crypto_aead_ivsize (tfm );
4366- iv = kzalloc (iv_len , GFP_KERNEL );
4367- if (!iv ) {
4368- cifs_server_dbg (VFS , "%s: Failed to alloc iv\n" , __func__ );
4369- rc = - ENOMEM ;
4370- goto free_sg ;
4371- }
4372-
43734369 if ((server -> cipher_type == SMB2_ENCRYPTION_AES128_GCM ) ||
43744370 (server -> cipher_type == SMB2_ENCRYPTION_AES256_GCM ))
43754371 memcpy (iv , (char * )tr_hdr -> Nonce , SMB3_AES_GCM_NONCE );
@@ -4378,6 +4374,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
43784374 memcpy (iv + 1 , (char * )tr_hdr -> Nonce , SMB3_AES_CCM_NONCE );
43794375 }
43804376
4377+ aead_request_set_tfm (req , tfm );
43814378 aead_request_set_crypt (req , sg , sg , crypt_len , iv );
43824379 aead_request_set_ad (req , assoc_data_len );
43834380
@@ -4390,11 +4387,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
43904387 if (!rc && enc )
43914388 memcpy (& tr_hdr -> Signature , sign , SMB2_SIGNATURE_SIZE );
43924389
4393- kfree_sensitive (iv );
4394- free_sg :
4395- kfree_sensitive (sg );
4396- free_req :
4397- kfree_sensitive (req );
4390+ kfree_sensitive (creq );
43984391 return rc ;
43994392}
44004393
0 commit comments