hw/display/exynos4210_fimd: hw_error() for illegal BLENDEQ coefficient
Title
exynos4210/fimd: illegal BLENDEQ coefficient reaches hw_error() during update
Version
commit: 2339d0a1 tag: v10.2.0-690-g2339d0a1cf
Device and source file
hw/display/exynos4210_fimd.c (`exynos4210.fimd`)
From the monitor-side `info mtree -f` dump, the repro sequence hits these mapped regions:
- `0x11c00000-0x11c04113` (`exynos4210.fimd`), so the access at `0x11c000a0` is in-range.
- `0x11c00000-0x11c04113` (`exynos4210.fimd`), so the access at `0x11c000a8` is in-range.
- `0x11c00000-0x11c04113` (`exynos4210.fimd`), so the access at `0x11c00100` is in-range.
- `0x11c00000-0x11c04113` (`exynos4210.fimd`), so the access at `0x11c00104` is in-range.
- `0x11c00000-0x11c04113` (`exynos4210.fimd`), so the access at `0x11c00044` is in-range.
- `0x11c00000-0x11c04113` (`exynos4210.fimd`), so the access at `0x11c00054` is in-range.
- `0x11c00000-0x11c04113` (`exynos4210.fimd`), so the access at `0x11c00020` is in-range.
- `0x11c00000-0x11c04113` (`exynos4210.fimd`), so the access at `0x11c00024` is in-range.
- `0x11c00000-0x11c04113` (`exynos4210.fimd`), so the access at `0x11c00248` is in-range.
- `0x11c00000-0x11c04113` (`exynos4210.fimd`), so the access at `0x11c00000` is in-range.
- `0x11c00000-0x11c04113` (`exynos4210.fimd`), so the access at `0x11c00180` is in-range.
Description of problem
The FIMD blend logic only accepts a fixed set of coefficient encodings. Anything else hits:
`hw_error("exynos4210.fimd: blend equation coef illegal value\n");`
What makes this interesting is that the crash is not at the write to `BLENDEQ` itself. I had to set up a minimal display state, program an illegal coefficient, and then trigger an update. Once the pipeline reaches the blend step, QEMU dies in the default case.
Key code:
```c
/* hw/display/exynos4210_fimd.c */
switch ((w->blendeq >> i * 6) & FIMD_BLENDEQ_COEF_MASK) {
case 0:
case 1:
case 2:
...
case 13:
...
break;
default:
hw_error("exynos4210.fimd: blend equation coef illegal value\n");
break;
}
```
Root cause analysis
Input source: guest register programming of `BLENDEQ`, followed by a display update. Missing validation: illegal coefficients are handled with `hw_error()`. Bug class: guest-triggerable fatal error / host DoS. Impact: a malformed but reachable display configuration aborts QEMU.
Steps to Reproduce
Configuration
```bash
./configure --target-list=arm-softmmu --enable-debug --disable-strip
make -j"$(nproc)"
```
Reproducer (qtest)
Once I had the mapped addresses from the running machine, the following qtest script reproduced it:
```bash
cat <<'EOF' | ./qemu-system-arm -M smdkc210 -nographic -display none -serial none -monitor none -nodefaults -qtest stdio -accel qtest
writel 0x11c000a0 0x40000000
writel 0x11c000a8 0x40001000
writel 0x11c00100 0x00000008
writel 0x11c00104 0x00000008
writel 0x11c00044 0x00000000
writel 0x11c00054 0x00000000
writel 0x11c00020 0x00000001
writel 0x11c00024 0x00000001
writel 0x11c00248 0x0000000e
writel 0x11c00000 0x00000003
writel 0x11c00180 0x01000000
writel 0x11c00180 0x00000000
EOF
```
Observed output (excerpt)
```text
[S +0.014099] OK
[R +0.014101] writel 0x11c00248 0x0000000e
[S +0.014102] OK
[R +0.014103] writel 0x11c00000 0x00000003
[S +0.014251] OK
[R +0.014263] writel 0x11c00180 0x01000000
qemu: hardware error: exynos4210.fimd: blend equation coef illegal value
CPU #0:
R00=00000000 R01=00000000 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00000000 R14=00000000 R15=00000000
PSR=400001d3 -Z-- A svc32
s00=00000000 s01=00000000 d00=0000000000000000
s02=00000000 s03=00000000 d01=0000000000000000
s04=00000000 s05=00000000 d02=0000000000000000
s06=00000000 s07=00000000 d03=0000000000000000
s08=00000000 s09=00000000 d04=0000000000000000
s10=00000000 s11=00000000 d05=0000000000000000
s12=00000000 s13=00000000 d06=0000000000000000
s14=00000000 s15=00000000 d07=0000000000000000
s16=00000000 s17=00000000 d08=0000000000000000
s18=00000000 s19=00000000 d09=0000000000000000
s20=00000000 s21=00000000 d10=0000000000000000
[local] exit code: -6
```
issue