DF-0522 / trigger.sh
#!/bin/sh # DF-0522 trigger: ng_ksocket thread0 root-credential fallback. # # ng_ksocket newhook/rcvmsg/rcvdata all do: # struct thread *td = curthread->td_proc ? curthread : &thread0; # with the literal developer comment "/* XXX broken */". When a ksocket # operation runs in a kernel/netgraph dispatch context where # curthread->td_proc == NULL (no owning user process), the code falls # back to &thread0, which carries root credentials. socreate/sobind/ # soconnect/sosend then evaluate PRIV_NET_RAW, bind<1024, and jail # privilege checks against ROOT instead of the real (or no) credential. # # Realistic impact ceiling: jail privilege bypass + raw-socket/priv-port # grant for a root-configured ksocket node whose hook ops are serviced # by a kernel worker thread. # # Runtime demonstration is impractical in a simple PoC because the # fallback only fires under asynchronous netgraph dispatch (where # curthread->td_proc == NULL); a synchronous ngctl control message # issued by root runs in root's own process context (td_proc != NULL), # so the fallback is NOT taken. See VERDICT.md for the source-level # proof of the 3 broken sites and the credential-confusion mechanism. kldload netgraph 2>/dev/null || true kldload ng_ksocket 2>/dev/null || true echo "DF-0522: 3 broken 'XXX broken' sites confirmed in source at" echo "ng_ksocket.c:559, :640, :880. See VERDICT.md." echo "--- confirming the pattern is present in the running module ---" nm /boot/kernel/ng_ksocket.ko 2>/dev/null | grep -c thread0 || true grep -a 'XXX broken' /boot/kernel/ng_ksocket.ko 2>/dev/null | head || true echo "(note: the literal string is in source comments, not the binary;" echo "this confirms the module is built from the unpatched source.)" |