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

sys_getsid reads the p_pgrp->pg_session chain without pt->p_token; sys_setpgid reads curp->p_session unlocked β€” lifetime race vs. enterpgrp's pgrp free (stale/UAF read)

Field Value
ID DF-2760
Status new
Severity Low
CVSS 3.1 CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:L
CWE CWE-667 / CWE-367
File sys/kern/kern_prot.c
Lines 153-154 (sibling correct at :124-126), 383, 404
Area kern
Confidence certain
Discovered 2026-08-30
Pass 2 (GLM 5.3 second pass)
Bucket memcorrupt
Reported pending
Known CVE none
CVE match novel

Summary

p_session is a macro over p_pgrp. sys_getpgid correctly wraps its chain deref in lwkt_gettoken_shared(&pt->p_token), but sys_getsid reads pt->p_pgrp->pg_session->s_sid with no token at all, and sys_setpgid reads curp->p_pgrp->pg_session unlocked while holding only targp's token. p->p_pgrp is only stable under p->p_token: enterpgrp swaps it and drops the old pgrp's refs, freeing the old pgrp (and possibly its session) when the mover was the last member. An unlocked reader that loads p_pgrp just before the swap then dereferences freed memory β€” getsid returns a sid through two chained loads of a freed object; setpgid compares a session pointer loaded from a freed pgrp. Realistic ceiling: stale/incorrect sid (correctness/info) with a practically unreachable groomed-garbage panic path; no write primitive.

Mirror sys_getpgid's token discipline: take pt->p_token shared around the getsid read; snapshot curp->p_pgrp->pg_session under curp's token (brief, non-nested) before the setpgid comparisons.

Timeline

  • 2026-08-30 Discovered during pass-2 audit of kern_prot.c (GLM 5.3).

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2760 Β· 3 files
FileTypeDescriptionSize
getsid_race.c β€” 2.6 KB view raw
run.log β€” 244 B view raw
fix.diff β€” 1.2 KB view raw

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

Token-discipline fix (getsid shared token; setpgid curp token) compile-validated; no observable anomaly to A/B (365K baseline samples clean).

compile-validated in the fix-all kernel build (make nativekernel, 0 errors)
↓ fix.diffper-fix-DF-2760

Confirmed kernel references

Detail

Evidence (decisive lines)

getsid_race.c; df2760_getsid.log: 365,448 samples, 0 anomalies, no panic

PoC changes

registry-based validation (shared mmap of churner pids)

Verified recommended fix

--- sys/kern/kern_prot.c 2026-06-29 12:51:19.000000000 +0000

Verdict

Code-verified lock-discipline gap; race window not observable externally. sys_getsid (sys/kern/kern_prot.c:153-154) dereferences pt->p_pgrp->pg_session with no p_token while the adjacent sys_getpgid wraps the same chain in a shared token (:124-126); sys_setpgid reads curp->p_session unlocked at :383/:404 while holding only targps token. A hammer run with 24 processes churning setpgid/setsid (pgrp/session alloc/free) and a checker performing 365,448 getsid() samples on a shared pid registry produced zero impossible values, zero stale-transition observations, and no panics - the p_ucred/p_pgrp swap window is too narrow to catch from another process without heavy grooming, matching the findings own assessment (realistic ceiling: stale/incorrect sid; groomed-garbage panic practically unreachable). The token-discipline fix (mirror getpgid) is compile-validated and A/B-safe.