# DF-2903 — Ontrack branch releases a pbuf via brelse() → panic from crafted MBR

## What
`mbrinit()`'s "Ontrack Disk Manager" path (sys/kern/subr_diskmbr.c:174-182)
does:

```c
bp->b_flags |= B_INVAL | B_AGE;
brelse(bp);              /* bp is a getpbuf_mem() PBUF — must be relpbuf()! */
mbr_offset = 63;
goto reread_mbr;
```

`bp` comes from `getpbuf_mem()` (subr_diskmbr.c:127) — a paging buffer with
`B_PAGING` set (vm/vm_pager.c:387).  Releasing it through `brelse()` is a
buffer-subsystem violation: on INVARIANTS kernels `brelse()`'s
`KASSERT(!(bp->b_flags & (B_CLUSTER|B_PAGING)))` (vfs_bio.c:1275) panics
immediately; on production (non-INVARIANTS) kernels the pbuf is handed to
the buffer-cache free machinery while the pbuf subsystem still owns it —
cross-subsystem buffer lifecycle corruption plus one pbuf leaked out of
`bswlist_mem` per attach (eventual `getpbuf_mem()` exhaustion wedging all
paging/probe I/O).

History: the FreeBSD original used `geteblk()` (a normal buffer, where
`brelse` is correct).  DragonFly converted the reads to `getpbuf_mem()` and
fixed the `done:` path to `relpbuf()` (subr_diskmbr.c:316) but missed the
Ontrack branch.

## Observed (stock INVARIANTS guest)
A single MBR partition-table entry of type 0x54 (DOSPTYP_ONTRACK) plus a
valid 0x55AA magic panics the kernel at disk-probe time:

```
panic: brelse: inappropriate B_PAGING or B_CLUSTER bp 0xfffff8004f3df690
brelse() at brelse+0x7f2
mbrinit() at mbrinit+0x1ae
disk_probe() at disk_probe+0x85
disk_msg_core() at disk_msg_core+0x252
```
(panic.txt — reproduced 2026-09-03, trigger: `vnconfig -c vn0 ontrack.img`.)

Secondary latent bug (same branch): once the release is fixed to `relpbuf()`,
the `goto reread_mbr` loop is unbounded — an Ontrack entry also present at
LBA 63 (offset 63*512) makes mbrinit re-read forever, wedging disk_msg_core
which holds `ds_token` (subr_disk.c:512) → every subsequent open of any disk
device in the system blocks forever.  The fix therefore also makes the
re-read one-shot (`mbr_offset == DOSBBSECTOR`).

## Threat
Runs with kernel privilege at disk attach: USB plug-in auto-probe (devd/CAM),
boot-time probe of an Ontrack-formatted disk, or root `vnconfig` of a crafted
image.  One crafted sector = guaranteed panic (INVARIANTS) / buffer-subsystem
corruption (production).

## Reproduce (guest, root)
```
python3 mkontrack.py                    # or use the shipped ontrack.img
vnconfig -c -v -S 512 vn0 ontrack.img   # stock kernel: instant panic (panic.txt)
```
Success criterion (stock): panic above; after fix.diff: attach completes
cleanly, /dev/vn0s1 appears, no panic (run_fix.log).
