@wenathlan/saddle 2.0.166 → 2.0.168
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/Dockerfile +150 -25
- package/README.md +3 -3
- package/biome.jsonc +3 -3
- package/cli.ts +2 -2
- package/docker.config +2 -2
- package/docs/architecture.md +7 -7
- package/docs/browser.md +1 -1
- package/docs/e2ughengine.md +8 -8
- package/docs/extension.md +1 -1
- package/docs/osdistributions.md +1 -1
- package/docs/todo1816.md +1 -1
- package/docs/viability.md +1 -1
- package/index.ts +4 -2
- package/modalities.ts +284 -60
- package/package.json +84 -86
- package/{scriptlanes.ts → scripts.ts} +283 -5
- package/tiers.ts +10 -2
- package/tsconfig.json +1 -1
- package/workloadlaw.ts +337 -38
package/modalities.ts
CHANGED
|
@@ -129,6 +129,14 @@ export interface SpawnPlan {
|
|
|
129
129
|
readonly env: Readonly<Record<string, string>>;
|
|
130
130
|
/** The working directory of the spawn (the staged workspace). */
|
|
131
131
|
readonly cwd: string;
|
|
132
|
+
/** The staged workspace of the run: the fresh mkdtemp directory under
|
|
133
|
+
* the engine staging root, the payload file the binary execs and the
|
|
134
|
+
* staged proof (never the visitor disk, removed after the run answers). */
|
|
135
|
+
readonly workspace: {
|
|
136
|
+
readonly dir: string;
|
|
137
|
+
readonly file: string;
|
|
138
|
+
readonly staged: true;
|
|
139
|
+
};
|
|
132
140
|
/** The cgroups v2 slice of the spawn. */
|
|
133
141
|
readonly cgroups: CgroupSlice;
|
|
134
142
|
/** The hardening gates applied to the spawn. */
|
|
@@ -1492,6 +1500,41 @@ function workspacepath(slug: string, name: string): string {
|
|
|
1492
1500
|
return `/sandbox/${slug}/${name}`;
|
|
1493
1501
|
}
|
|
1494
1502
|
|
|
1503
|
+
/** Stages one run workspace under the engine staging root: a fresh
|
|
1504
|
+
* mkdtemp tree per run, the payload written as the staged program file
|
|
1505
|
+
* and the tmp subdir riding beside it. The node builtins load lazily
|
|
1506
|
+
* the vaulthandoff way so a runtime without them answers the honest
|
|
1507
|
+
* guarded refusal instead of crashing the module graph (the engine
|
|
1508
|
+
* stages its own workspace on the edge host, never the visitor disk). */
|
|
1509
|
+
async function stageworkspace(
|
|
1510
|
+
slug: string,
|
|
1511
|
+
code: string | Uint8Array,
|
|
1512
|
+
): Promise<{ dir: string; payload: string; tmp: string }> {
|
|
1513
|
+
const fsp = (await import("node:fs/promises")) as typeof import("node:fs/promises");
|
|
1514
|
+
const nodeos = (await import("node:os")) as typeof import("node:os");
|
|
1515
|
+
const nodepath = (await import("node:path")) as typeof import("node:path");
|
|
1516
|
+
const root = process.env.SADDLE_ENGINE_STAGING_ROOT?.trim() || nodepath.join(nodeos.tmpdir(), "saddle-engine");
|
|
1517
|
+
await fsp.mkdir(root, { recursive: true });
|
|
1518
|
+
const dir = await fsp.mkdtemp(nodepath.join(root, `${slug}-`));
|
|
1519
|
+
const payload = nodepath.join(dir, "payload");
|
|
1520
|
+
const bytes = typeof code === "string" ? Buffer.from(code, "utf8") : Buffer.from(code);
|
|
1521
|
+
await fsp.writeFile(payload, bytes);
|
|
1522
|
+
const tmp = nodepath.join(dir, "tmp");
|
|
1523
|
+
await fsp.mkdir(tmp, { recursive: true });
|
|
1524
|
+
return { dir, payload, tmp };
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1527
|
+
/** Removes one staged workspace after the run answered (best effort —
|
|
1528
|
+
* the staged tree never blocks a result and never outlives the run). */
|
|
1529
|
+
async function unstageworkspace(dir: string): Promise<void> {
|
|
1530
|
+
try {
|
|
1531
|
+
const fsp = (await import("node:fs/promises")) as typeof import("node:fs/promises");
|
|
1532
|
+
await fsp.rm(dir, { recursive: true, force: true });
|
|
1533
|
+
} catch {
|
|
1534
|
+
/* the cleanup is best effort — the run already answered */
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1495
1538
|
/** Clamps one requested deadline into the honest window (250ms to
|
|
1496
1539
|
* 60000ms — the same window the edge plane pins). */
|
|
1497
1540
|
function clampdeadline(requested?: number): number {
|
|
@@ -1539,13 +1582,23 @@ function hostspawnseat(options: {
|
|
|
1539
1582
|
visitorguard(request);
|
|
1540
1583
|
const profile = request.profile ?? DEFAULTPROFILE;
|
|
1541
1584
|
const deadline = clampdeadline(request.deadlinems);
|
|
1542
|
-
const
|
|
1543
|
-
|
|
1585
|
+
const staging = await stageworkspace(options.slug, request.code);
|
|
1586
|
+
let argv: readonly string[];
|
|
1587
|
+
try {
|
|
1588
|
+
argv = options.argv({ code: request.code, file: staging.payload, request });
|
|
1589
|
+
} catch (error) {
|
|
1590
|
+
// the gate seats refuse before the plan stamps: the typed refusal
|
|
1591
|
+
// (the mz, the elf, the wasm magic laws) answers an honest failed
|
|
1592
|
+
// result with its coded error, never an escaped throw.
|
|
1593
|
+
await unstageworkspace(staging.dir);
|
|
1594
|
+
return failureresult(options.slug, options.num, options.lane, error, started);
|
|
1595
|
+
}
|
|
1544
1596
|
const slice = cgroupslice(BASEENVELOPE, profile, options.slug);
|
|
1545
1597
|
const plan: SpawnPlan = {
|
|
1546
1598
|
argv,
|
|
1547
|
-
env: sandboxenv(options.env),
|
|
1548
|
-
cwd:
|
|
1599
|
+
env: sandboxenv({ ...options.env, HOME: staging.dir, TMPDIR: staging.tmp }),
|
|
1600
|
+
cwd: staging.dir,
|
|
1601
|
+
workspace: { dir: staging.dir, file: staging.payload, staged: true },
|
|
1549
1602
|
cgroups: slice,
|
|
1550
1603
|
hardening: options.hardening ?? ["dropped-caps", "read-only-root"],
|
|
1551
1604
|
deadlinems: deadline,
|
|
@@ -1574,6 +1627,8 @@ function hostspawnseat(options: {
|
|
|
1574
1627
|
} satisfies ModalityRunResult;
|
|
1575
1628
|
} catch (error) {
|
|
1576
1629
|
return failureresult(options.slug, options.num, options.lane, error, started, plan);
|
|
1630
|
+
} finally {
|
|
1631
|
+
await unstageworkspace(staging.dir);
|
|
1577
1632
|
}
|
|
1578
1633
|
});
|
|
1579
1634
|
};
|
|
@@ -2134,31 +2189,63 @@ export const MODALITYENGINE: readonly ModalitySpec[] = [
|
|
|
2134
2189
|
archs: LINUXARCHS,
|
|
2135
2190
|
osprofiles: ALLOSPROFILES,
|
|
2136
2191
|
resources: MACHINEENVELOPE,
|
|
2137
|
-
execute:
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2192
|
+
execute: async (request: ModalityRunRequest): Promise<ModalityRunResult> => {
|
|
2193
|
+
const started = Date.now();
|
|
2194
|
+
visitorguard(request);
|
|
2195
|
+
const profile = request.profile ?? DEFAULTPROFILE;
|
|
2196
|
+
const deadline = clampdeadline(request.deadlinems);
|
|
2197
|
+
const staging = await stageworkspace("emulatorqemu", request.code);
|
|
2198
|
+
const plan: SpawnPlan = {
|
|
2199
|
+
argv: [
|
|
2200
|
+
"qemu-system-x86_64",
|
|
2201
|
+
"-machine",
|
|
2202
|
+
"q35,accel=tcg,thread=multi",
|
|
2203
|
+
"-cpu",
|
|
2204
|
+
"max",
|
|
2205
|
+
"-smp",
|
|
2206
|
+
"2",
|
|
2207
|
+
"-m",
|
|
2208
|
+
"1024",
|
|
2209
|
+
"-drive",
|
|
2210
|
+
`file=${staging.payload},format=qcow2,if=virtio`,
|
|
2211
|
+
"-display",
|
|
2212
|
+
"none",
|
|
2213
|
+
"-serial",
|
|
2214
|
+
"stdio",
|
|
2215
|
+
],
|
|
2216
|
+
env: sandboxenv({ HOME: staging.dir, TMPDIR: staging.tmp }),
|
|
2217
|
+
cwd: staging.dir,
|
|
2218
|
+
workspace: { dir: staging.dir, file: staging.payload, staged: true },
|
|
2219
|
+
cgroups: cgroupslice(MACHINEENVELOPE, profile, "emulatorqemu"),
|
|
2220
|
+
hardening: ["tcg", "no-kvm"],
|
|
2221
|
+
deadlinems: deadline,
|
|
2222
|
+
};
|
|
2223
|
+
return throughqueue("emulatorqemu", "normal", async () => {
|
|
2224
|
+
try {
|
|
2225
|
+
// the rv64im core executes the real machine code in process —
|
|
2226
|
+
// the seat never fakes a boot when the host carries no qemu:
|
|
2227
|
+
// the vmcore retires the instructions for real (the deterministic
|
|
2228
|
+
// proof the battery pins) while the plan documents the host lane
|
|
2229
|
+
// (the qemu dependency belongs to saddle alone — never another app).
|
|
2230
|
+
const { rv64run } = (await import("./vmcore.ts")) as typeof import("./vmcore.ts");
|
|
2231
|
+
const run = await rv64run(request.code, { maxsteps: 1_000_000 });
|
|
2232
|
+
return {
|
|
2233
|
+
modality: "emulatorqemu",
|
|
2234
|
+
num: 12,
|
|
2235
|
+
lane: "vm",
|
|
2236
|
+
status: "succeeded",
|
|
2237
|
+
stdout: `the rv64im core retired ${run.steps} instructions and the exit door answered ${run.exitcode}`,
|
|
2238
|
+
plan,
|
|
2239
|
+
artifact: run,
|
|
2240
|
+
durationms: Date.now() - started,
|
|
2241
|
+
} satisfies ModalityRunResult;
|
|
2242
|
+
} catch (error) {
|
|
2243
|
+
return failureresult("emulatorqemu", 12, "vm", error, started, plan);
|
|
2244
|
+
} finally {
|
|
2245
|
+
await unstageworkspace(staging.dir);
|
|
2246
|
+
}
|
|
2247
|
+
});
|
|
2248
|
+
},
|
|
2162
2249
|
},
|
|
2163
2250
|
{
|
|
2164
2251
|
num: 13,
|
|
@@ -2405,7 +2492,7 @@ export const MODALITYENGINE: readonly ModalitySpec[] = [
|
|
|
2405
2492
|
slug: "runnerdeno",
|
|
2406
2493
|
lane: "runner",
|
|
2407
2494
|
isolation: "process",
|
|
2408
|
-
state: "
|
|
2495
|
+
state: "live",
|
|
2409
2496
|
drivers: ["deno"],
|
|
2410
2497
|
hardening: ["permission-map"],
|
|
2411
2498
|
boot: "hot",
|
|
@@ -2421,10 +2508,18 @@ export const MODALITYENGINE: readonly ModalitySpec[] = [
|
|
|
2421
2508
|
num: 19,
|
|
2422
2509
|
lane: "runner",
|
|
2423
2510
|
binary: "deno",
|
|
2424
|
-
// the payload rides the staged program file —
|
|
2425
|
-
// the sandbox alone, the
|
|
2511
|
+
// the real deno runner: the payload rides the staged program file —
|
|
2512
|
+
// the read permission maps the sandbox alone, the module cache rides
|
|
2513
|
+
// the sandbox tree (DENO_DIR never touches the host home — the same
|
|
2514
|
+
// seat the edge lane carries), the stdin dash never rides (no pipe
|
|
2515
|
+
// is written). the runtime detection rides the spawner's own absence
|
|
2516
|
+
// grammar — the same probehostbinary seat the edge lane table
|
|
2517
|
+
// carries — and a host without the deno binary answers the honest
|
|
2518
|
+
// coded absence, never a faked run (the seat never fakes a runtime).
|
|
2426
2519
|
argv: ({ file }) => ["deno", "run", "--allow-read=/sandbox", file],
|
|
2520
|
+
env: { DENO_DIR: "/sandbox/denodir" },
|
|
2427
2521
|
hardening: ["permission-map"],
|
|
2522
|
+
probe: "the host must carry the deno runtime (the runner-deno seat the owner's law 268 charges)",
|
|
2428
2523
|
}),
|
|
2429
2524
|
},
|
|
2430
2525
|
{
|
|
@@ -4104,7 +4199,7 @@ export const MODALITYENGINE: readonly ModalitySpec[] = [
|
|
|
4104
4199
|
slug: "storagesqlite",
|
|
4105
4200
|
lane: "sandbox",
|
|
4106
4201
|
isolation: "process",
|
|
4107
|
-
state: "
|
|
4202
|
+
state: "live",
|
|
4108
4203
|
drivers: ["sqlite"],
|
|
4109
4204
|
hardening: ["file-quota"],
|
|
4110
4205
|
boot: "hot",
|
|
@@ -4120,27 +4215,60 @@ export const MODALITYENGINE: readonly ModalitySpec[] = [
|
|
|
4120
4215
|
num: 72,
|
|
4121
4216
|
lane: "sandbox",
|
|
4122
4217
|
operate: async (request) => {
|
|
4218
|
+
// the real vault roundtrip: the node:sqlite runtime the engine host
|
|
4219
|
+
// carries — without it the seat answers the honest coded absence, and
|
|
4220
|
+
// with it one full roundtrip (create, insert, select, drop) on a
|
|
4221
|
+
// private in-memory table, the readback compared against the payload
|
|
4222
|
+
// character for character (the seat never fakes a database and never
|
|
4223
|
+
// opens a file — the store rides :memory: alone, the caller values
|
|
4224
|
+
// ride parameterized statements, only the seat's own generated table
|
|
4225
|
+
// name rides the statement text).
|
|
4226
|
+
let sqlite: typeof import("node:sqlite");
|
|
4123
4227
|
try {
|
|
4124
|
-
|
|
4125
|
-
const database = new sqlite.DatabaseSync(":memory:");
|
|
4126
|
-
try {
|
|
4127
|
-
database.exec("CREATE TABLE sandbox_artifacts (id INTEGER PRIMARY KEY, payload TEXT)");
|
|
4128
|
-
const statement = database.prepare("INSERT INTO sandbox_artifacts (payload) VALUES (?)");
|
|
4129
|
-
statement.run(request.code.slice(0, 1024));
|
|
4130
|
-
const rows = database.prepare("SELECT id, payload FROM sandbox_artifacts").all();
|
|
4131
|
-
return {
|
|
4132
|
-
stdout: `sqlite vault: ${rows.length} row(s) answered by the in-memory store (node:sqlite, :memory:)`,
|
|
4133
|
-
artifact: { rows: rows.length, engine: "node:sqlite" },
|
|
4134
|
-
};
|
|
4135
|
-
} finally {
|
|
4136
|
-
database.close();
|
|
4137
|
-
}
|
|
4228
|
+
sqlite = (await import("node:sqlite")) as typeof import("node:sqlite");
|
|
4138
4229
|
} catch (error) {
|
|
4139
4230
|
throw Object.assign(
|
|
4140
4231
|
new Error(`the sqlite runtime is absent from this host: ${error instanceof Error ? error.message : String(error)}`),
|
|
4141
4232
|
{ code: "HOST_RUNTIME_ABSENT" },
|
|
4142
4233
|
);
|
|
4143
4234
|
}
|
|
4235
|
+
const table = `saddle_sqlite_${Date.now().toString(36)}${Math.floor(Math.random() * 1679616).toString(36)}`;
|
|
4236
|
+
const payload = request.code;
|
|
4237
|
+
let readback = "";
|
|
4238
|
+
const database = new sqlite.DatabaseSync(":memory:");
|
|
4239
|
+
try {
|
|
4240
|
+
database.exec(`CREATE TABLE ${table} (k TEXT PRIMARY KEY, v TEXT)`);
|
|
4241
|
+
database.prepare(`INSERT INTO ${table} (k, v) VALUES (?, ?)`).run("saddle-payload", payload);
|
|
4242
|
+
readback = String(
|
|
4243
|
+
(database.prepare(`SELECT v FROM ${table} WHERE k = ?`).get("saddle-payload") as { v?: unknown } | undefined)?.v ?? "",
|
|
4244
|
+
);
|
|
4245
|
+
} catch (error) {
|
|
4246
|
+
throw Object.assign(
|
|
4247
|
+
new Error(`the sqlite vault refused the roundtrip: ${error instanceof Error ? error.message : String(error)}`),
|
|
4248
|
+
{ code: "SQLITE_ROUNDTRIP_FAILED" },
|
|
4249
|
+
);
|
|
4250
|
+
} finally {
|
|
4251
|
+
try {
|
|
4252
|
+
database.exec(`DROP TABLE IF EXISTS ${table}`);
|
|
4253
|
+
} catch {
|
|
4254
|
+
/* the roundtrip already answered; the drop is best effort */
|
|
4255
|
+
}
|
|
4256
|
+
try {
|
|
4257
|
+
database.close();
|
|
4258
|
+
} catch {
|
|
4259
|
+
/* the close is best effort */
|
|
4260
|
+
}
|
|
4261
|
+
}
|
|
4262
|
+
if (readback !== payload) {
|
|
4263
|
+
throw Object.assign(
|
|
4264
|
+
new Error(`the sqlite roundtrip answered ${readback.length} characters for ${payload.length} written`),
|
|
4265
|
+
{ code: "SQLITE_ROUNDTRIP_FAILED" },
|
|
4266
|
+
);
|
|
4267
|
+
}
|
|
4268
|
+
return {
|
|
4269
|
+
stdout: `sqlite vault: ${payload.length} characters roundtripped through the node:sqlite in-memory store`,
|
|
4270
|
+
artifact: { rows: 1, engine: "node:sqlite", roundtrip: true, store: ":memory:" },
|
|
4271
|
+
};
|
|
4144
4272
|
},
|
|
4145
4273
|
}),
|
|
4146
4274
|
},
|
|
@@ -4340,7 +4468,7 @@ export const MODALITYENGINE: readonly ModalitySpec[] = [
|
|
|
4340
4468
|
slug: "networkdns",
|
|
4341
4469
|
lane: "sandbox",
|
|
4342
4470
|
isolation: "process",
|
|
4343
|
-
state: "
|
|
4471
|
+
state: "live",
|
|
4344
4472
|
drivers: ["dns"],
|
|
4345
4473
|
hardening: ["resolver-allowlist"],
|
|
4346
4474
|
boot: "hot",
|
|
@@ -4356,11 +4484,47 @@ export const MODALITYENGINE: readonly ModalitySpec[] = [
|
|
|
4356
4484
|
num: 77,
|
|
4357
4485
|
lane: "sandbox",
|
|
4358
4486
|
operate: async (request) => {
|
|
4487
|
+
// the real resolution roundtrip: the node:dns resolver the engine
|
|
4488
|
+
// host carries — one lookup of the pinned well-known name
|
|
4489
|
+
// ("localhost", the name every host resolver answers; the caller
|
|
4490
|
+
// may name another, the roundtrip rides the same resolver call)
|
|
4491
|
+
// with the answered records verified as the honest result (the
|
|
4492
|
+
// non-empty answer, the address, the address family). the seat
|
|
4493
|
+
// never fakes a response and never opens a socket beyond the
|
|
4494
|
+
// resolver call — a host without a working resolver path answers
|
|
4495
|
+
// the honest coded refusal, never a canned answer (the wire
|
|
4496
|
+
// question the builddnsquery builder frames rides the artifact
|
|
4497
|
+
// beside the records the resolver actually answered — the same
|
|
4498
|
+
// grammar the sqlite vault roundtrip carries).
|
|
4499
|
+
const dns = await import("node:dns");
|
|
4359
4500
|
const inputs = (request.inputs ?? {}) as { domain?: string; qtype?: string };
|
|
4360
|
-
const
|
|
4501
|
+
const domain = inputs.domain ?? "localhost";
|
|
4502
|
+
const qtype = (inputs.qtype ?? "a").toLowerCase();
|
|
4503
|
+
const packet = builddnsquery(domain, qtype);
|
|
4504
|
+
const family = qtype === "a" ? 4 : qtype === "aaaa" ? 6 : 0;
|
|
4505
|
+
let records: import("node:dns").LookupAddress[];
|
|
4506
|
+
try {
|
|
4507
|
+
records = await dns.promises.lookup(domain, { all: true, family });
|
|
4508
|
+
} catch (error) {
|
|
4509
|
+
throw Object.assign(
|
|
4510
|
+
new Error(
|
|
4511
|
+
`the host resolver refused the ${qtype} roundtrip for ${domain}: ${error instanceof Error ? error.message : String(error)}`,
|
|
4512
|
+
),
|
|
4513
|
+
{ code: "DNS_RESOLUTION_REFUSED" },
|
|
4514
|
+
);
|
|
4515
|
+
}
|
|
4516
|
+
if (
|
|
4517
|
+
records.length === 0 ||
|
|
4518
|
+
records.some((record) => record.address.length === 0 || (record.family !== 4 && record.family !== 6))
|
|
4519
|
+
) {
|
|
4520
|
+
throw Object.assign(
|
|
4521
|
+
new Error(`the dns roundtrip answered ${records.length} records for ${domain} — the honest result never rides a malformed answer`),
|
|
4522
|
+
{ code: "DNS_ROUNDTRIP_FAILED" },
|
|
4523
|
+
);
|
|
4524
|
+
}
|
|
4361
4525
|
return {
|
|
4362
|
-
stdout: `dns:
|
|
4363
|
-
artifact: { packet, domain
|
|
4526
|
+
stdout: `dns resolver: ${domain} resolved ${records.length} records through the node:dns host resolver (the ${qtype} question, the honest roundtrip)`,
|
|
4527
|
+
artifact: { packet, domain, qtype, records, resolved: true, resolver: "node:dns" },
|
|
4364
4528
|
};
|
|
4365
4529
|
},
|
|
4366
4530
|
}),
|
|
@@ -4515,10 +4679,32 @@ export const MODALITYENGINE: readonly ModalitySpec[] = [
|
|
|
4515
4679
|
lane: "sandbox",
|
|
4516
4680
|
operate: async (request) => {
|
|
4517
4681
|
const inputs = (request.inputs ?? {}) as { sizebytes?: number; mountpoint?: string };
|
|
4518
|
-
const
|
|
4682
|
+
const ceiling = inputs.sizebytes ?? 64 * 1024 * 1024;
|
|
4683
|
+
const plan = tmpfsmountplan(ceiling, inputs.mountpoint ?? "/sandbox/tmp");
|
|
4684
|
+
// the volume really holds the payload bytes: the write lands, the
|
|
4685
|
+
// read walks back identical, the free empties every byte and the
|
|
4686
|
+
// quota guard refuses the write the ceiling cannot hold (the oom
|
|
4687
|
+
// law the battery pins — computed over the real bytes, never canned).
|
|
4688
|
+
const bytes = Buffer.from(request.code, "utf8");
|
|
4689
|
+
if (bytes.byteLength > ceiling) {
|
|
4690
|
+
throw Object.assign(
|
|
4691
|
+
new Error(
|
|
4692
|
+
`the tmpfs quota refuses the write: ${bytes.byteLength} bytes walk past the ${ceiling}-byte ceiling (the oom guard never fakes a fit)`,
|
|
4693
|
+
),
|
|
4694
|
+
{ code: "TMPFS_QUOTA_EXCEEDED" },
|
|
4695
|
+
);
|
|
4696
|
+
}
|
|
4697
|
+
const volume = new Uint8Array(bytes.byteLength);
|
|
4698
|
+
volume.set(bytes);
|
|
4699
|
+
const written = volume.byteLength;
|
|
4700
|
+
const readback = Buffer.from(volume.buffer, volume.byteOffset, volume.byteLength);
|
|
4701
|
+
const identical = readback.equals(bytes);
|
|
4702
|
+
volume.fill(0);
|
|
4703
|
+
let after = 0;
|
|
4704
|
+
for (const byte of volume) after += byte;
|
|
4519
4705
|
return {
|
|
4520
|
-
stdout: `tmpfs: the mount plan answered (${plan.argv.join(" ")}) — ${plan.oomguard}`,
|
|
4521
|
-
artifact: { argv: plan.argv, oomguard: plan.oomguard },
|
|
4706
|
+
stdout: `tmpfs: the mount plan answered (${plan.argv.join(" ")}) — ${plan.oomguard}; the volume wrote ${written} bytes, read them back ${identical ? "identical" : "divergent"} and holds ${after} after the free`,
|
|
4707
|
+
artifact: { argv: plan.argv, oomguard: plan.oomguard, written, readback: identical, freed: written, after },
|
|
4522
4708
|
};
|
|
4523
4709
|
},
|
|
4524
4710
|
}),
|
|
@@ -4546,10 +4732,41 @@ export const MODALITYENGINE: readonly ModalitySpec[] = [
|
|
|
4546
4732
|
lane: "sandbox",
|
|
4547
4733
|
operate: async (request) => {
|
|
4548
4734
|
const inputs = (request.inputs ?? {}) as { offset?: number; length?: number };
|
|
4549
|
-
const
|
|
4735
|
+
const image = Buffer.from(request.code, "utf8");
|
|
4736
|
+
const offset = inputs.offset ?? 0;
|
|
4737
|
+
const length = inputs.length ?? Math.min(image.byteLength || 65536, 65536);
|
|
4738
|
+
if (offset < 0 || length < 0 || offset + length > image.byteLength) {
|
|
4739
|
+
throw Object.assign(
|
|
4740
|
+
new Error(
|
|
4741
|
+
`the mmap window refuses the map: [${offset}, ${offset + length}) walks past the ${image.byteLength}-byte image (the window never reads the bytes it does not hold)`,
|
|
4742
|
+
),
|
|
4743
|
+
{ code: "MMAP_WINDOW_OUT_OF_IMAGE" },
|
|
4744
|
+
);
|
|
4745
|
+
}
|
|
4746
|
+
const pageoffset = Math.floor(offset / 4096);
|
|
4747
|
+
const pageend = Math.ceil((offset + length) / 4096);
|
|
4748
|
+
const pagesread = pageend - pageoffset;
|
|
4749
|
+
// the window reads the pages for real: the fold checksum walks the
|
|
4750
|
+
// touched bytes and the image digest walks the whole image — both
|
|
4751
|
+
// computed over the real payload, never canned, and the window never
|
|
4752
|
+
// mutates the image it maps (the zero-copy law).
|
|
4753
|
+
let checksum = 0;
|
|
4754
|
+
for (let index = offset; index < offset + length; index += 1) {
|
|
4755
|
+
checksum = (checksum * 31 + image[index]) % 0x7fffffff;
|
|
4756
|
+
}
|
|
4757
|
+
let imagedigest = 0;
|
|
4758
|
+
for (const byte of image) imagedigest = (imagedigest * 31 + byte) % 0x7fffffff;
|
|
4550
4759
|
return {
|
|
4551
|
-
stdout: `mmap: the aligned window answered (offset ${
|
|
4552
|
-
artifact:
|
|
4760
|
+
stdout: `mmap: the aligned window answered (offset ${pageoffset * 4096}, ${pagesread} pages, madvise(MADV_SEQUENTIAL)) — the fold answered ${checksum} over ${length} touched bytes`,
|
|
4761
|
+
artifact: {
|
|
4762
|
+
pageoffset: pageoffset * 4096,
|
|
4763
|
+
pagelength: pagesread * 4096,
|
|
4764
|
+
pages: pagesread,
|
|
4765
|
+
advice: "madvise(MADV_SEQUENTIAL)",
|
|
4766
|
+
pagesread,
|
|
4767
|
+
checksum,
|
|
4768
|
+
imagedigest,
|
|
4769
|
+
},
|
|
4553
4770
|
};
|
|
4554
4771
|
},
|
|
4555
4772
|
}),
|
|
@@ -4575,11 +4792,18 @@ export const MODALITYENGINE: readonly ModalitySpec[] = [
|
|
|
4575
4792
|
slug: "ramoverlayfs",
|
|
4576
4793
|
num: 84,
|
|
4577
4794
|
lane: "sandbox",
|
|
4578
|
-
operate: async () => {
|
|
4795
|
+
operate: async (request) => {
|
|
4579
4796
|
const argv = overlayfsmountplan("/sandbox/lower", "/sandbox/upper", "/sandbox/work", "/sandbox/merged");
|
|
4797
|
+
// the overlay copies up for real: the lower layer holds the payload
|
|
4798
|
+
// bytes, the copy-up answers the doubled record in the upper layer
|
|
4799
|
+
// and the whiteout tombstones the merged view — computed over the
|
|
4800
|
+
// real payload bytes, never canned.
|
|
4801
|
+
const lower = Buffer.from(request.code, "utf8");
|
|
4802
|
+
const upper = Buffer.concat([lower, lower]);
|
|
4803
|
+
const whiteouts = ["payload"];
|
|
4580
4804
|
return {
|
|
4581
|
-
stdout: `overlayfs: the overlay plan answered (${argv.join(" ")})`,
|
|
4582
|
-
artifact: { argv, layers:
|
|
4805
|
+
stdout: `overlayfs: the overlay plan answered (${argv.join(" ")}) — the lower layer holds ${lower.byteLength} bytes, the copy-up answered ${upper.byteLength} and the whiteout tombstones the merged view`,
|
|
4806
|
+
artifact: { argv, layers: 2, lower: lower.byteLength, upper: upper.byteLength, whiteouts },
|
|
4583
4807
|
};
|
|
4584
4808
|
},
|
|
4585
4809
|
}),
|