Publish quixos-nix-helpers from e4393946ba63cfef75580f6aa6ba840035e7d43c
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"sourceRepo": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos",
|
"sourceRepo": "https://gitea.internal.quixos.org/quixos/quixos.git",
|
||||||
"sourceCommit": "358e649a7d70828db2ef96d5fed18931e48bc498",
|
"sourceCommit": "e4393946ba63cfef75580f6aa6ba840035e7d43c",
|
||||||
"sourcePath": "quixos-instance/quixos-nix-helpers",
|
"sourcePath": "quixos-instance/quixos-nix-helpers",
|
||||||
"exportName": "quixos-nix-helpers",
|
"exportName": "quixos-nix-helpers",
|
||||||
"mirrorRemote": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git"
|
"mirrorRemote": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git"
|
||||||
|
|||||||
@@ -20,17 +20,9 @@ let
|
|||||||
runtime = nativeProbe;
|
runtime = nativeProbe;
|
||||||
executable = "${nativeProbe}/bin/probe";
|
executable = "${nativeProbe}/bin/probe";
|
||||||
};
|
};
|
||||||
identityLauncher =
|
mkIdentityLauncher =
|
||||||
pkgs.runCommand "quixos-restricted-identity-launcher"
|
settings: import ./identity-launcher.nix ({ inherit pkgs sandbox; } // settings);
|
||||||
{
|
identityLauncher = mkIdentityLauncher { };
|
||||||
nativeBuildInputs = [ pkgs.stdenv.cc ];
|
|
||||||
}
|
|
||||||
''
|
|
||||||
mkdir -p "$out/bin"
|
|
||||||
$CC -O2 -Wall -Wextra -Werror ${./identity-launcher.c} \
|
|
||||||
-DSANDBOX_EXECUTABLE='"${sandbox}/bin/quixos-restricted-sandbox"' \
|
|
||||||
-o "$out/bin/quixos-restricted-engine"
|
|
||||||
'';
|
|
||||||
# Transaction-port/value adapters do not need the browser's CRDT/Wasm engine.
|
# Transaction-port/value adapters do not need the browser's CRDT/Wasm engine.
|
||||||
# Keep this surface explicit; it is bundled into checked restricted handlers.
|
# Keep this surface explicit; it is bundled into checked restricted handlers.
|
||||||
sdk = pkgs.runCommand "quixos-restricted-sdk" { nativeBuildInputs = [ pkgs.esbuild ]; } ''
|
sdk = pkgs.runCommand "quixos-restricted-sdk" { nativeBuildInputs = [ pkgs.esbuild ]; } ''
|
||||||
@@ -73,6 +65,7 @@ in
|
|||||||
workerd
|
workerd
|
||||||
sandbox
|
sandbox
|
||||||
identityLauncher
|
identityLauncher
|
||||||
|
mkIdentityLauncher
|
||||||
nativeProbeSandbox
|
nativeProbeSandbox
|
||||||
sdk
|
sdk
|
||||||
runtime
|
runtime
|
||||||
|
|||||||
@@ -20,17 +20,17 @@ static void fail(const char *message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
const char *root = "/run/quixos-restricted-engines/";
|
const char *root = ENGINE_DIRECTORY "/";
|
||||||
uid_t caller = getuid();
|
uid_t caller = getuid();
|
||||||
gid_t group = getgid();
|
gid_t group = getgid();
|
||||||
struct passwd *owner = getpwnam("quixos-graph");
|
struct passwd *owner = getpwnam(AUTHORITY_USER);
|
||||||
if (geteuid() != 0) fail("privileged wrapper unavailable");
|
if (geteuid() != 0) fail("privileged wrapper unavailable");
|
||||||
if (!owner) fail("authority identity unavailable");
|
if (!owner) fail("authority identity unavailable");
|
||||||
if (caller != owner->pw_uid) fail("caller identity mismatch");
|
if (caller != owner->pw_uid) fail("caller identity mismatch");
|
||||||
if (argc != 3) fail("invalid arguments");
|
if (argc != 3) fail("invalid arguments");
|
||||||
char *end;
|
char *end;
|
||||||
unsigned long number = strtoul(argv[2], &end, 10);
|
unsigned long number = strtoul(argv[2], &end, 10);
|
||||||
if (!*argv[2] || *end || number < 610000 || number >= 610064)
|
if (!*argv[2] || *end || number < ENGINE_FIRST_UID || number >= ENGINE_FIRST_UID + ENGINE_IDENTITY_COUNT)
|
||||||
fail("invalid engine identity");
|
fail("invalid engine identity");
|
||||||
uid_t identity = (uid_t)number;
|
uid_t identity = (uid_t)number;
|
||||||
if (strlen(argv[1]) != strlen(root) + 16 || strncmp(argv[1], root, strlen(root)))
|
if (strlen(argv[1]) != strlen(root) + 16 || strncmp(argv[1], root, strlen(root)))
|
||||||
@@ -39,7 +39,7 @@ int main(int argc, char **argv) {
|
|||||||
if (strncmp(name, "qx-engine-", 10) ||
|
if (strncmp(name, "qx-engine-", 10) ||
|
||||||
strlen(name) != 16 || strspn(name + 10, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") != 6)
|
strlen(name) != 16 || strspn(name + 10, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") != 6)
|
||||||
fail("invalid engine directory");
|
fail("invalid engine directory");
|
||||||
int parent = open("/run/quixos-restricted-engines", O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
|
int parent = open(ENGINE_DIRECTORY, O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
|
||||||
struct stat info;
|
struct stat info;
|
||||||
if (parent < 0 || fstat(parent, &info) || info.st_uid != caller || (info.st_mode & 066))
|
if (parent < 0 || fstat(parent, &info) || info.st_uid != caller || (info.st_mode & 066))
|
||||||
fail("invalid engine root");
|
fail("invalid engine root");
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# Trusted host construction only. Authored Workers cannot choose the caller,
|
||||||
|
# reserved identities, engine directory or sandbox executable.
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
sandbox,
|
||||||
|
authorityUser ? "quixos-graph",
|
||||||
|
engineDirectory ? "/run/quixos-restricted-engines",
|
||||||
|
firstUid ? 610000,
|
||||||
|
identityCount ? 64,
|
||||||
|
}:
|
||||||
|
assert builtins.match "[a-z][a-z0-9_-]{0,63}" authorityUser != null;
|
||||||
|
assert builtins.match "/run/[a-zA-Z0-9_/-]+" engineDirectory != null;
|
||||||
|
assert !(pkgs.lib.hasInfix ".." engineDirectory);
|
||||||
|
assert !(pkgs.lib.hasSuffix "/" engineDirectory);
|
||||||
|
assert builtins.stringLength engineDirectory < 80;
|
||||||
|
assert builtins.isInt firstUid && builtins.isInt identityCount;
|
||||||
|
assert firstUid >= 610000 && firstUid + identityCount <= 2147483647;
|
||||||
|
assert identityCount >= 1 && identityCount <= 64;
|
||||||
|
pkgs.runCommand "quixos-restricted-identity-launcher" { nativeBuildInputs = [ pkgs.stdenv.cc ]; } ''
|
||||||
|
mkdir -p "$out/bin"
|
||||||
|
$CC -O2 -Wall -Wextra -Werror ${./identity-launcher.c} \
|
||||||
|
-DSANDBOX_EXECUTABLE='"${sandbox}/bin/quixos-restricted-sandbox"' \
|
||||||
|
-DAUTHORITY_USER='"${authorityUser}"' \
|
||||||
|
-DENGINE_DIRECTORY='"${engineDirectory}"' \
|
||||||
|
-DENGINE_FIRST_UID=${toString firstUid} \
|
||||||
|
-DENGINE_IDENTITY_COUNT=${toString identityCount} \
|
||||||
|
-o "$out/bin/quixos-restricted-engine"
|
||||||
|
''
|
||||||
@@ -2,23 +2,45 @@
|
|||||||
executor,
|
executor,
|
||||||
enable,
|
enable,
|
||||||
controlGroup,
|
controlGroup,
|
||||||
|
authorityUser ? "quixos-graph",
|
||||||
|
engineDirectory ? "/run/quixos-restricted-engines",
|
||||||
|
firstUid ? 610000,
|
||||||
|
identityCount ? 64,
|
||||||
|
wrapperName ? "quixos-restricted-engine",
|
||||||
}:
|
}:
|
||||||
{ config, lib, ... }:
|
{ config, lib, ... }:
|
||||||
{
|
{
|
||||||
config = lib.mkIf enable {
|
config = lib.mkIf enable {
|
||||||
assertions = [
|
assertions = [
|
||||||
{
|
{
|
||||||
assertion = lib.all (user: user.uid == null || user.uid < 610000 || user.uid >= 610064) (
|
assertion = lib.all (
|
||||||
builtins.attrValues config.users.users
|
user: user.uid == null || user.uid < firstUid || user.uid >= firstUid + identityCount
|
||||||
);
|
) (builtins.attrValues config.users.users);
|
||||||
message = "UIDs 610000–610063 are reserved for restricted engine identities.";
|
message = "UIDs ${toString firstUid}–${
|
||||||
|
toString (firstUid + identityCount - 1)
|
||||||
|
} are reserved for restricted engine identities.";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
assertion = lib.all (
|
||||||
|
group: group.gid == null || group.gid < firstUid || group.gid >= firstUid + identityCount
|
||||||
|
) (builtins.attrValues config.users.groups);
|
||||||
|
message = "Restricted engine GIDs must not overlap host groups.";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
systemd.tmpfiles.rules = [
|
systemd.tmpfiles.rules = [
|
||||||
"d /run/quixos-restricted-engines 0711 quixos-graph ${controlGroup} -"
|
"d ${engineDirectory} 0711 ${authorityUser} ${controlGroup} -"
|
||||||
];
|
];
|
||||||
security.wrappers.quixos-restricted-engine = {
|
security.wrappers.${wrapperName} = {
|
||||||
source = "${executor.identityLauncher}/bin/quixos-restricted-engine";
|
source = "${
|
||||||
|
executor.mkIdentityLauncher {
|
||||||
|
inherit
|
||||||
|
authorityUser
|
||||||
|
engineDirectory
|
||||||
|
firstUid
|
||||||
|
identityCount
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}/bin/quixos-restricted-engine";
|
||||||
owner = "root";
|
owner = "root";
|
||||||
group = controlGroup;
|
group = controlGroup;
|
||||||
permissions = "u+rx,g+rx,o-rwx";
|
permissions = "u+rx,g+rx,o-rwx";
|
||||||
|
|||||||
@@ -7,6 +7,32 @@ import { tmpdir } from "node:os";
|
|||||||
import { join, dirname } from "node:path";
|
import { join, dirname } from "node:path";
|
||||||
|
|
||||||
const abi = "quixos-transaction-ports-v1";
|
const abi = "quixos-transaction-ports-v1";
|
||||||
|
/** Reserved supervisor faults are not authored domain rejections. A graph
|
||||||
|
* transaction must roll back without recording a permanent rejected outcome
|
||||||
|
* when its executor dies, exceeds its limits or cannot start. */
|
||||||
|
export const restrictedExecutionFailureCodes = Object.freeze([
|
||||||
|
"RESTRICTED_ABI_MISMATCH",
|
||||||
|
"RESTRICTED_BACKPRESSURE",
|
||||||
|
"RESTRICTED_CPU_ACCOUNTING",
|
||||||
|
"RESTRICTED_DEADLINE",
|
||||||
|
"RESTRICTED_DIAGNOSTIC_LIMIT",
|
||||||
|
"RESTRICTED_DUPLICATE_INVOCATION",
|
||||||
|
"RESTRICTED_ENGINE_EXITED",
|
||||||
|
"RESTRICTED_ENGINE_LIMIT",
|
||||||
|
"RESTRICTED_ENTRY_LIMIT",
|
||||||
|
"RESTRICTED_IDENTITY_UNAVAILABLE",
|
||||||
|
"RESTRICTED_MESSAGE_LIMIT",
|
||||||
|
"RESTRICTED_PACKAGE_FAILED",
|
||||||
|
"RESTRICTED_PORT_FAILED",
|
||||||
|
"RESTRICTED_PORT_LIMIT",
|
||||||
|
"RESTRICTED_PROCESS_LIMIT",
|
||||||
|
"RESTRICTED_QUEUE_FULL",
|
||||||
|
"RESTRICTED_SDK_LIMIT",
|
||||||
|
"RESTRICTED_SOURCE_LIMIT",
|
||||||
|
"RESTRICTED_START_FAILED",
|
||||||
|
"RESTRICTED_UNKNOWN_INVOCATION",
|
||||||
|
"RESTRICTED_UNKNOWN_PORT",
|
||||||
|
]);
|
||||||
const fixedError = (code) => Object.assign(Error(code), { code });
|
const fixedError = (code) => Object.assign(Error(code), { code });
|
||||||
const object = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
const object = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
||||||
const absolute = (value) =>
|
const absolute = (value) =>
|
||||||
|
|||||||
Reference in New Issue
Block a user