chore: adopt node-addon-landlock-run source as native/ subtree

Bring the node-addon-landlock-run tree (tag v0.0.1, commit 614f7fd) into
native/landlock-run as its source of record: launcher development happens
here, next to the harness consumers, and the standalone repository becomes
the release mirror the tree is exported to for packing and publishing
(procedure in native/README.md). The subtree keeps its own pnpm workspace
and lockfile and is NOT added to the harness workspace: harness installs,
gates, and CI never touch it. The mirror's .github/ stays out of the
subtree; a separate manually-dispatched workflow
(.github/workflows/landlock-run.yml) runs the subtree's CI legs — the
per-architecture native builds, real-kernel launcher proofs, and pack
rehearsal — adapted with working-directory/cache paths.

eslint ignores the subtree like vendor/; AGENTS.md gains the native/
layout line (+5 words on its budget ceiling).
This commit is contained in:
kingwl
2026-07-14 23:34:47 +08:00
parent 513a8d2177
commit 0a486f09c9
46 changed files with 2582 additions and 1 deletions

View File

@@ -0,0 +1,16 @@
# node-addon-landlock-run
Landlock self-restrict-then-exec launcher for confining subprocesses on Linux: this entry package resolves the per-platform prebuilt binary, runs its functional enforcement probe, and builds its grant argv — consumers never spell launcher flags or parse launcher output themselves.
```js
import { grantArgs, launcherPath, probe } from 'node-addon-landlock-run';
const launcher = launcherPath();
if (probe(launcher) !== 'unusable') {
const argv = [launcher, ...grantArgs({ readOnly: ['/'], readWrite: ['/tmp/work'] }), '--', 'bash', '-c', command];
}
```
The launcher installs a Landlock ruleset on itself and `exec`s the wrapped command; the ruleset is inherited across `execve`, so the whole process tree runs confined. Everything not granted is denied, and launcher failures exit `125` without running the command — fail-closed, never fail-open. The binary contract is pinned in the repo's `docs/cli-contract.md`; the C source rides this tarball (`src/main.c`) for audit.
Platform packages (`os`/`cpu`-selected optional dependencies, no JavaScript inside): `node-addon-landlock-run-linux-x64`, `node-addon-landlock-run-linux-arm64`. On hosts without one, `launcherPath()` returns a deterministic nonexistent path and `probe()` reports `'unusable'` — there is deliberately no install-time compile fallback.

View File

@@ -0,0 +1,36 @@
{
"name": "node-addon-landlock-run",
"version": "0.0.1",
"type": "module",
"description": "Landlock self-restrict-then-exec launcher for sandboxing subprocesses on Linux: per-platform prebuilt static binaries plus the JS seam that resolves, probes, and speaks their CLI contract",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"exports": {
".": {
"types": "./lib/index.d.ts",
"default": "./lib/index.js"
},
"./package.json": "./package.json"
},
"files": [
"README.md",
"lib/",
"!lib/*.tsbuildinfo",
"src/main.c"
],
"scripts": {
"build:js": "tsc -b",
"prepack": "node ../../scripts/verify-entry-lib.mjs"
},
"engines": {
"node": ">=20"
},
"license": "BSD-3-Clause",
"publishConfig": {
"access": "public"
},
"optionalDependencies": {
"node-addon-landlock-run-linux-arm64": "workspace:*",
"node-addon-landlock-run-linux-x64": "workspace:*"
}
}

View File

