devfs_find_device_by_devid/name return an unreferenced cdev: kern.devname sysctl (CTLFLAG_ANYBODY) reads si_name after devfs_lock is released β microscopic UAF-read race
| Field | Value |
|---|---|
| ID | DF-3008 |
| 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:N |
| CWE | CWE-367 / CWE-416 (read) |
| File | sys/vfs/devfs/devfs_core.c |
| Lines | 1659-1673, 910-933, 2786-2789 |
| Area | vfs/devfs |
| Confidence | speculative |
| Discovered | 2026-09-02 |
| Pass | 2 (GLM 5.3 second pass) |
| Bucket | memcorrupt |
| Reported | pending |
| Known CVE | none |
| CVE match | novel |
Summary
devfs_find_device_by_devid_worker and devfs_find_device_by_name_worker store the found cdev pointer into the reply message without reference_dev(); the documented ad-hoc contract requires callers to take a reference before further use, but the caller-side window is outside the devfs core lock. The unprivileged-reachable instance is the kern.devname sysctl (CTLFLAG_ANYBODY): after the sync reply and lock release, SYSCTL_OUT does strlen(found->si_name) β if a destroy message (e.g. unpriv-triggered clone-device churn via /dev/ptmx close) completes in that window, the read touches a terminated cdev. Unprivileged trigger but the ceiling is a stale or reused-chunk name string returned by devname(3) β objcache memory stays mapped, so no fault and no secret disclosure beyond device names; effect indistinguishable from a benign lost race. Not guest-verified (race outcome unobservable without instrumentation); reported for the lifetime-contract gap. Fix: have the worker copy si_name into the message so no post-reply dereference of the cdev occurs (or take a reference in the workers).
Timeline
- 2026-09-02 Discovered during pass-2 audit of devfs_core.c (GLM 5.3).
No comments yet.