hw/i2c/pmbus_device.c:pmbus_send_string()

Host environment

  • Operating system:

    Ubuntu 22.04.5 LTS

  • OS/kernel version:

    Linux flame 6.8.0-107-generic #107~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Wed Mar 18 23:40:43 UTC x86_64

  • Architecture:

    x86_64

  • QEMU flavor:

    qemu-system-arm

  • QEMU version:

    QEMU emulator version 10.2.50 (v10.2.0-690-g2339d0a1cf-dirty), commit 2339d0a1cfac6ecc667e6e062a593865c1541c35

  • QEMU command line:

    ./qemu-system-arm -machine imx25-pdk -nodefaults -display none -monitor none -serial none -qtest stdio -device adm1266,address=0x12,bus=i2c-bus.0 < reproducer.qtest

Emulated/Virtualized environment

  • Operating system:

    none (qtest-only reproducer)

  • OS/kernel version:

    N/A

  • Architecture:

    arm

Description of problem

A qtest-driven SMBus access pattern against the adm1266 PMBus device on imx25-pdk can make pmbus_send_string() abort with assert(len + pmdev->out_buf_len < SMBUS_DATA_MAX_LEN).

The reproducer repeatedly queries the device model string until the internal PMBus output buffer accounting overflows. This looks like a guest-triggerable host denial of service.

Steps to reproduce

  1. Build the affected QEMU flavor from qemu.git master (or checkout commit 2339d0a1cfac6ecc667e6e062a593865c1541c35) with debugging enabled.

  2. Save the following qtest program as reproducer.qtest:

    writeb 0x43f80008 0xf8
    readb 0x43f8000c
    writeb 0x43f80010 0x24
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x9a
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x20
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x41
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80008 0xc8
    readb 0x43f8000c
    writeb 0x43f80008 0xf8
    readb 0x43f8000c
    writeb 0x43f80010 0x24
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80010 0x9a
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80008 0xc8
    readb 0x43f8000c
    writeb 0x43f80008 0xf8
    readb 0x43f8000c
    writeb 0x43f80010 0x25
    readb 0x43f8000c
    writeb 0x43f8000c 0x00
    writeb 0x43f80008 0xe8
    readb 0x43f8000c
    readb 0x43f80010
  3. ./qemu-system-arm -machine imx25-pdk -nodefaults -display none -monitor none -serial none -qtest stdio -device adm1266,address=0x12,bus=i2c-bus.0 < reproducer.qtest

Additional information

  • Relevant source path: hw/i2c/pmbus_device.c:pmbus_send_string()

  • Local reproducer output excerpt:

    OK 0x00000000000000a0
    OK
    OK 0x00000000000000a2
    OK
    OK
    OK 0x00000000000000a0
    Bail out! ERROR:../qemu-2339d0a1cfac6ecc667e6e062a593865c1541c35/hw/i2c/pmbus_device.c:105:pmbus_send_string: assertion failed: (len + pmdev->out_buf_len < SMBUS_DATA_MAX_LEN)
    [I 0.000000] OPENED
    qemu-system-arm: warning: nic imx.fec.0 has no peer
    [R +0.004555] writeb 0x43f80008 0xf8
    [S +0.004576] OK
    [R +0.004581] readb 0x43f8000c
    [S +0.004585] OK 0x00000000000000a1
    [R +0.004586] writeb 0x43f80010 0x24
    [S +0.004590] OK
    [R +0.004591] readb 0x43f8000c
    [S +0.004593] OK 0x00000000000000a2
    [R +0.004594] writeb 0x43f8000c 0x00
    [S +0.004596] OK
    [R +0.004597] writeb 0x43f80010 0x9a
    [S +0.004600] OK
    [R +0.004601] readb 0x43f8000c
    [S +0.004602] OK 0x00000000000000a2
    [R +0.004604] writeb 0x43f8000c 0x00