DF-3533 / verdict.json
{ "finding_id": "DF-3533", "status": "reproduced", "reproduced": 1, "impact": "none", "confidence": "certain", "verdict": "The dangling-pointer condition is reproduced mechanically and confirmed LATENT exactly as filed (downgraded Low). ttyprobe.c pre-created a netgraph node named 'tty0' (echo node via generic NGM_MKPEER+NGM_NAME, held open), then issued TIOCSETD NETGRAPHDISC(6) on a pty slave: v1 ngt_open (ng_tty.c:200-231) installs tp->t_sc = sc at :225 BEFORE naming the node, and the pre-created 'tty0' forces ng_name_node to fail - ioctl returned -1 errno=48 (EADDRINUSE) and the kernel log printed 'tty0: node name exists?' (ng_tty.c:227), proving the error branch executed. That branch runs ng_rmnode(sc->node) -> ngt_shutdown, which bzero+kfree's sc synchronously WITHOUT clearing tp->t_sc (verified: no t_sc assignment on that path; the free is single-threaded in the caller, so the dangling store is certain). Guest stayed healthy; TIOCGETD showed the discipline unchanged (0) and a second TIOCSETD plus a restore completed cleanly - the tty core never dispatches through the stale pointer (all ngt_* entry points are t_line-gated), matching the finding's own latent-landmine assessment. No user-visible manifestation by construction; the stale pointer is only overwritten by a later successful TIOCSETD or destroyed with the tty.", "evidence": "run.log (ttyprobe output: EADDRINUSE first set, discipline unchanged, second set ok, guest alive; syslog 'tty0: node name exists?'), ttyprobe.c, kshold.c", "kernel_refs": [ "sys/netgraph/tty/ng_tty.c:225", "sys/netgraph/tty/ng_tty.c:226", "sys/netgraph/tty/ng_tty.c:228", "sys/netgraph/tty/ng_tty.c:230" ], "poc_changes": "written fresh (pty via /dev/ptmx + ptsname; NETGRAPHDISC=6 from sys/ttycom.h)", "attempts": 1, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 60, "guest_dirty": 0, "build_cmd": "gcc -O -o ttyprobe ttyprobe.c; kshold e1 e0 echo tty0 &", "run_cmd": "./ttyprobe", "code_hash": "d6e1928af8d2d09ea507aa94aeb0c85366491ad6c503f10e195b01d050cfa018", "notes": "v1 ng_tty module ships in /boot/kernel and loads/works on stock; this finding's path is stock-reachable (no constructor issue).", "recommended_fix": "in the ng_name_node failure branch set tp->t_sc = NULL before/after ng_rmnode (order the rmnode after clearing the back-pointer)." } |