[PATCH] nvme: fix use-after-free during booting

Tong Zhang ztong0001 at gmail.com
Wed Sep 16 11:36:05 EDT 2020


if a nvme controller is not responding during probing, a use-after-free
condition could happen

[  215.396884] nvme nvme0: Identify Controller failed (-4)
[  215.397239] nvme nvme0: Removing after probe failure status: -5
[  215.409079] Buffer I/O error on dev nvme0n1, logical block 0, async page read
[  215.409526] Buffer I/O error on dev nvme0n1, logical block 1, async page read
[  215.409924] Buffer I/O error on dev nvme0n1, logical block 2, async page read
[  215.410317] Buffer I/O error on dev nvme0n1, logical block 3, async page read
[  215.410706] Buffer I/O error on dev nvme0n1, logical block 4, async page read
[  215.411103] Buffer I/O error on dev nvme0n1, logical block 5, async page read
[  215.411498] Buffer I/O error on dev nvme0n1, logical block 6, async page read
[  215.411893] Buffer I/O error on dev nvme0n1, logical block 7, async page read
[  215.412272]  nvme0n1: unable to read partition table
[  215.412581] nvme0n1: partition table beyond EOD, truncated
[  215.966867] ------------[ cut here ]------------
[  215.967167] WARNING: CPU: 1 PID: 7 at block/genhd.c:838 __device_add_disk+0x79c/0x7c0
[  215.967558] Modules linked in:
[  215.967717] CPU: 1 PID: 7 Comm: kworker/u4:0 Not tainted 5.8.0+ #59
[  215.968618] Workqueue: nvme-wq nvme_scan_work
[  215.968849] RIP: 0010:__device_add_disk+0x79c/0x7c0
[  215.969098] Code: 85 30 04 00 00 48 89 44 24 20 e9 41 fa ff ff 48 89 df e8 07 e5 ca ff 80 a5 dc 00 00 00 ef e9 88 fc ff ff 0f 0b e9 81 fc ff ff <0f>
0b e9 a1 fc ff ff 0f 0b e9 b5 fa ff ff 0f 0b e9 51 ff ff ff e8
[  215.970032] RSP: 0000:ffff88806c06f9f0 EFLAGS: 00010246
[  215.970297] RAX: 0000000000000000 RBX: ffff88806c233400 RCX: ffffffff9ce3e74e
[  215.970653] RDX: dffffc0000000000 RSI: 0000000000000008 RDI: ffff888066135560
[  215.971015] RBP: ffff88806b2ce800 R08: 0000000000000001 R09: ffffed100cc26aad
[  215.971373] R10: ffff888066135567 R11: ffffed100cc26aac R12: ffff88806c40f940
[  215.971731] R13: ffff88806b2ce8a0 R14: ffff88806b2ce808 R15: ffff88806b2cebd8
[  215.972094] FS:  0000000000000000(0000) GS:ffff88806d100000(0000) knlGS:0000000000000000
[  215.972497] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  215.972789] CR2: 0000000000000000 CR3: 0000000024e0e000 CR4: 00000000000006e0
[  215.973153] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[  215.973513] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[  215.973875] Call Trace:
[  215.974007]  ? blk_alloc_devt+0x140/0x140
[  215.974213]  ? __hrtimer_init+0xb6/0xf0
[  215.974411]  ? rwsem_down_read_slowpath+0x7d0/0x7d0
[  215.974659]  ? __nvme_revalidate_disk+0x1ba/0x420
[  215.974905]  nvme_validate_ns+0x54c/0xe70
[  215.975113]  ? nvme_dev_ioctl+0x190/0x190
[  215.975318]  ? __blk_mq_free_request+0xe3/0x130
[  215.975549]  ? __nvme_submit_sync_cmd+0x153/0x300
[  215.975789]  ? kasan_unpoison_shadow+0x33/0x40
[  215.976022]  nvme_scan_work+0x20f/0x35f
[  215.976220]  ? nvme_fw_act_work+0x210/0x210
[  215.976434]  ? free_object+0x50/0x50
[  215.976619]  ? try_to_wake_up+0x37c/0x900
[  215.976619]  ? try_to_wake_up+0x37c/0x900
[  215.976843]  ? read_word_at_a_time+0xe/0x20
[  215.977057]  ? strscpy+0xbf/0x190
[  215.977229]  process_one_work+0x4ad/0x7e0
[  215.977435]  worker_thread+0x73/0x690
[  215.977623]  ? process_one_work+0x7e0/0x7e0
[  215.977842]  kthread+0x199/0x1f0
[  215.978011]  ? kthread_create_on_node+0xd0/0xd0
[  215.978240]  ret_from_fork+0x22/0x30
[  215.978423] ---[ end trace e8b38966135fe74b ]---
[  215.987504] refcount_t: underflow; use-after-free.
[  215.987772] WARNING: CPU: 1 PID: 7 at lib/refcount.c:28 refcount_warn_saturate+0xc5/0x110
[  215.988641] Modules linked in:
[  215.988827] CPU: 1 PID: 7 Comm: kworker/u4:0 Tainted: G        W         5.8.0+ #59
[  215.989784] Workqueue: nvme-wq nvme_scan_work
[  215.990013] RIP: 0010:refcount_warn_saturate+0xc5/0x110
0b e9 76 ff ff ff 80 3d cc 0f f6 01 00 0f 85 69 ff ff ff 48 c7
[  215.991220] RSP: 0000:ffff88806c06fb60 EFLAGS: 00010282
[  215.991485] RAX: 0000000000000000 RBX: 0000000000000003 RCX: 0000000000000000
[  215.991850] RDX: 0000000000000001 RSI: 0000000000000004 RDI: ffffed100d80df5e
[  215.992209] RBP: ffff8880661355b0 R08: 0000000000000001 R09: ffffed100d80df32
[  215.992568] R10: 0000000000000003 R11: ffffed100d80df31 R12: ffff88806b2ce830
[  215.992937] R13: ffff88806b2ce800 R14: ffff88806bf47a78 R15: ffff88806bdb6a88
[  215.993294] FS:  0000000000000000(0000) GS:ffff88806d100000(0000) knlGS:0000000000000000
[  215.993700] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  215.993997] CR2: 0000000000000000 CR3: 0000000024e0e000 CR4: 00000000000006e0
[  215.994356] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[  215.994714] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[  215.995077] Call Trace:
[  215.995208]  disk_release+0x114/0x130
[  215.995397]  device_release+0x3c/0xd0
[  215.995586]  kobject_put+0xa5/0x120
[  215.995767]  nvme_put_ns+0x40/0xa0
[  215.995950]  nvme_remove_invalid_namespaces+0x1bd/0x210
[  215.996214]  ? nvme_ns_remove+0x2c0/0x2c0
[  215.996420]  nvme_scan_work+0x258/0x35f
[  215.996618]  ? nvme_fw_act_work+0x210/0x210
[  215.996841]  ? free_object+0x50/0x50
[  215.997027]  ? try_to_wake_up+0x37c/0x900
[  215.997233]  ? read_word_at_a_time+0xe/0x20
[  215.997446]  ? strscpy+0xbf/0x190
[  215.997617]  process_one_work+0x4ad/0x7e0
[  215.997830]  worker_thread+0x73/0x690
[  215.998021]  ? process_one_work+0x7e0/0x7e0
[  215.998234]  kthread+0x199/0x1f0
[  215.998401]  ? kthread_create_on_node+0xd0/0xd0
[  215.998632]  ret_from_fork+0x22/0x30
[  215.998822] ---[ end trace e8b38966135fe74c ]---

Signed-off-by: Tong Zhang <ztong0001 at gmail.com>
---
 drivers/nvme/host/core.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index d543bc1747fd..cdd40aab10e9 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -481,6 +481,8 @@ static void nvme_free_ns(struct kref *kref)
 	if (ns->ndev)
 		nvme_nvm_unregister(ns);
 
+	/* prevent double queue cleanup */
+	ns->disk->queue = NULL;
 	put_disk(ns->disk);
 	nvme_put_ns_head(ns->head);
 	nvme_put_ctrl(ns->ctrl);
-- 
2.25.1




More information about the Linux-nvme mailing list