# DF-3427 — SET_MBUF_DESTRUCTOR / generic_mbuf_destructor ABI incoherence (VERIFIED)

The rig, build and run instructions are shared with DF-3426 (this pack
carries its own copies of the sources; see `../DF-3426/README.md`).

## Build (guest, root)
    ./build.sh          # verbatim-production netmap.ko + ./trigger

## Run (guest, root)
    ./run.sh evt                  # arming in isolation (dormant, no panic)
    ./run.sh uaf 512 4096 16384   # detonation: destructor fires inside a
                                  # recycled LIVE UDP mbuf -> Fatal trap 12

## Expected output
- `evt`: RIG trace `generic_set_tx_event e=511` (a slot already freed in
  the same lap) then nothing; guest alive but `netstat -m` underflows at
  close (the DF-3426 double frees).
- `uaf`: `RIG: generic_mbuf_destructor CALLED m=<mbcluster>` followed by
  the `m_free ← m_freem ← udp_input ← ip_input ← netmsg_service_loop`
  backtrace and `Fatal trap 12: page fault while in kernel mode`,
  `Stopped at generic_mbuf_destructor+0x3f: testb $0x80,0x75(%rdi)`,
  fault address 0x76 / 0xffffffff00000076 — the OOB-read `rcvif` garbage
  dereferenced as `ifp->if_capenable`.  Guest dead in DDB.

## Fix validation
    cd netmap-src && patch -p4 < ../fix.diff (macro no-op + __unused)
    # combined with the DF-3426 fix; all PoC modes rc=0, flat counters,
    # ZERO destructor callbacks (fix_run.log / fix_build.log)

## Verdict
reproduced — the ABI incoherence detonated at runtime with the exact
predicted crash signature; mechanism refined (see VERDICT.md): the armed
mbuf's own free never calls ext_free (CLCACHE branch); the stale
`ext_free=generic_mbuf_destructor` survives objcache magazine recycling
(no ctor re-run) and detonates in whichever subsystem next recycles the
mbuf — demonstrated in udp_input.  Full narrative: VERDICT.md.