@@ -0,0 +1,126 @@
/**
* The JS seam over the prebuilt `landlock-run` launcher: resolve the
* binary for this host, build its grant argv, and run its functional probe.
*
* This module owns the launcher's CLI contract (`docs/cli-contract.md`) so
* consumers never parse launcher output or spell launcher flags themselves —
* the contract and the binaries version together in one package family,
* which makes probe-parsing drift against the binary structurally
* impossible. Policy stays with the consumer: this package does not know
* what a "sandbox mode" is, only which paths are granted read or write.
*
* Deliberately no environment-variable overrides anywhere in this module:
* which binary confines a process must never be decidable by the ambient
* environment. Test injection is by function parameter.
*/
import { spawnSync } from 'node:child_process'
import { createRequire } from 'node:module'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
/** The launcher binary's file name inside each platform package's `bin/`. */
export const LAUNCHER_BIN = 'landlock-run'
/**
* The exit code for every launcher-level failure (usage error, unenforcing
* kernel, unopenable grant root, failed exec) — chosen because the wrapped
* command itself is unlikely to use it, so a consumer can tell launcher
* failures from command failures. Part of the CLI contract.
*/
export const LAUNCHER_FAILURE_EXIT = 125
/**
* The probe's verdict on this host: `full` when the running kernel enforces
* every access the launcher can govern, `partial` when an older Landlock ABI
* governs only a subset (still confined for everything it supports), and
* `unusable` when nothing can be enforced — a kernel without Landlock, a
* disabled LSM, or a missing binary, all indistinguishable on purpose
* because the consumer's answer is the same: do not trust this launcher.
*/
export type LandlockEnforcement = 'full' | 'partial' | 'unusable'
/**
* Filesystem grants for one confined run. Everything not granted is denied —
* Landlock rulesets are allow-lists.
*/
export interface LauncherGrants {
/** Roots granted read + execute beneath (the launcher's `--ro`). */
readonly readOnly?: readonly string[]
/** Roots granted full filesystem access beneath (the launcher's `--rw`). */
readonly readWrite?: readonly string[]
}
/**
* Path of the launcher binary for this host: resolved from the per-platform
* npm package `node-addon-landlock-run-<platform>-<arch>` (npm's
* `os`/`cpu` fields make installers fetch only the matching one). When the
* package is not resolvable — a platform without one, or an install that
* skipped the optional dependency — the returned fallback path points inside
* this package's own `node_modules` and simply never exists. Existence is
* deliberately not checked either way: {@link probe} is the single
* availability signal (a missing binary probes `unusable` the same way an
* unenforcing kernel does).
* @param resolvePackageJson - test seam over `require.resolve` (the default
* covers real installs); receives the platform package's `package.json`
* specifier and returns its absolute path, throwing when unresolvable.
* @returns the absolute launcher path to probe and exec.
*/
export function launcherPath(
resolvePackageJson: (specifier: string) => string = createRequire(import.meta.url).resolve,
): string {
const platformPackage = `node-addon-landlock-run-${process.platform}-${process.arch}`
try {
return join(dirname(resolvePackageJson(`${platformPackage}/package.json`)), 'bin', LAUNCHER_BIN)
} catch {
// Unresolvable platform package: no such package exists for this host, or
// it was not installed. Fall back to the path pnpm's layout WOULD use —
// absolute, inside this package's boundary (never cwd-relative: a
// spawnable relative path here would hand cwd control over which binary
// confines), and nonexistent exactly when the package is absent.
return fileURLToPath(new URL(`../node_modules/${platformPackage}/bin/${LAUNCHER_BIN}`, import.meta.url))
}
}
/**
* The launcher grant arguments for one set of filesystem grants — everything
* before the `--` argv separator. A caller spawns
* `[launcherPath(), ...grantArgs(grants), '--', ...command]`; the flag
* spellings stay private to this package.
* @param grants - the read-only and read-write roots to allow.
* @returns the `--ro <path>` / `--rw <path>` argument list, read-only roots
* first, in the caller's order.
*/
export function grantArgs(grants: LauncherGrants): string[] {
return [
...(grants.readOnly ?? []).flatMap(root => ['--ro', root]),
...(grants.readWrite ?? []).flatMap(root => ['--rw', root]),
]
}
/**
* Functional probe: `landlock-run --probe` builds and enforces a maximal
* ruleset in a short-lived child and exits 0 only when the running kernel
* actually enforces it — `--version`-style checks would miss a kernel that
* has the syscalls but refuses enforcement. The probe's one report line is
* part of the CLI contract and distinguishes complete from per-ABI-subset
* enforcement; a zero exit without the partial marker reads as `full`. A
* failed or timed-out spawn (missing binary, wrong architecture, unenforcing
* kernel) probes `unusable`. Synchronous by design: consumers run it once
* and cache the verdict.
* @param launcher - the launcher path to probe; defaults to
* {@link launcherPath}'s resolution for this host.
* @param options - `timeoutMs` bounds the probe child (default 2000).
* @returns the enforcement verdict for this host.
*/
export function probe(
launcher: string = launcherPath(),
options: { timeoutMs?: number } = {},
): LandlockEnforcement {
const result = spawnSync(launcher, ['--probe'], {
timeout: options.timeoutMs ?? 2000,
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'ignore'],
})
if (result.status !== 0) return 'unusable'
return /partially enforced/.test(result.stdout) ? 'partial' : 'full'
}

