kobj API robustness gaps: double kobj_init() silently leaks a permanent class reference (pins KLD class+ops forever), kobj_delete() on an uninitialized/deleted object NULL-derefs obj->ops->cls, and cyclic baseclass graphs recurse without bound
| Field | Value |
|---|---|
| ID | DF-2962 |
| 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:L |
| CWE | CWE-476 / CWE-401 / CWE-835 |
| File | sys/kern/subr_kobj.c |
| Lines | 137-157, 257-273 |
| Area | kern/kobj |
| 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
Three contract-robustness gaps in the kobj object protocol, each requiring a buggy privileged-authored kernel consumer (none found in-tree — all audited callers in subr_bus.c, libiconv, and dev/sound are balanced): (1) kobj_init() re-initializes without checking obj->ops, so a second init permanently inflates cls->refs — the class and its 2056-byte ops table can then never be freed, and for a KLD-registered driver the leaked ref keeps the class compiled after devclass_delete_driver, leaking kernel memory per load/unload cycle; (2) kobj_delete() reads obj->ops->cls with no NULL guard, so double-delete or delete-of-uninitialized-object is a NULL-deref panic instead of a caught invariant violation; (3) kobj_lookup_method_mi() walks baseclasses[] with no cycle or depth guard, so a driver author who constructs a cyclic class graph gets unbounded kernel recursion and stack-overflow panic at first dispatch/compile. All availability-only and developer-error-gated. Fix: cheap invariant checks (KASSERT on obj->ops state in init/delete; depth cap in lookup_method_mi).
Timeline
- 2026-09-02 Discovered during pass-2 audit of subr_kobj.c (GLM 5.3).
No comments yet.