linux/drivers/nvme/target
Maurizio Lombardi bec9cb90fe nvmet-auth: complete a request only after freeing the dhchap pointers
commit f965b281fd upstream.

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: db1312dd95 ("nvmet: implement basic In-Band Authentication")
Signed-off-by: Maurizio Lombardi <mlombard@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
History 2023-10-25 12:03:14 +02:00
..
admin-cmd.c nvmet: fix I/O Command Set specific Identify Controller 2023-05-11 23:03:22 +09:00
auth.c nvmet: fix a memory leak in nvmet_auth_set_key 2022-11-16 07:20:56 +01:00
configfs.c nvmet: fix a memory leak 2022-11-09 14:29:13 +01:00
core.c nvmet: avoid potential UAF in nvmet_req_complete() 2023-03-22 13:33:47 +01:00
discovery.c nvme: move from strlcpy with unused retval to strscpy 2022-09-19 11:33:53 +02:00
fabrics-cmd-auth.c nvmet-auth: complete a request only after freeing the dhchap pointers 2023-10-25 12:03:14 +02:00
fabrics-cmd.c nvmet: add helpers to set the result field for connect commands 2022-09-27 09:22:09 +02:00
fc.c nvme-fc: fix a missing queue put in nvmet_fc_ls_create_association 2023-02-22 12:59:44 +01:00
fcloop.c nvme-fcloop: fix "inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage" 2023-05-11 23:03:22 +09:00
io-cmd-bdev.c nvmet: don't look at the request_queue in nvmet_bdev_set_limits 2022-09-27 18:51:50 +02:00
io-cmd-file.c nvmet: use bvec_set_page to initialize bvecs 2023-09-23 11:11:08 +02:00
Kconfig nvmet-auth: select the intended CRYPTO_DH_RFC7919_GROUPS 2022-08-02 17:22:51 -06:00
loop.c nvme: consolidate setting the tagset flags 2023-02-01 08:34:43 +01:00
Makefile nvmet: implement basic In-Band Authentication 2022-08-02 17:14:49 -06:00
nvmet.h nvmet: fix I/O Command Set specific Identify Controller 2023-05-11 23:03:22 +09:00
passthru.c nvmet: don't defer passthrough commands with trivial effects to the workqueue 2023-01-04 11:28:52 +01:00
rdma.c RDMA/core: introduce ib_dma_pci_p2p_dma_supported() 2022-07-26 07:28:07 -04:00
tcp.c nvmet-tcp: Fix a possible UAF in queue intialization setup 2023-10-25 12:03:05 +02:00
trace.c nvmet: add set feature tracing support 2021-08-16 14:42:23 +02:00
trace.h nvmet: use min of device_path and disk len 2021-02-10 16:38:05 +01:00
zns.c nvmet: fix I/O Command Set specific Identify Controller 2023-05-11 23:03:22 +09:00