Skip to content

Commit fcef5df

Browse files
committed
bdev/nvme: prevent UAF by unregistering connect poller and null-guarding qpair
longhorn/longhorn-11698 Signed-off-by: Chin-Ya Huang <chin-ya.huang@suse.com>
1 parent f2b9769 commit fcef5df

1 file changed

Lines changed: 26 additions & 0 deletions

File tree

module/bdev/nvme/bdev_nvme.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2410,6 +2410,17 @@ bdev_nvme_reset_check_qpair_connected(void *ctx)
24102410
struct nvme_qpair *nvme_qpair = ctrlr_ch->qpair;
24112411
struct spdk_nvme_qpair *qpair;
24122412

2413+
/* Check if nvme_qpair or its controller was freed due to disconnect callback.
2414+
* This can happen when ctrlr_ch was set to NULL and nvme_qpair was freed
2415+
* in bdev_nvme_disconnected_qpair_cb() while this poller was still scheduled.
2416+
* Just return and let the poller be cleaned up through normal channel destruction.
2417+
*/
2418+
if (nvme_qpair == NULL || nvme_qpair->ctrlr == NULL) {
2419+
SPDK_DEBUGLOG(bdev_nvme, "connect_poller: nvme_qpair=%p or ctrlr freed, "
2420+
"returning (UAF avoided).\n", nvme_qpair);
2421+
return SPDK_POLLER_BUSY;
2422+
}
2423+
24132424
if (ctrlr_ch->reset_iter == NULL) {
24142425
/* qpair was already failed to connect and the reset sequence is being aborted. */
24152426
assert(ctrlr_ch->connect_poller == NULL);
@@ -3719,7 +3730,22 @@ bdev_nvme_destroy_ctrlr_channel_cb(void *io_device, void *ctx_buf)
37193730
* We need to poll it until it is actually disconnected.
37203731
* Just detach the qpair from the deleting ctrlr_channel.
37213732
*/
3733+
if (ctrlr_ch->connect_poller) {
3734+
/* Unregister the connect poller to avoid it firing after this
3735+
* ctrlr_channel context has been freed. The poller may still
3736+
* be running if a connect/disconnect/reset sequence was in flight.
3737+
*/
3738+
NVME_CTRLR_INFOLOG(nvme_qpair->ctrlr,
3739+
"Unregistering connect_poller %p during channel destroy "
3740+
"(ctrlr_ch=%p, nvme_qpair=%p).\n",
3741+
ctrlr_ch->connect_poller, ctrlr_ch, nvme_qpair);
3742+
spdk_poller_unregister(&ctrlr_ch->connect_poller);
3743+
}
3744+
NVME_CTRLR_DEBUGLOG(nvme_qpair->ctrlr,
3745+
"Clearing ctrlr_ch->qpair pointer (ctrlr_ch=%p, nvme_qpair=%p).\n",
3746+
ctrlr_ch, nvme_qpair);
37223747
nvme_qpair->ctrlr_ch = NULL;
3748+
ctrlr_ch->qpair = NULL;
37233749
} else {
37243750
assert(ctrlr_ch->reset_iter == NULL);
37253751

0 commit comments

Comments
 (0)