HMP expression evaluator signed integer overflow reaches xp physical-memory address

Host environment

  • Operating system: Ubuntu 24.04.5 LTS (Noble Numbat)
  • OS/kernel version: Linux bea1e-HP-ZHAN66-14-G1a-AI 6.17.0-40-generic #40~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue Jun 23 16:48:12 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
  • Architecture: x86_64
  • QEMU flavor: qemu-system-x86_64
  • QEMU version: QEMU emulator version 11.1.50 (v11.1.0-1360-g209b2afafa)
  • QEMU command line:
    ./build/qemu-system-x86_64 -M none -nographic -S -qmp unix:/tmp/qemu-poc-m02.sock,server=on,wait=off -no-shutdown

Emulated/Virtualized environment

  • Operating system: N/A (-M none; no guest was started)
  • OS/kernel version: N/A
  • Architecture: N/A

Description of problem

AI-assisted static auditing was used to discover this issue. I manually reviewed the reported code path, built the latest upstream qemu.git master from source, and reproduced the behavior directly against that build. The exact tested revision is 209b2afaface001c7d4d981e38f186afe7b24a50.

The HMP expression evaluator in monitor/hmp.c performs signed int64_t arithmetic without detecting overflow. On the tested master revision, multiplication in expr_prod() uses val *= val2 at monitor/hmp.c:574, while addition and subtraction in expr_sum() use val += val2 and val -= val2 at monitor/hmp.c:635-637.

The expression result is accepted for an HMP l argument and stored with qdict_put_int() at monitor/hmp.c:1033. For the xp command, hmp_physical_memory_dump() obtains that value as an hwaddr, and memory_dump() passes it to address_space_read() at monitor/hmp-cmds.c:645.

For example, the mathematical result of 2*4611686018427387904 is 9223372036854775808 (INT64_MAX + 1). On the tested build, HMP silently produces 0x8000000000000000 and accepts the wrapped value as the address supplied to xp:

p 2*4611686018427387904
0x8000000000000000

xp /1x 2*4611686018427387904
8000000000000000: Cannot access memory

Expected behavior is for the parser to reject an arithmetic expression whose result is outside the int64_t range, rather than execute signed-overflow undefined behavior and pass the resulting value to a command handler.

Security scope: reaching this code requires access to HMP, directly or through QMP human-monitor-command. QEMU documents the monitor as a privileged control interface, and an authorized monitor client can already request arbitrary addresses with xp. The reproducer confirms the arithmetic bug and its propagation into the physical-memory read path, but it does not establish an additional authorization bypass, disclosure of mapped memory, host crash, or guest-to-host escape. I am filing confidentially so maintainers can determine whether this behavior has a meaningful misuse case within QEMU's security boundary.

Steps to reproduce

  1. Fetch and build upstream QEMU master. The exact tested commit was 209b2afaface001c7d4d981e38f186afe7b24a50:

    git clone https://gitlab.com/qemu-project/qemu.git
    cd qemu
    git checkout 209b2afaface001c7d4d981e38f186afe7b24a50
    ./configure --target-list=x86_64-softmmu --disable-werror --enable-debug --disable-docs
    ninja -C build qemu-system-x86_64
  2. Save the attached poc.py, then run it against the resulting binary:

    python3 poc.py ./build/qemu-system-x86_64
  3. Observe that p 2*4611686018427387904 returns 0x8000000000000000, and that xp /1x 2*4611686018427387904 reports the same wrapped value as its physical address before returning Cannot access memory under -M none.

Additional information

Exact upstream revision and commit date:

209b2afaface001c7d4d981e38f186afe7b24a50
2026-09-10T22:02:18-10:00
Merge tag 'pull-parallels-2026-09-11' of https://gitlab.com/dlunev/qemu into staging

Relevant current-master code path:

HMP command string
  -> monitor_parse_arguments()
  -> get_expr()
  -> expr_prod() / expr_sum()
  -> qdict_put_int(qdict, key, val)
  -> hmp_physical_memory_dump()
  -> memory_dump()
  -> address_space_read()

The minimal reproducer uses -M none, so no MemoryRegion is mapped at the wrapped address and address_space_read() returns an error. No QEMU crash was observed. The result should not be described as confirmed information disclosure without a separate mapped-region reproducer showing an access that the same monitor client could not request directly.

A robust fix should use checked arithmetic for multiplication, addition, and subtraction and report an HMP expression error on overflow. The same audit should cover unary negation of INT64_MIN, division/remainder of INT64_MIN by -1, and M-suffix scaling, which are related signed-arithmetic edge cases but are not all exercised by the attached reproducer.

Attached source-code test case: poc.py. It was created for this report and is included as auditable Python source; it was not obtained from a third party.

poc.py