• Maurizio Lombardi's avatar
    nvmet-auth: complete a request only after freeing the dhchap pointers · f965b281
    Maurizio Lombardi authored
    It may happen that the work to destroy a queue
    (for example nvmet_tcp_release_queue_work()) is started while
    an auth-send or auth-receive command is still completing.
    
    nvmet_sq_destroy() will block, waiting for all the references
    to the sq to be dropped, the last reference is then
    dropped when nvmet_req_complete() is called.
    
    When this happens, both nvmet_sq_destroy() and
    nvmet_execute_auth_send()/_receive() will free the dhchap pointers by
    calling nvmet_auth_sq_free().
    Since there isn't any lock, the two threads may race against each other,
    causing double frees and memory corruptions, as reported by KASAN.
    
    Reproduced by stress blktests nvme/041 nvme/042 nvme/043
    
     nvme nvme2: qid 0: authenticated with hash hmac(sha512) dhgroup ffdhe4096
     ==================================================================
     BUG: KASAN: double-free in kfree+0xec/0x4b0
    
     Call Trace:
      <TASK>
      kfree+0xec/0x4b0
      nvmet_auth_sq_free+0xe1/0x160 [nvmet]
      nvmet_execute_auth_send+0x482/0x16d0 [nvmet]
      process_one_work+0x8e5/0x1510
    
     Allocated by task 191846:
      __kasan_kmalloc+0x81/0xa0
      nvmet_auth_ctrl_sesskey+0xf6/0x380 [nvmet]
      nvmet_auth_reply+0x119/0x990 [nvmet]
    
     Freed by task 143270:
      kfree+0xec/0x4b0
      nvmet_auth_sq_free+0xe1/0x160 [nvmet]
      process_one_work+0x8e5/0x1510
    
    Fix this bug by calling nvmet_req_complete() only after freeing the
    pointers, so we will prevent the race by holding the sq reference.
    
    V2: remove redundant code
    
    Fixes: db1312dd ("nvmet: implement basic In-Band Authentication")
    Signed-off-by: default avatarMaurizio Lombardi <mlombard@redhat.com>
    Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
    Signed-off-by: default avatarKeith Busch <kbusch@kernel.org>
    f965b281
fabrics-cmd-auth.c 15.6 KB