DF-0622 / args_overflow.c
/* * DF-0622 — ng_car_disconnect NULL-deref panic PoC (DEMONSTRATION ONLY). * * *** THE ng_car MODULE CANNOT BE LOADED ON THIS KERNEL *** * * sys/netgraph7/ng_car.c references three FreeBSD-isms that DO NOT EXIST in * DragonFlyBSD: * * line 62, 588: struct bintime (no such type in sys/) * line 210, 592: getbinuptime() (no such function in sys/) * line 596: bintime_sub() (no such function in sys/) * * grep -rln "struct bintime" sys/ => ONLY sys/netgraph7/ng_car.c * * The file is therefore NOT in any build Makefile (`sys/netgraph7/Makefile` * SUBDIR list) and no ng_car.ko ships in /boot/kernel/. Trying to build it * standalone fails immediately at compile time: * * ng_car.c:596:2: error: implicit declaration of function 'bintime_sub' * ng_car.c:588:17: error: unused variable 'newt' [-Werror=unused-variable] * * The bug pattern identified by the finding is REAL in the source: * * * ng_car_shutdown (ng_car.c:539-540) correctly does: * ng_uncallout(&priv->upper.q_callout, node); * ng_uncallout(&priv->lower.q_callout, node); * * * ng_car_disconnect (ng_car.c:553-580) does NOT — it only purges the * mbuf queue (NG_FREE_M each entry NULLs the slot at :563) and clears * hook refs (:569-573). A pending callout therefore survives and later * fires ng_car_q_event, whose drain loop has no empty-queue guard: * * 676: while (hinfo->tc >= 0) { * 679: m = hinfo->q[hinfo->q_first]; // NULL (purged) * 695: m = hinfo->q[hinfo->q_first]; // another NULL * 699: hinfo->tc -= m->m_pkthdr.len; // NULL DEREF -> panic * * But the runtime trigger path is **unreachable on this kernel** because * the module cannot be loaded. Classification: real bug in DEAD CODE. * * This file documents what the PoC WOULD do if ng_car.c were ported. It is * kept here to demonstrate the trigger logic and as a ready-to-run PoC for * whenever the module is fixed upstream. */ /* * The PoC would use the standard ng_socket control socket API: * * 1. open AF_NETGRAPH / control socket * 2. ngctl mkpeer car upper socket lower * -> creates a `car` node with two ng_socket peers * 3. NGM_CAR_SET_CONF on the upper hook: * mode = NG_CAR_SHAPE * cir = 10240 (small committed rate so packets queue) * cbs = 8192 * ebs = 8192 * 4. Send a burst of >100 packets on the upper data hook * -> fills the SHAPE queue, schedules ng_car_q_event callout * 5. While the callout is pending, ngctl rmhook on the upper hook * -> ng_car_disconnect purges queue, does NOT uncallout * 6. Within a few ticks the callout fires ng_car_q_event, reads NULL mbuf, * NULL-derefs at m->m_pkthdr.len -> Fatal trap 12: page fault in * kernel mode. * * Requires root (NGF_NETGRAPH control socket is privileged). */ #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> /* * A full C implementation against the netgraph control socket is large and * error-prone; for an admin-reproducible trigger, the equivalent ngctl(8) * script is provided in ng_car_trigger.sh. */ int main(void) { fprintf(stderr, "DF-0622: ng_car.ko CANNOT be loaded on this kernel\n" "(struct bintime / getbinuptime / bintime_sub are unported\n" " FreeBSD-isms; the module is not built, not in the SUBDIR\n" " Makefile, and not in /boot/kernel/). The bug pattern is\n" " confirmed in the source (see VERDICT.md). The runtime trigger\n" " requires a ported ng_car.ko.\n" "\n" "See ng_car_trigger.sh for the ngctl sequence that would fire\n" "the panic on a kernel with a working ng_car module.\n"); return 0; } |