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>] [day] [month] [year] [list]
Date:   Thu, 18 Feb 2021 23:14:53 -0500
From:   Tong Zhang <ztong0001@...il.com>
To:     "James E.J. Bottomley" <jejb@...ux.ibm.com>,
        "Martin K. Petersen" <martin.petersen@...cle.com>,
        ching Huang <ching2048@...ca.com.tw>,
        Lee Jones <lee.jones@...aro.org>,
        Vaibhav Gupta <vaibhavgupta40@...il.com>,
        "Gustavo A. R. Silva" <gustavoars@...nel.org>,
        Mauro Carvalho Chehab <mchehab+huawei@...nel.org>,
        linux-scsi@...r.kernel.org, linux-kernel@...r.kernel.org
Cc:     ztong0001@...il.com
Subject: [PATCH] scsi: arcmsr: catch bounds error earlier and dont panic

pARCMSR_CDB is calculated from a base address + a value read from
controller with some bit shifting, the value is not checked and could possibly
overflow the buffer and cause panic. The buffer is allocated using
dma_alloc_coherent and the size is acb->uncache_size.
Instead of crashing the system, we can try to catch the bounds error
earlier and return an error.

[   25.820995] BUG: unable to handle page fault for address: ffffed1010383dd3
[   25.821451] #PF: supervisor read access in kernel mode
[   25.821737] #PF: error_code(0x0000) - not-present page
[   25.822023] PGD 17fff1067 P4D 17fff1067 PUD 17fff0067 PMD 0
[   25.822342] Oops: 0000 [#1] SMP KASAN NOPTI
[   25.822578] CPU: 0 PID: 66 Comm: kworker/u2:2 Not tainted 5.11.0 #27
[   25.822931] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-48-gd9c812dda519-4
[   25.823553] Workqueue: scsi_tmf_6 scmd_eh_abort_handler
[   25.823853] RIP: 0010:__asan_load8+0x3c/0xa0
[   25.824097] Code: 00 00 00 00 00 00 ff 48 39 f8 77 57 48 8d 47 07 48 89 c2 83 e2 07 48 83 fa 07 78
[   25.825123] RSP: 0018:ffff888101ea7d10 EFLAGS: 00010a03
[   25.825417] RAX: 1ffff11010383dd3 RBX: ffff888102a2a8c8 RCX: ffffffffc000ac23
[   25.825813] RDX: dffffc0000000000 RSI: ffffc90004000030 RDI: ffff888081c1ee98
[   25.826210] RBP: ffff888081c1eec0 R08: ffffffffc000a5ea R09: ffffed102054551a
[   25.826606] R10: ffff888102a2a8cb R11: ffffed1020545519 R12: ffff888081c1ee80
[   25.827004] R13: 0000000081c1ee00 R14: ffff888102a28000 R15: ffffc90004000030
[   25.827400] FS:  0000000000000000(0000) GS:ffff88815b400000(0000) knlGS:0000000000000000
[   25.827853] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   25.828174] CR2: ffffed1010383dd3 CR3: 00000001029ca000 CR4: 00000000000006f0
[   25.828570] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[   25.828966] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[   25.829362] Call Trace:
[   25.829503]  arcmsr_abort.cold+0xd41/0xf40 [arcmsr]
[   25.829788]  ? __schedule+0x5ae/0xd40
[   25.829999]  scmd_eh_abort_handler+0xbd/0x1a0
[   25.830247]  process_one_work+0x470/0x750
[   25.830476]  worker_thread+0x73/0x690
[   25.830685]  ? process_one_work+0x750/0x750
[   25.830922]  kthread+0x199/0x1f0
[   25.831108]  ? kthread_create_on_node+0xd0/0xd0
[   25.831363]  ret_from_fork+0x1f/0x30
[   25.831571] Modules linked in: arcmsr(+)
[   25.831796] CR2: ffffed1010383dd3
[   25.831984] ---[ end trace 4a558ca3660a5f82 ]---
[   25.832243] RIP: 0010:__asan_load8+0x3c/0xa0
[   25.832485] Code: 00 00 00 00 00 00 ff 48 39 f8 77 57 48 8d 47 07 48 89 c2 83 e2 07 48 83 fa 07 78
[   25.833512] RSP: 0018:ffff888101ea7d10 EFLAGS: 00010a03
[   25.833805] RAX: 1ffff11010383dd3 RBX: ffff888102a2a8c8 RCX: ffffffffc000ac23
[   25.834201] RDX: dffffc0000000000 RSI: ffffc90004000030 RDI: ffff888081c1ee98
[   25.834596] RBP: ffff888081c1eec0 R08: ffffffffc000a5ea R09: ffffed102054551a
[   25.834992] R10: ffff888102a2a8cb R11: ffffed1020545519 R12: ffff888081c1ee80
[   25.835388] R13: 0000000081c1ee00 R14: ffff888102a28000 R15: ffffc90004000030
[   25.835784] FS:  0000000000000000(0000) GS:ffff88815b400000(0000) knlGS:0000000000000000
[   25.836229] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   25.836547] CR2: ffffed1010383dd3 CR3: 00000001029ca000 CR4: 00000000000006f0
[   25.836940] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[   25.837333] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400

Signed-off-by: Tong Zhang <ztong0001@...il.com>
---
 drivers/scsi/arcmsr/arcmsr_hba.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 4b79661275c9..e0227bf12ab2 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -1482,6 +1482,11 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
 		while(((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF)
 				&& (i++ < acb->maxOutstanding)) {
 			ccb_cdb_phy = (flag_ccb << 5) & 0xffffffff;
+			if (ccb_cdb_phy>=acb->uncache_size) {
+				printk(KERN_WARNING "arcmsr%d: ccb_cdb_phy bounds error detected",
+					 acb->host->host_no);
+				break;
+			}
 			if (acb->cdb_phyadd_hipart)
 				ccb_cdb_phy = ccb_cdb_phy | acb->cdb_phyadd_hipart;
 			pARCMSR_CDB = (struct ARCMSR_CDB *)(acb->vir2phy_offset + ccb_cdb_phy);
@@ -2451,6 +2456,11 @@ static void arcmsr_hbaA_postqueue_isr(struct AdapterControlBlock *acb)
 
 	while ((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) {
 		cdb_phy_addr = (flag_ccb << 5) & 0xffffffff;
+		if (cdb_phy_addr>=acb->uncache_size) {
+			printk(KERN_WARNING "arcmsr%d: cdb_phy_addr bounds error detected",
+				 acb->host->host_no);
+			break;
+		}
 		if (acb->cdb_phyadd_hipart)
 			cdb_phy_addr = cdb_phy_addr | acb->cdb_phyadd_hipart;
 		pARCMSR_CDB = (struct ARCMSR_CDB *)(acb->vir2phy_offset + cdb_phy_addr);
@@ -3503,6 +3513,11 @@ static int arcmsr_hbaA_polling_ccbdone(struct AdapterControlBlock *acb,
 			}
 		}
 		ccb_cdb_phy = (flag_ccb << 5) & 0xffffffff;
+		if (ccb_cdb_phy>=acb->uncache_size) {
+			printk(KERN_WARNING "arcmsr%d: ccb_cdb_phy bounds error detected",
+				 acb->host->host_no);
+			return FAILED;
+		}
 		if (acb->cdb_phyadd_hipart)
 			ccb_cdb_phy = ccb_cdb_phy | acb->cdb_phyadd_hipart;
 		arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset + ccb_cdb_phy);
-- 
2.25.1

Powered by blists - more mailing lists