View File

@@ -0,0 +1,302 @@
/*
* landlock-run: self-restrict-then-exec Landlock launcher.
*
* The Landlock rung of a consuming sandbox seam, for Linux hosts where
* `bwrap` is
* unusable (not installed, unprivileged user namespaces disabled, or an LSM
* profile that denies mount — Landlock is an independent syscall family and
* needs none of those). The launcher installs a Landlock
* ruleset on itself and `exec`s the wrapped command; the ruleset is inherited
* across `execve`, so the command (and every process it spawns) runs confined
* while the invoking process stays unrestricted.
*
* CLI contract (mirrors the `bwrap` runner argv shape the executor wraps):
*
* landlock-run [--ro <path>]... [--rw <path>]... -- <argv>...
* landlock-run --probe
*
* `--ro` grants read+execute beneath the path; `--rw` grants full filesystem
* access beneath the path. Everything else is denied (Landlock is an
* allow-list). `--probe` builds a maximal ruleset and reports whether the
* running kernel actually enforces it — the executor's functional probe.
*
* Fail-closed: if the ruleset cannot be created or is NOT enforced by the
* kernel, the launcher exits non-zero WITHOUT exec'ing the command. A partial
* (best-effort) enforcement on an older ABI is accepted and reported on
* stderr; the consumer's mode vocabulary keeps its file-effect promises
* honest per ABI level (surfaced as `full` vs `partial` by the entry
* package's probe).
*
* Plain C11 over the raw Landlock UAPI — no libraries beyond libc (musl,
* linked statically), so the whole audit surface is this file plus the
* kernel's stable syscall contract. Built natively per architecture by
* `scripts/build.ts` into the per-platform npm packages
* (`node-addon-landlock-run-linux-{x64,arm64}`); the argv grammar,
* exit codes, and report lines are pinned in `docs/cli-contract.md`.
*/
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <unistd.h>
/*
* The Landlock UAPI, defined locally instead of via <linux/landlock.h>: the
* kernel's user-space ABI is stable by contract, self-defining it keeps the
* build independent of the toolchain's header vintage, and the definitions
* double as the audit record of exactly which kernel surface this launcher
* touches. Layouts and values are verbatim from the kernel header (the
* path-beneath struct is packed there, so it must be packed here).
*/
struct landlock_ruleset_attr {
uint64_t handled_access_fs;
};
struct landlock_path_beneath_attr {
uint64_t allowed_access;
int32_t parent_fd;
} __attribute__((packed));
#define LANDLOCK_CREATE_RULESET_VERSION (1U << 0)
#define LANDLOCK_RULE_PATH_BENEATH 1
/* Filesystem access bits, grouped by the Landlock ABI that introduced them. */
#define LL_FS_EXECUTE (UINT64_C(1) << 0) /* ABI 1 */
#define LL_FS_WRITE_FILE (UINT64_C(1) << 1)
#define LL_FS_READ_FILE (UINT64_C(1) << 2)
#define LL_FS_READ_DIR (UINT64_C(1) << 3)
#define LL_FS_REMOVE_DIR (UINT64_C(1) << 4)
#define LL_FS_REMOVE_FILE (UINT64_C(1) << 5)
#define LL_FS_MAKE_CHAR (UINT64_C(1) << 6)
#define LL_FS_MAKE_DIR (UINT64_C(1) << 7)
#define LL_FS_MAKE_REG (UINT64_C(1) << 8)
#define LL_FS_MAKE_SOCK (UINT64_C(1) << 9)
#define LL_FS_MAKE_FIFO (UINT64_C(1) << 10)
#define LL_FS_MAKE_BLOCK (UINT64_C(1) << 11)
#define LL_FS_MAKE_SYM (UINT64_C(1) << 12)
#define LL_FS_REFER (UINT64_C(1) << 13) /* ABI 2 */
#define LL_FS_TRUNCATE (UINT64_C(1) << 14) /* ABI 3 (ABI 4 added TCP bits only) */
#define LL_FS_IOCTL_DEV (UINT64_C(1) << 15) /* ABI 5 */
#define LL_ABI1_MASK (LL_FS_REFER - 1) /* bits 0..12: every ABI-1 access, nothing newer */
/*
* Newest ABI this build knows; the negotiation below scales the actual
* ruleset down to what the running kernel supports (the best-effort compat
* stance of the previous Rust launcher, made explicit).
*/
#define MAX_ABI 5L
/*
* Landlock has no libc wrappers; these are the raw syscalls. The numbers are
* identical on every architecture (the post-2011 unified table) — the
* fallbacks only matter to a libc older than the feature.
*/
#ifndef __NR_landlock_create_ruleset
#define __NR_landlock_create_ruleset 444
#define __NR_landlock_add_rule 445
#define __NR_landlock_restrict_self 446
#endif
/*
* Every fatal launcher error prints `landlock-run: <message>` to stderr
* and exits 125 — a code the wrapped command itself is unlikely to use, so
* the executor can tell launcher failures from command failures.
*/
#define EXIT_LAUNCHER_FAILURE 125
static const char NOT_ENFORCED_MESSAGE[] =
"landlock is not enforced by this kernel (ABI unsupported or disabled)";
/* Print one fatal `landlock-run: ...` line; returns the fatal exit code. */
static int fail(const char *prefix, const char *detail) {
if (detail == NULL) {
fprintf(stderr, "landlock-run: %s\n", prefix);
} else {
fprintf(stderr, "landlock-run: %s: %s\n", prefix, detail);
}
return EXIT_LAUNCHER_FAILURE;
}
static int fail_usage(const char *message, const char *detail) {
fprintf(stderr, "landlock-run: usage error: %s%s\n", message, detail == NULL ? "" : detail);
return EXIT_LAUNCHER_FAILURE;
}
/* Parsed CLI: either a probe, or grants plus the command argv after `--`. */
struct cli {
int probe;
const char **ro;
size_t ro_count;
const char **rw;
size_t rw_count;
char **command; /* NULL-terminated tail of main's argv */
};
/*
* Hand-rolled argv parsing — four flags do not justify a parsing library,
* and the previous Rust launcher made the same call for the same reason.
* Returns 0 on success, else the process exit code (message already printed).
*/
static int parse(int argc, char **argv, struct cli *cli) {
/* argc bounds each grant list; the launcher execs or exits, so no free. */
cli->ro = calloc(argc > 0 ? (size_t)argc : 1, sizeof *cli->ro);
cli->rw = calloc(argc > 0 ? (size_t)argc : 1, sizeof *cli->rw);
if (cli->ro == NULL || cli->rw == NULL) return fail("out of memory", NULL);
int index = 1;
while (index < argc) {
const char *arg = argv[index];
if (strcmp(arg, "--probe") == 0) {
cli->probe = 1;
index += 1;
} else if (strcmp(arg, "--ro") == 0 || strcmp(arg, "--rw") == 0) {
if (index + 1 >= argc) {
return fail_usage(arg, " requires a path");
}
if (strcmp(arg, "--ro") == 0) {
cli->ro[cli->ro_count++] = argv[index + 1];
} else {
cli->rw[cli->rw_count++] = argv[index + 1];
}
index += 2;
} else if (strcmp(arg, "--") == 0) {
cli->command = &argv[index + 1];
break;
} else {
return fail_usage("unknown argument: ", arg);
}
}
if (cli->probe) {
if (cli->ro_count > 0 || cli->rw_count > 0 || (cli->command != NULL && cli->command[0] != NULL)) {
return fail_usage("--probe takes no other arguments", NULL);
}
} else if (cli->command == NULL || cli->command[0] == NULL) {
return fail_usage("missing `-- <argv>...` command", NULL);
}
return 0;
}
/* The filesystem accesses the running kernel's ABI can govern. */
static uint64_t fs_mask_for_abi(long abi) {
uint64_t mask = LL_ABI1_MASK;
if (abi >= 2) mask |= LL_FS_REFER;
if (abi >= 3) mask |= LL_FS_TRUNCATE;
if (abi >= 5) mask |= LL_FS_IOCTL_DEV;
return mask;
}
/* Add one path-beneath rule; 0 on success, else the exit code. */
static int add_rule(int ruleset_fd, const char *path, uint64_t access) {
int path_fd = open(path, O_PATH | O_CLOEXEC);
if (path_fd < 0) {
/* Fail closed on an unopenable grant root: silently narrowing the
* granted set would be safe, but running with a profile the caller did
* not get is not worth the ambiguity. */
fprintf(stderr, "landlock-run: cannot open rule path: %s: %s\n", path, strerror(errno));
return EXIT_LAUNCHER_FAILURE;
}
/* The kernel rejects directory-only accesses on a non-directory rule
* (EINVAL), so a file grant keeps only the file-compatible bits — how the
* `--rw /dev/null` grant works. Same clamp the Rust crate's
* path_beneath_rules helper applied. */
struct stat st;
if (fstat(path_fd, &st) == 0 && !S_ISDIR(st.st_mode)) {
access &= LL_FS_EXECUTE | LL_FS_WRITE_FILE | LL_FS_READ_FILE | LL_FS_TRUNCATE | LL_FS_IOCTL_DEV;
}
struct landlock_path_beneath_attr attr = { .allowed_access = access, .parent_fd = path_fd };
if (syscall(__NR_landlock_add_rule, ruleset_fd, LANDLOCK_RULE_PATH_BENEATH, &attr, 0) != 0) {
int saved = errno;
close(path_fd);
return fail("landlock ruleset error", strerror(saved));
}
close(path_fd);
return 0;
}
/*
* Install the ruleset on the current thread, negotiating the kernel's ABI
* down from MAX_ABI. `--ro` paths get the read side of the vocabulary (read
* file/dir + execute — the wrapped `bash` and everything it spawns must
* remain executable); `--rw` paths get every filesystem access the
* negotiated ABI can grant. Sets `no_new_privs` first (mandatory for an
* unprivileged restrict, and it neutralizes setuid/setgid escalation inside
* the sandbox). On success `*partial` reports whether the kernel governs
* only a subset of MAX_ABI's accesses. Returns 0, else the exit code.
*/
static int restrict_self(const struct cli *cli, int *partial) {
long abi = syscall(__NR_landlock_create_ruleset, NULL, 0, LANDLOCK_CREATE_RULESET_VERSION);
if (abi < 0) {
/* ENOSYS: kernel built without Landlock; EOPNOTSUPP: built but disabled.
* Either way: not enforceable — fail CLOSED, never exec unconfined. */
return fail(NOT_ENFORCED_MESSAGE, NULL);
}
*partial = abi < MAX_ABI;
uint64_t handled = fs_mask_for_abi(abi < MAX_ABI ? abi : MAX_ABI);
struct landlock_ruleset_attr attr = { .handled_access_fs = handled };
int ruleset_fd = (int)syscall(__NR_landlock_create_ruleset, &attr, sizeof attr, 0);
if (ruleset_fd < 0) return fail("landlock ruleset error", strerror(errno));
const uint64_t read_side = LL_FS_EXECUTE | LL_FS_READ_FILE | LL_FS_READ_DIR;
for (size_t i = 0; i < cli->ro_count; i++) {
int code = add_rule(ruleset_fd, cli->ro[i], read_side & handled);
if (code != 0) return code;
}
for (size_t i = 0; i < cli->rw_count; i++) {
int code = add_rule(ruleset_fd, cli->rw[i], handled);
if (code != 0) return code;
}
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0) {
return fail("landlock ruleset error", strerror(errno));
}
if (syscall(__NR_landlock_restrict_self, ruleset_fd, 0) != 0) {
return fail("landlock ruleset error", strerror(errno));
}
close(ruleset_fd);
return 0;
}
int main(int argc, char **argv) {
struct cli cli = { 0 };
int code = parse(argc, argv, &cli);
if (code != 0) return code;
if (cli.probe) {
/* The functional probe: build and enforce a maximal ruleset in THIS
* short-lived process (the probe run exits right after). `--version`
* style checks would miss a kernel that has the syscalls but refuses
* enforcement; actually restricting is the only honest signal. The one
* report line is part of the launcher CLI contract — the executor reads
* enforcement completeness from it. */
static const char *probe_root = "/";
struct cli probe = { .ro = &probe_root, .ro_count = 1 };
int partial = 0;
code = restrict_self(&probe, &partial);
if (code != 0) return code;
printf("landlock: %s\n", partial ? "partially enforced (older ABI)" : "fully enforced");
return 0;
}
int partial = 0;
code = restrict_self(&cli, &partial);
if (code != 0) return code;
if (partial) {
/* Older ABI: some handled accesses are not governed (e.g. truncate
* before ABI 3). Still confined for everything the kernel supports —
* report, do not refuse. */
fprintf(stderr, "landlock-run: partial enforcement (older Landlock ABI)\n");
}
execvp(cli.command[0], cli.command);
/* exec only returns on failure. */
return fail("exec failed", strerror(errno));
}

