mirror of
https://github.com/morluto/rea.git
synced 2026-10-11 21:39:55 +00:00
fix(windows): preserve drive-root private runtime paths
Join the admitted parent and generated child name without duplicating a drive-root separator. Reuse that name for handle-relative creation and path provenance. Add native snapshot, readback, and cleanup coverage through the Ghidra dot-prefixed temp fallback, plus a session-root contract regression. Fixes #1690
This commit is contained in:
@@ -219,9 +219,10 @@ std::unique_ptr<Runtime> createRuntime(const std::wstring& parentPath, const std
|
|||||||
require(BCryptGenRandom(nullptr, random.data(), random.size(), BCRYPT_USE_SYSTEM_PREFERRED_RNG) == 0,
|
require(BCryptGenRandom(nullptr, random.data(), random.size(), BCRYPT_USE_SYSTEM_PREFERRED_RNG) == 0,
|
||||||
"Generate runtime identity failed", parentPath, ERROR_GEN_FAILURE);
|
"Generate runtime identity failed", parentPath, ERROR_GEN_FAILURE);
|
||||||
auto result = std::make_unique<Runtime>();
|
auto result = std::make_unique<Runtime>();
|
||||||
result->path = parent->path + L"\\" + prefix + hex(random.data(), random.size());
|
const auto name = prefix + hex(random.data(), random.size());
|
||||||
|
result->path = parent->path + (parent->path.back() == L'\\' ? L"" : L"\\") + name;
|
||||||
Security security;
|
Security security;
|
||||||
result->directory = createRelative(parent->get(), prefix + hex(random.data(), random.size()),
|
result->directory = createRelative(parent->get(), name,
|
||||||
DELETE | FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | READ_CONTROL,
|
DELETE | FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | READ_CONTROL,
|
||||||
true, security, result->path);
|
true, security, result->path);
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
open,
|
open,
|
||||||
} from "node:fs/promises";
|
} from "node:fs/promises";
|
||||||
import { tmpdir } from "node:os";
|
import { tmpdir } from "node:os";
|
||||||
import { join, resolve } from "node:path";
|
import { dirname, join, parse, resolve } from "node:path";
|
||||||
import { pathToFileURL } from "node:url";
|
import { pathToFileURL } from "node:url";
|
||||||
import { verifyWindowsProtocolInput } from "./lib/windows-protocol-input.mjs";
|
import { verifyWindowsProtocolInput } from "./lib/windows-protocol-input.mjs";
|
||||||
|
|
||||||
@@ -33,6 +33,9 @@ const native = requireWindowsNativeAuthority();
|
|||||||
const { WindowsPrivateRuntime, windowsPrivateRuntime } = await import(
|
const { WindowsPrivateRuntime, windowsPrivateRuntime } = await import(
|
||||||
pathToFileURL(join(packageRoot, "dist/windows/WindowsPrivateRuntime.js"))
|
pathToFileURL(join(packageRoot, "dist/windows/WindowsPrivateRuntime.js"))
|
||||||
);
|
);
|
||||||
|
const { ghidraSessionRoot } = await import(
|
||||||
|
pathToFileURL(join(packageRoot, "dist/ghidra/GhidraSessionRoot.js"))
|
||||||
|
);
|
||||||
const workspace = await mkdtemp(join(tmpdir(), "rea-native-conformance-"));
|
const workspace = await mkdtemp(join(tmpdir(), "rea-native-conformance-"));
|
||||||
const environment = Object.entries(process.env)
|
const environment = Object.entries(process.env)
|
||||||
.filter(([, value]) => value !== undefined)
|
.filter(([, value]) => value !== undefined)
|
||||||
@@ -136,6 +139,47 @@ process.stdout.write(JSON.stringify({executable:basename(process.execPath),abiVe
|
|||||||
])
|
])
|
||||||
assert.throws(() => native.call("open", [rejected]));
|
assert.throws(() => native.call("open", [rejected]));
|
||||||
report.controls.ordinaryDriveSeparatorsAndRequestedIdentity = true;
|
report.controls.ordinaryDriveSeparatorsAndRequestedIdentity = true;
|
||||||
|
const driveRoot = parse(workspace).root;
|
||||||
|
const runtimeParent = ghidraSessionRoot({
|
||||||
|
base: join(driveRoot, ".Tmp", "scratch"),
|
||||||
|
});
|
||||||
|
assert.equal(runtimeParent, driveRoot);
|
||||||
|
const driveRootRuntime = native.call("runtime_create", [
|
||||||
|
runtimeParent,
|
||||||
|
"rea-drive-root-",
|
||||||
|
]);
|
||||||
|
try {
|
||||||
|
assert.equal(driveRootRuntime.path.startsWith(`${driveRoot}\\`), false);
|
||||||
|
assert.equal(dirname(driveRootRuntime.path), driveRoot);
|
||||||
|
const snapshot = await native.call("runtime_snapshot", [
|
||||||
|
driveRootRuntime.handle,
|
||||||
|
source,
|
||||||
|
"probe.bin",
|
||||||
|
]);
|
||||||
|
const sourceBytes = await readFile(source);
|
||||||
|
assert.equal(
|
||||||
|
snapshot.sha256,
|
||||||
|
createHash("sha256").update(sourceBytes).digest("hex"),
|
||||||
|
);
|
||||||
|
assert.equal(snapshot.source.requestedPath, source);
|
||||||
|
const readback = native.call("runtime_open", [
|
||||||
|
driveRootRuntime.handle,
|
||||||
|
"probe.bin",
|
||||||
|
]);
|
||||||
|
try {
|
||||||
|
assert.equal(readback.size, sourceBytes.byteLength);
|
||||||
|
assert.deepEqual(
|
||||||
|
native.call("read", [readback.handle, 0, 65536]),
|
||||||
|
sourceBytes.subarray(0, 65536),
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
native.call("close", [readback.handle]);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
native.call("runtime_close", [driveRootRuntime.handle]);
|
||||||
|
}
|
||||||
|
assert.equal(await exists(driveRootRuntime.path), false);
|
||||||
|
report.controls.driveRootRuntimeParent = true;
|
||||||
const snapshotOwner = WindowsPrivateRuntime.create(
|
const snapshotOwner = WindowsPrivateRuntime.create(
|
||||||
workspace.replace(/\\/u, "/"),
|
workspace.replace(/\\/u, "/"),
|
||||||
"single-flight-",
|
"single-flight-",
|
||||||
|
|||||||
@@ -44,6 +44,15 @@ describe("ghidraSessionRoot", () => {
|
|||||||
).toBe(posixBase("Users", "operator"));
|
).toBe(posixBase("Users", "operator"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("can select a filesystem root when the inherited temp starts with a dot-prefixed element", () => {
|
||||||
|
expect(
|
||||||
|
ghidraSessionRoot({
|
||||||
|
base: posixBase(".Tmp", "scratch"),
|
||||||
|
platform: "win32",
|
||||||
|
}),
|
||||||
|
).toBe(resolve(sep));
|
||||||
|
});
|
||||||
|
|
||||||
it.skipIf(!POSIX)("prefers the platform temp directory by default", () => {
|
it.skipIf(!POSIX)("prefers the platform temp directory by default", () => {
|
||||||
expect(
|
expect(
|
||||||
ghidraSessionRoot({ base: posixBase("home", "operator", ".cache") }),
|
ghidraSessionRoot({ base: posixBase("home", "operator", ".cache") }),
|
||||||
|
|||||||
Reference in New Issue
Block a user