@ai-ecoverse/slicc-kernel 1.81.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 +7 -0
- package/dist/index.js +44 -3
- package/dist/index.js.map +3 -3
- package/dist/kernel-worker.js +263 -41
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +226 -37
- package/dist/node.js.map +4 -4
- 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(
|
|
@@ -4467,6 +4586,27 @@ function clipboardAsker(port) {
|
|
|
4467
4586
|
return { hook, answer };
|
|
4468
4587
|
}
|
|
4469
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
|
+
|
|
4470
4610
|
// src/kernel/net/loopback-names.ts
|
|
4471
4611
|
var HOST_LOOPBACK = "host.slicc.internal";
|
|
4472
4612
|
var HOST_LOOPBACK_ADDRESS = [10, 0, 2, 2];
|
|
@@ -7093,7 +7233,7 @@ function owned(path, st) {
|
|
|
7093
7233
|
function unchanged(a, b, bytes) {
|
|
7094
7234
|
return a.ino === b.ino && a.mtime.getTime() === b.mtime.getTime() && a.size === b.size && bytes.length === b.size;
|
|
7095
7235
|
}
|
|
7096
|
-
async function
|
|
7236
|
+
async function sha2562(bytes) {
|
|
7097
7237
|
const digest = new Uint8Array(
|
|
7098
7238
|
await crypto.subtle.digest("SHA-256", bytes)
|
|
7099
7239
|
);
|
|
@@ -7149,7 +7289,7 @@ async function attest(fs, asked, o) {
|
|
|
7149
7289
|
const bytes = (await fs.readFileBuffer(path)).slice();
|
|
7150
7290
|
const after = await fs.lstat(path);
|
|
7151
7291
|
if (unchanged(before, after, bytes)) {
|
|
7152
|
-
return attested(path, after, bytes, await
|
|
7292
|
+
return attested(path, after, bytes, await sha2562(bytes), o, parents);
|
|
7153
7293
|
}
|
|
7154
7294
|
if (tries >= 1) refuse("EAGAIN", path, "changed while it was read");
|
|
7155
7295
|
}
|
|
@@ -16453,6 +16593,13 @@ var Launcher = class {
|
|
|
16453
16593
|
unwatchScopes = () => void 0;
|
|
16454
16594
|
warned = /* @__PURE__ */ new Set();
|
|
16455
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
|
+
}
|
|
16456
16603
|
processes = /* @__PURE__ */ new Map();
|
|
16457
16604
|
zombies = /* @__PURE__ */ new Set();
|
|
16458
16605
|
orphans = /* @__PURE__ */ new Set();
|
|
@@ -16556,7 +16703,7 @@ var Launcher = class {
|
|
|
16556
16703
|
if (options.uplink) this.net.useUplink({ uplink: options.uplink, routes: this.routes });
|
|
16557
16704
|
enableNetwork(this.net, {
|
|
16558
16705
|
transport: this.transport,
|
|
16559
|
-
engine: kernelTlsEngine(packageTlsEngine(options.fs, this.modulesDir)),
|
|
16706
|
+
engine: kernelTlsEngine(packageTlsEngine(this.verifiedFs(options.fs), this.modulesDir)),
|
|
16560
16707
|
ca: this.ca
|
|
16561
16708
|
});
|
|
16562
16709
|
enableCdp(this.net, this.cdp);
|
|
@@ -16591,6 +16738,16 @@ var Launcher = class {
|
|
|
16591
16738
|
this.prefixes = protectedPrefixes(options.protect?.paths ?? []);
|
|
16592
16739
|
this.processFs = this.prefixes.length > 0 ? new ProtectedFs(this.prefixes).view(this.fs) : this.fs;
|
|
16593
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
|
+
}
|
|
16594
16751
|
this.users = new UserDb(this.fs, this.owners);
|
|
16595
16752
|
this.sudoer = new Sudo({
|
|
16596
16753
|
fs: this.fs,
|
|
@@ -16636,7 +16793,7 @@ var Launcher = class {
|
|
|
16636
16793
|
commands(scope = "") {
|
|
16637
16794
|
let found = this.catalogs.get(scope);
|
|
16638
16795
|
if (!found) {
|
|
16639
|
-
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));
|
|
16640
16797
|
this.catalogs.set(scope, found);
|
|
16641
16798
|
}
|
|
16642
16799
|
return found;
|
|
@@ -16644,7 +16801,7 @@ var Launcher = class {
|
|
|
16644
16801
|
ownCommands(scope) {
|
|
16645
16802
|
let found = this.ownCatalogs.get(scope);
|
|
16646
16803
|
if (!found) {
|
|
16647
|
-
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()));
|
|
16648
16805
|
this.ownCatalogs.set(scope, found);
|
|
16649
16806
|
}
|
|
16650
16807
|
return found;
|
|
@@ -16653,7 +16810,7 @@ var Launcher = class {
|
|
|
16653
16810
|
let found = this.binfmts.get(scope);
|
|
16654
16811
|
if (!found) {
|
|
16655
16812
|
found = this.roots(scope).then(
|
|
16656
|
-
(roots) => scanBinfmts(this.
|
|
16813
|
+
(roots) => scanBinfmts(this.scanned, roots, (message3) => {
|
|
16657
16814
|
if (this.warned.has(message3)) return;
|
|
16658
16815
|
this.warned.add(message3);
|
|
16659
16816
|
console.warn(message3);
|
|
@@ -16772,10 +16929,16 @@ var Launcher = class {
|
|
|
16772
16929
|
}
|
|
16773
16930
|
const inner = await this.interpreted(interp, [interp, ...passed], cwd, scope, depth + 1);
|
|
16774
16931
|
const via = [interp, ...inner?.via ?? []];
|
|
16775
|
-
|
|
16932
|
+
const sources = [script, ...inner?.sources ?? []];
|
|
16933
|
+
return inner && { ...inner, target: withScriptEnv(inner.target, command), via, sources };
|
|
16776
16934
|
}
|
|
16777
16935
|
const target = withScriptEnv(found, command);
|
|
16778
|
-
return {
|
|
16936
|
+
return {
|
|
16937
|
+
target,
|
|
16938
|
+
args: [...target.prefix ?? [], ...passed],
|
|
16939
|
+
via: [interp],
|
|
16940
|
+
sources: [script]
|
|
16941
|
+
};
|
|
16779
16942
|
}
|
|
16780
16943
|
async plan(file, argv, cwd, scope, argv0) {
|
|
16781
16944
|
const found = await this.resolve(file, argv[0] ?? file, cwd, scope);
|
|
@@ -16807,7 +16970,7 @@ var Launcher = class {
|
|
|
16807
16970
|
}
|
|
16808
16971
|
async binfmtManifests(scripts) {
|
|
16809
16972
|
const sources = /* @__PURE__ */ new Map();
|
|
16810
|
-
const binfmts = await scanBinfmts(this.
|
|
16973
|
+
const binfmts = await scanBinfmts(this.scanned, await this.roots(), void 0, sources);
|
|
16811
16974
|
const manifests = [];
|
|
16812
16975
|
for (const script of scripts) {
|
|
16813
16976
|
const head = await this.head(script);
|
|
@@ -16842,25 +17005,72 @@ var Launcher = class {
|
|
|
16842
17005
|
if (!head || head[0] === 35 && head[1] === 33) return "ENOENT";
|
|
16843
17006
|
return binfmtOf(await this.interpreters(scope), path) ? "ENOENT" : "ENOEXEC";
|
|
16844
17007
|
}
|
|
16845
|
-
|
|
16846
|
-
|
|
16847
|
-
|
|
16848
|
-
|
|
16849
|
-
|
|
16850
|
-
|
|
16851
|
-
|
|
16852
|
-
|
|
16853
|
-
|
|
16854
|
-
|
|
16855
|
-
|
|
16856
|
-
|
|
16857
|
-
|
|
16858
|
-
|
|
16859
|
-
|
|
16860
|
-
|
|
16861
|
-
|
|
16862
|
-
|
|
16863
|
-
|
|
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 };
|
|
16864
17074
|
});
|
|
16865
17075
|
}
|
|
16866
17076
|
async names(path, module) {
|
|
@@ -16872,23 +17082,23 @@ var Launcher = class {
|
|
|
16872
17082
|
const optional = `${root}-names${beside.slice(root.length)}`;
|
|
16873
17083
|
return await this.base.exists(optional) ? optional : void 0;
|
|
16874
17084
|
}
|
|
16875
|
-
async program(target, env) {
|
|
17085
|
+
async program(target, env, caller) {
|
|
16876
17086
|
if (target.abi === "js" && target.wasm === SUDO_PATH) {
|
|
16877
17087
|
return { abi: "js", glue: SUDO_SOURCE, path: SUDO_PATH };
|
|
16878
17088
|
}
|
|
16879
17089
|
if (target.abi === "js") {
|
|
16880
|
-
return { abi: "js", glue: await this.
|
|
17090
|
+
return { abi: "js", glue: await this.text(target.wasm, caller), path: target.wasm };
|
|
16881
17091
|
}
|
|
16882
17092
|
if (target.abi !== "wasi") {
|
|
16883
17093
|
const [glue, { module: module2 }] = await Promise.all([
|
|
16884
|
-
this.
|
|
16885
|
-
this.module(target.wasm)
|
|
17094
|
+
this.text(target.glue, caller),
|
|
17095
|
+
this.module(target.wasm, caller)
|
|
16886
17096
|
]);
|
|
16887
17097
|
return { glue, module: module2 };
|
|
16888
17098
|
}
|
|
16889
|
-
const { module, memory, foreign } = await this.module(target.wasm);
|
|
17099
|
+
const { module, memory, foreign } = await this.module(target.wasm, caller);
|
|
16890
17100
|
const names = env.SLICC_WASM_BACKTRACE === "1" ? await this.names(target.wasm, module) : void 0;
|
|
16891
|
-
const imports = target.imports ? await this.
|
|
17101
|
+
const imports = target.imports ? await this.text(target.imports, caller) : void 0;
|
|
16892
17102
|
return {
|
|
16893
17103
|
abi: "wasi",
|
|
16894
17104
|
glue: "",
|
|
@@ -16910,7 +17120,9 @@ var Launcher = class {
|
|
|
16910
17120
|
env.HOSTNAME = this.hostname;
|
|
16911
17121
|
let program;
|
|
16912
17122
|
try {
|
|
16913
|
-
|
|
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);
|
|
16914
17126
|
} catch (err) {
|
|
16915
17127
|
await req.fds.closeAll();
|
|
16916
17128
|
throw err;
|
|
@@ -17402,11 +17614,14 @@ var Launcher = class {
|
|
|
17402
17614
|
}
|
|
17403
17615
|
};
|
|
17404
17616
|
}
|
|
17405
|
-
const module = (await scanFilesystems(this.
|
|
17617
|
+
const module = (await scanFilesystems(this.scanned, await this.roots())).get(type);
|
|
17406
17618
|
if (!module) throw fsError("ENODEV", `unknown file system type ${type}`);
|
|
17407
17619
|
if (!this.createDriverWorker)
|
|
17408
17620
|
throw fsError("ENODEV", `this kernel cannot start ${type} drivers`);
|
|
17409
|
-
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));
|
|
17410
17625
|
const worker = this.createDriverWorker();
|
|
17411
17626
|
const driver = new MessageChannel();
|
|
17412
17627
|
const client = new MessageChannel();
|
|
@@ -17977,16 +18192,20 @@ function usersOp(l, req) {
|
|
|
17977
18192
|
if (req.op === "groups-remove-member") return l.users.removeMember(req.group, req.user);
|
|
17978
18193
|
return l.users.list();
|
|
17979
18194
|
}
|
|
17980
|
-
function hostOptions(req, port, sealed, clipboard) {
|
|
18195
|
+
function hostOptions(req, port, sealed, clipboard, lookup) {
|
|
17981
18196
|
return {
|
|
17982
18197
|
...req.hostname !== void 0 ? { hostname: req.hostname } : {},
|
|
17983
18198
|
...req.users !== void 0 ? { users: req.users } : {},
|
|
17984
18199
|
...req.denials ? { onDenial: (denial) => port.postMessage({ denial }) } : {},
|
|
17985
|
-
...req.protect ? { protect:
|
|
18200
|
+
...req.protect ? { protect: hostProtect(req.protect, lookup) } : {},
|
|
17986
18201
|
...req.sealed ? { sealed } : {},
|
|
17987
18202
|
...req.clipboard ? { clipboard } : {}
|
|
17988
18203
|
};
|
|
17989
18204
|
}
|
|
18205
|
+
function hostProtect(init, lookup) {
|
|
18206
|
+
const { integrity, ...rest2 } = protectInit(init);
|
|
18207
|
+
return { ...rest2, ...integrity ? { integrity: { ...integrity, lookup } } : {} };
|
|
18208
|
+
}
|
|
17990
18209
|
function policyAsker(port) {
|
|
17991
18210
|
const policies = /* @__PURE__ */ new Map();
|
|
17992
18211
|
let nextPolicy = 0;
|
|
@@ -18015,6 +18234,7 @@ function serveKernel(port, deps) {
|
|
|
18015
18234
|
const clients = /* @__PURE__ */ new Set();
|
|
18016
18235
|
const sealed = sealedAsker(port);
|
|
18017
18236
|
const clipboard = clipboardAsker(port);
|
|
18237
|
+
const integrity = integrityAsker(port);
|
|
18018
18238
|
const approvals = sudoApprovals(port);
|
|
18019
18239
|
const locks = deps.locks === null ? void 0 : deps.locks ?? locksOf();
|
|
18020
18240
|
let holding;
|
|
@@ -18081,7 +18301,7 @@ function serveKernel(port, deps) {
|
|
|
18081
18301
|
...deps.createDriverWorker ? { createDriverWorker: deps.createDriverWorker } : {},
|
|
18082
18302
|
...req.modules ? { modules: req.modules } : {},
|
|
18083
18303
|
...req.env ? { env: req.env } : {},
|
|
18084
|
-
...hostOptions(req, port, sealed.hook, clipboard.hook),
|
|
18304
|
+
...hostOptions(req, port, sealed.hook, clipboard.hook, integrity.lookup),
|
|
18085
18305
|
...req.approve ? { approve: approvals.ask } : {},
|
|
18086
18306
|
...net,
|
|
18087
18307
|
...media ? { media } : {},
|
|
@@ -18151,6 +18371,8 @@ function serveKernel(port, deps) {
|
|
|
18151
18371
|
if (sealedReply) return sealed.answer(sealedReply);
|
|
18152
18372
|
const clipboardReply = event.data.clipboardReply;
|
|
18153
18373
|
if (clipboardReply) return clipboard.answer(clipboardReply);
|
|
18374
|
+
const integrityReply = event.data.integrityReply;
|
|
18375
|
+
if (integrityReply) return integrity.answer(integrityReply);
|
|
18154
18376
|
const grant = event.data.hostfsGrant;
|
|
18155
18377
|
if (grant) return granted2(grant);
|
|
18156
18378
|
if (allowed(event.data)) return;
|