# PoC DF-1511: vga_switcheroo_force_migd NULL deref racing unregister_handler

**Class:** NULL pointer deref (race)
**Cited site:** `sys/dev/video/vga/vga_switcheroo.c:1225-1238`

## Reproduction status

HW/module gated — **cannot be live-triggered on the audit QEMU guest.**

No — vga_switcheroo is part of vga.ko and only meaningful on dual-GPU laptops with a gmux mux. The audit guest has no such HW; trigger is concurrent unregister_handler racing i915 force_migd.

The bug is **confirmed at the source level** by tracing the cited path:line in
`sys/dev/video/vga/vga_switcheroo.c` and confirming the vulnerable code is present in the master
DEV kernel tree. The `fix.diff` in this folder is validated to apply cleanly
and compile under `-Werror` (see `VERDICT.md`).

## Mechanism

vga_switcheroo_force_migd (1225-1238) acquires only `mux_hw_lk` and derefs `vgasr_priv->handler->switchto` with NO NULL check. Caller i915_drv.c:741-742 reads handler_flags (helper at 289-294 NO lock) THEN calls force_migd. Concurrent unregister_handler (263-278) sets handler=NULL under vgasr_mutex + mux_hw_lk. Window: i915 reads flags non-NULL, then handler becomes NULL before force_migd acquires mux_hw_lk → NULL deref of handler->switchto → panic.

## Realistic impact ceiling

panic (DoS, race)

## Fix

Inside force_migd (under mux_hw_lk), check `handler == NULL || handler->switchto == NULL` and return -ENODEV.

See `fix.diff` for the git-apply-able patch.

## How to validate the fix

```
# 1. Apply fix.diff against the in-guest source:
scp -F dfbsd-qemu/config fix.diff dfbsd:/root/DF-1511.diff
ssh -F dfbsd-qemu/config dfbsd 'cd /usr/src && patch -p1 < /root/DF-1511.diff'

# 2. Rebuild the affected module (preferred) or a single-fix kernel:
ssh -F dfbsd-qemu/config dfbsd 'cd /usr/src/sys/sys/dev/video/vga && make'

# 3. The compile must succeed with -Werror (it does — see build.log).
```
