From 1710ac17547ac8b5c44fbd74de41dee3fe26ee81 Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Fri, 12 Apr 2019 14:33:09 -0700 Subject: [PATCH] scsi: qla2xxx: Fix read offset in qla24xx_load_risc_flash() This patch fixes regression introduced by commit f8f97b0c5b7f ("scsi: qla2xxx: Cleanups for NVRAM/Flash read/write path") where flash read/write routine cleanup left out code which resulted into checksum failure leading to use-after-free stack during driver load. Following stack trace is seen in the log file qla2xxx [0000:00:00.0]-0005: : QLogic Fibre Channel HBA Driver: 10.01.00.16-k. qla2xxx [0000:00:0b.0]-001d: : Found an ISP2532 irq 11 iobase 0x0000000000f47f03. qla2xxx [0000:00:0b.0]-00cd:8: ISP Firmware failed checksum. qla2xxx [0000:00:0b.0]-00cf:8: Setup chip ****FAILED****. qla2xxx [0000:00:0b.0]-00d6:8: Failed to initialize adapter - Adapter flags 2. ================================================================== BUG: KASAN: use-after-free in __list_del_entry_valid+0x15/0xd0 Read of size 8 at addr ffff8880ca05a490 by task modprobe/857 CPU: 0 PID: 857 Comm: modprobe Not tainted 5.1.0-rc1-dbg+ #4 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 Call Trace: dump_stack+0x86/0xca print_address_description+0x6c/0x234 ? __list_del_entry_valid+0x15/0xd0 kasan_report.cold.3+0x1b/0x34 ? __list_del_entry_valid+0x15/0xd0 ? __kmem_cache_shutdown.cold.95+0xf5/0x176 ? __list_del_entry_valid+0x15/0xd0 __asan_load8+0x54/0x90 __list_del_entry_valid+0x15/0xd0 dma_pool_destroy+0x4f/0x260 ? dma_free_attrs+0xb4/0xd0 qla2x00_mem_free+0x529/0xcc0 [qla2xxx] ? kobject_put+0xdb/0x230 qla2x00_probe_one+0x2b5e/0x45f0 [qla2xxx] ? qla2xxx_pci_error_detected+0x210/0x210 [qla2xxx] ? match_held_lock+0x20/0x240 ? find_held_lock+0xca/0xf0 ? mark_held_locks+0x86/0xb0 ? _raw_spin_unlock_irqrestore+0x52/0x60 ? __pm_runtime_resume+0x5b/0xb0 ? lockdep_hardirqs_on+0x185/0x260 ? _raw_spin_unlock_irqrestore+0x52/0x60 ? trace_hardirqs_on+0x24/0x130 ? preempt_count_sub+0x13/0xc0 ? _raw_spin_unlock_irqrestore+0x3d/0x60 pci_device_probe+0x154/0x1e0 really_probe+0x17d/0x540 ? device_driver_attach+0x90/0x90 driver_probe_device+0x113/0x170 ? device_driver_attach+0x90/0x90 device_driver_attach+0x88/0x90 __driver_attach+0xb5/0x190 bus_for_each_dev+0xf8/0x160 ? subsys_dev_iter_exit+0x10/0x10 ? kasan_check_read+0x11/0x20 ? preempt_count_sub+0x13/0xc0 ? _raw_spin_unlock+0x2c/0x50 driver_attach+0x26/0x30 bus_add_driver+0x238/0x2f0 driver_register+0xd7/0x150 __pci_register_driver+0xd5/0xe0 ? 0xffffffffa06c8000 qla2x00_module_init+0x208/0x254 [qla2xxx] do_one_initcall+0xc0/0x3c9 ? trace_event_raw_event_initcall_finish+0x150/0x150 ? __kasan_kmalloc.constprop.5+0xc7/0xd0 ? kasan_unpoison_shadow+0x35/0x50 ? kasan_poison_shadow+0x2f/0x40 ? __asan_register_globals+0x5a/0x70 do_init_module+0x103/0x330 load_module+0x36df/0x3b70 ? fsnotify+0x611/0x640 ? module_frob_arch_sections+0x20/0x20 ? kernel_read+0x74/0xa0 ? kasan_check_write+0x14/0x20 ? kernel_read_file+0x25e/0x320 ? do_mmap+0x42c/0x6c0 __do_sys_finit_module+0x133/0x1c0 ? __do_sys_finit_module+0x133/0x1c0 ? __do_sys_init_module+0x210/0x210 ? fput_many+0x1b/0xc0 ? fput+0xe/0x10 ? do_syscall_64+0x14/0x210 ? entry_SYSCALL_64_after_hwframe+0x49/0xbe __x64_sys_finit_module+0x3e/0x50 do_syscall_64+0x72/0x210 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x7f8bd5c03219 Code: 00 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 47 fc 0c 00 f7 d8 64 89 01 48 RSP: 002b:00007fff9d11de98 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 RAX: ffffffffffffffda RBX: 000055ef21596b50 RCX: 00007f8bd5c03219 RDX: 0000000000000000 RSI: 000055ef21596570 RDI: 0000000000000004 RBP: 000055ef21596570 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000004 R11: 0000000000000246 R12: 0000000000000000 R13: 000055ef21596c80 R14: 0000000000040000 R15: 000055ef21596b50 Allocated by task 857: save_stack+0x43/0xd0 __kasan_kmalloc.constprop.5+0xc7/0xd0 kasan_kmalloc+0x9/0x10 kmem_cache_alloc_trace+0x144/0x300 dma_pool_create+0xb5/0x3b0 qla2x00_mem_alloc+0xb98/0x1ad0 [qla2xxx] qla2x00_probe_one+0xe28/0x45f0 [qla2xxx] pci_device_probe+0x154/0x1e0 really_probe+0x17d/0x540 driver_probe_device+0x113/0x170 device_driver_attach+0x88/0x90 __driver_attach+0xb5/0x190 bus_for_each_dev+0xf8/0x160 driver_attach+0x26/0x30 bus_add_driver+0x238/0x2f0 driver_register+0xd7/0x150 __pci_register_driver+0xd5/0xe0 qla2x00_module_init+0x208/0x254 [qla2xxx] do_one_initcall+0xc0/0x3c9 do_init_module+0x103/0x330 load_module+0x36df/0x3b70 __do_sys_finit_module+0x133/0x1c0 __x64_sys_finit_module+0x3e/0x50 do_syscall_64+0x72/0x210 entry_SYSCALL_64_after_hwframe+0x49/0xbe Freed by task 857: save_stack+0x43/0xd0 __kasan_slab_free+0x139/0x190 kasan_slab_free+0xe/0x10 kfree+0xf0/0x2c0 dma_pool_destroy+0x24c/0x260 qla2x00_mem_free+0x529/0xcc0 [qla2xxx] qla2x00_free_device+0x167/0x1b0 [qla2xxx] qla2x00_probe_one+0x2b28/0x45f0 [qla2xxx] pci_device_probe+0x154/0x1e0 really_probe+0x17d/0x540 driver_probe_device+0x113/0x170 device_driver_attach+0x88/0x90 __driver_attach+0xb5/0x190 bus_for_each_dev+0xf8/0x160 driver_attach+0x26/0x30 bus_add_driver+0x238/0x2f0 driver_register+0xd7/0x150 __pci_register_driver+0xd5/0xe0 qla2x00_module_init+0x208/0x254 [qla2xxx] do_one_initcall+0xc0/0x3c9 do_init_module+0x103/0x330 load_module+0x36df/0x3b70 __do_sys_finit_module+0x133/0x1c0 __x64_sys_finit_module+0x3e/0x50 do_syscall_64+0x72/0x210 entry_SYSCALL_64_after_hwframe+0x49/0xbe The buggy address belongs to the object at ffff8880ca05a400 which belongs to the cache kmalloc-192 of size 192 The buggy address is located 144 bytes inside of 192-byte region [ffff8880ca05a400, ffff8880ca05a4c0) The buggy address belongs to the page: page:ffffea0003281680 count:1 mapcount:0 mapping:ffff88811bf03380 index:0x0 compound_mapcount: 0 flags: 0x4000000000010200(slab|head) raw: 4000000000010200 0000000000000000 0000000c00000001 ffff88811bf03380 raw: 0000000000000000 0000000080200020 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff8880ca05a380: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc ffff8880ca05a400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb >ffff8880ca05a480: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc ^ ffff8880ca05a500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ffff8880ca05a580: 00 00 00 00 00 00 00 00 fc fc fc fc fc fc fc fc ================================================================== Fixes: f8f97b0c5b7f ("scsi: qla2xxx: Cleanups for NVRAM/Flash read/write path") Reported-by: Bart Van Assche Tested-by: Bart Van Assche Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 1ad4fbe76262..948f20805111 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -7720,8 +7720,6 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, dcode = fwdt->template; qla24xx_read_flash_data(vha, dcode, faddr, risc_size); - for (i = 0; i < risc_size; i++) - dcode[i] = le32_to_cpu(dcode[i]); if (!qla27xx_fwdt_template_valid(dcode)) { ql_log(ql_log_warn, vha, 0x0165, @@ -7887,22 +7885,11 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) } fwcode = (void *)blob->fw->data; - dcode = fwcode + 4; + dcode = fwcode; if (qla24xx_risc_firmware_invalid(dcode)) { ql_log(ql_log_fatal, vha, 0x0093, "Unable to verify integrity of firmware image (%zd).\n", blob->fw->size); - return QLA_FUNCTION_FAILED; - } - for (i = 0; i < 4; i++) - dcode[i] = be32_to_cpu(fwcode[i + 4]); - if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff && - dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) || - (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && - dcode[3] == 0)) { - ql_log(ql_log_fatal, vha, 0x0094, - "Unable to verify integrity of firmware image (%zd).\n", - blob->fw->size); ql_log(ql_log_fatal, vha, 0x0095, "Firmware data: %08x %08x %08x %08x.\n", dcode[0], dcode[1], dcode[2], dcode[3]); @@ -7925,7 +7912,6 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) dlen = ha->fw_transfer_size >> 2; for (fragment = 0; risc_size; fragment++) { - dlen = (uint32_t)(ha->fw_transfer_size >> 2); if (dlen > risc_size) dlen = risc_size; -- 2.30.2