@ai-ecoverse/slicc-kernel 1.135.1 → 1.135.2
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 +1 -1
- package/dist/kernel-worker.js +22 -3
- package/dist/kernel-worker.js.map +2 -2
- package/dist/node-process-worker.js +1 -1
- package/dist/node.js +22 -3
- package/dist/node.js.map +2 -2
- package/dist/process-worker.js +1 -1
- package/dist/types/fs/unlinked.d.ts +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -967,7 +967,7 @@ With `users: 'enforce'` the kernel checks every file call that reaches it agains
|
|
|
967
967
|
- **The layout:** with `users: 'report'` or `'enforce'`, the kernel gives its own paths an owner and a mode when they have no owner record yet: on a fresh root, and once on a root from before owners. These are `/` `0755`, `/root` `0700`, `/home` `0755`, `/etc` `0755`, `/etc/passwd` and `/etc/group` `0644`, `/usr` and `/usr/local` `0755`, `/node_modules` (or the `modules` option) and the system `PNPM_HOME` `0755`, all root's. A path that has a record keeps it, so an admin's `chmod 711 /home` or `chown cone /node_modules` lasts across restarts; a mounted path is left to its mount, and a path below a symlinked directory is stamped where it really is. Only a root that records owners is stamped: the OPFS root with its sidecar, which the page and the Node entry (in memory) both use; a custom root file system without owner records is left as it is. The directory for files removed while open, `/.slicc-unlinked`, is made root's `0700`. `/tmp` is the exception: it is set to `1777` at every start, and the first time owners are on for a root from before owners (and at every start after that until it has listed `/tmp` and succeeded for every entry), what is in it without an owner of its own is removed (as a boot empties `/tmp` on Linux; a file that is open is kept, a symlinked `/tmp` is left alone, and one `console.warn` line says how many entries went), since it would otherwise be root's, and a program that made it for its user, such as pnpm's lock directories, would find it isn't its own. Emscripten programs see `/` at `0755`, `/dev` at `0755`, `null`, `zero`, `full`, `random`, `urandom` and `tty` at `0666`, and `/dev/shm` at `1777`. With `users: 'off'` nothing is stamped. Paths the embedder makes (bios's `/opt` and `/var/lib/slicc`) are the embedder's to set. `/etc/sudoers` and `/etc/sudoers.d` are written when missing (see [Sudo](#sudo)).
|
|
968
968
|
- **Terminals:** a terminal from `openTerminal` belongs to its session's user, with group `tty` when `/etc/group` has one (the user's own group otherwise), mode `0620`; a pseudo-terminal's slave `/dev/pts/N` belongs to the uid and gid that opened `/dev/ptmx`, mode `0620`. Opening one by name (`/dev/ttyN`, `/dev/pts/N`, from every runtime) needs both `r` and `w`, so only its owner and root open it: the kernel's terminal descriptor always reads and writes, so the group's `w` bit (`write`, `wall` on Linux) does not let a group member open it. `/dev/tty` is the opener's own controlling terminal and is not checked, and descriptors a process inherited (across `sudo` or a `setresuid` too) keep working. Emscripten programs' `stat` of `/dev/ttyN` and `/dev/pts/N` shows the owner and mode. With `users: 'off'` terminals have no owner, as before.
|
|
969
969
|
- **A client's `fs`:** checked as the client's user; a page's client (root) passes.
|
|
970
|
-
- **Removed files still open:** a process that holds a removed file may look it up (`stat`, `lstat`) under the hidden name the kernel gave it in `/.slicc-unlinked`, which is root's `0700`; every other process is refused there, so the kernel's own bookkeeping of held files raises no denials for their holders.
|
|
970
|
+
- **Removed files still open:** a process that holds a removed file may look it up (`stat`, `lstat`) under the hidden name the kernel gave it in `/.slicc-unlinked`, which is root's `0700`; every other process is refused there, so the kernel's own bookkeeping of held files raises no denials for their holders. If the kernel can't move a held file into `/.slicc-unlinked` (OPFS refuses the move and the copy twice), the removal fails with `EBUSY` and the file stays where it was, so the holder keeps reading it ([#1218](https://github.com/ai-ecoverse/slicc-kernel/issues/1218)). Files of the same removal already moved aside are moved back. If one of those moves back fails too, that file stays in `/.slicc-unlinked`: its holder still reads it, but its name is gone although the removal reported `EBUSY`. That's a double failure, and rare.
|
|
971
971
|
|
|
972
972
|
`users: 'enforce'` is the default of `createKernel` and `createNodeKernel`; pass `'report'` to find what a program would be refused without refusing it, or `'off'` for kernels without owners. A `Launcher` made directly (see [What is in here](#what-is-in-here)) still defaults to `'off'`.
|
|
973
973
|
|
package/dist/kernel-worker.js
CHANGED
|
@@ -7098,7 +7098,7 @@ function satisfies(version, range2) {
|
|
|
7098
7098
|
}
|
|
7099
7099
|
|
|
7100
7100
|
// src/version.ts
|
|
7101
|
-
var KERNEL_VERSION = true ? "1.135.
|
|
7101
|
+
var KERNEL_VERSION = true ? "1.135.2" : "0.0.0-dev";
|
|
7102
7102
|
var OS_RELEASE = "6.0.0-slicc";
|
|
7103
7103
|
function procVersion() {
|
|
7104
7104
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -8166,12 +8166,20 @@ var UnlinkedKeeper = class {
|
|
|
8166
8166
|
const holders = now.get(path);
|
|
8167
8167
|
held.set(path, holders);
|
|
8168
8168
|
for (const holder of holders) moved2.push(holder.moving?.(path) ?? (() => void 0));
|
|
8169
|
-
const at = await this.
|
|
8170
|
-
if (at
|
|
8169
|
+
const at = await this.keepAside(path);
|
|
8170
|
+
if (at === void 0) continue;
|
|
8171
|
+
hidden.set(path, at);
|
|
8171
8172
|
}
|
|
8172
8173
|
}
|
|
8173
8174
|
} catch (err) {
|
|
8175
|
+
for (const [path, at] of hidden) {
|
|
8176
|
+
await this.serial(async () => {
|
|
8177
|
+
await Promise.allSettled([this.fs.rename(at, path)]);
|
|
8178
|
+
this.unlinkedName(at);
|
|
8179
|
+
});
|
|
8180
|
+
}
|
|
8174
8181
|
for (const settle3 of moved2) settle3();
|
|
8182
|
+
for (const release of releases) release();
|
|
8175
8183
|
throw err;
|
|
8176
8184
|
}
|
|
8177
8185
|
sealed();
|
|
@@ -8205,6 +8213,17 @@ var UnlinkedKeeper = class {
|
|
|
8205
8213
|
}
|
|
8206
8214
|
};
|
|
8207
8215
|
}
|
|
8216
|
+
async keepAside(path) {
|
|
8217
|
+
const at = await this.hide(path) ?? await this.hide(path);
|
|
8218
|
+
if (at !== void 0 || !await this.present(path)) return at;
|
|
8219
|
+
throw fsError("EBUSY", `${path}: open, and it could not be kept aside`);
|
|
8220
|
+
}
|
|
8221
|
+
present(path) {
|
|
8222
|
+
return this.fs.lstat(path).then(
|
|
8223
|
+
() => true,
|
|
8224
|
+
(err) => err?.code !== "ENOENT" && err?.code !== "ENOTDIR"
|
|
8225
|
+
);
|
|
8226
|
+
}
|
|
8208
8227
|
keptFile(hidden, entry) {
|
|
8209
8228
|
return {
|
|
8210
8229
|
hidden,
|