# DF-0406 — in_delayed_cksum unchecked m_pullup return

## Bug (certain by inspection)
`sys/netinet/ip_output.c:940-951`:
```c
if (offset + sizeof(u_short) > m->m_len) {
    kprintf("delayed m_pullup, m->len: %d  off: %d  p: %d\n", ...);
    /*
     * XXX
     * this shouldn't happen, but if it does, the
     * correct behavior may be to insert the checksum
     * in the existing chain instead of rearranging it.
     */
    m = m_pullup(m, offset + sizeof(u_short));   /* <-- return NOT checked */
}
*(u_short *)(m->m_data + offset) = csum;         /* <-- NULL deref if m_pullup fails */
```
The comment "this shouldn't happen but if it does" acknowledges the
possibility without actually handling the failure. If `m_pullup` returns
NULL (memory pressure), the assignment writes to address `0 + offset` →
panic.

## Trigger requirements
1. The egress interface must NOT advertise `CSUM_DELAY_DATA` in
   `if_hwassist` (otherwise `ip_output:641` skips `in_delayed_cksum`).
   `vtnet0` and `lo0` both advertise TX csum offload by default, so on the
   default guest `ifconfig vtnet0 -txcsum -rxcsum` is required to make
   `in_delayed_cksum` actually run on TX.
2. The checksum field must straddle an mbuf boundary
   (`offset + sizeof(u_short) > m->m_len`). Normal UDP/TX packs the whole
   packet into a single mbuf cluster, so `m->m_len` equals the full packet
   length and the straddle `if` is never entered. The straddle needs a
   multi-mbuf chain whose first mbuf ends near `offset` (typically 26 for
   UDP, 36 for TCP, more with IP options) — an unusual layout.
3. `m_pullup` must return NULL — i.e., memory pressure.

## Build / Run
```
cc -O2 -Wall -o df_0406_cksum df_0406_cksum.c
cc -O2 -Wall -o df_0406_sf   df_0406_sf.c
```
Setup (as root): `ifconfig vtnet0 -txcsum -rxcsum`
Run (as any user): `./df_0406_cksum 10.0.2.2 9` and `./df_0406_sf 10.0.2.2 9`

## Expected
* BUG (live, requires straddle + memory pressure): kernel panic
  `Fatal trap 12: page fault while in kernel mode` at the assignment in
  `in_delayed_cksum`.
* LIVE (this guest): `in_delayed_cksum` is called for every TX packet but
  the straddle `if` is never entered (single-mbuf TX). No `delayed m_pullup`
  kprintf, no panic. Code-certain; non-deterministic live trigger.
* FIX: drop the packet on `m_pullup` failure instead of dereferencing NULL.

## Reality
Code-certain CWE-690 / CWE-476. The path runs on every TX when HW csum is
disabled, but the straddle condition requires unusual mbuf-chain layout and
the NULL-deref additionally requires memory pressure. Non-deterministic on
this guest; the fix is trivially correct.
