Kernel threads leak one td_ucred reference per exit: crhold at creation is never crfreed on the LWKT teardown path
| Field | Value |
|---|---|
| ID | DF-2968 |
| Status | new |
| Severity | Info |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:N/I:N/A:N (0.0) |
| CWE | CWE-401 |
| File | sys/kern/kern_kthread.c |
| Lines | 62 (teardown: lwkt_thread.c:1684+) |
| Area | kern |
| Confidence | certain |
| Discovered | 2026-09-02 |
| Pass | 2 (GLM 5.3 second pass) |
| Bucket | kernleak |
| Reported | pending |
| Known CVE | none |
| CVE match | novel |
Summary
_kthread_create sets td->td_ucred = crhold(proc0.p_ucred) (:62). When the thread later exits via kthread_exit() β lwkt_exit(), the teardown path performs biosched_done/dsched_exit_thread/tsleep_remove/ lwkt_remove_tdallq and parks the struct WITHOUT ever calling crfree(td->td_ucred) β lwkt_thread.c contains zero crfree calls. The only crfree of td_ucred in the kernel is the LWP path (kern_exit.c:717), unreachable for pure LWKT threads. On recycle, lwkt_init_thread's bzero silently destroys the held reference. Minimal today: the leaked reference is always on proc0.p_ucred, an immortal credential, and cr_ref is a 64-bit long β neither premature free nor overflow is reachable; each kthread create/exit cycle merely bumps an unbounded counter on a never-freed object. Refcount-discipline defect that becomes dangerous only if kthreads are ever given non-proc0 creds without also teaching lwkt_exit to drop them. Fix: crfree in lwkt_exit() before parking the struct.
Timeline
- 2026-09-02 Discovered during pass-2 audit of kern_kthread.c (GLM 5.3).
No comments yet.