@ai-ecoverse/slicc-kernel 1.63.0 → 1.64.1
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 +2 -1
- package/dist/kernel-worker.js +101 -13
- package/dist/kernel-worker.js.map +3 -3
- package/dist/node-process-worker.js +22 -2
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +101 -13
- package/dist/node.js.map +3 -3
- package/dist/process-worker.js +22 -2
- package/dist/process-worker.js.map +2 -2
- package/package.json +2 -2
package/dist/node.js
CHANGED
|
@@ -410,6 +410,11 @@ var Created = class {
|
|
|
410
410
|
function deny(g, op, path, errno = "EACCES") {
|
|
411
411
|
g.dac.denied({ pid: g.pid, uid: g.cred.euid, op, path, errno });
|
|
412
412
|
}
|
|
413
|
+
var TTY_MODE = 400;
|
|
414
|
+
function ttyOpenable(g, tty) {
|
|
415
|
+
if (!g || !tty.owner || permits(g.cred, tty.owner, R_OK | W_OK, false)) return;
|
|
416
|
+
deny(g, "open", tty.name ?? "/dev/tty");
|
|
417
|
+
}
|
|
413
418
|
async function need(g, op, path, want, options = {}, shown = path) {
|
|
414
419
|
const walked = await access(g.fs, g.cred, path, want, options);
|
|
415
420
|
if (walked.denied !== void 0) deny(g, op, shown);
|
|
@@ -2307,10 +2312,18 @@ var UserDb = class {
|
|
|
2307
2312
|
};
|
|
2308
2313
|
}
|
|
2309
2314
|
async lookup(user) {
|
|
2315
|
+
return (await this.lookupTerminal(user))?.account;
|
|
2316
|
+
}
|
|
2317
|
+
async ttyGroup() {
|
|
2318
|
+
return parsed(parseGroup(await this.read(GROUP, DEFAULT_GROUP))).find((g) => g.name === "tty")?.gid;
|
|
2319
|
+
}
|
|
2320
|
+
async lookupTerminal(user) {
|
|
2310
2321
|
const { passwd, group } = await this.tables();
|
|
2311
2322
|
const key = typeof user === "number" ? "uid" : "name";
|
|
2312
2323
|
const row = parsed(passwd).find((r) => r[key] === user);
|
|
2313
|
-
|
|
2324
|
+
const groups = parsed(group);
|
|
2325
|
+
const tty = groups.find((g) => g.name === "tty")?.gid;
|
|
2326
|
+
return row && { account: this.account(row, groups), tty };
|
|
2314
2327
|
}
|
|
2315
2328
|
async list() {
|
|
2316
2329
|
const { passwd, group } = await this.tables();
|
|
@@ -3030,6 +3043,9 @@ var OpfsFs = class {
|
|
|
3030
3043
|
trackOwners() {
|
|
3031
3044
|
this.owners = true;
|
|
3032
3045
|
}
|
|
3046
|
+
async hasOwner(path) {
|
|
3047
|
+
return ownOf((await this.meta.get([path]))[0]) !== void 0;
|
|
3048
|
+
}
|
|
3033
3049
|
async ancestry(path) {
|
|
3034
3050
|
const entries = await this.meta.get(chain(path));
|
|
3035
3051
|
const out = [];
|
|
@@ -3801,8 +3817,10 @@ var UnlinkedKeeper = class {
|
|
|
3801
3817
|
count = 0;
|
|
3802
3818
|
links = /* @__PURE__ */ new Map();
|
|
3803
3819
|
linked = /* @__PURE__ */ new Map();
|
|
3820
|
+
dirOwner;
|
|
3804
3821
|
constructor(fs, holders, rootOf, options = {}) {
|
|
3805
3822
|
const { locks, owner } = options;
|
|
3823
|
+
this.dirOwner = options.dirOwner;
|
|
3806
3824
|
this.fs = fs;
|
|
3807
3825
|
this.holders = holders;
|
|
3808
3826
|
this.rootOf = rootOf;
|
|
@@ -3913,7 +3931,8 @@ var UnlinkedKeeper = class {
|
|
|
3913
3931
|
const dir = dirOf(this.rootOf(path));
|
|
3914
3932
|
const hidden = `${dir}/${this.instance}.${++this.count}`;
|
|
3915
3933
|
try {
|
|
3916
|
-
|
|
3934
|
+
const owner = this.dirOwner;
|
|
3935
|
+
await this.fs.mkdir(dir, { recursive: true, ...owner ? { owner } : {} });
|
|
3917
3936
|
await this.fs.rename(path, hidden);
|
|
3918
3937
|
await this.linkedName(hidden);
|
|
3919
3938
|
return hidden;
|
|
@@ -5071,6 +5090,7 @@ function withCommandDirs(fs, names, userDir = async () => void 0, owners = false
|
|
|
5071
5090
|
...fs.realpath ? { realpath: fs.realpath.bind(fs) } : {},
|
|
5072
5091
|
...fs.chown ? { chown: fs.chown.bind(fs) } : {},
|
|
5073
5092
|
...fs.ancestry ? { ancestry: fs.ancestry.bind(fs) } : {},
|
|
5093
|
+
...fs.hasOwner ? { hasOwner: fs.hasOwner.bind(fs) } : {},
|
|
5074
5094
|
chmod: (path, mode) => fs.chmod(path, mode),
|
|
5075
5095
|
utimes: (path, atime, mtime) => fs.utimes(path, atime, mtime),
|
|
5076
5096
|
lutimes: (path, atime, mtime) => lutimesOf(fs, path, atime, mtime),
|
|
@@ -6442,6 +6462,10 @@ var MountFs = class {
|
|
|
6442
6462
|
if (this.at(real)) throw errnoError("ENOSYS", path);
|
|
6443
6463
|
return real;
|
|
6444
6464
|
}
|
|
6465
|
+
async hasOwner(path) {
|
|
6466
|
+
if (this.at(path)) return true;
|
|
6467
|
+
return await this.base.hasOwner?.(path) ?? true;
|
|
6468
|
+
}
|
|
6445
6469
|
async ancestry(path) {
|
|
6446
6470
|
const names = chain(normalizePath(path));
|
|
6447
6471
|
const first = names.findIndex((name2) => this.at(name2));
|
|
@@ -9578,6 +9602,7 @@ var KernelTty = class {
|
|
|
9578
9602
|
waiters = [];
|
|
9579
9603
|
hungUp = false;
|
|
9580
9604
|
name;
|
|
9605
|
+
owner;
|
|
9581
9606
|
onRead;
|
|
9582
9607
|
readers = 0;
|
|
9583
9608
|
screen;
|
|
@@ -9921,10 +9946,11 @@ var PtyTable = class {
|
|
|
9921
9946
|
this.signal = signal;
|
|
9922
9947
|
this.onRead = onRead;
|
|
9923
9948
|
}
|
|
9924
|
-
open() {
|
|
9949
|
+
open(owner) {
|
|
9925
9950
|
let index = 0;
|
|
9926
9951
|
while (this.pairs.has(index)) index += 1;
|
|
9927
9952
|
const pair = new PtyPair(index, this.signal, (p) => this.pairs.delete(p.index), this.onRead);
|
|
9953
|
+
if (owner) pair.slave.owner = { uid: owner.uid, gid: owner.gid, mode: TTY_MODE };
|
|
9928
9954
|
this.pairs.set(index, pair);
|
|
9929
9955
|
return { pair, master: pair.master() };
|
|
9930
9956
|
}
|
|
@@ -9937,6 +9963,10 @@ var PtyTable = class {
|
|
|
9937
9963
|
return [...this.pairs.keys()].sort((a, b) => a - b);
|
|
9938
9964
|
}
|
|
9939
9965
|
};
|
|
9966
|
+
function ptsNumber(path) {
|
|
9967
|
+
const m = /^\/dev\/pts\/(\d+)$/.exec(path);
|
|
9968
|
+
return m ? Number(m[1]) : void 0;
|
|
9969
|
+
}
|
|
9940
9970
|
var PTY_OPS = [
|
|
9941
9971
|
"pty-open",
|
|
9942
9972
|
"pty-slave-open",
|
|
@@ -9964,11 +9994,12 @@ function ptySyscall(req, ctx) {
|
|
|
9964
9994
|
switch (req.op) {
|
|
9965
9995
|
case "pty-open": {
|
|
9966
9996
|
if (!ctx.ptys) throw new KernelError("ENOENT");
|
|
9967
|
-
return json4(ctx.fds.install(ctx.ptys.open().master, 3));
|
|
9997
|
+
return json4(ctx.fds.install(ctx.ptys.open(ctx.owner).master, 3));
|
|
9968
9998
|
}
|
|
9969
9999
|
case "pty-slave-open": {
|
|
9970
10000
|
if (!ctx.ptys) throw new KernelError("ENOENT");
|
|
9971
10001
|
const pair = ctx.ptys.get(req.n);
|
|
10002
|
+
ttyOpenable(ctx.guard, pair.slave);
|
|
9972
10003
|
const fd = ctx.fds.install(pair.openSlave(), 3);
|
|
9973
10004
|
if (!req.noctty) ctx.jobs?.acquireTerminal(ctx.pid, pair.slave);
|
|
9974
10005
|
return json4(fd);
|
|
@@ -10784,6 +10815,7 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
|
|
|
10784
10815
|
"fd-promote",
|
|
10785
10816
|
"fd-open-tty",
|
|
10786
10817
|
"fd-tty-names",
|
|
10818
|
+
"fd-tty-owner",
|
|
10787
10819
|
"tty-get",
|
|
10788
10820
|
"tty-set",
|
|
10789
10821
|
"tty-winsz",
|
|
@@ -10985,7 +11017,9 @@ var WasmProcess = class {
|
|
|
10985
11017
|
}
|
|
10986
11018
|
if (isPtySyscall(req)) {
|
|
10987
11019
|
const { ptys, jobs } = this.options;
|
|
10988
|
-
|
|
11020
|
+
const owner = this.options.owners ? this.ttyOwner() : void 0;
|
|
11021
|
+
const guard2 = this.guarded();
|
|
11022
|
+
return ptySyscall(req, { pid: this.pid, fds: this.fds, ptys, jobs, guard: guard2, owner });
|
|
10989
11023
|
}
|
|
10990
11024
|
return await this.procSyscall(req, cancelled);
|
|
10991
11025
|
} catch (e) {
|
|
@@ -11117,6 +11151,25 @@ var WasmProcess = class {
|
|
|
11117
11151
|
const want = (access2 === 1 ? 0 : R_OK) | (access2 !== 0 || req.truncate ? W_OK : 0);
|
|
11118
11152
|
await openable(g, "open", req.path, want, req.create === true);
|
|
11119
11153
|
}
|
|
11154
|
+
openTty(name2) {
|
|
11155
|
+
const tty = name2 === void 0 ? this.controllingTerminal() : this.options.jobs?.terminalNamed(name2);
|
|
11156
|
+
if (!tty) throw new KernelError("ENXIO");
|
|
11157
|
+
if (name2 !== void 0) ttyOpenable(this.guarded(), tty);
|
|
11158
|
+
return this.fds.install(tty.file(), 3);
|
|
11159
|
+
}
|
|
11160
|
+
guarded() {
|
|
11161
|
+
const { guard: guard2 } = this.options;
|
|
11162
|
+
return guard2 && { fs: guard2.fs, dac: guard2.dac, cred: this.cred, pid: this.pid };
|
|
11163
|
+
}
|
|
11164
|
+
ttyOwner() {
|
|
11165
|
+
return { uid: this.cred.euid, gid: this.cred.egid, mode: TTY_MODE };
|
|
11166
|
+
}
|
|
11167
|
+
terminalByName(name2) {
|
|
11168
|
+
const n = ptsNumber(name2);
|
|
11169
|
+
const tty = n === void 0 ? this.options.jobs?.terminalNamed(name2) : this.options.ptys?.get(n).slave;
|
|
11170
|
+
if (!tty) throw new KernelError("ENOENT");
|
|
11171
|
+
return tty;
|
|
11172
|
+
}
|
|
11120
11173
|
newOwner() {
|
|
11121
11174
|
if (!this.options.owners) return void 0;
|
|
11122
11175
|
return { uid: this.cred.euid, gid: this.cred.egid, mode: 438 & ~this.umask };
|
|
@@ -11220,13 +11273,12 @@ var WasmProcess = class {
|
|
|
11220
11273
|
if (!req.keep) await Promise.resolve(this.fds.close(req.from));
|
|
11221
11274
|
}
|
|
11222
11275
|
return { ok: true, kind: "void" };
|
|
11223
|
-
case "fd-open-tty":
|
|
11224
|
-
|
|
11225
|
-
if (!tty) throw new KernelError("ENXIO");
|
|
11226
|
-
return { ok: true, kind: "json", json: this.fds.install(tty.file(), 3) };
|
|
11227
|
-
}
|
|
11276
|
+
case "fd-open-tty":
|
|
11277
|
+
return { ok: true, kind: "json", json: this.openTty(req.name) };
|
|
11228
11278
|
case "fd-tty-names":
|
|
11229
11279
|
return { ok: true, kind: "json", json: this.options.jobs?.terminalNames() ?? [] };
|
|
11280
|
+
case "fd-tty-owner":
|
|
11281
|
+
return { ok: true, kind: "json", json: this.terminalByName(req.name).owner ?? null };
|
|
11230
11282
|
case "fd-select": {
|
|
11231
11283
|
const { read, write, timeoutMs } = req;
|
|
11232
11284
|
if (this.owed && timeoutMs !== 0) {
|
|
@@ -14002,6 +14054,16 @@ var NOT_FOUND = 127;
|
|
|
14002
14054
|
var DECIDE_MS = 100;
|
|
14003
14055
|
var INIT_PID = 1;
|
|
14004
14056
|
var SHARED_DIRS = ["/tmp", "/home"];
|
|
14057
|
+
var LAYOUT = [
|
|
14058
|
+
["/", 493],
|
|
14059
|
+
["/root", 448],
|
|
14060
|
+
["/home", 493],
|
|
14061
|
+
["/etc", 493],
|
|
14062
|
+
[PASSWD, 420],
|
|
14063
|
+
[GROUP, 420],
|
|
14064
|
+
["/usr", 493],
|
|
14065
|
+
["/usr/local", 493]
|
|
14066
|
+
];
|
|
14005
14067
|
var encoder3 = new TextEncoder();
|
|
14006
14068
|
var USERS_MODES = ["off", "report", "enforce"];
|
|
14007
14069
|
function usersMode(mode = "off") {
|
|
@@ -14195,7 +14257,8 @@ var Launcher = class {
|
|
|
14195
14257
|
{
|
|
14196
14258
|
locks: webLocks(),
|
|
14197
14259
|
busy: (path) => [...this.openFiles].some((nodes) => nodes.holds(path)),
|
|
14198
|
-
owner: options.unlinkOwner
|
|
14260
|
+
owner: options.unlinkOwner,
|
|
14261
|
+
...this.owners ? { dirOwner: { uid: 0, gid: 0, mode: 448 } } : {}
|
|
14199
14262
|
}
|
|
14200
14263
|
);
|
|
14201
14264
|
this.fs = this.unlinked.wrap(keepingOpen(fs, this.nodes));
|
|
@@ -14820,6 +14883,24 @@ var Launcher = class {
|
|
|
14820
14883
|
await this.provisionPnpmHome();
|
|
14821
14884
|
return entry;
|
|
14822
14885
|
}
|
|
14886
|
+
async stampLayout() {
|
|
14887
|
+
const layout = [
|
|
14888
|
+
...LAYOUT,
|
|
14889
|
+
[this.modulesDir, 493],
|
|
14890
|
+
[this.pnpmHome, 493],
|
|
14891
|
+
[`/${UNLINKED_DIR}`, 448]
|
|
14892
|
+
];
|
|
14893
|
+
for (const [path, mode] of layout) {
|
|
14894
|
+
const real = await this.realLayoutPath(path);
|
|
14895
|
+
const fresh = real !== void 0 && !await this.base.hasOwner?.(real);
|
|
14896
|
+
if (fresh) await this.base.chown?.(real, { uid: 0, gid: 0, mode, follow: false });
|
|
14897
|
+
}
|
|
14898
|
+
}
|
|
14899
|
+
async realLayoutPath(path) {
|
|
14900
|
+
if (!await this.base.exists(path)) return void 0;
|
|
14901
|
+
if (path === "/") return path;
|
|
14902
|
+
return joinName(await realDir(this.base, parentOf(path)), baseName(path));
|
|
14903
|
+
}
|
|
14823
14904
|
async provisionPnpmHome() {
|
|
14824
14905
|
await this.base.mkdir(this.pnpmHome, { recursive: true }).catch(() => void 0);
|
|
14825
14906
|
}
|
|
@@ -14893,6 +14974,7 @@ var Launcher = class {
|
|
|
14893
14974
|
if (this.owners) await this.base.chmod("/tmp", 1023);
|
|
14894
14975
|
await this.provisionPnpmHome();
|
|
14895
14976
|
await this.users.ensure();
|
|
14977
|
+
if (this.owners) await this.stampLayout();
|
|
14896
14978
|
await writeCaFile(this.base, this.ca).catch(() => void 0);
|
|
14897
14979
|
this.fstab = this.mountFstab();
|
|
14898
14980
|
}
|
|
@@ -14921,7 +15003,12 @@ var Launcher = class {
|
|
|
14921
15003
|
}
|
|
14922
15004
|
async account(user) {
|
|
14923
15005
|
if (typeof user === "object") return user;
|
|
14924
|
-
|
|
15006
|
+
return (await this.terminalAccount(user)).account;
|
|
15007
|
+
}
|
|
15008
|
+
async terminalAccount(user) {
|
|
15009
|
+
if (typeof user === "object")
|
|
15010
|
+
return { account: user, tty: this.owners ? await this.users.ttyGroup() : void 0 };
|
|
15011
|
+
const found = await this.users.lookupTerminal(user ?? 0);
|
|
14925
15012
|
if (!found) throw fsError("ENOENT", `no user ${String(user)}`);
|
|
14926
15013
|
return found;
|
|
14927
15014
|
}
|
|
@@ -14943,7 +15030,7 @@ var Launcher = class {
|
|
|
14943
15030
|
return { cwd, file, planned };
|
|
14944
15031
|
}
|
|
14945
15032
|
async openTerminal(argv, options) {
|
|
14946
|
-
const account = await this.
|
|
15033
|
+
const { account, tty: ttyGroup } = await this.terminalAccount(options.user);
|
|
14947
15034
|
const { cwd, file, planned } = await this.starting(argv, options.cwd, account);
|
|
14948
15035
|
if (!planned) throw new Error(`${file}: command not found`);
|
|
14949
15036
|
let leader = 0;
|
|
@@ -14953,6 +15040,7 @@ var Launcher = class {
|
|
|
14953
15040
|
);
|
|
14954
15041
|
tty.onRead = () => this.settling.reading(this.jobs.tcgetpgrp(tty, leader));
|
|
14955
15042
|
tty.name = `/dev/tty${++this.terminals}`;
|
|
15043
|
+
if (this.owners) tty.owner = { uid: account.uid, gid: ttyGroup ?? account.gid, mode: TTY_MODE };
|
|
14956
15044
|
tty.setSize(options.cols ?? 80, options.rows ?? 24);
|
|
14957
15045
|
const fds = new FdTable();
|
|
14958
15046
|
const stdio = tty.file();
|