Files
reverse-engineering-anything/src/pcap/PcapNativeBound.ts
T
morluto cb4e5cfbff feat(analysis): make resource budgets recoverable across CLI and MCP (#9706)
* refactor(analysis): centralize resource budgets and recovery facts

* feat(analysis): expose ASAR and Ghidra runtime admission controls

* feat(artifacts): expose reader admission and preserve limited recognition

* feat(javascript): expose recoverable semantic precision budgets

* feat(web): add recoverable source-map budgets and compact retained views

* feat(web): make historical capture decoding budgets recoverable

* fix(desktop): enforce selected view policies across capture and export

* feat(runtime): make Frida and LLDB retention budgets selectable

* feat(native): expose diagnostic budgets and preserve exhaustion causes

* feat(managed): expose recoverable snapshot and representation budgets

* feat(metadata): make Go and Rust inspection budgets recoverable

* feat(wasm): expose representation and producer admissions

* feat(evm): expose per-call worker resource budgets

* feat(android): make resource and string-pool omissions recoverable

* feat(producers): expose command and recorded-capture budgets

* docs(analysis): record recovery contracts and integrated validation

* fix(docs): link calibration oracle from published verification pages

* fix(docs): restore desktop task anchors and receipt links

* test(analysis): align fixtures with selectable budget contracts

* fix(analysis): remove source-location projector dependency cycle

* test(analysis): refresh budget recovery and verifier regressions

* test(analysis): preserve format and publication recovery expectations

* test(windows): align conformance with owned runtime admission

* fix(desktop): preserve selected alias kinds in exported state

* test(analysis): align provider fixtures with recoverable budgets

* test(desktop): validate emitted alias metadata structurally

* fix(ghidra): classify bounded Windows endpoint refusals

* test(cli): assert selectable artifact admission recovery

* fix(cli): preserve capture provenance in environment builds
2026-11-10 05:11:20 -05:00

147 lines
5.8 KiB
TypeScript

import { BOUNDED_PRODUCER_LIMITS } from "../domain/producerResourceLimits.js";
import { selectArtifactCommandPath } from "../process/ArtifactCommandPath.js";
import {
pcapCaptureHostSupported,
PCAP_CAPTURE_UNSUPPORTED_HOST_REASON,
} from "../domain/pcap/pcapAnalysis.js";
import { access, stat } from "node:fs/promises";
import { constants } from "node:fs";
import { basename, isAbsolute } from "node:path";
import {
AnalysisError,
type AnalysisCapturedOutput,
} from "../domain/analysisErrorBase.js";
import {
AnalysisCancelledError,
AnalysisCapabilityUnavailableError,
AnalysisOutputError,
} from "../domain/analysisErrorCore.js";
import type { ArtifactAnalysisResources } from "../process/ArtifactAnalysisResources.js";
import { prlimitCeilingArguments } from "../process/LinuxResourceLimits.js";
import type { runPcapCommand } from "./PcapCommand.js";
import type { ArtifactCommandPath } from "../process/ArtifactCommandPath.js";
const PRLIMIT_COMMAND_ENV = "REA_TSHARK_PRLIMIT_COMMAND";
/** Repair for an unusable selected capture limiter; readiness and admission share it. */
const PCAP_LIMITER_REMEDIATION = `Check that ${PRLIMIT_COMMAND_ENV} (default /usr/bin/prlimit) names an absolute, executable util-linux prlimit.`;
/** Capture CPU ceiling, in seconds. */
const PCAP_CPU_SECONDS = 300;
/** Own native capture admission and the exact enforced resource profile. */
export const preparePcapNativeBound = async (
environment: Readonly<Record<string, string | undefined>>,
resources: ArtifactAnalysisResources,
probe: (
selected: ArtifactCommandPath,
arguments_: string[],
) => Promise<{
readonly stdout: string;
readonly capturedOutput: AnalysisCapturedOutput;
}>,
signal?: AbortSignal,
operation:
| "inspect_pcap_client"
| "inspect_pcap_capture" = "inspect_pcap_capture",
): Promise<{
nativeBound: NonNullable<Parameters<typeof runPcapCommand>[0]["nativeBound"]>;
limitations: readonly string[];
}> => {
if (process.platform === "win32") {
return {
nativeBound: {
memoryLimitBytes: BOUNDED_PRODUCER_LIMITS.address_space_bytes,
},
limitations: [
"Each owned Windows tool tree has a 1 GiB Job Object committed-memory limit; this is not a machine-wide quota.",
],
};
}
if (!pcapCaptureHostSupported(process.platform)) {
const reason = PCAP_CAPTURE_UNSUPPORTED_HOST_REASON;
throw new AnalysisCapabilityUnavailableError("pcap", operation, reason, {
userMessage: reason,
});
}
const configured = environment[PRLIMIT_COMMAND_ENV] ?? "/usr/bin/prlimit";
let probeFailure: AnalysisError | undefined;
let capturedOutput: AnalysisCapturedOutput | undefined;
try {
if (!isAbsolute(configured))
throw new Error(`${PRLIMIT_COMMAND_ENV} must be absolute.`);
const selection = await selectArtifactCommandPath(configured, signal);
if (!(await stat(selection.resolvedPath)).isFile())
throw new Error("The selected limiter is not a regular file.");
await access(selection.resolvedPath, constants.X_OK);
const readProbe = async (argument: "--version" | "--help") => {
try {
const output = await probe(selection, [argument]);
capturedOutput = output.capturedOutput;
return output.stdout;
} catch (cause) {
if (
(cause instanceof AnalysisCapabilityUnavailableError ||
cause instanceof AnalysisOutputError) &&
!cause.cleanupIncomplete
) {
probeFailure = cause;
throw new Error(
cause instanceof AnalysisOutputError
? `The selected limiter produced unreadable ${argument === "--version" ? "version" : "help"} output.`
: "The selected limiter could not be run.",
{ cause },
);
}
throw cause;
}
};
const version = await readProbe("--version");
const prefix = `${basename(selection.invocationPath)} from util-linux `;
if (
!version.startsWith(prefix) ||
version.slice(prefix.length).trim() === ""
)
throw new Error(
"The selected limiter did not report a util-linux prlimit version.",
);
const help = await readProbe("--help");
for (const flag of ["--as", "--fsize", "--cpu", "--core"]) {
if (!new RegExp(`(?:^|\\s)${flag}(?:[=\\[\\s,]|$)`, "u").test(help))
throw new Error(`The selected limiter does not advertise ${flag}.`);
}
const limits = await resources.readLimits({
address_space_bytes: BOUNDED_PRODUCER_LIMITS.address_space_bytes,
file_bytes: BOUNDED_PRODUCER_LIMITS.file_bytes,
cpu_seconds: PCAP_CPU_SECONDS,
});
const nativeBound = {
limiter: {
command: selection,
arguments: prlimitCeilingArguments(limits),
},
};
const limitations = [
`Linux prlimit preserves stricter inherited ceilings: ${limits.address_space_bytes} bytes of per-process address space, ${limits.file_bytes} bytes per file and ${limits.cpu_seconds} CPU seconds; core dumps are disabled. These are not aggregate machine quotas.`,
];
return { nativeBound, limitations };
} catch (cause) {
if (signal?.aborted === true && !(cause instanceof AnalysisError))
throw new AnalysisCancelledError(operation, {
cause: signal.reason,
});
if (cause instanceof AnalysisError) throw cause;
const reason =
"Cannot establish the selected Linux resource limiter before processing capture bytes.";
throw new AnalysisCapabilityUnavailableError("pcap", operation, reason, {
cause,
capturedOutput: probeFailure?.capturedOutput ?? capturedOutput,
diagnostics: {
...probeFailure?.diagnostics,
configuration_key: PRLIMIT_COMMAND_ENV,
configured,
},
userMessage: `${reason} (${cause instanceof Error ? cause.message : String(cause)}) ${PCAP_LIMITER_REMEDIATION}`,
remediationAction: PCAP_LIMITER_REMEDIATION,
});
}
};