blob: 43d58f751dc2126416b3b6689790f17931c93ddc [file]
import { closeSync, constants, fstatSync, lstatSync, openSync } from 'node:fs';
export interface PinnedLinuxProfilePath {
readonly path: string;
readonly access: 'read' | 'write';
readonly sourceFd: number;
readonly releaseSource: () => void;
readonly childFd: number;
readonly device: bigint;
readonly inode: bigint;
readonly mtimeNs: bigint;
readonly ctimeNs: bigint;
}
export function pinExistingLinuxProfilePath(input: {
path: string;
access: 'read' | 'write';
targetType: 'file' | 'directory' | 'other';
childFd: number;
}): PinnedLinuxProfilePath | undefined {
const existing = (() => {
try {
return lstatSync(input.path);
} catch (error) {
if ((error as NodeJS.ErrnoException).code === 'ENOENT') return undefined;
throw error;
}
})();
if (!existing) return undefined;
if (existing.isSymbolicLink() || !matchesTargetType(existing, input.targetType)) {
throw new Error(`Approved sandbox path changed type: ${input.path}`);
}
const linuxConstants = constants as typeof constants & { O_PATH?: number };
const sourceFd = openSync(
input.path,
(linuxConstants.O_PATH ?? constants.O_RDONLY) | (constants.O_NOFOLLOW ?? 0),
);
let sourceOpen = true;
const releaseSource = () => {
if (!sourceOpen) return;
sourceOpen = false;
closeSync(sourceFd);
};
try {
const metadata = fstatSync(sourceFd, { bigint: true });
if (
metadata.dev !== BigInt(existing.dev) ||
metadata.ino !== BigInt(existing.ino) ||
!matchesTargetType(metadata, input.targetType)
) {
throw new Error(`Approved sandbox path changed while pinning: ${input.path}`);
}
return {
path: input.path,
access: input.access,
sourceFd,
releaseSource,
childFd: input.childFd,
device: metadata.dev,
inode: metadata.ino,
mtimeNs: metadata.mtimeNs,
ctimeNs: metadata.ctimeNs,
};
} catch (error) {
releaseSource();
throw error;
}
}
function matchesTargetType(
metadata: {
isFile(): boolean;
isDirectory(): boolean;
},
targetType: 'file' | 'directory' | 'other',
): boolean {
if (targetType === 'file') return metadata.isFile();
if (targetType === 'directory') return metadata.isDirectory();
return !metadata.isFile() && !metadata.isDirectory();
}