β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-2850

_gtaskqueue_start_threads() reports total thread-creation failure as success; queue teardown lifecycle is stubbed, so a half-born queue silently hangs all future drainers

Field Value
ID DF-2850
Status new
Severity Low
CVSS 3.1 CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:N/I:N/A:L
CWE CWE-755 Improper Handling of Exceptional Conditions
File sys/kern/subr_gtaskqueue.c
Lines 455-471 (dead teardown :147-160/:801-804)
Area kern
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

If lwkt_create() fails, _gtaskqueue_start_threads() NULLs the slot, skips tq_tcount++ and still returns 0 unconditionally β€” the comment's promised cleanup points at gtaskqueue_free(), which is static __unused dead code, and taskqgroup_destroy() is an empty stub. A queue whose threads failed to start still accepts enqueues and wakes nobody; its tasks never run; any drain on it sleeps forever (timo=0) with no error. Silent permanent kernel-thread hang under thread-table/ kmem exhaustion at queue-start time. No deterministic guest PoC (code-path analysis; findings/poc/DF-2850/NOTES.md).

Track successful creates, tear down partial state and return the error; make TASKQGROUP_DEFINE's SYSINIT treat a failed queue as fatal at boot; implement or delete the dead destroy/free declarations.

Timeline

  • 2026-09-02 Discovered during pass-2 audit of subr_gtaskqueue.c (GLM 5.3).

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2850 Β· 1 files
FileTypeDescriptionSize
fix.diff β€” 1.3 KB view raw

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

Error propagation + partial teardown fix compile-validated; lwkt_create failure not injectable for A/B.

compile-validated in the fix-all kernel build (make nativekernel, 0 errors)
↓ fix.diffper-fix-DF-2850

Confirmed kernel references

Detail

Evidence (decisive lines)

subr_gtaskqueue.c:455-461 swallow + :471 return 0; :147 static __unused gtaskqueue_free; :801-804 empty taskqgroup_destroy

PoC changes

n/a

Verified recommended fix

--- sys/kern/subr_gtaskqueue.c 2026-06-29 12:51:19.000000000 +0000

Verdict

Code-verified failure-swallowing; the failure cannot be injected on a live guest. _gtaskqueue_start_threads (sys/kern/subr_gtaskqueue.c:442-471) NULLs the thread slot and continues on lwkt_create error, then unconditionally returns 0 (:471) - total failure yields a thread-less queue whose enqueues succeed, tasks never run, and every drain sleeps forever (timo=0). The promised cleanup is dead code: gtaskqueue_free is static void __unused (:147-148) and taskqgroup_destroy is an empty stub (:801-804). Injecting the failure requires making lwkt_create fail (thread-structure exhaustion at exactly queue-start time) - not producible deterministically on this guest, and no sysctl pins the thread limit. The consequence (a never-started queue hangs all drainers) is structural and code-certain; the fix (track first error, tear down partial state, return it) is compile-validated.