In the Linux kernel, the following vulnerability has been resolved:
null_blk: fix poll request timeout handling
When doing io_uring benchmark on /dev/nullb0, it's easy to crash the kernel if poll requests timeout triggered, as reported by David. [1]
BUG: kernel NULL pointer dereference, address: 0000000000000008 Workqueue: kblockd blkmqtimeoutwork RIP: 0010:nulltimeoutrq+0x4e/0x91 Call Trace: ? nulltimeoutrq+0x4e/0x91 blkmqhandleexpired+0x31/0x4b btiter+0x68/0x84 ? bttagsiter+0x81/0x81 _sbitmapforeachset.constprop.0+0xb0/0xf2 ? _blkmqcompleterequestremote+0xf/0xf btforeach+0x46/0x64 ? _blkmqcompleterequestremote+0xf/0xf ? percpurefgetmany+0xc/0x2a blkmqqueuetagbusyiter+0x14d/0x18e blkmqtimeoutwork+0x95/0x127 processonework+0x185/0x263 worker_thread+0x1b5/0x227
This is indeed a race problem between nulltimeoutrq() and null_poll().
nullpoll() nulltimeoutrq() spinlock(&nq->polllock) listspliceinit(&nq->polllist, &list) spinunlock(&nq->polllock)
while (!listempty(&list)) req = listfirstentry() listdelinit() ... blkmqaddtobatch() // req->rqnext = NULL spinlock(&nq->polllock)
// rq->queuelist->next == NULL
list_del_init(&rq->queuelist)
spin_unlock(&nq->poll_lock)
Fix these problems by setting requests state to MQRQCOMPLETE under nq->polllock protection, in which nulltimeout_rq() can safely detect this race and early return.
Note this patch just fix the kernel panic when request timeout happen.
[1] https://lore.kernel.org/all/3893581.1691785261@warthog.procyon.org.uk/
[
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@5a26e45edb4690d58406178b5a9ea4c6dcf2c105",
"target": {
"function": "null_poll",
"file": "drivers/block/null_blk/main.c"
},
"signature_version": "v1",
"deprecated": false,
"digest": {
"function_hash": "65980709049133529157460310363914274377",
"length": 640.0
},
"id": "CVE-2023-53531-0b8b9710",
"signature_type": "Function"
},
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@5a26e45edb4690d58406178b5a9ea4c6dcf2c105",
"target": {
"function": "null_timeout_rq",
"file": "drivers/block/null_blk/main.c"
},
"signature_version": "v1",
"deprecated": false,
"digest": {
"function_hash": "46128675065097258766918862675661731119",
"length": 469.0
},
"id": "CVE-2023-53531-59fccab8",
"signature_type": "Function"
},
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@5a26e45edb4690d58406178b5a9ea4c6dcf2c105",
"target": {
"file": "drivers/block/null_blk/main.c"
},
"signature_version": "v1",
"deprecated": false,
"digest": {
"line_hashes": [
"298991706957752478433625383919050061285",
"334818859063533480173252352212291693749",
"128774643468816272577032126515845473912",
"42762040461290358470890769491199502377",
"29615062799998189796595998502735460136",
"134299910995136990241099448082714079888",
"333942187150972691113743970372270592441",
"305438166178729228757621049061783766790",
"11009681987136482230641262447710091451",
"121743287106415890432665268758961456030",
"106944477760650927546344069104419953386",
"310136908659366113783976509882949352961",
"69104093679616116233061874571896709976",
"125549250484857250457410246267630336503",
"205235872170415324003811459993285187158",
"219498705163911867202220762789388810939"
],
"threshold": 0.9
},
"id": "CVE-2023-53531-f3cc8222",
"signature_type": "Line"
}
]