Message ID | 20230512125114.1329613-2-bigunclemax@gmail.com |
---|---|
State | New |
Headers | show |
Series | [1/1] scsi: aacraid: Prevent stopping of already finished thread on adapter reset | expand |
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index deb32c9f4b3e..9f253a360e9f 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -1494,9 +1494,10 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) * commands are completing in the interrupt service. */ aac_adapter_disable_int(aac); - if (aac->thread && aac->thread->pid != current->pid) { + if (!aac->aif_thread || (aac->thread && aac->thread->pid != current->pid)) { spin_unlock_irq(host->host_lock); - kthread_stop(aac->thread); + if (aac->aif_thread) + kthread_stop(aac->thread); aac->thread = NULL; jafo = 1; }
For some reason `aac_adapter_check_health` may fail what leads to `aac_command_thread` finish. After that if `scsi_try_host_reset` happens, it leads to access to 'aac->thread->pid' and attempt to stop already finished thread (`kthread_stop(aac->thread`). As a result we have use-after-free warning and NULL pointer dereference crash. This patch should prevent access to already finished thread. [ 461.707724] ------------[ cut here ]------------ [ 461.707725] refcount_t: addition on 0; use-after-free. [ 461.707729] WARNING: CPU: 1 PID: 116 at lib/refcount.c:25 refcount_warn_saturate+0x72/0x100 [ 461.707783] CPU: 1 PID: 116 Comm: scsi_eh_0 Tainted: G W 6.3.0.0-g2cd293ea6f73-dirty #12 [ 461.707785] Hardware name: Supermicro Super Server/X11SSH-LN4F, BIOS 2.7 12/07/2021 [ 461.707786] RIP: 0010:refcount_warn_saturate+0x72/0x100 [ 461.707804] Call Trace: [ 461.707805] <TASK> [ 461.707806] kthread_stop+0xdb/0xe0 [ 461.707809] aac_reset_adapter+0x409/0x6f0 [aacraid] [ 461.707815] aac_eh_host_reset+0x50/0x90 [aacraid] [ 461.707819] scsi_try_host_reset+0x26/0xc0 [scsi_mod] [ 461.707825] scsi_eh_ready_devs+0x34e/0x920 [scsi_mod] [ 461.707831] ? scsi_eh_get_sense+0x160/0x160 [scsi_mod] [ 461.707838] scsi_error_handler+0x355/0x360 [scsi_mod] [ 461.707845] kthread+0xda/0x100 [ 461.707847] ? kthread_complete_and_exit+0x20/0x20 [ 461.707849] ret_from_fork+0x1f/0x30 [ 461.707852] </TASK> [ 461.707852] ---[ end trace 0000000000000000 ]--- [ 461.707855] BUG: kernel NULL pointer dereference, address: 0000000000000000 [ 461.708215] #PF: supervisor write access in kernel mode [ 461.708552] #PF: error_code(0x0002) - not-present page [ 461.708900] PGD 0 P4D 0 [ 461.709234] Oops: 0002 [#1] PREEMPT SMP [ 461.709558] CPU: 1 PID: 116 Comm: scsi_eh_0 Tainted: G W 6.3.0.0-g2cd293ea6f73-dirty #12 [ 461.710521] RIP: 0010:kthread_stop+0x3f/0xe0 [ 461.715884] Call Trace: [ 461.716267] <TASK> [ 461.716651] aac_reset_adapter+0x409/0x6f0 [aacraid] [ 461.717052] aac_eh_host_reset+0x50/0x90 [aacraid] [ 461.717455] scsi_try_host_reset+0x26/0xc0 [scsi_mod] [ 461.717856] scsi_eh_ready_devs+0x34e/0x920 [scsi_mod] [ 461.718262] ? scsi_eh_get_sense+0x160/0x160 [scsi_mod] [ 461.718656] scsi_error_handler+0x355/0x360 [scsi_mod] [ 461.719044] kthread+0xda/0x100 [ 461.719429] ? kthread_complete_and_exit+0x20/0x20 [ 461.719823] ret_from_fork+0x1f/0x30 [ 461.720216] </TASK> [ 461.724589] CR2: 0000000000000000 [ 461.725038] ---[ end trace 0000000000000000 ]--- [ 461.732223] note: scsi_eh_0[116] exited with irqs disabled Signed-off-by: Maksim Kiselev <bigunclemax@gmail.com> --- drivers/scsi/aacraid/commsup.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)