# PoC DF-4781 — unchecked `contigmalloc` in dcons_drv_init → NULL-deref panic at kldload (REPRODUCED)

## What this proves

`dcons_drv_init()` (sys/dev/misc/dcons/dcons_os.c:462-464) does not check
`contigmalloc()` for NULL before calling `dcons_init(dg.buf, dg.size, sc)`.
The very first thing `dcons_init()` does is write the shared-buffer header:

```
dcons_init_port():	buf->osize[port] = htonl(osize);	/* dcons.c:147 */
```

so a failed allocation is an immediate NULL+0x14 store — `Fatal trap 12`
at `kldload dcons` time.

The trigger is `contigmalloc(16KB, M_DEVBUF, M_NOWAIT /* flags=0 */, ...)` 
failing under kernel-memory pressure (it is called with M_NOWAIT, so it can
legitimately return NULL).

## Reproduce (guest, root)

```
cd /root/dconsrig && make
kldload dcons                       # baseline: module loads fine
kenv dconsnull.mode=1               # simulate the allocation failure
kldload ./dconsnull.ko              # -> panic (Fatal trap 12, va=0x14)
```

`dconsnull.c` calls the *same* exported `dcons_init()` entry that
`dcons_drv_init()` calls on the allocation-failure path.

## Expected output (serial console)

```
dconsnull: loaded, mode=1
dconsnull: DF-4781: calling dcons_init(NULL, 16384, sc) -- unchecked contigmalloc sink
Fatal user address access from kernel mode from kldload at ...
Fatal trap 12: page fault while in kernel mode
fault virtual address  = 0x14
fault code             = supervisor write data, page not present
Stopped at      dcons_init_port+0x83:   movl    %edi,0x14(%rcx)
```

`0x14` is `offsetof(struct dcons_buf, osize[0])` — exactly the store that
runs on the unchecked-NULL path.

## Negative control

`kenv dconsnull.mode=0` runs the identical `dcons_init()`+`dcons_putc()`
calls on a valid 16KB buffer and prints
`dconsnull: NEGCTRL init+putc OK` — the crash is specific to the NULL.
