# DF-2811 — SHT_SYMTAB/SHT_STRTAB sh_size truncated into int symcnt/strcnt → negative kmalloc()/vn_rdwr() lengths → kernel panic

## Build
```
python3 gen_exec_ko.py shsize-trunc.ko shsize-trunc
```

## Run
```
scp -F dfbsd-qemu/config shsize-trunc.ko dfbsd:/tmp/
dfbsd-qemu/vm.sh run_root 'kldload /tmp/shsize-trunc.ko; echo RC=$?'
dfbsd-qemu/vm.sh log 30
```

## Expected (stock kernel, verified 2026-09-01)
```
panic: kmem_slab_alloc(): kernel_map ran out of space!
Trace:
kmem_slab_alloc() at kmem_slab_alloc+0x42b
_kmalloc() at _kmalloc+0x5be
link_elf_load_file() at link_elf_load_file+0x5cb
linker_load_file.part.3() ...
```

## Expected (patched kernel)
```
kldload: Symbol table too large, RC=1, guest stays up
```

## Why (root cause, sys/kern/link_elf.c)
The ddb-symbol loading path stores 64-bit section sizes into signed 32-bit
ints and feeds them to kmalloc()/vn_rdwr() unchecked:

```c
414:  int symcnt;
415:  int strcnt;
...
610:  symcnt = shdr[symtabindex].sh_size;      /* Elf64_Xword -> int */
611:  ef->symbase = kmalloc(symcnt, ...);      /* 0x80000100 -> -2147483392 */
612:  strcnt = shdr[symstrindex].sh_size;
613:  ef->strbase = kmalloc(strcnt, ...);
614:  vn_rdwr(UIO_READ, vp, ef->symbase, symcnt, ...);   /* huge size_t */
```

`sh_size = 0x80000100` (> INT_MAX) truncates to the negative int
-2147483392; sign-extension turns it into a ~2^63 kmalloc() which
kmem_slab_alloc cannot satisfy → panic (with M_WAITOK and no M_NULLOK the
allocator panics instead of returning NULL). A `sh_size` in
(0x100000000+x) wraps modulo 2^32 and yields an under-sized allocation
silently accepted as a "successfully loaded" symbol table; the reads at
:614/:619 also ignore `resid`, so short files leave the non-M_ZERO buffers
partially populated with stale kernel heap that is then parsed as
Elf_Sym/string data by link_elf_lookup_symbol's exhaustive fallback
(:846-858) and link_elf_search_symbol (:899-913).

Sibling int math in the same path: `nbytes = hdr->e_shnum *
hdr->e_shentsize` (:590) can overflow int for e_shentsize near 0xffff
(kept in check only after the e_shentsize==sizeof(Elf_Shdr) validation
added by fix.diff).
