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

sys_kenv KENV_SET ignores ksetenv() failure β€” variables rejected at limit boundaries (name/value of exactly KENV_M*LEN, full table) silently appear 'set'

Field Value
ID DF-2895
Status new
Severity Info
CVSS 3.1 CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
CWE CWE-252 Unchecked Return Value
File sys/kern/kern_environment.c
Lines 164
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

sys_kenv() calls ksetenv(name, value) and discards its return; ksetenv returns βˆ’1 (and sets nothing) when strlen(name)==128, the value hits the same boundary, or the dynamic table is full (512 entries). The privileged caller sees syscall success while the variable was never stored β€” silent configuration drop for boot-time tunables set at runtime. Info: not memory-unsafe; privileged-only. Fix: propagate EINVAL.

Timeline

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

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2895 Β· 10 files
FileTypeDescriptionSize
README.md β€” 690 B ↓ raw
VERDICT.md β€” 860 B ↓ raw
build.sh β€” 75 B view raw
env.txt β€” 509 B view raw
fix.diff β€” 387 B view raw
kenv_set.c β€” 1.5 KB view raw
manifest.json β€” 546 B view raw
run.log β€” 253 B view raw
run.sh β€” 71 B view raw
verdict.json β€” 2.0 KB view raw

DF-2895 β€” sys_kenv KENV_SET ignores ksetenv failure (Info-tier hardening verification)

What

sys_kenv KENV_SET ignores ksetenv failure

Build

cc -Wall -O2 -o kenv_set kenv_set.c (as root)

Run

./kenv_set

Expected

baseline (stock kernel): see verdict below fix kernel (all-41-fixes build): the bad behavior is gone

Files

README.md VERDICT.md build.sh env.txt fix.diff kenv_set.c manifest.json run.log run.sh verdict.json

Shared harness: h41.c (combined KLD, sysctl debug.h41.cmd=N driven). Full batch context: the fix kernel contains all 41 hardening fixes of this batch compiled together (build RC=0) and passed the complete A/B suite plus a clean reboot.

VERDICT.md
↓ download raw

DF-2895 β€” VERDICT

status: reproduced | reproduced: 1 | impact: none | confidence: certain

Mechanically reproduced as root on the stock guest via the kenv(2) syscall: KENV_SET with a name of exactly KENV_MNAMELEN (128) chars returns 0 (success) - the syscall's copyinstr accepts 129 bytes (kern_environment.c:132) but ksetenv rejects namelen 129 > 128 and stores nothing (kern_environment.c:265-266) - and a follow-up KENV_GET returns ENOENT: the privileged caller believes a boot tunable was set at runtime while it was silently dropped (return of ksetenv discarded at :164). Same at the value boundary and with a full dynamic table. Control: a 127-char name round-trips correctly. On the fix kernel the 128-char set returns -1/EINVAL.

Baseline vs fix kernel

baseline: see verdict above / run log fix: behavior changed as designed (see verdict)

Fix verification

fixed
baseline reproduced→ patch + rebuild →patched clean

A/B: baseline silent drop; fix kernel propagates EINVAL from ksetenv failure.

↓ fix.diffDragonFly dfbsd 6.5-DEVELOPMENT #1: Mon Oct 26 01:57:23 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 (h41 fix kernel, all 41 hardening fixes applied)

Confirmed kernel references

Detail

Evidence (decisive lines)

run.log baseline: SET rv=0 + GET ENOENT; control 127 chars works; fix kernel: SET rv=-1 errno=22

PoC changes

KENV_* constants and kenv() prototype declared locally (not in stock headers)

Verified recommended fix

Propagate ksetenv failure as EINVAL

Verdict

Mechanically reproduced as root on the stock guest via the kenv(2) syscall: KENV_SET with a name of exactly KENV_MNAMELEN (128) chars returns 0 (success) - the syscalls copyinstr accepts 129 bytes (kern_environment.c:132) but ksetenv rejects namelen 129 > 128 and stores nothing (kern_environment.c:265-266) - and a follow-up KENV_GET returns ENOENT: the privileged caller believes a boot tunable was set at runtime while it was silently dropped (return of ksetenv discarded at :164). Same at the value boundary and with a full dynamic table. Control: a 127-char name round-trips correctly. On the fix kernel the 128-char set returns -1/EINVAL.