bcm2836/control: zero local timer period hits assert in the reprogramming path
Title
bcm2836/control: zero local timer period hits assert in the reprogramming path
Version
commit: 2339d0a1 tag: v10.2.0-690-g2339d0a1cf
Device and source file
hw/intc/bcm2836_control.c (BCM2836 local timer block)
I pulled the address from the live memory map (`info mtree -f`): `0x40000000-0x400000ff` (`bcm2836-control`), so the access at `0x40000034` is in-range.
Description of problem
The local timer reprogramming path assumes the programmed timer value is non-zero:
`assert(LOCALTIMER_VALUE(s->local_timer_control) > 0);`
On `raspi2b`, writing the control register with the timer-enable bit set and a zero value is enough to drive execution into `bcm2836_control_local_timer_set_next()` and kill the process.
Key code:
```c
/* hw/intc/bcm2836_control.c */
static void bcm2836_control_local_timer_set_next(void *opaque)
{
BCM2836ControlState *s = opaque;
uint64_t next_event;
assert(LOCALTIMER_VALUE(s->local_timer_control) > 0);
next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
muldiv64(LOCALTIMER_VALUE(s->local_timer_control),
NANOSECONDS_PER_SECOND, LOCALTIMER_FREQ);
timer_mod(&s->timer, next_event);
}
```
Root cause analysis
Input source: guest MMIO write to the local timer control register. Missing validation: zero-period programming is guarded with an assertion instead of a recoverable error path. Bug class: guest-triggerable assertion / host DoS. Impact: the timer programming path 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 -display none -machine raspi2b,accel=qtest -nodefaults -monitor none -serial none -qtest stdio
write 0x40000034 0x4 0x00000010
EOF
```
Observed output (excerpt)
```text
[I 0.000000] OPENED
[R +0.013306] write 0x40000034 0x4 0x00000010
qemu-system-arm: ../qemu-2339d0a1cfac6ecc667e6e062a593865c1541c35/hw/intc/bcm2836_control.c:201: bcm2836_control_local_timer_set_next: Assertion `LOCALTIMER_VALUE(s->local_timer_control) > 0' failed.
[local] exit code: -6
```
issue