@ai-ecoverse/slicc-kernel 1.80.0 → 1.82.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 +8 -0
- package/dist/index.js +44 -3
- package/dist/index.js.map +3 -3
- package/dist/kernel-worker.js +264 -41
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +20 -9
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +227 -37
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +20 -9
- package/dist/process-worker.js.map +2 -2
- package/package.json +1 -1
package/dist/kernel-worker.js
CHANGED
|
@@ -360,10 +360,106 @@ async function chownAs(fs, cred, path, change) {
|
|
|
360
360
|
});
|
|
361
361
|
}
|
|
362
362
|
|
|
363
|
+
// src/fs/integrity.ts
|
|
364
|
+
var KERNEL_CALLER = { pid: 0, uid: 0 };
|
|
365
|
+
function integrityOptions(options) {
|
|
366
|
+
if (options && typeof options.lookup !== "function") {
|
|
367
|
+
throw new TypeError("protect.integrity.lookup must be a function");
|
|
368
|
+
}
|
|
369
|
+
integrityUnknown(options);
|
|
370
|
+
}
|
|
371
|
+
function integrityUnknown(options) {
|
|
372
|
+
const unknown = options?.unknown ?? "allow";
|
|
373
|
+
if (unknown !== "allow" && unknown !== "deny") {
|
|
374
|
+
throw new TypeError("protect.integrity.unknown must be 'allow' or 'deny'");
|
|
375
|
+
}
|
|
376
|
+
return unknown;
|
|
377
|
+
}
|
|
378
|
+
function hex(digest) {
|
|
379
|
+
return [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
380
|
+
}
|
|
381
|
+
async function sha256(bytes) {
|
|
382
|
+
return hex(await crypto.subtle.digest("SHA-256", bytes));
|
|
383
|
+
}
|
|
384
|
+
var Integrity = class {
|
|
385
|
+
prefixes;
|
|
386
|
+
root;
|
|
387
|
+
lookup;
|
|
388
|
+
unknown;
|
|
389
|
+
report;
|
|
390
|
+
unverified = /* @__PURE__ */ new Set();
|
|
391
|
+
constructor(prefixes2, root, options, report) {
|
|
392
|
+
this.prefixes = prefixes2;
|
|
393
|
+
this.root = root;
|
|
394
|
+
this.lookup = options.lookup;
|
|
395
|
+
this.unknown = integrityUnknown(options);
|
|
396
|
+
this.report = report;
|
|
397
|
+
}
|
|
398
|
+
async real(path) {
|
|
399
|
+
const at = normalizePath(path);
|
|
400
|
+
const real = await this.root.realpath?.(at, true).catch(() => void 0) ?? at;
|
|
401
|
+
return isProtected(this.prefixes, real) ? real : void 0;
|
|
402
|
+
}
|
|
403
|
+
async key(path) {
|
|
404
|
+
const real = await this.real(path);
|
|
405
|
+
if (real === void 0 || !this.root.version) return void 0;
|
|
406
|
+
return `${real}\0${await this.root.version(real)}`;
|
|
407
|
+
}
|
|
408
|
+
async read(path, caller, plain) {
|
|
409
|
+
return (await this.readKeyed(path, caller, plain)).bytes;
|
|
410
|
+
}
|
|
411
|
+
async readKeyed(path, caller, plain) {
|
|
412
|
+
const real = await this.real(path);
|
|
413
|
+
if (real === void 0) return { bytes: await plain() };
|
|
414
|
+
const read = this.root.readVersioned ? await this.root.readVersioned(real) : { bytes: await this.root.readFileBuffer(real), version: void 0 };
|
|
415
|
+
const { bytes } = read;
|
|
416
|
+
const keyed = read.version === void 0 ? { bytes } : { bytes, key: `${real}\0${read.version}` };
|
|
417
|
+
const actual = await sha256(bytes);
|
|
418
|
+
const denial = { pid: caller.pid, uid: caller.uid, path: real, actual };
|
|
419
|
+
const tagged = caller.tag !== void 0 ? { tag: caller.tag } : {};
|
|
420
|
+
let expected;
|
|
421
|
+
try {
|
|
422
|
+
expected = await this.expected(real);
|
|
423
|
+
} catch {
|
|
424
|
+
this.say({ ...denial, ...tagged, op: "exec-integrity", errno: "EACCES" });
|
|
425
|
+
throw fsError("EACCES", `integrity lookup failed: ${real}`);
|
|
426
|
+
}
|
|
427
|
+
if (expected === void 0) {
|
|
428
|
+
if (this.unknown === "allow") {
|
|
429
|
+
if (!this.unverified.has(real)) {
|
|
430
|
+
this.unverified.add(real);
|
|
431
|
+
this.say({ ...denial, ...tagged, op: "exec-unverified", errno: "ENODATA" });
|
|
432
|
+
}
|
|
433
|
+
return keyed;
|
|
434
|
+
}
|
|
435
|
+
} else if (expected === actual) {
|
|
436
|
+
return keyed;
|
|
437
|
+
}
|
|
438
|
+
const known = expected !== void 0 ? { expected } : {};
|
|
439
|
+
this.say({ ...denial, ...tagged, ...known, op: "exec-integrity", errno: "EACCES" });
|
|
440
|
+
throw fsError("EACCES", `integrity check failed: ${real}`);
|
|
441
|
+
}
|
|
442
|
+
async expected(path) {
|
|
443
|
+
const answer = await this.lookup(path);
|
|
444
|
+
return typeof answer === "string" ? answer.toLowerCase() : void 0;
|
|
445
|
+
}
|
|
446
|
+
say(event) {
|
|
447
|
+
try {
|
|
448
|
+
this.report(event);
|
|
449
|
+
} catch {
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
|
|
363
454
|
// src/fs/protect.ts
|
|
364
455
|
function protectInit(protection) {
|
|
365
456
|
const writers = [...writerTags(protection)];
|
|
366
|
-
|
|
457
|
+
const { integrity } = protection;
|
|
458
|
+
return {
|
|
459
|
+
paths: [...protection.paths],
|
|
460
|
+
...writers.length > 0 ? { writers } : {},
|
|
461
|
+
...integrity ? { integrity: { unknown: integrityUnknown(integrity) } } : {}
|
|
462
|
+
};
|
|
367
463
|
}
|
|
368
464
|
function writerTags(protection) {
|
|
369
465
|
const writers = protection?.writers ?? [];
|
|
@@ -1220,6 +1316,29 @@ var OpfsFs = class {
|
|
|
1220
1316
|
false
|
|
1221
1317
|
);
|
|
1222
1318
|
}
|
|
1319
|
+
async readVersioned(path) {
|
|
1320
|
+
const handle = await this.existing(path);
|
|
1321
|
+
return this.retrying(
|
|
1322
|
+
path,
|
|
1323
|
+
async () => {
|
|
1324
|
+
const file = await handle.getFile();
|
|
1325
|
+
const bytes = new Uint8Array(await file.arrayBuffer());
|
|
1326
|
+
return { bytes, version: `${file.lastModified}:${file.size}` };
|
|
1327
|
+
},
|
|
1328
|
+
false
|
|
1329
|
+
);
|
|
1330
|
+
}
|
|
1331
|
+
async version(path) {
|
|
1332
|
+
const handle = await this.existing(path);
|
|
1333
|
+
return this.retrying(
|
|
1334
|
+
path,
|
|
1335
|
+
async () => {
|
|
1336
|
+
const file = await handle.getFile();
|
|
1337
|
+
return `${file.lastModified}:${file.size}`;
|
|
1338
|
+
},
|
|
1339
|
+
false
|
|
1340
|
+
);
|
|
1341
|
+
}
|
|
1223
1342
|
async pread(path, offset, length2) {
|
|
1224
1343
|
const handle = await this.existing(path);
|
|
1225
1344
|
return this.retrying(
|
|
@@ -2150,6 +2269,7 @@ function id(value) {
|
|
|
2150
2269
|
return value;
|
|
2151
2270
|
}
|
|
2152
2271
|
function changeCred(cur, change) {
|
|
2272
|
+
if (typeof change !== "object" || change === null) throw fsError("EINVAL", "not a change");
|
|
2153
2273
|
const privileged = cur.euid === 0;
|
|
2154
2274
|
const next2 = copyCred(cur);
|
|
2155
2275
|
for (const keys of [UIDS, GIDS]) {
|
|
@@ -4466,6 +4586,27 @@ function clipboardAsker(port) {
|
|
|
4466
4586
|
return { hook, answer };
|
|
4467
4587
|
}
|
|
4468
4588
|
|
|
4589
|
+
// src/integrity-relay.ts
|
|
4590
|
+
function integrityAsker(port) {
|
|
4591
|
+
const asks = /* @__PURE__ */ new Map();
|
|
4592
|
+
let next2 = 0;
|
|
4593
|
+
const lookup = (path) => {
|
|
4594
|
+
const id2 = ++next2;
|
|
4595
|
+
const waiting = Promise.withResolvers();
|
|
4596
|
+
asks.set(id2, waiting);
|
|
4597
|
+
port.postMessage({ integrityAsk: { id: id2, path } });
|
|
4598
|
+
return waiting.promise;
|
|
4599
|
+
};
|
|
4600
|
+
const answer = ({ id: id2, hash, error }) => {
|
|
4601
|
+
const waiting = asks.get(id2);
|
|
4602
|
+
if (!waiting) return;
|
|
4603
|
+
asks.delete(id2);
|
|
4604
|
+
if (error !== void 0) waiting.reject(new Error(error));
|
|
4605
|
+
else waiting.resolve(hash);
|
|
4606
|
+
};
|
|
4607
|
+
return { lookup, answer };
|
|
4608
|
+
}
|
|
4609
|
+
|
|
4469
4610
|
// src/kernel/net/loopback-names.ts
|
|
4470
4611
|
var HOST_LOOPBACK = "host.slicc.internal";
|
|
4471
4612
|
var HOST_LOOPBACK_ADDRESS = [10, 0, 2, 2];
|
|
@@ -7092,7 +7233,7 @@ function owned(path, st) {
|
|
|
7092
7233
|
function unchanged(a, b, bytes) {
|
|
7093
7234
|
return a.ino === b.ino && a.mtime.getTime() === b.mtime.getTime() && a.size === b.size && bytes.length === b.size;
|
|
7094
7235
|
}
|
|
7095
|
-
async function
|
|
7236
|
+
async function sha2562(bytes) {
|
|
7096
7237
|
const digest = new Uint8Array(
|
|
7097
7238
|
await crypto.subtle.digest("SHA-256", bytes)
|
|
7098
7239
|
);
|
|
@@ -7148,7 +7289,7 @@ async function attest(fs, asked, o) {
|
|
|
7148
7289
|
const bytes = (await fs.readFileBuffer(path)).slice();
|
|
7149
7290
|
const after = await fs.lstat(path);
|
|
7150
7291
|
if (unchanged(before, after, bytes)) {
|
|
7151
|
-
return attested(path, after, bytes, await
|
|
7292
|
+
return attested(path, after, bytes, await sha2562(bytes), o, parents);
|
|
7152
7293
|
}
|
|
7153
7294
|
if (tries >= 1) refuse("EAGAIN", path, "changed while it was read");
|
|
7154
7295
|
}
|
|
@@ -16452,6 +16593,13 @@ var Launcher = class {
|
|
|
16452
16593
|
unwatchScopes = () => void 0;
|
|
16453
16594
|
warned = /* @__PURE__ */ new Set();
|
|
16454
16595
|
compiled = /* @__PURE__ */ new Map();
|
|
16596
|
+
texts = /* @__PURE__ */ new Map();
|
|
16597
|
+
integrity;
|
|
16598
|
+
scannedFs;
|
|
16599
|
+
get scanned() {
|
|
16600
|
+
this.scannedFs ??= this.verifiedFs(this.base);
|
|
16601
|
+
return this.scannedFs;
|
|
16602
|
+
}
|
|
16455
16603
|
processes = /* @__PURE__ */ new Map();
|
|
16456
16604
|
zombies = /* @__PURE__ */ new Set();
|
|
16457
16605
|
orphans = /* @__PURE__ */ new Set();
|
|
@@ -16555,7 +16703,7 @@ var Launcher = class {
|
|
|
16555
16703
|
if (options.uplink) this.net.useUplink({ uplink: options.uplink, routes: this.routes });
|
|
16556
16704
|
enableNetwork(this.net, {
|
|
16557
16705
|
transport: this.transport,
|
|
16558
|
-
engine: kernelTlsEngine(packageTlsEngine(options.fs, this.modulesDir)),
|
|
16706
|
+
engine: kernelTlsEngine(packageTlsEngine(this.verifiedFs(options.fs), this.modulesDir)),
|
|
16559
16707
|
ca: this.ca
|
|
16560
16708
|
});
|
|
16561
16709
|
enableCdp(this.net, this.cdp);
|
|
@@ -16590,6 +16738,16 @@ var Launcher = class {
|
|
|
16590
16738
|
this.prefixes = protectedPrefixes(options.protect?.paths ?? []);
|
|
16591
16739
|
this.processFs = this.prefixes.length > 0 ? new ProtectedFs(this.prefixes).view(this.fs) : this.fs;
|
|
16592
16740
|
options.fs.protect?.(this.prefixes);
|
|
16741
|
+
const integrity = options.protect?.integrity;
|
|
16742
|
+
integrityOptions(integrity);
|
|
16743
|
+
if (integrity && this.prefixes.length > 0) {
|
|
16744
|
+
this.integrity = new Integrity(
|
|
16745
|
+
this.prefixes,
|
|
16746
|
+
options.fs,
|
|
16747
|
+
integrity,
|
|
16748
|
+
(event) => options.onDenial?.(event)
|
|
16749
|
+
);
|
|
16750
|
+
}
|
|
16593
16751
|
this.users = new UserDb(this.fs, this.owners);
|
|
16594
16752
|
this.sudoer = new Sudo({
|
|
16595
16753
|
fs: this.fs,
|
|
@@ -16635,7 +16793,7 @@ var Launcher = class {
|
|
|
16635
16793
|
commands(scope = "") {
|
|
16636
16794
|
let found = this.catalogs.get(scope);
|
|
16637
16795
|
if (!found) {
|
|
16638
|
-
found = this.roots(scope).then((roots) => scanCommands(this.
|
|
16796
|
+
found = this.roots(scope).then((roots) => scanCommands(this.scanned, roots)).then((commands) => commands.set(SUDO_COMMAND.name, SUDO_COMMAND));
|
|
16639
16797
|
this.catalogs.set(scope, found);
|
|
16640
16798
|
}
|
|
16641
16799
|
return found;
|
|
@@ -16643,7 +16801,7 @@ var Launcher = class {
|
|
|
16643
16801
|
ownCommands(scope) {
|
|
16644
16802
|
let found = this.ownCatalogs.get(scope);
|
|
16645
16803
|
if (!found) {
|
|
16646
|
-
found = pnpmGlobalRoots(this.base, scope).then((roots) => scanCommands(this.
|
|
16804
|
+
found = pnpmGlobalRoots(this.base, scope).then((roots) => scanCommands(this.scanned, roots)).then((commands) => new Set(commands.keys()));
|
|
16647
16805
|
this.ownCatalogs.set(scope, found);
|
|
16648
16806
|
}
|
|
16649
16807
|
return found;
|
|
@@ -16652,7 +16810,7 @@ var Launcher = class {
|
|
|
16652
16810
|
let found = this.binfmts.get(scope);
|
|
16653
16811
|
if (!found) {
|
|
16654
16812
|
found = this.roots(scope).then(
|
|
16655
|
-
(roots) => scanBinfmts(this.
|
|
16813
|
+
(roots) => scanBinfmts(this.scanned, roots, (message3) => {
|
|
16656
16814
|
if (this.warned.has(message3)) return;
|
|
16657
16815
|
this.warned.add(message3);
|
|
16658
16816
|
console.warn(message3);
|
|
@@ -16771,10 +16929,16 @@ var Launcher = class {
|
|
|
16771
16929
|
}
|
|
16772
16930
|
const inner = await this.interpreted(interp, [interp, ...passed], cwd, scope, depth + 1);
|
|
16773
16931
|
const via = [interp, ...inner?.via ?? []];
|
|
16774
|
-
|
|
16932
|
+
const sources = [script, ...inner?.sources ?? []];
|
|
16933
|
+
return inner && { ...inner, target: withScriptEnv(inner.target, command), via, sources };
|
|
16775
16934
|
}
|
|
16776
16935
|
const target = withScriptEnv(found, command);
|
|
16777
|
-
return {
|
|
16936
|
+
return {
|
|
16937
|
+
target,
|
|
16938
|
+
args: [...target.prefix ?? [], ...passed],
|
|
16939
|
+
via: [interp],
|
|
16940
|
+
sources: [script]
|
|
16941
|
+
};
|
|
16778
16942
|
}
|
|
16779
16943
|
async plan(file, argv, cwd, scope, argv0) {
|
|
16780
16944
|
const found = await this.resolve(file, argv[0] ?? file, cwd, scope);
|
|
@@ -16806,7 +16970,7 @@ var Launcher = class {
|
|
|
16806
16970
|
}
|
|
16807
16971
|
async binfmtManifests(scripts) {
|
|
16808
16972
|
const sources = /* @__PURE__ */ new Map();
|
|
16809
|
-
const binfmts = await scanBinfmts(this.
|
|
16973
|
+
const binfmts = await scanBinfmts(this.scanned, await this.roots(), void 0, sources);
|
|
16810
16974
|
const manifests = [];
|
|
16811
16975
|
for (const script of scripts) {
|
|
16812
16976
|
const head = await this.head(script);
|
|
@@ -16841,25 +17005,72 @@ var Launcher = class {
|
|
|
16841
17005
|
if (!head || head[0] === 35 && head[1] === 33) return "ENOENT";
|
|
16842
17006
|
return binfmtOf(await this.interpreters(scope), path) ? "ENOENT" : "ENOEXEC";
|
|
16843
17007
|
}
|
|
16844
|
-
|
|
16845
|
-
|
|
16846
|
-
|
|
16847
|
-
|
|
16848
|
-
|
|
16849
|
-
|
|
16850
|
-
|
|
16851
|
-
|
|
16852
|
-
|
|
16853
|
-
|
|
16854
|
-
|
|
16855
|
-
|
|
16856
|
-
|
|
16857
|
-
|
|
16858
|
-
|
|
16859
|
-
|
|
16860
|
-
|
|
16861
|
-
|
|
16862
|
-
|
|
17008
|
+
verifiedFs(fs) {
|
|
17009
|
+
const read = (path) => this.verified(path, KERNEL_CALLER, fs);
|
|
17010
|
+
return Object.assign(Object.create(fs), {
|
|
17011
|
+
readFileBuffer: read,
|
|
17012
|
+
readFile: (path) => this.integrity ? this.text(path, KERNEL_CALLER) : fs.readFile(path)
|
|
17013
|
+
});
|
|
17014
|
+
}
|
|
17015
|
+
async cacheKey(path) {
|
|
17016
|
+
const verified = await this.integrity?.key(path);
|
|
17017
|
+
if (verified !== void 0) return verified;
|
|
17018
|
+
const st = await this.base.stat(path);
|
|
17019
|
+
return `${path}:${st.size}:${st.mtime.getTime()}`;
|
|
17020
|
+
}
|
|
17021
|
+
verified(path, caller, fs = this.base) {
|
|
17022
|
+
const plain = () => fs.readFileBuffer(path);
|
|
17023
|
+
return this.integrity ? this.integrity.read(path, caller, plain) : plain();
|
|
17024
|
+
}
|
|
17025
|
+
keyed(path, caller) {
|
|
17026
|
+
const plain = async () => this.base.readFileBuffer(path);
|
|
17027
|
+
return this.integrity ? this.integrity.readKeyed(path, caller, plain) : plain().then((bytes) => ({ bytes }));
|
|
17028
|
+
}
|
|
17029
|
+
cached(cache, key, load) {
|
|
17030
|
+
const hit = cache.get(key);
|
|
17031
|
+
if (hit !== void 0) return hit;
|
|
17032
|
+
const loading2 = load();
|
|
17033
|
+
const found = loading2.then(({ value }) => value);
|
|
17034
|
+
cache.set(key, found);
|
|
17035
|
+
loading2.then(
|
|
17036
|
+
(done4) => {
|
|
17037
|
+
if (done4.key === key || done4.key === void 0 && !key.includes("\0")) return;
|
|
17038
|
+
if (cache.get(key) === found) cache.delete(key);
|
|
17039
|
+
if (done4.key !== void 0) cache.set(done4.key, found);
|
|
17040
|
+
},
|
|
17041
|
+
() => cache.delete(key)
|
|
17042
|
+
);
|
|
17043
|
+
return found;
|
|
17044
|
+
}
|
|
17045
|
+
async module(path, caller) {
|
|
17046
|
+
const key = await this.cacheKey(path);
|
|
17047
|
+
return this.cached(this.compiled, key, async () => {
|
|
17048
|
+
const { bytes, key: read } = await this.keyed(path, caller);
|
|
17049
|
+
const memory = importedMemory(bytes);
|
|
17050
|
+
const foreign = foreignImports(bytes);
|
|
17051
|
+
const compiled = await WebAssembly.compile(bytes);
|
|
17052
|
+
return { value: { module: compiled, ...memory ? { memory } : {}, foreign }, key: read };
|
|
17053
|
+
});
|
|
17054
|
+
}
|
|
17055
|
+
async checkedSources(planned, caller) {
|
|
17056
|
+
const { target } = planned;
|
|
17057
|
+
const files = [target.wasm, target.glue, target.imports, ...planned.sources ?? []];
|
|
17058
|
+
const manifests = /* @__PURE__ */ new Set();
|
|
17059
|
+
for (const file of files) {
|
|
17060
|
+
const root = file === void 0 ? void 0 : PACKAGE_ROOT.exec(file)?.[1];
|
|
17061
|
+
if (root !== void 0) manifests.add(`${root}/package.json`);
|
|
17062
|
+
}
|
|
17063
|
+
for (const source of planned.sources ?? []) await this.text(source, caller);
|
|
17064
|
+
for (const manifest of manifests) {
|
|
17065
|
+
if (await this.base.exists(manifest)) await this.text(manifest, caller);
|
|
17066
|
+
}
|
|
17067
|
+
}
|
|
17068
|
+
async text(path, caller) {
|
|
17069
|
+
if (!this.integrity) return this.base.readFile(path);
|
|
17070
|
+
const key = await this.cacheKey(path);
|
|
17071
|
+
return this.cached(this.texts, key, async () => {
|
|
17072
|
+
const { bytes, key: read } = await this.keyed(path, caller);
|
|
17073
|
+
return { value: new TextDecoder().decode(bytes), key: read };
|
|
16863
17074
|
});
|
|
16864
17075
|
}
|
|
16865
17076
|
async names(path, module) {
|
|
@@ -16871,23 +17082,23 @@ var Launcher = class {
|
|
|
16871
17082
|
const optional = `${root}-names${beside.slice(root.length)}`;
|
|
16872
17083
|
return await this.base.exists(optional) ? optional : void 0;
|
|
16873
17084
|
}
|
|
16874
|
-
async program(target, env) {
|
|
17085
|
+
async program(target, env, caller) {
|
|
16875
17086
|
if (target.abi === "js" && target.wasm === SUDO_PATH) {
|
|
16876
17087
|
return { abi: "js", glue: SUDO_SOURCE, path: SUDO_PATH };
|
|
16877
17088
|
}
|
|
16878
17089
|
if (target.abi === "js") {
|
|
16879
|
-
return { abi: "js", glue: await this.
|
|
17090
|
+
return { abi: "js", glue: await this.text(target.wasm, caller), path: target.wasm };
|
|
16880
17091
|
}
|
|
16881
17092
|
if (target.abi !== "wasi") {
|
|
16882
17093
|
const [glue, { module: module2 }] = await Promise.all([
|
|
16883
|
-
this.
|
|
16884
|
-
this.module(target.wasm)
|
|
17094
|
+
this.text(target.glue, caller),
|
|
17095
|
+
this.module(target.wasm, caller)
|
|
16885
17096
|
]);
|
|
16886
17097
|
return { glue, module: module2 };
|
|
16887
17098
|
}
|
|
16888
|
-
const { module, memory, foreign } = await this.module(target.wasm);
|
|
17099
|
+
const { module, memory, foreign } = await this.module(target.wasm, caller);
|
|
16889
17100
|
const names = env.SLICC_WASM_BACKTRACE === "1" ? await this.names(target.wasm, module) : void 0;
|
|
16890
|
-
const imports = target.imports ? await this.
|
|
17101
|
+
const imports = target.imports ? await this.text(target.imports, caller) : void 0;
|
|
16891
17102
|
return {
|
|
16892
17103
|
abi: "wasi",
|
|
16893
17104
|
glue: "",
|
|
@@ -16909,7 +17120,9 @@ var Launcher = class {
|
|
|
16909
17120
|
env.HOSTNAME = this.hostname;
|
|
16910
17121
|
let program;
|
|
16911
17122
|
try {
|
|
16912
|
-
|
|
17123
|
+
const caller = { pid: req.ppid ?? 0, uid: req.cred.euid, tag: req.tag };
|
|
17124
|
+
if (this.integrity) await this.checkedSources(planned, caller);
|
|
17125
|
+
program = await this.program(target, env, caller);
|
|
16913
17126
|
} catch (err) {
|
|
16914
17127
|
await req.fds.closeAll();
|
|
16915
17128
|
throw err;
|
|
@@ -17401,11 +17614,14 @@ var Launcher = class {
|
|
|
17401
17614
|
}
|
|
17402
17615
|
};
|
|
17403
17616
|
}
|
|
17404
|
-
const module = (await scanFilesystems(this.
|
|
17617
|
+
const module = (await scanFilesystems(this.scanned, await this.roots())).get(type);
|
|
17405
17618
|
if (!module) throw fsError("ENODEV", `unknown file system type ${type}`);
|
|
17406
17619
|
if (!this.createDriverWorker)
|
|
17407
17620
|
throw fsError("ENODEV", `this kernel cannot start ${type} drivers`);
|
|
17408
|
-
const
|
|
17621
|
+
const root = PACKAGE_ROOT.exec(module)?.[1];
|
|
17622
|
+
if (this.integrity && root !== void 0)
|
|
17623
|
+
await this.text(`${root}/package.json`, KERNEL_CALLER);
|
|
17624
|
+
const code = new TextDecoder().decode(await this.verified(module, KERNEL_CALLER));
|
|
17409
17625
|
const worker = this.createDriverWorker();
|
|
17410
17626
|
const driver = new MessageChannel();
|
|
17411
17627
|
const client = new MessageChannel();
|
|
@@ -17976,16 +18192,20 @@ function usersOp(l, req) {
|
|
|
17976
18192
|
if (req.op === "groups-remove-member") return l.users.removeMember(req.group, req.user);
|
|
17977
18193
|
return l.users.list();
|
|
17978
18194
|
}
|
|
17979
|
-
function hostOptions(req, port, sealed, clipboard) {
|
|
18195
|
+
function hostOptions(req, port, sealed, clipboard, lookup) {
|
|
17980
18196
|
return {
|
|
17981
18197
|
...req.hostname !== void 0 ? { hostname: req.hostname } : {},
|
|
17982
18198
|
...req.users !== void 0 ? { users: req.users } : {},
|
|
17983
18199
|
...req.denials ? { onDenial: (denial) => port.postMessage({ denial }) } : {},
|
|
17984
|
-
...req.protect ? { protect:
|
|
18200
|
+
...req.protect ? { protect: hostProtect(req.protect, lookup) } : {},
|
|
17985
18201
|
...req.sealed ? { sealed } : {},
|
|
17986
18202
|
...req.clipboard ? { clipboard } : {}
|
|
17987
18203
|
};
|
|
17988
18204
|
}
|
|
18205
|
+
function hostProtect(init, lookup) {
|
|
18206
|
+
const { integrity, ...rest2 } = protectInit(init);
|
|
18207
|
+
return { ...rest2, ...integrity ? { integrity: { ...integrity, lookup } } : {} };
|
|
18208
|
+
}
|
|
17989
18209
|
function policyAsker(port) {
|
|
17990
18210
|
const policies = /* @__PURE__ */ new Map();
|
|
17991
18211
|
let nextPolicy = 0;
|
|
@@ -18014,6 +18234,7 @@ function serveKernel(port, deps) {
|
|
|
18014
18234
|
const clients = /* @__PURE__ */ new Set();
|
|
18015
18235
|
const sealed = sealedAsker(port);
|
|
18016
18236
|
const clipboard = clipboardAsker(port);
|
|
18237
|
+
const integrity = integrityAsker(port);
|
|
18017
18238
|
const approvals = sudoApprovals(port);
|
|
18018
18239
|
const locks = deps.locks === null ? void 0 : deps.locks ?? locksOf();
|
|
18019
18240
|
let holding;
|
|
@@ -18080,7 +18301,7 @@ function serveKernel(port, deps) {
|
|
|
18080
18301
|
...deps.createDriverWorker ? { createDriverWorker: deps.createDriverWorker } : {},
|
|
18081
18302
|
...req.modules ? { modules: req.modules } : {},
|
|
18082
18303
|
...req.env ? { env: req.env } : {},
|
|
18083
|
-
...hostOptions(req, port, sealed.hook, clipboard.hook),
|
|
18304
|
+
...hostOptions(req, port, sealed.hook, clipboard.hook, integrity.lookup),
|
|
18084
18305
|
...req.approve ? { approve: approvals.ask } : {},
|
|
18085
18306
|
...net,
|
|
18086
18307
|
...media ? { media } : {},
|
|
@@ -18150,6 +18371,8 @@ function serveKernel(port, deps) {
|
|
|
18150
18371
|
if (sealedReply) return sealed.answer(sealedReply);
|
|
18151
18372
|
const clipboardReply = event.data.clipboardReply;
|
|
18152
18373
|
if (clipboardReply) return clipboard.answer(clipboardReply);
|
|
18374
|
+
const integrityReply = event.data.integrityReply;
|
|
18375
|
+
if (integrityReply) return integrity.answer(integrityReply);
|
|
18153
18376
|
const grant = event.data.hostfsGrant;
|
|
18154
18377
|
if (grant) return granted2(grant);
|
|
18155
18378
|
if (allowed(event.data)) return;
|