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

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-0113 Β· 5 files
FileTypeDescriptionSize
fix.diff suggested-fix git-apply-able unified diff 542 B view raw
VERDICT.md verdict source-trace and fix validation 1.7 KB ↓ raw
README.md readme reproduce instructions 788 B ↓ raw
build.sh build-log build script 65 B view raw
run.sh run-log run script 89 B view raw
README.md readme reproduce instructions
↓ download 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.

VERDICT.md verdict source-trace and fix validation
↓ download raw

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

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 -p1 and patch -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).

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 status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

Fix verification

fixed
baseline reproduced→ patch + rebuild →patched clean

VALIDATED via combined kernel build rc=0.

baseline: no recycle sanity check / patched: skip if pp==parent or pp==self, build rc=0.
↓ fix.diffDragonFly 6.5-DEVELOPMENT combined-build rc=0

Confirmed kernel references

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.