View File

@@ -0,0 +1,11 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"declaration": true,
"outDir": "lib",
"rootDir": "src",
"tsBuildInfoFile": "lib/.tsbuildinfo"
},
"include": ["src/**/*.ts"]
}

View File

@@ -0,0 +1,28 @@
BSD 3-Clause License
Copyright (c) 2026, node-addon-landlock-run contributors
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,7 @@
# node-addon-landlock-run-linux-arm64
Prebuilt `bin/landlock-run` Landlock launcher for linux-arm64 — a static musl binary compiled natively (no cross toolchain) from the C source shipped in [`node-addon-landlock-run`](https://www.npmjs.com/package/node-addon-landlock-run). npm's `os`/`cpu` fields select this package at install time; the entry package resolves it to a file path — it ships no JavaScript and is never imported.
The binary is git-ignored and rides the npm tarball via the `files` list; the `prepack` gate refuses to pack when it is missing or has the wrong ELF architecture, and the release pipeline byte-pins the packed binary against the CI build it came from. Static musl linking means one binary for glibc and musl distros alike — hence no libc suffix in the name.
Sibling: `node-addon-landlock-run-linux-x64`.

View File

@@ -0,0 +1,26 @@
{
"name": "node-addon-landlock-run-linux-arm64",
"version": "0.0.1",
"description": "Prebuilt landlock-run Landlock launcher binary for linux-arm64 (static musl) — resolved as a file path by node-addon-landlock-run, never imported",
"os": [
"linux"
],
"cpu": [
"arm64"
],
"files": [
"README.md",
"bin/",
"prebuilds.json"
],
"scripts": {
"prepack": "node ../../scripts/verify-launcher-binary.mjs"
},
"engines": {
"node": ">=20"
},
"license": "BSD-3-Clause",
"publishConfig": {
"access": "public"
}
}

View File

@@ -0,0 +1,10 @@
{
"platform": "linux-arm64",
"binaries": [
{
"tool": "landlock-run",
"kind": "static-musl",
"path": "bin/landlock-run"
}
]
}

View File

@@ -0,0 +1,28 @@
BSD 3-Clause License
Copyright (c) 2026, node-addon-landlock-run contributors
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,7 @@
# node-addon-landlock-run-linux-x64
Prebuilt `bin/landlock-run` Landlock launcher for linux-x64 — a static musl binary compiled natively (no cross toolchain) from the C source shipped in [`node-addon-landlock-run`](https://www.npmjs.com/package/node-addon-landlock-run). npm's `os`/`cpu` fields select this package at install time; the entry package resolves it to a file path — it ships no JavaScript and is never imported.
The binary is git-ignored and rides the npm tarball via the `files` list; the `prepack` gate refuses to pack when it is missing or has the wrong ELF architecture, and the release pipeline byte-pins the packed binary against the CI build it came from. Static musl linking means one binary for glibc and musl distros alike — hence no libc suffix in the name.
Sibling: `node-addon-landlock-run-linux-arm64`.

View File

@@ -0,0 +1,26 @@
{
"name": "node-addon-landlock-run-linux-x64",
"version": "0.0.1",
"description": "Prebuilt landlock-run Landlock launcher binary for linux-x64 (static musl) — resolved as a file path by node-addon-landlock-run, never imported",
"os": [
"linux"
],
"cpu": [
"x64"
],
"files": [
"README.md",
"bin/",
"prebuilds.json"
],
"scripts": {
"prepack": "node ../../scripts/verify-launcher-binary.mjs"
},
"engines": {
"node": ">=20"
},
"license": "BSD-3-Clause",
"publishConfig": {
"access": "public"
}
}

View File

@@ -0,0 +1,10 @@
{
"platform": "linux-x64",
"binaries": [
{
"tool": "landlock-run",
"kind": "static-musl",
"path": "bin/landlock-run"
}
]
}