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.
Recommended fix
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).
No comments yet.