net_add_domain publishes a domain into the global domains list before net_init_domain stubs its NULL pru_* entries β a socket created in the kldload window dispatches a NULL function pointer in the netisr protocol thread (guaranteed panic)
| Field | Value |
|---|---|
| ID | DF-2966 |
| Status | new |
| Severity | Low |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:L |
| CWE | CWE-362 β CWE-476 |
| File | sys/kern/uipc_domain.c |
| Lines | 137-140 (NULL fills :95-114; sinks: uipc_msg.c:355/513, netisr.c:370) |
| Area | kern/net |
| Confidence | certain |
| Discovered | 2026-09-02 |
| Pass | 2 (GLM 5.3 second pass) |
| Bucket | base:kern |
| Reported | pending |
| Known CVE | none |
| CVE match | novel |
Summary
net_add_domain() inserts the new struct domain into the global lockless 'domains' list at :138 and only afterwards calls net_init_domain(dp) at :140, whose PRU_NOTSUPP loop replaces statically-NULL pru_accept/bind/connect/peeraddr/shutdown/... pointers with pr_generic_notsupp. Between the insert and those fills, any CPU in socreate can find the half-initialized domain; socreate only validates pru_attach (statically non-NULL), so the socket is created and an fd handed to the user. A subsequent getpeername(2) or shutdown(2) reaches so_pru_peeraddr/so_pru_shutdown which pass the still-NULL pointer into netmsg_init as nm_dispatch; the netisr message loop invokes msg->nm_dispatch(msg) with no NULL guard β a call through address 0 in protocol-thread context: guaranteed kernel panic. Distinct from DF-0233 (list-mutation visibility): a plain ordering bug hittable even on strongly-ordered x86. Window opens only when a domain-registering module is loaded after boot (ng_socket/netgraph7/ng_btsocket via privileged kldload; no syscall-driven autoload exists) β an unprivileged user racing socket(AF_NETGRAPH, SOCK_DGRAM, NG_DATA) (ngd_attach has no priv check) + getpeername/shutdown on another CPU can hit the NULL call and panic the kernel. Impact ceiling is panic (page 0 unmapped); not a corruption primitive. Not guest-verified per conditional rule (Low, no unpriv-alone trigger). Fix: initialize before publishing (net_init_domain ahead of SLIST_INSERT_HEAD β safe for all in-tree pr_init callbacks, which do not consult the domains list).
Timeline
- 2026-09-02 Discovered during pass-2 audit of uipc_domain.c (GLM 5.3).
No comments yet.