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@xxxxxxxxx> --- 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(®->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(®->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