mirror of
https://github.com/morluto/rea
synced 2026-10-26 22:28:27 -04:00
26356dc34a
* fix(process): record withheld unrelated Linux processes as unverified The token sweep after an owned command (for example the Ghidra Java probe run by setup and doctor) failed cleanup when an unrelated same-UID process started during the sweep and Linux denied its /proc/<pid>/environ. Setgid or setuid programs (mismatched real/saved IDs) and non-dumpable processes are withheld by the kernel exactly like another account's processes, which were already recorded as unverified. Derive the kernel restriction from the same stat-bracketed procfs read that already supplies the effective UID: all Uid/Gid IDs from status, and the root ownership procfs reports for a non-dumpable process's environ. Keep that fact through exit settlement. Related candidates still fail closed. Fixes #6204 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(process): define caller credentials on hosts without geteuid Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
73 lines
2.0 KiB
TypeScript
73 lines
2.0 KiB
TypeScript
import { expect, it } from "vitest";
|
|
|
|
import {
|
|
linuxEnvironmentRestriction,
|
|
parseLinuxProcessIds,
|
|
} from "./LinuxProcessStatus.js";
|
|
|
|
it("parses the single native status Uid and Gid rows", () => {
|
|
const status =
|
|
"Name:\tworker\nUid:\t1000\t1001\t1002\t1003\nGid:\t20\t21\t22\t23\n";
|
|
expect(parseLinuxProcessIds(status, "Uid")).toEqual([1000, 1001, 1002, 1003]);
|
|
expect(parseLinuxProcessIds(status, "Gid")).toEqual([20, 21, 22, 23]);
|
|
});
|
|
|
|
it.each([
|
|
"Name:\tworker\n",
|
|
"Uid:\t1000\t1001\t1002\n",
|
|
"Uid:\t1000\t1001\t1002\t1003\nUid:\t1000\t1001\t1002\t1003\n",
|
|
"Uid:\t1000\t-1\t1002\t1003\n",
|
|
"Uid:\t1000\t9007199254740992\t1002\t1003\n",
|
|
"Uid:\t1000\t1001\t1002\t1003 extra\n",
|
|
])("does not infer IDs from malformed status: %s", (status) => {
|
|
expect(parseLinuxProcessIds(status, "Uid")).toBeUndefined();
|
|
});
|
|
|
|
const caller = { callerUid: 1000, callerGid: 1000 } as const;
|
|
const matching = [1000, 1000, 1000, 1000] as const;
|
|
|
|
it.each([
|
|
[
|
|
"a setgid program",
|
|
{ uids: matching, gids: [1000, 2, 2, 2], procfsOwnerUid: 1000 },
|
|
"credentials",
|
|
],
|
|
[
|
|
"a saved UID from another account",
|
|
{ uids: [1000, 1000, 0, 1000], gids: matching, procfsOwnerUid: 1000 },
|
|
"credentials",
|
|
],
|
|
[
|
|
"a non-dumpable process",
|
|
{ uids: matching, gids: matching, procfsOwnerUid: 0 },
|
|
"non-dumpable",
|
|
],
|
|
[
|
|
"an inspectable process",
|
|
{ uids: matching, gids: matching, procfsOwnerUid: 1000 },
|
|
undefined,
|
|
],
|
|
[
|
|
"a process with unknown procfs ownership and GIDs",
|
|
{ uids: matching, gids: undefined, procfsOwnerUid: undefined },
|
|
undefined,
|
|
],
|
|
] as const)(
|
|
"derives the kernel environment restriction for %s",
|
|
(_name, facts, expected) => {
|
|
expect(linuxEnvironmentRestriction({ ...caller, ...facts })).toBe(expected);
|
|
},
|
|
);
|
|
|
|
it("does not derive a credential restriction without caller credentials", () => {
|
|
expect(
|
|
linuxEnvironmentRestriction({
|
|
uids: [0, 0, 0, 0],
|
|
gids: [0, 0, 0, 0],
|
|
procfsOwnerUid: 0,
|
|
callerUid: undefined,
|
|
callerGid: undefined,
|
|
}),
|
|
).toBeUndefined();
|
|
});
|