@torkbot/sandbox 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +237 -133
- package/dist/artifacts.d.ts +6 -0
- package/dist/artifacts.d.ts.map +1 -1
- package/dist/artifacts.js +58 -4
- package/dist/artifacts.js.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/control-codec.d.ts +23 -1
- package/dist/control-codec.d.ts.map +1 -1
- package/dist/control-codec.js.map +1 -1
- package/dist/control.d.ts +16 -2
- package/dist/control.d.ts.map +1 -1
- package/dist/control.js +12 -29
- package/dist/control.js.map +1 -1
- package/dist/host-process.d.ts +3 -8
- package/dist/host-process.d.ts.map +1 -1
- package/dist/host-process.js +355 -28
- package/dist/host-process.js.map +1 -1
- package/dist/index.d.ts +104 -199
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +298 -268
- package/dist/index.js.map +1 -1
- package/dist/launch-options.d.ts +64 -0
- package/dist/launch-options.d.ts.map +1 -0
- package/dist/launch-options.js +2 -0
- package/dist/launch-options.js.map +1 -0
- package/dist/memory-fs.d.ts +3 -0
- package/dist/memory-fs.d.ts.map +1 -0
- package/dist/memory-fs.js +308 -0
- package/dist/memory-fs.js.map +1 -0
- package/dist/spawn-options.d.ts +7 -6
- package/dist/spawn-options.d.ts.map +1 -1
- package/dist/vfs.d.ts +2 -1
- package/dist/vfs.d.ts.map +1 -1
- package/dist/vfs.js +14 -0
- package/dist/vfs.js.map +1 -1
- package/package.json +3 -3
- package/dist/host-filesystem-tools.d.ts +0 -3
- package/dist/host-filesystem-tools.d.ts.map +0 -1
- package/dist/host-filesystem-tools.js +0 -330
- package/dist/host-filesystem-tools.js.map +0 -1
package/dist/control.d.ts
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SandboxControlCommand, SandboxControlEvent } from "./control-codec.ts";
|
|
2
|
+
export interface SandboxControl extends Transport<SandboxControlEvent, SandboxControlCommand> {
|
|
3
|
+
exec(input: {
|
|
4
|
+
readonly id?: string;
|
|
5
|
+
readonly argv: readonly string[];
|
|
6
|
+
readonly env?: Record<string, string>;
|
|
7
|
+
}): Promise<Extract<SandboxControlEvent, {
|
|
8
|
+
type: "guest.exec.complete";
|
|
9
|
+
}>>;
|
|
10
|
+
}
|
|
11
|
+
export interface Transport<TIncoming = unknown, TOutgoing = unknown> {
|
|
12
|
+
readonly incoming: AsyncIterable<TIncoming>;
|
|
13
|
+
send(message: TOutgoing): Promise<void>;
|
|
14
|
+
close(): Promise<void>;
|
|
15
|
+
}
|
|
2
16
|
export interface HostControlChannel {
|
|
17
|
+
readonly packets: AsyncIterable<Uint8Array>;
|
|
3
18
|
writeControlPacket(packet: Uint8Array): void;
|
|
4
|
-
tryReadControlPacket(): Uint8Array | null;
|
|
5
19
|
}
|
|
6
20
|
export declare class HostControlTransport implements SandboxControl {
|
|
7
21
|
#private;
|
package/dist/control.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control.d.ts","sourceRoot":"","sources":["../src/control.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"control.d.ts","sourceRoot":"","sources":["../src/control.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAM5B,MAAM,WAAW,cAAe,SAAQ,SAAS,CAAC,mBAAmB,EAAE,qBAAqB,CAAC;IAC3F,IAAI,CAAC,KAAK,EAAE;QACV,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;QACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACvC,GAAG,OAAO,CAAC,OAAO,CAAC,mBAAmB,EAAE;QAAE,IAAI,EAAE,qBAAqB,CAAA;KAAE,CAAC,CAAC,CAAC;CAC5E;AAED,MAAM,WAAW,SAAS,CAAC,SAAS,GAAG,OAAO,EAAE,SAAS,GAAG,OAAO;IACjE,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IAC5C,IAAI,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAC5C,kBAAkB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;CAC9C;AAED,qBAAa,oBAAqB,YAAW,cAAc;;IACzD,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;IAWtD,YAAY,OAAO,GAAE;QACnB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;QAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC;KAClC,EAeL;IAEK,IAAI,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAMxD;IAEK,IAAI,CAAC,KAAK,EAAE;QAChB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;QACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACvC,GAAG,OAAO,CAAC,OAAO,CAAC,mBAAmB,EAAE;QAAE,IAAI,EAAE,qBAAqB,CAAA;KAAE,CAAC,CAAC,CAqBzE;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAQ3B;IAED,IAAI,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAGrC;CA4DF"}
|
package/dist/control.js
CHANGED
|
@@ -72,34 +72,23 @@ export class HostControlTransport {
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
async #pumpIncoming() {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
catch (error) {
|
|
81
|
-
if (this.#closed) {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
this.#fail(error);
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
if (packet !== null) {
|
|
75
|
+
if (this.#channel === null) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
for await (const packet of this.#channel.packets) {
|
|
88
80
|
if (this.#closed) {
|
|
89
81
|
return;
|
|
90
82
|
}
|
|
91
|
-
|
|
92
|
-
try {
|
|
93
|
-
event = decodeControlEvent(packet);
|
|
94
|
-
}
|
|
95
|
-
catch (error) {
|
|
96
|
-
this.#fail(error);
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
83
|
+
const event = decodeControlEvent(packet);
|
|
99
84
|
this.#dispatchEvent(event);
|
|
100
|
-
continue;
|
|
101
85
|
}
|
|
102
|
-
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
if (this.#closed) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
this.#fail(error);
|
|
103
92
|
}
|
|
104
93
|
}
|
|
105
94
|
#dispatchEvent(event) {
|
|
@@ -129,12 +118,6 @@ export class HostControlTransport {
|
|
|
129
118
|
this.#pendingExec.clear();
|
|
130
119
|
}
|
|
131
120
|
}
|
|
132
|
-
function sleep(ms) {
|
|
133
|
-
return new Promise((resolve) => {
|
|
134
|
-
const timeout = setTimeout(resolve, ms);
|
|
135
|
-
timeout.unref();
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
121
|
class AsyncQueue {
|
|
139
122
|
#values = [];
|
|
140
123
|
#waiters = [];
|
package/dist/control.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control.js","sourceRoot":"","sources":["../src/control.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"control.js","sourceRoot":"","sources":["../src/control.ts"],"names":[],"mappings":"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"}
|
package/dist/host-process.d.ts
CHANGED
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
import { hostBinaryPath } from "./artifacts.ts";
|
|
2
2
|
import type { HostControlChannel } from "./control.ts";
|
|
3
3
|
import type { HostSpawnSandboxOptions } from "./spawn-options.ts";
|
|
4
|
-
import type {
|
|
5
|
-
type RegisteredHttpRequestHeadersHook = {
|
|
6
|
-
readonly selector: SandboxHttpRequestSelector;
|
|
7
|
-
readonly hook: SandboxHttpRequestHook;
|
|
8
|
-
active: boolean;
|
|
9
|
-
};
|
|
4
|
+
import type { InternalSandboxOptions, RegisteredHttpRequestHeadersHook } from "./launch-options.ts";
|
|
10
5
|
export declare class HostProcessSandboxVm implements HostControlChannel {
|
|
11
6
|
#private;
|
|
12
7
|
readonly hasControlSocket = true;
|
|
8
|
+
readonly packets: AsyncIterable<Uint8Array>;
|
|
13
9
|
private constructor();
|
|
14
|
-
static spawn(options:
|
|
10
|
+
static spawn(options: InternalSandboxOptions, hostOptions: HostSpawnSandboxOptions, requestHeaderHooks?: Map<string, RegisteredHttpRequestHeadersHook>): Promise<HostProcessSandboxVm>;
|
|
15
11
|
writeControlPacket(packet: Uint8Array): void;
|
|
16
|
-
tryReadControlPacket(): Uint8Array | null;
|
|
17
12
|
close(): Promise<void>;
|
|
18
13
|
terminateHostForTest(): Promise<void>;
|
|
19
14
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host-process.d.ts","sourceRoot":"","sources":["../src/host-process.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"host-process.d.ts","sourceRoot":"","sources":["../src/host-process.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAyB,MAAM,gBAAgB,CAAC;AACvE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAQlE,OAAO,KAAK,EACV,sBAAsB,EACtB,gCAAgC,EACjC,MAAM,qBAAqB,CAAC;AAI7B,qBAAa,oBAAqB,YAAW,kBAAkB;;IAC7D,QAAQ,CAAC,gBAAgB,QAAQ;IACjC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAiB5C,OAAO,eA6CN;IAED,OAAa,KAAK,CAChB,OAAO,EAAE,sBAAsB,EAC/B,WAAW,EAAE,uBAAuB,EACpC,kBAAkB,GAAE,GAAG,CAAC,MAAM,EAAE,gCAAgC,CAAa,GAC5E,OAAO,CAAC,oBAAoB,CAAC,CAyB/B;IAED,kBAAkB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAG3C;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CA4B3B;IAEK,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAiB1C;CAqhBF;AA2BD,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
package/dist/host-process.js
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { once } from "node:events";
|
|
3
3
|
import { Binary, BSON } from "bson";
|
|
4
|
-
import { hostBinaryPath } from "./artifacts.js";
|
|
4
|
+
import { hostBinaryPath, macosHostSigningError } from "./artifacts.js";
|
|
5
5
|
import { isSandboxWritableFileSystem } from "./vfs.js";
|
|
6
|
+
const DEFAULT_LAUNCH_TIMEOUT_MS = 60_000;
|
|
6
7
|
export class HostProcessSandboxVm {
|
|
7
8
|
hasControlSocket = true;
|
|
9
|
+
packets;
|
|
8
10
|
#child;
|
|
9
11
|
#options;
|
|
10
|
-
#packets =
|
|
11
|
-
#
|
|
12
|
+
#packets = new AsyncQueue();
|
|
13
|
+
#packetActivity = new AsyncSignal();
|
|
14
|
+
#launchReady = new AsyncSignal("sandbox-host launch acknowledgement closed");
|
|
12
15
|
#hostFs = new Map();
|
|
16
|
+
#rootBlockStore;
|
|
17
|
+
#rootBlockStoreContext;
|
|
13
18
|
#requestHeaderHooks;
|
|
14
19
|
#buffer = new Uint8Array();
|
|
15
20
|
#stderr = "";
|
|
@@ -19,11 +24,12 @@ export class HostProcessSandboxVm {
|
|
|
19
24
|
constructor(child, options, requestHeaderHooks) {
|
|
20
25
|
this.#child = child;
|
|
21
26
|
this.#options = options;
|
|
27
|
+
this.packets = this.#packets;
|
|
22
28
|
this.#requestHeaderHooks = requestHeaderHooks;
|
|
29
|
+
this.#rootBlockStore = options.rootfs.storage?.blockStore;
|
|
30
|
+
this.#rootBlockStoreContext = options.rootfs.storage?.context;
|
|
23
31
|
for (const mount of options.mounts ?? []) {
|
|
24
|
-
|
|
25
|
-
this.#hostFs.set(mount.path, mount.fileSystem);
|
|
26
|
-
}
|
|
32
|
+
this.#hostFs.set(mount.path, mount.fileSystem);
|
|
27
33
|
}
|
|
28
34
|
child.stdout.on("data", (chunk) => {
|
|
29
35
|
this.#receive(chunk);
|
|
@@ -48,12 +54,16 @@ export class HostProcessSandboxVm {
|
|
|
48
54
|
? `sandbox-host exited with ${code ?? "unknown status"}`
|
|
49
55
|
: `sandbox-host exited from signal ${signal}`;
|
|
50
56
|
this.#exitError = new Error(this.#stderr.length === 0 ? exitText : `${exitText}\n${this.#stderr}`);
|
|
57
|
+
this.#packets.close(this.#exitError);
|
|
58
|
+
this.#packetActivity.close(this.#exitError);
|
|
59
|
+
this.#launchReady.close(this.#exitError);
|
|
51
60
|
});
|
|
52
61
|
}
|
|
53
62
|
static async spawn(options, hostOptions, requestHeaderHooks = new Map()) {
|
|
54
63
|
let vm;
|
|
64
|
+
const hostPath = hostBinaryPath();
|
|
55
65
|
try {
|
|
56
|
-
const child = spawn(
|
|
66
|
+
const child = spawn(hostPath, ["--stdio"], {
|
|
57
67
|
stdio: ["pipe", "pipe", "pipe"],
|
|
58
68
|
});
|
|
59
69
|
vm = new HostProcessSandboxVm(child, options, requestHeaderHooks);
|
|
@@ -69,6 +79,10 @@ export class HostProcessSandboxVm {
|
|
|
69
79
|
}
|
|
70
80
|
catch (error) {
|
|
71
81
|
await vm?.close();
|
|
82
|
+
const signingError = macosHostSigningError(hostPath);
|
|
83
|
+
if (signingError !== null) {
|
|
84
|
+
throw signingError;
|
|
85
|
+
}
|
|
72
86
|
throw error;
|
|
73
87
|
}
|
|
74
88
|
}
|
|
@@ -76,15 +90,13 @@ export class HostProcessSandboxVm {
|
|
|
76
90
|
this.#assertOpen();
|
|
77
91
|
this.#writeToHost(packet);
|
|
78
92
|
}
|
|
79
|
-
tryReadControlPacket() {
|
|
80
|
-
this.#assertOpen();
|
|
81
|
-
return this.#packets.shift() ?? null;
|
|
82
|
-
}
|
|
83
93
|
async close() {
|
|
84
94
|
if (this.#closed) {
|
|
85
95
|
return;
|
|
86
96
|
}
|
|
87
97
|
this.#closed = true;
|
|
98
|
+
this.#packets.close();
|
|
99
|
+
this.#packetActivity.close();
|
|
88
100
|
const exited = this.#child.exitCode !== null || this.#child.signalCode !== null
|
|
89
101
|
? Promise.resolve()
|
|
90
102
|
: once(this.#child, "exit").then(() => undefined);
|
|
@@ -173,8 +185,11 @@ export class HostProcessSandboxVm {
|
|
|
173
185
|
}
|
|
174
186
|
const packet = this.#buffer.slice(0, packetLength);
|
|
175
187
|
this.#buffer = this.#buffer.slice(packetLength);
|
|
176
|
-
this.#
|
|
188
|
+
this.#packetActivity.notify();
|
|
177
189
|
if (!this.#routeHostPacket(packet)) {
|
|
190
|
+
if (isInitReadyPacket(packet)) {
|
|
191
|
+
this.#launchReady.notify();
|
|
192
|
+
}
|
|
178
193
|
this.#packets.push(packet);
|
|
179
194
|
}
|
|
180
195
|
}
|
|
@@ -198,10 +213,19 @@ export class HostProcessSandboxVm {
|
|
|
198
213
|
&& type !== "host.vfs.unlink"
|
|
199
214
|
&& type !== "host.vfs.rmdir"
|
|
200
215
|
&& type !== "host.vfs.rename"
|
|
216
|
+
&& type !== "host.vfs.link"
|
|
201
217
|
&& type !== "host.vfs.symlink"
|
|
202
218
|
&& type !== "host.vfs.readlink"
|
|
219
|
+
&& type !== "host.vfs.setxattr"
|
|
220
|
+
&& type !== "host.vfs.getxattr"
|
|
221
|
+
&& type !== "host.vfs.listxattr"
|
|
222
|
+
&& type !== "host.vfs.removexattr"
|
|
203
223
|
&& type !== "host.http.requestHeaders"
|
|
204
|
-
&& type !== "host.http.activeRequestHeaderHooks"
|
|
224
|
+
&& type !== "host.http.activeRequestHeaderHooks"
|
|
225
|
+
&& type !== "host.block.list"
|
|
226
|
+
&& type !== "host.block.read"
|
|
227
|
+
&& type !== "host.block.write"
|
|
228
|
+
&& type !== "host.block.flush") {
|
|
205
229
|
return false;
|
|
206
230
|
}
|
|
207
231
|
if (type === "host.http.requestHeaders") {
|
|
@@ -210,6 +234,12 @@ export class HostProcessSandboxVm {
|
|
|
210
234
|
else if (type === "host.http.activeRequestHeaderHooks") {
|
|
211
235
|
void this.#handleActiveRequestHeaderHooks(document);
|
|
212
236
|
}
|
|
237
|
+
else if (type === "host.block.list"
|
|
238
|
+
|| type === "host.block.read"
|
|
239
|
+
|| type === "host.block.write"
|
|
240
|
+
|| type === "host.block.flush") {
|
|
241
|
+
void this.#handleBlockStoreRequest(document);
|
|
242
|
+
}
|
|
213
243
|
else {
|
|
214
244
|
void this.#handleVirtualFsRequest(document);
|
|
215
245
|
}
|
|
@@ -416,6 +446,18 @@ export class HostProcessSandboxVm {
|
|
|
416
446
|
}));
|
|
417
447
|
return;
|
|
418
448
|
}
|
|
449
|
+
case "host.vfs.link": {
|
|
450
|
+
const posix = assertPosixFileSystem(fileSystem, mountPath);
|
|
451
|
+
const from = assertString(document.from, "from");
|
|
452
|
+
const to = assertString(document.to, "to");
|
|
453
|
+
this.#tryWriteToHost(encodePacket({
|
|
454
|
+
type: "host.vfs.response",
|
|
455
|
+
id,
|
|
456
|
+
ok: true,
|
|
457
|
+
stat: await posix.link(from, to),
|
|
458
|
+
}));
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
419
461
|
case "host.vfs.symlink": {
|
|
420
462
|
const path = assertString(document.path, "path");
|
|
421
463
|
const posix = assertPosixFileSystem(fileSystem, mountPath);
|
|
@@ -440,6 +482,83 @@ export class HostProcessSandboxVm {
|
|
|
440
482
|
}));
|
|
441
483
|
return;
|
|
442
484
|
}
|
|
485
|
+
case "host.vfs.setxattr": {
|
|
486
|
+
const path = assertString(document.path, "path");
|
|
487
|
+
const name = assertString(document.name, "name");
|
|
488
|
+
const value = binaryField(document.value, "value");
|
|
489
|
+
const flags = assertNumber(document.flags, "flags");
|
|
490
|
+
const posix = assertPosixFileSystem(fileSystem, mountPath);
|
|
491
|
+
await posix.setxattr(path, name, value, flags);
|
|
492
|
+
this.#tryWriteToHost(encodePacket({
|
|
493
|
+
type: "host.vfs.response",
|
|
494
|
+
id,
|
|
495
|
+
ok: true,
|
|
496
|
+
}));
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
case "host.vfs.getxattr": {
|
|
500
|
+
const path = assertString(document.path, "path");
|
|
501
|
+
const name = assertString(document.name, "name");
|
|
502
|
+
const size = assertNumber(document.size, "size");
|
|
503
|
+
const posix = assertPosixFileSystem(fileSystem, mountPath);
|
|
504
|
+
const value = await posix.getxattr(path, name);
|
|
505
|
+
if (size === 0) {
|
|
506
|
+
this.#tryWriteToHost(encodePacket({
|
|
507
|
+
type: "host.vfs.response",
|
|
508
|
+
id,
|
|
509
|
+
ok: true,
|
|
510
|
+
count: value.byteLength,
|
|
511
|
+
}));
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
if (value.byteLength > size) {
|
|
515
|
+
throw new Error("xattr value is larger than requested size");
|
|
516
|
+
}
|
|
517
|
+
this.#tryWriteToHost(encodePacket({
|
|
518
|
+
type: "host.vfs.response",
|
|
519
|
+
id,
|
|
520
|
+
ok: true,
|
|
521
|
+
value: new Binary(value),
|
|
522
|
+
}));
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
case "host.vfs.listxattr": {
|
|
526
|
+
const path = assertString(document.path, "path");
|
|
527
|
+
const size = assertNumber(document.size, "size");
|
|
528
|
+
const posix = assertPosixFileSystem(fileSystem, mountPath);
|
|
529
|
+
const names = encodeXattrNameList(await posix.listxattr(path));
|
|
530
|
+
if (size === 0) {
|
|
531
|
+
this.#tryWriteToHost(encodePacket({
|
|
532
|
+
type: "host.vfs.response",
|
|
533
|
+
id,
|
|
534
|
+
ok: true,
|
|
535
|
+
count: names.byteLength,
|
|
536
|
+
}));
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
if (names.byteLength > size) {
|
|
540
|
+
throw new Error("xattr name list is larger than requested size");
|
|
541
|
+
}
|
|
542
|
+
this.#tryWriteToHost(encodePacket({
|
|
543
|
+
type: "host.vfs.response",
|
|
544
|
+
id,
|
|
545
|
+
ok: true,
|
|
546
|
+
names: new Binary(names),
|
|
547
|
+
}));
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
case "host.vfs.removexattr": {
|
|
551
|
+
const path = assertString(document.path, "path");
|
|
552
|
+
const name = assertString(document.name, "name");
|
|
553
|
+
const posix = assertPosixFileSystem(fileSystem, mountPath);
|
|
554
|
+
await posix.removexattr(path, name);
|
|
555
|
+
this.#tryWriteToHost(encodePacket({
|
|
556
|
+
type: "host.vfs.response",
|
|
557
|
+
id,
|
|
558
|
+
ok: true,
|
|
559
|
+
}));
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
443
562
|
}
|
|
444
563
|
}
|
|
445
564
|
catch (error) {
|
|
@@ -451,27 +570,107 @@ export class HostProcessSandboxVm {
|
|
|
451
570
|
}));
|
|
452
571
|
}
|
|
453
572
|
}
|
|
454
|
-
async #
|
|
455
|
-
|
|
456
|
-
|
|
573
|
+
async #handleBlockStoreRequest(document) {
|
|
574
|
+
const id = typeof document.id === "string" ? document.id : "";
|
|
575
|
+
try {
|
|
576
|
+
const blockStore = this.#rootBlockStore;
|
|
577
|
+
const blockStoreContext = this.#rootBlockStoreContext;
|
|
578
|
+
if (blockStore === undefined || blockStoreContext === undefined) {
|
|
579
|
+
throw new Error("root block store is not configured");
|
|
580
|
+
}
|
|
581
|
+
switch (document.type) {
|
|
582
|
+
case "host.block.list": {
|
|
583
|
+
this.#tryWriteToHost(encodePacket({
|
|
584
|
+
type: "host.block.response",
|
|
585
|
+
id,
|
|
586
|
+
ok: true,
|
|
587
|
+
blocks: (await blockStore.list(blockStoreContext)).map((block) => block.toString()),
|
|
588
|
+
}));
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
case "host.block.read": {
|
|
592
|
+
const chunks = await blockStore.read({
|
|
593
|
+
start: BigInt(assertString(document.start, "start")),
|
|
594
|
+
count: assertNumber(document.count, "count"),
|
|
595
|
+
}, blockStoreContext);
|
|
596
|
+
this.#tryWriteToHost(encodePacket({
|
|
597
|
+
type: "host.block.response",
|
|
598
|
+
id,
|
|
599
|
+
ok: true,
|
|
600
|
+
chunks: chunks.map((chunk) => ({
|
|
601
|
+
start: chunk.start.toString(),
|
|
602
|
+
data: new Binary(chunk.data),
|
|
603
|
+
})),
|
|
604
|
+
}));
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
case "host.block.write": {
|
|
608
|
+
const chunks = assertDocumentArray(document.chunks, "chunks").map((chunk) => ({
|
|
609
|
+
start: BigInt(assertString(chunk.start, "chunks.start")),
|
|
610
|
+
data: binaryField(chunk.data, "chunks.data"),
|
|
611
|
+
}));
|
|
612
|
+
await blockStore.write(chunks, blockStoreContext);
|
|
613
|
+
this.#tryWriteToHost(encodePacket({
|
|
614
|
+
type: "host.block.response",
|
|
615
|
+
id,
|
|
616
|
+
ok: true,
|
|
617
|
+
}));
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
case "host.block.flush": {
|
|
621
|
+
await blockStore.flush?.(blockStoreContext);
|
|
622
|
+
this.#tryWriteToHost(encodePacket({
|
|
623
|
+
type: "host.block.response",
|
|
624
|
+
id,
|
|
625
|
+
ok: true,
|
|
626
|
+
}));
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
457
630
|
}
|
|
631
|
+
catch (error) {
|
|
632
|
+
this.#tryWriteToHost(encodePacket({
|
|
633
|
+
type: "host.block.response",
|
|
634
|
+
id,
|
|
635
|
+
ok: false,
|
|
636
|
+
error: error instanceof Error ? error.message : String(error),
|
|
637
|
+
}));
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
async #waitForLaunch() {
|
|
641
|
+
const timeoutMs = launchTimeoutMs();
|
|
458
642
|
await Promise.race([
|
|
459
|
-
|
|
460
|
-
this.#hostPacketWaiters.push(resolvePromise);
|
|
461
|
-
}),
|
|
643
|
+
this.#launchReady.wait(),
|
|
462
644
|
once(this.#child, "exit").then(() => {
|
|
463
645
|
throw this.#exitError ?? new Error("sandbox-host exited before VM launch completed");
|
|
464
646
|
}),
|
|
465
|
-
|
|
466
|
-
throw new Error(
|
|
647
|
+
unrefDelay(timeoutMs).then(() => {
|
|
648
|
+
throw new Error(`sandbox-host did not produce a launch acknowledgement within ${timeoutMs}ms`);
|
|
467
649
|
}),
|
|
468
650
|
]);
|
|
469
651
|
}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
652
|
+
}
|
|
653
|
+
function launchTimeoutMs() {
|
|
654
|
+
const value = process.env.SANDBOX_LAUNCH_TIMEOUT_MS;
|
|
655
|
+
if (value === undefined || value.length === 0) {
|
|
656
|
+
return DEFAULT_LAUNCH_TIMEOUT_MS;
|
|
657
|
+
}
|
|
658
|
+
const parsed = Number(value);
|
|
659
|
+
if (!Number.isSafeInteger(parsed) || parsed <= 0) {
|
|
660
|
+
throw new Error(`SANDBOX_LAUNCH_TIMEOUT_MS must be a positive integer, got ${value}`);
|
|
661
|
+
}
|
|
662
|
+
return parsed;
|
|
663
|
+
}
|
|
664
|
+
function encodeXattrNameList(names) {
|
|
665
|
+
return new TextEncoder().encode(names.map((name) => `${name}\0`).join(""));
|
|
666
|
+
}
|
|
667
|
+
function isInitReadyPacket(packet) {
|
|
668
|
+
try {
|
|
669
|
+
const document = BSON.deserialize(packet.slice(4));
|
|
670
|
+
return document.type === "init.ready";
|
|
671
|
+
}
|
|
672
|
+
catch {
|
|
673
|
+
return false;
|
|
475
674
|
}
|
|
476
675
|
}
|
|
477
676
|
export { hostBinaryPath };
|
|
@@ -505,6 +704,12 @@ function assertHeaderPairs(value, field) {
|
|
|
505
704
|
}
|
|
506
705
|
return value;
|
|
507
706
|
}
|
|
707
|
+
function assertDocumentArray(value, field) {
|
|
708
|
+
if (!Array.isArray(value) || value.some((entry) => entry === null || typeof entry !== "object")) {
|
|
709
|
+
throw new Error(`host request ${field} must be documents`);
|
|
710
|
+
}
|
|
711
|
+
return value;
|
|
712
|
+
}
|
|
508
713
|
function trackHeaderMutations(headers) {
|
|
509
714
|
let mutated = false;
|
|
510
715
|
const set = headers.set.bind(headers);
|
|
@@ -571,8 +776,13 @@ function assertPosixFileSystem(fileSystem, mountPath) {
|
|
|
571
776
|
|| typeof candidate.unlink !== "function"
|
|
572
777
|
|| typeof candidate.rmdir !== "function"
|
|
573
778
|
|| typeof candidate.rename !== "function"
|
|
779
|
+
|| typeof candidate.link !== "function"
|
|
574
780
|
|| typeof candidate.symlink !== "function"
|
|
575
|
-
|| typeof candidate.readlink !== "function"
|
|
781
|
+
|| typeof candidate.readlink !== "function"
|
|
782
|
+
|| typeof candidate.setxattr !== "function"
|
|
783
|
+
|| typeof candidate.getxattr !== "function"
|
|
784
|
+
|| typeof candidate.listxattr !== "function"
|
|
785
|
+
|| typeof candidate.removexattr !== "function") {
|
|
576
786
|
throw new Error(`host filesystem mount does not support POSIX mutations: ${mountPath}`);
|
|
577
787
|
}
|
|
578
788
|
return candidate;
|
|
@@ -580,6 +790,118 @@ function assertPosixFileSystem(fileSystem, mountPath) {
|
|
|
580
790
|
function delay(milliseconds) {
|
|
581
791
|
return new Promise((resolvePromise) => setTimeout(resolvePromise, milliseconds));
|
|
582
792
|
}
|
|
793
|
+
function unrefDelay(milliseconds) {
|
|
794
|
+
return new Promise((resolvePromise) => {
|
|
795
|
+
const timeout = setTimeout(resolvePromise, milliseconds);
|
|
796
|
+
timeout.unref();
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
class AsyncQueue {
|
|
800
|
+
#values = [];
|
|
801
|
+
#nextWaiters = [];
|
|
802
|
+
#closed = false;
|
|
803
|
+
#error;
|
|
804
|
+
get length() {
|
|
805
|
+
return this.#values.length;
|
|
806
|
+
}
|
|
807
|
+
push(value) {
|
|
808
|
+
if (this.#closed) {
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
const nextWaiter = this.#nextWaiters.shift();
|
|
812
|
+
if (nextWaiter !== undefined) {
|
|
813
|
+
nextWaiter.resolve({ value, done: false });
|
|
814
|
+
}
|
|
815
|
+
else {
|
|
816
|
+
this.#values.push(value);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
close(error) {
|
|
820
|
+
if (this.#closed) {
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
this.#closed = true;
|
|
824
|
+
this.#error = error;
|
|
825
|
+
for (const waiter of this.#nextWaiters.splice(0)) {
|
|
826
|
+
if (error === undefined) {
|
|
827
|
+
waiter.resolve({ value: undefined, done: true });
|
|
828
|
+
}
|
|
829
|
+
else {
|
|
830
|
+
waiter.reject(error);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
[Symbol.asyncIterator]() {
|
|
835
|
+
return {
|
|
836
|
+
next: async () => {
|
|
837
|
+
const value = this.#values.shift();
|
|
838
|
+
if (value !== undefined) {
|
|
839
|
+
return { value, done: false };
|
|
840
|
+
}
|
|
841
|
+
if (this.#closed) {
|
|
842
|
+
if (this.#error !== undefined) {
|
|
843
|
+
throw this.#error;
|
|
844
|
+
}
|
|
845
|
+
return { value: undefined, done: true };
|
|
846
|
+
}
|
|
847
|
+
return await new Promise((resolve, reject) => {
|
|
848
|
+
this.#nextWaiters.push({
|
|
849
|
+
resolve,
|
|
850
|
+
reject,
|
|
851
|
+
});
|
|
852
|
+
});
|
|
853
|
+
},
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
class AsyncSignal {
|
|
858
|
+
#waiters = [];
|
|
859
|
+
#closedMessage;
|
|
860
|
+
#signaled = false;
|
|
861
|
+
#closed = false;
|
|
862
|
+
#error;
|
|
863
|
+
constructor(closedMessage = "sandbox-host packet activity closed") {
|
|
864
|
+
this.#closedMessage = closedMessage;
|
|
865
|
+
}
|
|
866
|
+
notify() {
|
|
867
|
+
if (this.#closed) {
|
|
868
|
+
return;
|
|
869
|
+
}
|
|
870
|
+
this.#signaled = true;
|
|
871
|
+
for (const waiter of this.#waiters.splice(0)) {
|
|
872
|
+
waiter.resolve();
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
close(error) {
|
|
876
|
+
if (this.#closed) {
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
this.#closed = true;
|
|
880
|
+
this.#error = error;
|
|
881
|
+
for (const waiter of this.#waiters.splice(0)) {
|
|
882
|
+
if (error === undefined) {
|
|
883
|
+
waiter.resolve();
|
|
884
|
+
}
|
|
885
|
+
else {
|
|
886
|
+
waiter.reject(error);
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
async wait() {
|
|
891
|
+
if (this.#signaled) {
|
|
892
|
+
return;
|
|
893
|
+
}
|
|
894
|
+
if (this.#closed) {
|
|
895
|
+
if (this.#error !== undefined) {
|
|
896
|
+
throw this.#error;
|
|
897
|
+
}
|
|
898
|
+
throw new Error(this.#closedMessage);
|
|
899
|
+
}
|
|
900
|
+
return await new Promise((resolve, reject) => {
|
|
901
|
+
this.#waiters.push({ resolve, reject });
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
}
|
|
583
905
|
function encodeHostSpawn(options) {
|
|
584
906
|
return encodePacket({
|
|
585
907
|
type: "host.spawn",
|
|
@@ -591,7 +913,12 @@ function encodeHostSpawn(options) {
|
|
|
591
913
|
rootfsPath: options.rootfs.path,
|
|
592
914
|
rootfsReadonly: options.rootfs.readonly,
|
|
593
915
|
rootfsFormat: options.rootfs.format,
|
|
594
|
-
|
|
916
|
+
rootfsStorage: options.rootfs.storage === undefined
|
|
917
|
+
? undefined
|
|
918
|
+
: {
|
|
919
|
+
kind: options.rootfs.storage.kind,
|
|
920
|
+
blockSize: options.rootfs.storage.blockSize,
|
|
921
|
+
},
|
|
595
922
|
mounts: options.mounts ?? [],
|
|
596
923
|
networkOutbound: options.network?.outbound,
|
|
597
924
|
networkHttp: options.network?.http === undefined ? undefined : options.network.http,
|