From 1e846990180a09b52b0f9741f75a3ff3c111781c Mon Sep 17 00:00:00 2001 From: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com> Date: Mon, 19 Oct 2026 14:46:50 +0000 Subject: [PATCH] fix(ci): reject priority access to historical PIDs --- docs/recorded-crashes.md | 3 ++- scripts/verify/recorded-crash/trace-policy.mjs | 9 +++++++++ scripts/verify/recorded-crash/trace.mjs | 2 +- .../process/recordedCrashTracePolicy.test.ts | 16 ++++++++++++++++ 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/docs/recorded-crashes.md b/docs/recorded-crashes.md index 3a7bbfcde7..ad689cfcf0 100644 --- a/docs/recorded-crashes.md +++ b/docs/recorded-crashes.md @@ -112,7 +112,8 @@ historical PID above the host's assignable PID range and rejects every lookup, including Node `stat` reads, to detect historical-PID-driven access separately from live inventory. Descriptor paths come from strace's `-yy` decoding; exact PID-directory opens and relative accesses through those handles are rejected. -The trace includes signal calls and rejects PID-targeted signals/probes and +The trace includes signal and priority calls and rejects PID-targeted priority +queries/changes, signals/probes and pidfd controls, including nonfatal signals and signal zero. These checks cover the recorded file/process/signal syscall surfaces, not every possible kernel interaction. The syscall trace also rejects access to the still-present diff --git a/scripts/verify/recorded-crash/trace-policy.mjs b/scripts/verify/recorded-crash/trace-policy.mjs index 9760f3a6f4..32e845e2e4 100644 --- a/scripts/verify/recorded-crash/trace-policy.mjs +++ b/scripts/verify/recorded-crash/trace-policy.mjs @@ -48,6 +48,15 @@ export function nodeInventoryThreads(traces, executable) { } const targetsHistoricalPid = (line, pid) => { + const priority = /^(?:getpriority|setpriority)\(([^,]+), (-?\d+)[,)]/u.exec( + line, + ); + if ( + priority !== null && + Number(priority[2]) === pid && + priority[1] !== "PRIO_USER" + ) + return true; const first = /^(kill|tkill|rt_sigqueueinfo|pidfd_open)\((-?\d+),/u.exec( line, ); diff --git a/scripts/verify/recorded-crash/trace.mjs b/scripts/verify/recorded-crash/trace.mjs index d37fb99942..867d070747 100644 --- a/scripts/verify/recorded-crash/trace.mjs +++ b/scripts/verify/recorded-crash/trace.mjs @@ -63,7 +63,7 @@ export async function verifyCoreInspectionTrace({ "-s", "8192", "-e", - "trace=%process,%signal,%network,%file,ptrace,process_vm_readv,process_vm_writev,pidfd_open,pidfd_send_signal,pidfd_getfd", + "trace=%process,%signal,%network,%file,ptrace,process_vm_readv,process_vm_writev,pidfd_open,pidfd_send_signal,pidfd_getfd,getpriority,setpriority", "-o", prefix, process.execPath, diff --git a/tests/boundary/process/recordedCrashTracePolicy.test.ts b/tests/boundary/process/recordedCrashTracePolicy.test.ts index cd196e0862..2af766f48b 100644 --- a/tests/boundary/process/recordedCrashTracePolicy.test.ts +++ b/tests/boundary/process/recordedCrashTracePolicy.test.ts @@ -136,6 +136,22 @@ it.each([ expect(() => check(101, line, live)).toThrow("non-inventory lookup"); }); +it.each([ + "getpriority(PRIO_PROCESS, 900) = 20", + "setpriority(PRIO_PROCESS, 900, 0) = 0", + "getpriority(PRIO_PGRP, 900) = 20", + "setpriority(PRIO_PGRP, 900, 0) = 0", + "getpriority(0x3 /* unknown PRIO selector */, 900) = -1 EINVAL (Invalid argument)", +])("rejects historical PID priority access: %s", (line) => { + for (const live of [true, false]) + expect(() => check(101, line, live)).toThrow("non-inventory lookup"); +}); + +it("keeps native priority UID selectors and distinct PIDs separate", () => { + expect(check(101, "getpriority(PRIO_USER, 900) = 20")).toEqual([]); + expect(check(101, "getpriority(PRIO_PROCESS, 9000) = 20")).toEqual([]); +}); + it("keeps exec-replaced threads foreign and follows acknowledged unfinished thread clones", () => { const observed = [ {