# DF-5713 — stack_protector.c: kernel stack-smashing protection is a no-op

## What this PoC proves (all demonstrated live on the QEMU guest)

1. **The canary is a compile-time constant, never seeded.**
   `sys/libkern/stack_protector.c:36` (`int __guard = 0x00000aff;`) is the
   only definition/assignment of `__guard` in the entire tree (tree-wide
   grep). Live proof:
   - `/dev/kmem` read of the running kernel's `__guard`
     (`0xffffffff8113bae0`): `ff 0a 00 00` = `0x00000aff` — run.2.log
   - KLD `guard_probe.ko` reads the exported symbol: `__guard=0xaff`
     — run.2.log / msgbuf
   - The shipped `/boot/kernel/kernel` ELF `.data` cell at the symbol
     address holds `ff0a0000` — identical, i.e. nothing rewrote it at boot.
   - **Two independent fresh boots** (`vm.sh reset with-src`) read the same
     `ff 0a 00 00` — no per-boot seeding exists (run.2.log, run.4.log).

2. **The modern stack-protector ABI does not exist in the kernel.**
   `sys/` contains no `__stack_chk_guard`/`__stack_chk_fail` definition
   (tree-wide grep) and `nm /boot/kernel/kernel` confirms absence. A KLD
   compiled with `-fstack-protector-all` (ssp_smash_ssp.ko, manually built
   because the build system strips the flag) fails to load:
   `link_elf_obj_obj: symbol __stack_chk_guard undefined` — panic.txt /
   console_full.log.

3. **Kernel code is force-built WITHOUT any stack protector.**
   `sys/platform/pc64/conf/kern.mk:7` — `CFLAGS+= -fno-stack-protector ...`
   (grep of the guest's `/usr/src`). The default-built `ssp_smash.ko`
   performs a 48-byte `strcpy` into a 16-byte kernel-stack buffer and the
   kernel dies instantly with the saved frame pointer smashed:
   `frame pointer = 0x10:0x4242424242424242 ... Stopped at boom+0x2c: ret`
   — panic.txt. No canary sits between the buffer and the saved frame.

4. **The legacy fail path works but is attached to nothing.**
   `guard_panic.ko` calls `__stack_smash_handler()` directly →
   `panic: stack overflow in function guard_panic_smash_test` — panic2.txt.

## Build

    # on the guest (sources pushed via the pack below):
    cc -O2 -o /tmp/guest/guard_read /tmp/guest/guard_read.c
    cd /tmp/guest/guard_probe && make -m /usr/share/mk
    cd /tmp/guest/guard_panic && make -m /usr/share/mk
    cd /tmp/guest/ssp_smash    && make -m /usr/share/mk        # default (no SSP)
    # SSP variant (build system strips -fstack-protector-all, so compile by hand):
    cc <kern flags> -fstack-protector-all -c ssp_smash.c -o ssp_smash_ssp.o
    cc -nostdlib -r -o ssp_smash_ssp.ko ssp_smash_ssp.o        # exact flags in build.log

## Run

    /tmp/guest/guard_read 0xffffffff8113bae0 /dev/kmem   # -> ff 0a 00 00, rc=42
    kldload /tmp/guest/ssp_smash/ssp_smash_ssp.ko        # -> Undefined symbol __stack_chk_guard
    kldload /tmp/guest/guard_probe/guard_probe.ko        # -> __guard=0xaff
    kldload /tmp/guest/ssp_smash/ssp_smash.ko            # -> kernel GPF, fp=0x4242...42 (PANIC)
    kldload /tmp/guest/guard_panic/guard_panic.ko        # -> panic: stack overflow in function ... (PANIC)
    # leave the guest clean:  vm.sh reset with-src

## Expected results

See the four numbered points above; all captured in build.log, run.log,
run.2.log, run.3.log, run.4.log, panic.txt, panic2.txt, console_full.log.
