Jailed uid-0 passes the sysctl write gate and can write every host-global RW MIB defined here β kern.securelevel raised irreversibly from inside a jail (host root gets EPERM lowering it), plus kern.hostid/domainname/bootfile/maxprocperuid/maxposixlocksperuid/tls_extra corruption; CTLFLAG_PRISON is dead
| Field | Value |
|---|---|
| ID | DF-2950 |
| Status | new |
| Severity | Medium |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:N/I:H/A:H |
| CWE | CWE-863 Incorrect Authorization |
| File | sys/kern/kern_mib.c |
| Lines | 142-153, 178-181, 248-271 (gate: kern_sysctl.c:1445-1450) |
| Area | kern + jail |
| Confidence | certain |
| Discovered | 2026-09-02 |
| Pass | 2 (GLM 5.3 second pass) |
| Bucket | privesc |
| Reported | pending |
| Known CVE | none |
| CVE match | novel |
Summary
sysctl_root's only write-privilege gate is caps_priv_check(td_ucred, SYSCAP_NOSYSCTL_WR). caps_priv_check rewrites group-2 leaf caps to the meta group SYSCAP_SENSITIVEROOT (kern_caps.c:336-348) and prison_priv_check blanket-allows that meta group for jailed creds (kern_jail.c:854-857). Every CTLFLAG_RW oid in kern_mib.c therefore becomes writable by a jailed uid-0: kern.securelevel (no jail check) can be raised one-way β the ratchet denies lowering to host root too, permanently locking CTLFLAG_SECURE sysctls and all securelevel-gated kernel paths; kern.hostid, kern.domainname, kern.bootfile/kernelname, kern.maxprocperuid, kern.maxposixlocksperuid, kern.tls_extra are equally host-global and jail-writable. CTLFLAG_PRISON ('Prisoned roots can fiddle') exists for exactly this distinction but is consulted nowhere in the tree except kern.hostname. Root cause shared with DF-2800 (which covered only the time syscalls); this is the sysctl-write sink with a distinct file, impact, and fix locus. VERIFIED on the stock guest: jailed root wrote kern.securelevel β1β1 rc=0; host root then got EPERM lowering it; kern.hostid 0β4242, kern.domainnameβpwned-by-jail, kern.maxposixlocksperuid 32528β1, kern.tls_extraβ777. Jailed nobody and host unpriv correctly get EPERM β the gate is specifically jail-blind. No uid0-on-host route (authorization flaw) β impact ceiling is host-global state manipulation: irreversible host administration DoS. Fix validated in-guest (CTLFLAG_PRISON enforcement at the core write gate): jailed uid-0 β EPERM on all tested oids with values unchanged, jail-scoped hostname read and host root writes unaffected.
Timeline
- 2026-09-02 Discovered during pass-2 audit of kern_mib.c (GLM 5.3); reproduced from jail + fix validated; DF-0181 re-verified still present (live corroboration captured).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2950 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| poc_jail_sysctl.sh | β | 1.4 KB | view raw | |
| poc_jail_sysctl2.sh | β | 1.2 KB | view raw | |
| run.log | β | 2.3 KB | view raw | |
| run.2.log | β | 2.2 KB | view raw | |
| df0181_live_corroboration.txt | β | 2.2 KB | view raw | |
| env.txt | β | 208 B | view raw | |
| fixtest.sh | β | 1004 B | view raw | |
| fixtest.log | β | 1.9 KB | view raw | |
| fix.diff | β | 783 B | view raw | |
| VERDICT.md | β | 4.1 KB | β raw | |
| verdict.json | β | 4.8 KB | view raw |
DF-2950 VERDICT
Status: reproduced (impact=dos, S:C). Confidence: certain.
How it was reproduced
Stock guest, kernel DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2
06:02:54 UTC 2026 (env.txt). jail(8) created plain jails (no special
caps) on the host; commands inside run with uid=0 and the jail's prison.
jail / df2950ja 127.0.0.4 /bin/sh -c 'id; sysctl -w kern.securelevel=1'βuid=0(root)...andkern.securelevel: -1 -> 1rc=0. Path: userland_sysctl (kern_sysctl.c:1569-1576) β sysctl_root:1441 (no CTLFLAG_SECURE on this oid) β :1447caps_priv_check(td->td_ucred, SYSCAP_NOSYSCTL_WR): cr_uid==0 passes the uid test (kern_caps.c:328), group-2 rewrite (kern_caps.c:337-341) turns the cap into SYSCAP_SENSITIVEROOT, prison_priv_check returns 0 (kern_jail.c:856-857) β handlersysctl_kern_securelvl(kern_mib.c:248-261) has no jail check and level 1 β₯ -1 βsecurelevel = 1.- Host root
sysctl -w kern.securelevel=0βsysctl: kern.securelevel=0: Operation not permitted(sysctl_kern_securelvl's ratchet, kern_mib.c:257-258, applies to host root). The damage is permanent until reboot: CTLFLAG_SECURE sysctls become unwritable (kern_sysctl.c:1441-1444) and every other securelevel-gated kernel path engages. This is a host-wide administration denial-of-service from inside a jail. - Same gate lets jailed uid-0 corrupt host-global identity and resource
MIBs (run.2.log [3]/[6]):
kern.hostid 0β4242,kern.domainname ""βpwned-by-jail,kern.maxposixlocksperuid 32528β1,kern.tls_extra 6144β777(alsokern.bootfile/kernelnameandkern.maxprocperuidare in the same class). - Control cases behave exactly as the code predicts: jailed non-root β EPERM (caps_priv_check uid test, kern_caps.c:328-331); host unprivileged user β EPERM. The hole is specifically that the gate is jail-blind for uid-0-in-jail.
Relationship to DF-2800
DF-2800 (kern_jail.c) found the same root cause (group-2 blanket allow, meta-group rewrite) for the time syscalls. This finding is the sysctl-write sink: different file (sys/kern/kern_mib.c oids are the demonstrated attack surface), different impact (irreversible securelevel ratchet + host/cross-jail global-state corruption), fixed most naturally at the sysctl core by making CTLFLAG_PRISON mean something (see fix.diff). Not a re-report: DF-2800's scope ends at settimeofday/clock_settime/adjtime/ntp_adjtime.
Side observation
The first run (run.log) wedged the guest after its final step: a jail hostname write without PRISON_CAP_SYS_SET_HOSTNAME returns EPERM from sysctl_hostname while holding the all-CPU sysctl XLOCK (kern_mib.c:217-226) β known DF-0181, still unfixed on this kernel. Captured in df0181_live_corroboration.txt. My finding's evidence (steps [1]-[5]) completed before that wedge.
Fix validation
fix.diff = gate jailed writes on CTLFLAG_PRISON in sysctl_root
(kern_sysctl.c, +#include <sys/jail.h> for the jailed() inline,
sys/jail.h:158). Applied on a vm.sh reset with-src guest, built with
make -j4 nativekernel KERNCONF=X86_64_GENERIC (rc=0), installed,
rebooted into #1: Fri Sep 4 00:17:28 UTC 2026. fixtest.log:
jailed uid-0 β EPERM for kern.securelevel / kern.hostid /
kern.domainname / kern.maxposixlocksperuid, all values unchanged;
jail-scoped kern.hostname READ still works; host root writes still work.
Baseline reproduced=1, patched reproduced=0 β fix_status=fixed.
Guest reset to stock afterwards.
Exploit chain
host runs a jail for an untrusted tenant/service (uid 0 inside the jail
= attacker) β sysctl -w kern.securelevel=1 (or higher) β host-global
irreversible ratchet: host root cannot lower it; at level β₯1 further
CTLFLAG_SECURE knobs lock, /dev/mem closes, immutable flags engage β
permanent host administration DoS; additionally hostid/domainname/
bootfile/maxprocperuid corruption leaks across the jail boundary into
the host and every other jail. Ceiling for this bug class is
host-global state manipulation, not uid=0-on-host: memory-safety is not
involved, so no escalation chain beyond the integrity/availability
impact exists.
Fix verification
fixedPatched kernel (#1, nativekernel build with fix.diff): jailed uid-0 gets EPERM on kern.securelevel/kern.hostid/kern.domainname/kern.maxposixlocksperuid and values stay unchanged; jail-scoped kern.hostname read still works; host root write (kern.hostid=99) still works. No over-restriction observed. Baseline had reproduced=1 on stock #0.
['fixtest.log:F1 jailed uid-0 EPERM, kern.securelevel stays -1', 'fixtest.log:F2 hostid/domainname/maxposixlocks EPERM, values unchanged', 'fixtest.log:F3 jail hostname read OK (df2950fc)', 'fixtest.log:F4 host root kern.hostid 0->99 OK']
Confirmed kernel references
Detail
Exploit chain
host-root creates jail for untrusted tenant -> attacker holds uid 0 inside jail -> sysctl -w kern.securelevel=1 -> host-global irreversible ratchet (host root cannot lower; CTLFLAG_SECURE sysctls permanently locked at level>=1) -> permanent host administration denial-of-service; same gate permits host/cross-jail corruption of kern.hostid, kern.domainname, kern.bootfile/kernelname, kern.maxprocperuid, kern.maxposixlocksperuid, kern.tls_extra
Evidence (decisive lines)
['run.2.log:14 kern.securelevel: -1 -> 1 (jailed uid-0, rc=0)', 'run.2.log:19-20 host root: sysctl: kern.securelevel=0: Operation not permitted', 'run.2.log:27-32 kern.hostid 0->4242, kern.domainname ->pwned-by-jail from jail', 'run.2.log:40-47 jailed nobody EPERM + host unpriv (su maxx) EPERM control cases', 'run.2.log:52-55 kern.maxposixlocksperuid 32528->1, kern.tls_extra 6144->777 from jail', 'run.log:53-55 + df0181_live_corroboration.txt: incidental live re-trigger of DF-0181 XLOCK wedge (guest down)', 'fixtest.log: jailed uid-0 EPERM on all oids under patched kernel #1; host root write still OK']
PoC changes
Seed sketch corrected: step [5] of run 1 mislabeled host-root as unprivileged (runs inside the root ssh session); run 2 uses su -m maxx for a genuine unprivileged host-user control. Jail-hostname-write step removed from run 2 because on this guest the jail lacks PRISON_CAP_SYS_SET_HOSTNAME and the write exercises known DF-0181 (XLOCK leak -> guest wedge), truncating run 1; that wedge is preserved as side-evidence.
Verified recommended fix
In sysctl_root (kern_sysctl.c), deny writes from jailed creds unless the oid has CTLFLAG_PRISON; see fix.diff (also makes the documented-but-dead CTLFLAG_PRISON flag meaningful).
Verdict
On the stock INVARIANTS guest, a plain jail(2) tenant with uid 0 inside the jail successfully wrote host-global MIBs: kern.securelevel -1->1 (rc=0), after which HOST root got EPERM lowering it (irreversible host-admin DoS), plus kern.hostid 0->4242, kern.domainname ->pwned-by-jail, kern.maxposixlocksperuid 32528->1, kern.tls_extra->777. Root cause: sysctl_root's only write gate is caps_priv_check(SYSCAP_NOSYSCTL_WR) (kern_sysctl.c:1447), which the group-2 meta rewrite (kern_caps.c:337-341) turns into SYSCAP_SENSITIVEROOT, blanket-allowed in jails (kern_jail.c:856-857); none of the kern_mib.c RW oids have a jail check and CTLFLAG_PRISON (sysctl.h:97) is consulted nowhere. Control cases: jailed nobody EPERM, host unpriv EPERM - the gate is specifically jail-blind for jailed uid-0. Jailed-root hostname write without the SET_HOSTNAME cap additionally re-triggered known DF-0181's XLOCK leak live (guest wedged; corroboration file). fix.diff (kern_sysctl.c: enforce CTLFLAG_PRISON for jailed writes) built via make nativekernel and validated: jailed uid-0 now EPERM on all tested oids, host root unaffected.
No comments yet.