Assertion failure in fifo8_push_all() through am53c974

Bug #1919036 reported by Cheolwoo,Myung
10
This bug affects 1 person
Affects Status Importance Assigned to Milestone
QEMU
Fix Released
Undecided
Unassigned

Bug Description

Hello,

Using hypervisor fuzzer, hyfuzz, I found an assertion failure through am53c974 emulator.

A malicious guest user/process could use this flaw to abort the QEMU process on the host, resulting in a denial of service.

This was found in version 5.2.0 (master, 3f8d1885e4)

```
qemu-system-i386: ../util/fifo8.c:43: fifo8_push_all: Assertion `fifo->num + num <= fifo->capacity' failed.

#0 0x00007ffff0218fb7 in __GI_raise (sig=sig@entry=0x6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00007ffff021a921 in __GI_abort () at abort.c:79
#2 0x00007ffff020a48a in __assert_fail_base (fmt=0x7ffff0391750 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=assertion@entry=0x555558ed2400 "fifo->num + num <= fifo->capacity", file=file@entry=0x555558ed2380 "../util/fifo8.c", line=line@entry=0x2b, function=function@entry=0x555558ed2560 <__PRETTY_FUNCTION__.16583> "fifo8_push_all")
    at assert.c:92
#3 0x00007ffff020a502 in __GI___assert_fail (assertion=assertion@entry=0x555558ed2400 "fifo->num + num <= fifo->capacity", file=file@entry=0x555558ed2380 "../util/fifo8.c", line=line@entry=0x2b, function=function@entry=0x555558ed2560 <__PRETTY_FUNCTION__.16583> "fifo8_push_all") at assert.c:101
#4 0x00005555587749c4 in fifo8_push_all (fifo=fifo@entry=0x61f000005200, data=data@entry=0x7fff72bfa640 "", num=num@entry=0x24) at ../util/fifo8.c:43
#5 0x00005555572bd13e in esp_do_dma (s=s@entry=0x61f000005088) at ../hw/scsi/esp.c:577
#6 0x00005555572bfc8f in handle_ti (s=0x61f000005088) at ../hw/scsi/esp.c:845
#7 0x00005555572c419c in esp_reg_write (s=0x61f000005088, saddr=saddr@entry=0x3, val=<optimized out>)
    at ../hw/scsi/esp.c:987
#8 0x0000555557bb916a in esp_pci_io_write (opaque=0x61f000004680, addr=<optimized out>, val=<optimized out>, size=<optimized out>) at ../hw/scsi/esp-pci.c:214
#9 0x000055555817ea28 in memory_region_write_accessor (mr=0x61f000004f70, addr=<optimized out>, value=<optimized out>, size=<optimized out>, shift=<optimized out>, mask=<optimized out>, attrs=...) at ../softmmu/memory.c:491
#10 0x0000555558176671 in access_with_adjusted_size (addr=addr@entry=0xc, value=value@entry=0x7fff72bfb2a8, size=size@entry=0x1, access_size_min=<optimized out>, access_size_max=<optimized out>, access_fn=
    0x55555817e7c0 <memory_region_write_accessor>, mr=0x61f000004f70, attrs=...) at ../softmmu/memory.c:552
#11 0x00005555581892aa in memory_region_dispatch_write (mr=mr@entry=0x61f000004f70, addr=<optimized out>, data=<optimized out>, data@entry=0xffffff90, op=op@entry=MO_8, attrs=..., attrs@entry=...) at ../softmmu/memory.c:1508
#12 0x0000555558024b66 in address_space_stb (as=<optimized out>, addr=<optimized out>, val=<optimized out>, attrs=..., result=0x0) at /home/cwmyung/prj/hyfuzz/src/qemu-master/memory_ldst.c.inc:382
#13 0x00007fff9323641c in code_gen_buffer ()
#14 0x0000555557e793bb in cpu_tb_exec (tb_exit=<optimized out>, itb=<optimized out>, cpu=0x62e0000004b4)
    at ../accel/tcg/cpu-exec.c:190
#15 0x0000555557e793bb in cpu_loop_exec_tb (tb_exit=<optimized out>, last_tb=<optimized out>, tb=<optimized out>, cpu=0x62e0000004b4) at ../accel/tcg/cpu-exec.c:673
#16 0x0000555557e793bb in cpu_exec (cpu=cpu@entry=0x62e000000400) at ../accel/tcg/cpu-exec.c:798
#17 0x0000555557f5fc5a in tcg_cpus_exec (cpu=cpu@entry=0x62e000000400) at ../accel/tcg/tcg-accel-ops.c:68
#18 0x00005555582260af in mttcg_cpu_thread_fn (arg=arg@entry=0x62e000000400) at ../accel/tcg/tcg-accel-ops-mttcg.c:70
#19 0x0000555558777b05 in qemu_thread_start (args=<optimized out>) at ../util/qemu-thread-posix.c:521
#20 0x00007ffff05d26db in start_thread (arg=0x7fff72bff700) at pthread_create.c:463
#21 0x00007ffff02fb71f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
```

To reproduce the assertion failure, please run the QEMU with the following command line.

```

$ ./qemu-system-i386 -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

```

Please let me know if I can provide any further info.

Thank you.

- Cheolwoo, Myung (Seoul National University)

Tags: fuzzer
Revision history for this message
Cheolwoo,Myung (cwmyung) wrote :
Revision history for this message
Mark Cave-Ayland (mark-cave-ayland) wrote :

Thanks for the test case - looks like the problem occurs because a command hasn't been submitted before initiating a DMA transfer, and TC is set to a value higher than the size of cmdfifo. Can you confirm that the following fix works for you?

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 507ab363bc..0a26ee1dfd 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -573,6 +573,7 @@ static void esp_do_dma(ESPState *s)
         cmdlen = fifo8_num_used(&s->cmdfifo);
         trace_esp_do_dma(cmdlen, len);
         if (s->dma_memory_read) {
+ len = MIN(len, fifo8_num_free(&s->cmdfifo));
             s->dma_memory_read(s->dma_opaque, buf, len);
             fifo8_push_all(&s->cmdfifo, buf, len);
         } else {

ATB,

Mark.

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

QTest Reproducer:
/*
 * 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 0x80001004
 * outw 0xcfc 0x01
 * outl 0xcf8 0x8000100e
 * outl 0xcfc 0x0e000000
 * outl 0xe40 0x03
 * outl 0xe0b 0x4100
 * outl 0xe0b 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, 0x80001004);
    qtest_outw(s, 0xcfc, 0x01);
    qtest_outl(s, 0xcf8, 0x8000100e);
    qtest_outl(s, 0xcfc, 0x0e000000);
    qtest_outl(s, 0xe40, 0x03);
    qtest_outl(s, 0xe0b, 0x4100);
    qtest_outl(s, 0xe0b, 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
Cheolwoo,Myung (cwmyung) wrote :

Hello Mark,

I tested on fixed version, and checked that it does not trigger the assertion failure.

Thanks,
- Cheolwoo Myung

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 :
Changed in qemu:
status: New → Fix Released
Revision history for this message
Mauro Matteo Cascella (mauro-cascella) wrote :

I'm not able to change the status of this bug anymore. It should have been closed as "Fix committed" - QEMU 6.0.0 is not yet released.

Thomas Huth (th-huth)
Changed in qemu:
status: Fix Released → Fix Committed
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.