feat(worker): judge versioned sealed runtime programs

This commit is contained in:
2026-10-09 20:15:17 +08:00
parent 2f1166954a
commit 802e019699
21 changed files with 2867 additions and 84 deletions
+181
View File
@@ -0,0 +1,181 @@
"""Offline GNU catalog from an explicitly pinned, verified public package closure.
No target executable, package hook, submitted source or network installer runs.
Root publication and real execution acceptance remain separate steps.
"""
import argparse
import hashlib
import json
import re
from pathlib import Path
def sha(path):
with path.open("rb") as source:
return hashlib.file_digest(source, "sha256").hexdigest()
def canonical(name):
return len(name) <= 4096 and all(
re.fullmatch(r"[A-Za-z0-9_.+\-]{1,255}", p) and p not in (".", "..")
for p in name.split("/")
)
def resolve_verified(root, records, name):
parts = name.split("/")
for _ in range(9):
changed = False
for i in range(len(parts)):
prefix = "/".join(parts[: i + 1])
record = records.get(prefix)
path = root / prefix
if record and record["kind"] == "symlink":
if not path.is_symlink() or str(path.readlink()) != record["target"]:
raise ValueError("GNU package link differs from verified manifest")
target = record["target"]
expanded = (
([] if target.startswith("/") else parts[:i])
+ target.split("/")
+ parts[i + 1 :]
)
parts = []
for p in expanded:
if p in ("", "."):
continue
if p == "..":
if not parts:
raise ValueError("GNU image-relative link escapes closure")
parts.pop()
else:
parts.append(p)
changed = True
break
if path.is_symlink():
raise ValueError("unverified GNU ancestor link")
if not changed:
relative = "/".join(parts)
record = records.get(relative)
if record is None or record["kind"] != "file":
raise ValueError("GNU link outside verified regular-file closure")
source = root / relative
source.resolve(strict=True).relative_to(root)
return source, record
raise ValueError("GNU link cycle or depth budget")
def build(args):
if sha(args.support_manifest) != args.support_manifest_sha256:
raise ValueError("verified GNU support manifest fingerprint differs")
manifest = json.loads(args.support_manifest.read_bytes())
packages = {p["name"]: p for p in manifest["packages"]}
expected = {
"gcc": (
"16.2.1+r23+gd564253eb6c8-1",
"ebac12ceef494c616a36fc6f0f792b365dc59b6ed46ca1a69f138aecc810b6ab",
),
"glibc": (
"2.44+r50+g1848099f063e-3",
"071d807f4d3bf6b921f86b9a91e83a47ecc026c5821634efa46b09d890e06785",
),
"binutils": ("2.47-2", "62efd213e87590f025cf861b646793d3cacb03e7e26187b73d33b00adaf7a977"),
}
for name, (version, digest) in expected.items():
if (packages[name]["version"], packages[name]["sha256"]) != (version, digest):
raise ValueError("GNU image requires the pinned compiler/libc/linker closure")
records = {f["path"]: f for f in manifest["files"]}
source_root = args.support_dir.resolve(strict=True)
if args.output.exists():
raise ValueError("refuse to replace an image")
args.output.mkdir(mode=0o700)
directories = {"dev", "proc", "tmp", "work", "usr", "lib64"}
files = []
def put(name, source, expected_file):
if not canonical(name) or expected_file["kind"] != "file":
raise ValueError("noncanonical verified GNU file")
if (
source.stat().st_size != expected_file["bytes"]
or sha(source) != expected_file["sha256"]
):
raise ValueError("GNU file differs from verified public package bytes")
if len(files) >= 4096 or sum(f["bytes"] for f in files) + source.stat().st_size > 1024**3:
raise ValueError("GNU image exceeds finite catalog budget")
target = args.output / name
target.parent.mkdir(parents=True, exist_ok=True)
# Copy to a fresh regular inode; never publish source links/hard links.
with source.open("rb") as reader, target.open("xb") as writer:
while data := reader.read(1024 * 1024):
writer.write(data)
executable = bool(source.stat().st_mode & 0o111)
target.chmod(0o555 if executable else 0o444)
if sha(target) != expected_file["sha256"]:
raise ValueError("GNU copy fingerprint differs")
files.append(
{
"path": name,
"bytes": target.stat().st_size,
"sha256": sha(target),
"executable": executable,
}
)
directories.update(p.as_posix() for p in Path(name).parents if p != Path("."))
for name, record in sorted(records.items()):
if not (
name.startswith(("usr/include/", "usr/lib/"))
or name in ("usr/bin/gcc", "usr/bin/g++", "usr/bin/as", "usr/bin/ld")
):
continue
if record["kind"] == "directory":
continue
source, real = resolve_verified(source_root, records, name)
put(name, source, real)
loader, loader_record = resolve_verified(source_root, records, "usr/lib/ld-linux-x86-64.so.2")
put("lib64/ld-linux-x86-64.so.2", loader, loader_record)
for name in directories:
(args.output / name).mkdir(parents=True, exist_ok=True)
catalog = dict(
format_version=2,
architecture="x86_64_v3",
image_kind="linux_gnu_cxx_x86_64_v1",
image_revision=1,
toolchain_id="gnu-cxx-v1",
runtime_version="16.2.1+r23+gd564253eb6c8",
directories=sorted(directories),
files=sorted(files, key=lambda f: f["path"]),
)
raw = (json.dumps(catalog, sort_keys=True, separators=(",", ":")) + "\n").encode()
if len(raw) > 1024 * 1024:
raise ValueError("GNU catalog transport budget")
(args.output / "manifest.json").write_bytes(raw)
(args.output / "manifest.json").chmod(0o444)
for path in sorted((p for p in args.output.rglob("*") if p.is_dir()), reverse=True):
path.chmod(0o555)
args.output.chmod(0o555)
print(
json.dumps(
dict(
image_digest=hashlib.sha256(raw).hexdigest(),
files=len(files),
bytes=sum(f["bytes"] for f in files),
support_manifest_sha256=args.support_manifest_sha256,
source_execution=False,
root_publication_and_VM_acceptance=False,
)
)
)
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--support-dir", required=True, type=Path)
parser.add_argument("--support-manifest", required=True, type=Path)
parser.add_argument("--support-manifest-sha256", required=True)
parser.add_argument("--output", required=True, type=Path)
build(parser.parse_args())
if __name__ == "__main__":
main()