Re: [PATCH] cifs: Allocate crypto structures on the fly for calculating signatures of incoming packets

From: Pavel Shilovsky
Date: Fri Apr 03 2020 - 20:16:47 EST


ÐÑ, 3 ÐÐÑ. 2020 Ð. Ð 17:04, Pavel Shilovsky <piastryyy@xxxxxxxxx>:
>
> ÐÑ, 3 ÐÐÑ. 2020 Ð. Ð 16:11, Long Li <longli@xxxxxxxxxxxxx>:
> >
> > >Subject: Re: [PATCH] cifs: Allocate crypto structures on the fly for calculating
> > >signatures of incoming packets
> > >
> > >ÐÑ, 31 ÐÐÑ. 2020 Ð. Ð 16:22, <longli@xxxxxxxxxxxxxxxxx>:
> > >>
> > >> From: Long Li <longli@xxxxxxxxxxxxx>
> > >>
> > >> CIFS uses pre-allocated crypto structures to calculate signatures for
> > >> both incoming and outgoing packets. In this way it doesn't need to
> > >> allocate crypto structures for every packet, but it requires a lock to
> > >> prevent concurrent access to crypto structures.
> > >>
> > >> Remove the lock by allocating crypto structures on the fly for
> > >> incoming packets. At the same time, we can still use pre-allocated
> > >> crypto structures for outgoing packets, as they are already protected
> > >> by transport lock srv_mutex.
> > >>
> > >> Signed-off-by: Long Li <longli@xxxxxxxxxxxxx>
> > >> ---
> > >> fs/cifs/cifsglob.h | 3 +-
> > >> fs/cifs/smb2proto.h | 6 ++-
> > >> fs/cifs/smb2transport.c | 87
> > >> +++++++++++++++++++++++++----------------
> > >> 3 files changed, 60 insertions(+), 36 deletions(-)
> > >>
> > >> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index
> > >> 0d956360e984..7448e7202e7a 100644
> > >> --- a/fs/cifs/cifsglob.h
> > >> +++ b/fs/cifs/cifsglob.h
> > >> @@ -426,7 +426,8 @@ struct smb_version_operations {
> > >> /* generate new lease key */
> > >> void (*new_lease_key)(struct cifs_fid *);
> > >> int (*generate_signingkey)(struct cifs_ses *);
> > >> - int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *);
> > >> + int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *,
> > >> + bool allocate_crypto);
> > >> int (*set_integrity)(const unsigned int, struct cifs_tcon *tcon,
> > >> struct cifsFileInfo *src_file);
> > >> int (*enum_snapshots)(const unsigned int xid, struct cifs_tcon
> > >> *tcon, diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index
> > >> 4d1ff7b66fdc..087d5f14320b 100644
> > >> --- a/fs/cifs/smb2proto.h
> > >> +++ b/fs/cifs/smb2proto.h
> > >> @@ -55,9 +55,11 @@ extern struct cifs_ses *smb2_find_smb_ses(struct
> > >> TCP_Server_Info *server, extern struct cifs_tcon
> > >*smb2_find_smb_tcon(struct TCP_Server_Info *server,
> > >> __u64 ses_id, __u32
> > >> tid); extern int smb2_calc_signature(struct smb_rqst *rqst,
> > >> - struct TCP_Server_Info *server);
> > >> + struct TCP_Server_Info *server,
> > >> + bool allocate_crypto);
> > >> extern int smb3_calc_signature(struct smb_rqst *rqst,
> > >> - struct TCP_Server_Info *server);
> > >> + struct TCP_Server_Info *server,
> > >> + bool allocate_crypto);
> > >> extern void smb2_echo_request(struct work_struct *work); extern
> > >> __le32 smb2_get_lease_state(struct cifsInodeInfo *cinode); extern
> > >> bool smb2_is_valid_oplock_break(char *buffer, diff --git
> > >> a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index
> > >> 08b703b7a15e..c01e19a3b112 100644
> > >> --- a/fs/cifs/smb2transport.c
> > >> +++ b/fs/cifs/smb2transport.c
> > >> @@ -40,14 +40,6 @@
> > >> #include "smb2status.h"
> > >> #include "smb2glob.h"
> > >>
> > >> -static int
> > >> -smb2_crypto_shash_allocate(struct TCP_Server_Info *server) -{
> > >> - return cifs_alloc_hash("hmac(sha256)",
> > >> - &server->secmech.hmacsha256,
> > >> - &server->secmech.sdeschmacsha256);
> > >> -}
> > >> -
> > >> static int
> > >> smb3_crypto_shash_allocate(struct TCP_Server_Info *server) { @@
> > >> -219,7 +211,8 @@ smb2_find_smb_tcon(struct TCP_Server_Info *server,
> > >> __u64 ses_id, __u32 tid) }
> > >>
> > >> int
> > >> -smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info
> > >> *server)
> > >> +smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info
> > >*server,
> > >> + bool allocate_crypto)
> > >> {
> > >> int rc;
> > >> unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
> > >> @@ -228,6 +221,8 @@ smb2_calc_signature(struct smb_rqst *rqst, struct
> > >TCP_Server_Info *server)
> > >> struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base;
> > >> struct cifs_ses *ses;
> > >> struct shash_desc *shash;
> > >> + struct crypto_shash *hash;
> > >> + struct sdesc *sdesc = NULL;
> > >> struct smb_rqst drqst;
> > >>
> > >> ses = smb2_find_smb_ses(server, shdr->SessionId); @@ -239,24
> > >> +234,32 @@ smb2_calc_signature(struct smb_rqst *rqst, struct
> > >TCP_Server_Info *server)
> > >> memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
> > >> memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
> > >>
> > >> - rc = smb2_crypto_shash_allocate(server);
> > >> - if (rc) {
> > >> - cifs_server_dbg(VFS, "%s: sha256 alloc failed\n", __func__);
> > >> - return rc;
> > >> + if (allocate_crypto) {
> > >> + rc = cifs_alloc_hash("hmac(sha256)", &hash, &sdesc);
> > >> + if (rc) {
> > >> + cifs_server_dbg(VFS,
> > >> + "%s: sha256 alloc failed\n", __func__);
> > >> + return rc;
> > >> + }
> > >> + shash = &sdesc->shash;
> > >> + } else {
> > >> + hash = server->secmech.hmacsha256;
> > >> + shash = &server->secmech.sdeschmacsha256->shash;
> > >> }
> > >
> > >smb2_crypto_shash_allocate() unconditionally allocated
> > >server->secmech.hmacsha256 and server->secmech.sdeschmacsha256-
> > >>shash.
> >
> > I think they are allocated in smb311_crypto_shash_allocate(), through
> > => smb311_crypto_shash_allocate
> > => smb311_update_preauth_hash
> > => compound_send_recv
> > => cifs_send_recv
> > => SMB2_negotiate
> >
> > The function names are a little misleading...
>
> smb311_crypto_shash_allocate() only allocate those structures for SMB
> 3.1.1 protocol version, see the code below:
>
> 797 int
> 798 smb311_update_preauth_hash(struct cifs_ses *ses, struct kvec *iov, int nvec)
> 799 {
> 800 >-------int i, rc;
> 801 >-------struct sdesc *d;
> 802 >-------struct smb2_sync_hdr *hdr;
> 803
> 804 >-------if (ses->server->tcpStatus == CifsGood) {
> 805 >------->-------/* skip non smb311 connections */
> 806 >------->-------if (ses->server->dialect != SMB311_PROT_ID)
> 807 >------->------->-------return 0;
>

+ Aurelien

Ok, before negotiate tcpStatus is not CifsGood, so, the allocation
won't be skipped. I think this function should be no-op for all
protocols except SMB 3.1.1 to reflect the meaning. Other protocols
don't use preauth hash anyway.

@Aurelien, @everybody, what would be your thoughts about moving
protocol version check from IF block to the top of the function thus
skipping to allocate preauth hash for protocols that don't need it? In
this case Long's patch will require a change to keep
smb2_crypto_shash_allocate() and its invocation.

--
Best regards,
Pavel Shilovsky