lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <20230512125114.1329613-2-bigunclemax@gmail.com>
Date:   Fri, 12 May 2023 15:51:13 +0300
From:   Maksim Kiselev <bigunclemax@...il.com>
To:     Adaptec OEM Raid Solutions <aacraid@...rosemi.com>
Cc:     Maksim Kiselev <bigunclemax@...il.com>,
        "James E.J. Bottomley" <jejb@...ux.ibm.com>,
        "Martin K. Petersen" <martin.petersen@...cle.com>,
        linux-scsi@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [PATCH 1/1] scsi: aacraid: Prevent stopping of already finished thread on adapter reset

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@...il.com>
---
 drivers/scsi/aacraid/commsup.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

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;
 	}
-- 
2.39.2

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