fix(windows): admit volume roots with existing write handles

This commit is contained in:
morluto
2026-10-15 06:12:23 +08:00
parent bb49252523
commit 709e99d781
4 changed files with 151 additions and 1 deletions
+4 -1
View File
@@ -67,7 +67,10 @@ std::unique_ptr<File> openFile(const std::wstring& requested, DWORD access, bool
result->requestedPath = requested;
const auto& path = result->path;
require(directory || path.size() > 3, "Target is not a regular file", requested, ERROR_DIRECTORY);
result->handles.push_back(openComponent(path.substr(0, 3), 0, true));
// The volume root cannot be replaced or deleted. Match the later root
// reopen's write sharing here so a root writer cannot block admission.
result->handles.push_back(openComponent(path.substr(0, 3), 0, true,
FILE_SHARE_READ | FILE_SHARE_WRITE));
wchar_t filesystem[64]{};
DWORD flags = 0;
require(GetVolumeInformationByHandleW(result->handles.front().get(), nullptr, 0, nullptr, nullptr,
@@ -0,0 +1,118 @@
import assert from "node:assert/strict";
import { spawn } from "node:child_process";
import { once } from "node:events";
import { createInterface } from "node:readline";
import { resolve } from "node:path";
const withDeadline = async (promise, milliseconds, description) => {
let timer;
try {
return await Promise.race([
promise,
new Promise((_, reject) => {
timer = setTimeout(
() =>
reject(new Error(`${description} exceeded ${milliseconds} ms.`)),
milliseconds,
);
}),
]);
} finally {
clearTimeout(timer);
}
};
export async function verifyVolumeRootAppendLease({
fixturePath,
volumeRoot,
verifyAdmission,
}) {
const lease = spawn(
resolve(fixturePath),
["volume-root-append-lease", volumeRoot],
{ stdio: ["pipe", "pipe", "pipe"], windowsHide: true },
);
const lines = createInterface({ input: lease.stdout });
let leaseStderr = "";
lease.stderr.setEncoding("utf8");
lease.stderr.on("data", (chunk) => {
if (leaseStderr.length < 8192) leaseStderr += chunk;
});
const closed = once(lease, "close").then(([code, signal]) => ({
code,
signal,
}));
const leaseLine = once(lines, "line").then(([line]) => ({ line }));
const leaseError = once(lease, "error").then(([error]) => {
throw error;
});
let verificationFailure;
try {
const ready = await withDeadline(
Promise.race([leaseLine, closed, leaseError]),
10_000,
"Volume-root append lease readiness",
);
assert.equal(
"line" in ready,
true,
`Volume-root append lease exited before readiness (code ${ready.code}, signal ${ready.signal}): ${leaseStderr}`,
);
const observation = JSON.parse(ready.line);
assert.equal(
observation.writeAccessGranted,
true,
`Windows test token cannot hold FILE_ADD_SUBDIRECTORY on ${volumeRoot} (Win32 ${observation.win32Code}).`,
);
await verifyAdmission();
} catch (error) {
verificationFailure = error;
}
lines.close();
if (
lease.exitCode === null &&
lease.signalCode === null &&
!lease.stdin.destroyed
)
lease.stdin.end("x");
let releaseFailure;
try {
const result = await withDeadline(
closed,
10_000,
"Volume-root append lease release",
).catch(async (error) => {
lease.kill();
try {
return await withDeadline(
closed,
5_000,
"Volume-root append lease termination",
);
} catch (terminationError) {
throw new AggregateError(
[error, terminationError],
`Volume-root append lease could not be released: ${leaseStderr}`,
);
}
});
assert.equal(
result.code,
0,
`Volume-root append lease exited with code ${result.code}, signal ${result.signal}: ${leaseStderr}`,
);
} catch (error) {
releaseFailure = error;
}
if (verificationFailure !== undefined && releaseFailure !== undefined)
throw new AggregateError(
[verificationFailure, releaseFailure],
"Volume-root append lease verification and cleanup both failed.",
);
if (verificationFailure !== undefined) throw verificationFailure;
if (releaseFailure !== undefined) throw releaseFailure;
}
+12
View File
@@ -22,6 +22,7 @@ import { dirname, join, parse, resolve } from "node:path";
import { pathToFileURL } from "node:url";
import { verifyWindowsProtocolInput } from "./lib/windows-protocol-input.mjs";
import { verifyWindowsJobMemoryLimit } from "./lib/windows-job-memory-limit.mjs";
import { verifyVolumeRootAppendLease } from "./lib/windows-volume-root-append-lease.mjs";
if (process.platform !== "win32")
throw new Error(
@@ -251,6 +252,17 @@ process.stdout.write(JSON.stringify({executable:basename(process.execPath),abiVe
}
const unrelatedFile = join(workspace, "unrelated-file");
await writeFile(unrelatedFile, "preserve unrelated writes");
if (process.argv[3] !== undefined) {
await verifyVolumeRootAppendLease({
fixturePath: process.argv[3],
volumeRoot: parse(source).root,
verifyAdmission: () => {
const rootGuard = native.call("open", [source]);
native.call("close", [rootGuard.handle]);
},
});
report.controls.volumeRootAdmissionWithAppendHandle = true;
}
const admitted = native.call("open", [source]);
try {
await assert.rejects(
+17
View File
@@ -97,6 +97,23 @@ int wmain(int count, wchar_t** args) {
? "true" : "false", observed);
return 0;
}
if (count == 3 && std::wstring(args[1]) == L"volume-root-append-lease") {
// A real directory append right participates in Windows' write-share
// check. The lease performs no mutation; it stays open while the native
// admission probe requests the same volume root for directory listing.
HANDLE root = CreateFileW(args[2], FILE_ADD_SUBDIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
if (root == INVALID_HANDLE_VALUE) {
std::printf("{\"writeAccessGranted\":false,\"win32Code\":%lu}\n", GetLastError());
return 0;
}
std::puts("{\"writeAccessGranted\":true}");
std::fflush(stdout);
const int release = std::getchar();
CloseHandle(root);
return release == 'x' || release == EOF ? 0 : 10;
}
if (count > 1 && std::wstring(args[1]) == L"breakaway") {
wchar_t executable[32768]; GetModuleFileNameW(nullptr, executable, 32768);
std::wstring line = L"\"" + std::wstring(executable) + L"\" exit";