Null Dereference in pnv_phb3
<!--
This is the upstream QEMU issue tracker.
If you are able to, it will greatly facilitate bug triage if you attempt
to reproduce the problem with the latest qemu.git master built from
source. See https://www.qemu.org/download/#source for instructions on
how to do this.
QEMU generally supports the last two releases advertised on
https://www.qemu.org/. Problems with distro-packaged versions of QEMU
older than this should be reported to the distribution instead.
See https://www.qemu.org/contribute/report-a-bug/ for additional
guidance.
If this is a security issue, please consult
https://www.qemu.org/contribute/security-process/
-->
## Version
commit: 2339d0a1cf
tag: v10.2.0-690-g2339d0a1cf
## Description of the issue
This issue is a NULL pointer dereference caused by a cross-module input chain:
1. External input enters through the PHB3 SPCI XSCOM window (`hw/pci-host/pnv_phb3_pbcq.c`).
2. Writing `PHB_FFI_REQUEST` triggers `pnv_phb3_msi_ffi()` (`hw/pci-host/pnv_phb3.c`).
3. `pnv_phb3_msi_ffi()` calls `pnv_phb3_msi_send()`, and then `qemu_irq_pulse()` reaches `phb3_msi_set_irq()` (`hw/pci-host/pnv_phb3_msi.c`).
4. `phb3_msi_set_irq()` calls `phb3_msi_try_send()`, which reads and parses `server/prio/PQ` from the IVE table.
5. `phb3_msi_try_send()` directly calls `icp_irq(ics, server, ...)` when not masked.
6. Inside `icp_irq()`, `xics_icp_get(ics->xics, server)` is called; when `server` is invalid it returns `NULL`, but the code immediately evaluates `CPPR(icp)`/`XISR(icp)`, causing a NULL dereference.
Therefore, the core issue is: controllable `IVE.server` lacks bounds validation, and `icp_irq()` lacks a NULL check on the return value of `xics_icp_get()`.
```c
/* hw/intc/xics.c */
void icp_irq(ICSState *ics, int server, int nr, uint8_t priority)
{
ICPState *icp = xics_icp_get(ics->xics, server);
...
if ((priority >= CPPR(icp)) || ...) { // <--- icp can be NULL
...
}
}
```
Direct impact: QEMU process crash (DoS).
## Steps to Reproduce
### Configure QEMU
```bash
mkdir build && cd build
CC=clang \
../configure --target-list=ppc64-softmmu --enable-debug --disable-strip \
--extra-cflags="-fsanitize=address -fno-omit-frame-pointer -O1" \
--extra-ldflags="-fsanitize=address"
ninja -j"$(nproc)" qemu-system-ppc64
```
### Trigger the bug
Run in `build/`:
```bash
cat << "EOF" | ./qemu-system-ppc64 \
-M powernv8 -accel tcg -cpu POWER8 \
-display none \
-serial none -monitor none \
-qtest stdio -S \
-d guest_errors -D /tmp/phb3.log \
-trace enable=xics_icp_irq
readq 0x3fc0000f00078
writeq 0x3fc0020120428 0x1800000000000000
writeq 0x3fc009013c000 0x150
writeq 0x3fc009013c010 0x8000000000200100
writeq 0x200010 0xffffff0100000000
writeq 0x3fc009013c000 0x238
writeq 0x3fc009013c010 0x10
EOF
```
### Crash stack
ASAN crash trace:
```text
==115213==ERROR: AddressSanitizer: SEGV on unknown address 0x0000000000a8 (pc 0x5bfa981ba504 bp 0x7ffebf2038f0 sp 0x7ffebf2038a0 T0)
==115213==The signal is caused by a READ memory access.
==115213==Hint: address points to the zero page.
#0 0x5bfa981ba504 in icp_irq /home/kiki/bug-verify/qemu-test/build/../hw/intc/xics.c:225:22
#1 0x5bfa981fa961 in phb3_msi_try_send /home/kiki/bug-verify/qemu-test/build/../hw/pci-host/pnv_phb3_msi.c:132:13
#2 0x5bfa981fa62b in phb3_msi_set_irq /home/kiki/bug-verify/qemu-test/build/../hw/pci-host/pnv_phb3_msi.c:152:9
#3 0x5bfa9828d95b in qemu_set_irq /home/kiki/bug-verify/qemu-test/build/../hw/core/irq.c:34:5
#4 0x5bfa981f9896 in qemu_irq_pulse /home/kiki/bug-verify/qemu-test/include/hw/core/irq.h:33:5
#5 0x5bfa981f9896 in pnv_phb3_msi_send /home/kiki/bug-verify/qemu-test/build/../hw/pci-host/pnv_phb3_msi.c:181:5
#6 0x5bfa981f9896 in pnv_phb3_msi_ffi /home/kiki/bug-verify/qemu-test/build/../hw/pci-host/pnv_phb3_msi.c:187:5
#7 0x5bfa981f546a in pnv_phb3_reg_write /home/kiki/bug-verify/qemu-test/build/../hw/pci-host/pnv_phb3.c:566:9
#8 0x5bfa981fc7e6 in pnv_pbcq_spci_xscom_write /home/kiki/bug-verify/qemu-test/build/../hw/pci-host/pnv_phb3_pbcq.c:196:9
#9 0x5bfa97c6decf in memory_region_write_accessor /home/kiki/bug-verify/qemu-test/build/../system/memory.c:491:5
#10 0x5bfa97c6dac5 in access_with_adjusted_size /home/kiki/bug-verify/qemu-test/build/../system/memory.c:562:18
#11 0x5bfa97c6d746 in memory_region_dispatch_write /home/kiki/bug-verify/qemu-test/build/../system/memory.c
#12 0x5bfa97c9a7c1 in address_space_stq_internal /home/kiki/bug-verify/qemu-test/build/../system/memory_ldst.c.inc:440:13
#13 0x5bfa97c9a42b in address_space_stq /home/kiki/bug-verify/qemu-test/build/../system/memory_ldst.c.inc:471:5
#14 0x5bfa97f6243a in xscom_write /home/kiki/bug-verify/qemu-test/build/../hw/ppc/pnv_xscom.c:188:5
#15 0x5bfa97c6decf in memory_region_write_accessor /home/kiki/bug-verify/qemu-test/build/../system/memory.c:491:5
#16 0x5bfa97c6dac5 in access_with_adjusted_size /home/kiki/bug-verify/qemu-test/build/../system/memory.c:562:18
#17 0x5bfa97c6d746 in memory_region_dispatch_write /home/kiki/bug-verify/qemu-test/build/../system/memory.c
#18 0x5bfa97ca2675 in flatview_write_continue_step /home/kiki/bug-verify/qemu-test/build/../system/physmem.c:3272:18
#19 0x5bfa97c942f3 in flatview_write_continue /home/kiki/bug-verify/qemu-test/build/../system/physmem.c:3302:19
#20 0x5bfa97c942f3 in flatview_write /home/kiki/bug-verify/qemu-test/build/../system/physmem.c:3333:12
#21 0x5bfa97c93fb4 in address_space_write /home/kiki/bug-verify/qemu-test/build/../system/physmem.c:3453:18
#22 0x5bfa97ca8881 in qtest_process_command /home/kiki/bug-verify/qemu-test/build/../system/qtest.c:537:13
#23 0x5bfa97ca8881 in qtest_process_inbuf /home/kiki/bug-verify/qemu-test/build/../system/qtest.c:777:9
#24 0x5bfa97cac8c6 in qtest_read /home/kiki/bug-verify/qemu-test/build/../system/qtest.c:786:5
#25 0x5bfa984bdd28 in qemu_chr_be_write_impl /home/kiki/bug-verify/qemu-test/build/../chardev/char.c:214:9
#26 0x5bfa984bdd28 in qemu_chr_be_write /home/kiki/bug-verify/qemu-test/build/../chardev/char.c:226:9
#27 0x5bfa984c297d in fd_chr_read /home/kiki/bug-verify/qemu-test/build/../chardev/char-fd.c:72:9
#28 0x5bfa982bf7a4 in qio_channel_fd_source_dispatch /home/kiki/bug-verify/qemu-test/build/../io/channel-watch.c:84:12
#29 0x772b54b7ac43 in g_main_context_dispatch (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x55c43) (BuildId: 6b4f160dbc5397c2f502dc4f08a8cff259917926)
#30 0x5bfa98672cd4 in glib_pollfds_poll /home/kiki/bug-verify/qemu-test/build/../util/main-loop.c:290:9
#31 0x5bfa98672cd4 in os_host_main_loop_wait /home/kiki/bug-verify/qemu-test/build/../util/main-loop.c:313:5
#32 0x5bfa98672cd4 in main_loop_wait /home/kiki/bug-verify/qemu-test/build/../util/main-loop.c:592:11
#33 0x5bfa97caff59 in qemu_main_loop /home/kiki/bug-verify/qemu-test/build/../system/runstate.c:903:9
#34 0x5bfa984cddb0 in qemu_default_main /home/kiki/bug-verify/qemu-test/build/../system/main.c:50:14
#35 0x5bfa984cdd7c in main /home/kiki/bug-verify/qemu-test/build/../system/main.c:93:9
#36 0x772b54629d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#37 0x772b54629e3f in __libc_start_main csu/../csu/libc-start.c:392:3
#38 0x5bfa9753a344 in _start (/home/kiki/bug-verify/qemu-test/build/qemu-system-ppc64+0xc62344) (BuildId: f47b8dca3e4a85b38916ef915dde03aa666fa530)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/kiki/bug-verify/qemu-test/build/../hw/intc/xics.c:225:22 in icp_irq
==115213==ABORTING
```
<!--
Attach logs, stack traces, screenshots, etc. Compress the files if necessary.
If using libvirt, libvirt logs and XML domain information may be relevant.
-->
<!--
The line below ensures that proper tags are added to the issue.
Please do not remove it.
-->
issue