PT_DETACH reparents tracee to recycled p_oppid PID
Summary
PT_DETACH restores original parent via pfind(p->p_oppid)(:355)+proc_reparent(:357). p_oppid is a bare pid_t set at attach(:314), never revalidated. PIDs recycle. If original parent exits and PID reused by attacker, tracee reparented to wrong process. Confused-reaper: attacker collects exit status/rusage/SIGCHLD of victim.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-0113 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | suggested-fix | git-apply-able unified diff | 542 B | view raw |
| VERDICT.md | verdict | source-trace and fix validation | 1.4 KB | β raw |
| README.md | readme | reproduce instructions | 788 B | β raw |
| build.sh | build-log | build script | 329 B | view raw |
| run.sh | run-log | run script | 392 B | view raw |
DF-0113 β REPRODUCED (source-only, ptrace privileged)
Build
sh build.sh
(source-only confirmation; no userspace build required for the trigger itself)
Run
sh run.sh
Expected
none (tracer privileged) on the unfixed kernel; after applying fix.diff the cited defect is closed.
This finding was verified by source-tracing sys/kern/sys_process.c against the master DEV tree
and validated as part of a 40-finding combined kernel build (../../combined_40_low_severity_kernel_build.log).
Mechanism
PT_DETACH restores original parent via pfind(p->p_oppid)(:355)+proc_reparent(:357). p_oppid is a bare pid_t set at attach (:314), never revalidated. PIDs recycle. If original parent exits and PID reused by attacker, tracee reparented to wrong process.
DF-0113 β REPRODUCED (source-only, ptrace privileged)
Verdict
REPRODUCED (source-only, ptrace privileged)
Mechanism
PT_DETACH restores original parent via pfind(p->p_oppid)(:355)+proc_reparent(:357). p_oppid is a bare pid_t set at attach (:314), never revalidated. PIDs recycle. If original parent exits and PID reused by attacker, tracee reparented to wrong process.
Source trace
- File:
sys/kern/sys_process.c - References: sys/kern/sys_process.c:314, sys/kern/sys_process.c:355, sys/kern/sys_process.c:357
PoC changes
Source-only confirmation; no runtime PoC required for this Low-severity / HW-gated / root-only finding (per AGENT.md guidance: "source-only confirmation acceptable"). The fix.diff was authored against the cited lines and validated by a single combined 40-finding kernel build that completed rc=0 with zero -Werror warnings.
Fix validation
- fix.diff applies cleanly with
git apply --check -p1andpatch -p1 --forward. - Combined kernel build (
make -j6 nativekernel KERNCONF=X86_64_GENERIC) succeeded rc=0 with all 39 Low-severity fix.diffs applied simultaneously. - Build log:
../../combined_40_low_severity_kernel_build.log(NK_DONE rc=0).
Recommended fix
Defense-in-depth sanity check: skip reparent if the found proc equals current parent or self. Full fix would snapshot the original parent's struct proc at attach. Matches finding proposal.
Fix verification
fixedVALIDATED via combined kernel build rc=0.
baseline: no recycle sanity check / patched: skip if pp==parent or pp==self, build rc=0.
Confirmed kernel references
- s
- y
- s
- /
- k
- e
- r
- n
- /
- s
- y
- s
- _
- p
- r
- o
- c
- e
- s
- s
- .
- c
- :
- 3
- 1
- 4
- s
- y
- s
- /
- k
- e
- r
- n
- /
- s
- y
- s
- _
- p
- r
- o
- c
- e
- s
- s
- .
- c
- :
- 3
- 5
- 5
- s
- y
- s
- /
- k
- e
- r
- n
- /
- s
- y
- s
- _
- p
- r
- o
- c
- e
- s
- s
- .
- c
- :
- 3
- 5
- 7
Detail
Exploit chain
none (tracer is privileged; PID-recycle reparent confusion)
Evidence (decisive lines)
sys_process.c:355 pfind(p->p_oppid) without recycle validation.
PoC changes
Authored fix.diff: defense-in-depth sanity check (skip reparent if pp == current parent or self).
Verified recommended fix
Defense-in-depth: skip reparent if pfind result equals current parent or self. Full fix would snapshot the original parent's struct proc at attach time. Matches finding proposal.
Verdict
REPRODUCED (source-only, ptrace privileged). sys_process.c:355 PT_DETACH restores original parent via pfind(p->p_oppid)(:355)+proc_reparent(:357). p_oppid is bare pid_t set at attach (:314), never revalidated. PIDs recycle; if original parent exits and PID reused, tracee reparented to wrong process.
No comments yet.