refactor: run cores and builds in a sandbox

core_probe starts its worker with only the --env values, the worker clears its own environment before loading the core, and a working bubblewrap runs it with a read-only tree, no network and the user's credentials masked. The record names the isolation used. A timeout kills the whole process group. campaign.py starts core_probe, git, make and romfetch with the allowlist, make inside the same sandbox. --record refuses a folder that is not a checkout root.
This commit is contained in:
Abdessamad Derraz committed 2026-10-27 11:48:22 +01:00
1 parent e5cc1b5255
commit 95ca227bce
5 files changed
+316 -35

No files matched your search

+84 -5
View File
@@ -11,6 +11,7 @@ import argparse
import contextlib
import io
import json
import os
import shutil
import struct
import subprocess
@@ -99,6 +100,13 @@ def mednafen_state(sections: dict[str, dict[str, bytes]]) -> bytes:
return b"MDFNSVST".ljust(32, b"\0") + body
def checkout(path: Path) -> Path:
"""A folder made the root of a git checkout, as --record requires."""
path.mkdir(parents=True, exist_ok=True)
subprocess.run(["git", "init", "-q", str(path)], check=True)
return path
class ParsingTests(unittest.TestCase):
def test_assignment(self) -> None:
self.assertEqual(core_probe.parse_assignment("a=b=c", "--option"), ("a", "b=c"))
@@ -244,7 +252,7 @@ class FakeCoreTests(unittest.TestCase):
return code, json.loads(out.getvalue()) if code == 0 else None
def test_run_record(self) -> None:
record_dir = self.tmp / "records"
record_dir = checkout(self.tmp / "records")
code, record = self.probe(["check", "--core", str(self.core), "--frames", "3",
"--vary", f"card.bin={self.cards[0]}", "--vary", f"card.bin={self.cards[1]}",
"--vary", f"card.bin={self.cards[2]}", "--vary", "card.bin=",
@@ -268,7 +276,8 @@ class FakeCoreTests(unittest.TestCase):
self.assertEqual(first["frames"], 3)
self.assertEqual(record["emulator"], "fake")
self.assertEqual([p.relative_to(record_dir).as_posix()
for p in record_dir.rglob("*") if p.is_file()], ["measurements/fake.jsonl"])
for p in record_dir.rglob("*") if p.is_file() and ".git" not in p.parts],
["measurements/fake.jsonl"])
line = json.loads((record_dir / "measurements" / "fake.jsonl").read_text())
self.assertEqual(measurement_records.check_line(line), [])
# The line is the record the run printed, id included.
@@ -281,7 +290,7 @@ class FakeCoreTests(unittest.TestCase):
self.assertEqual(list(Draft202012Validator(schema).iter_errors(line)), [])
def test_second_run_is_appended_beside_the_first(self) -> None:
record_dir = self.tmp / "appended"
record_dir = checkout(self.tmp / "appended")
argv = ["run", "--core", str(self.core), "--frames", "1", "--no-trace", "--max-load", "1000",
"--record", str(record_dir), "--subject", "smoke"]
self.assertEqual(self.probe(argv)[0], 0)
@@ -313,10 +322,80 @@ class FakeCoreTests(unittest.TestCase):
self.assertEqual(record["flags"], [])
def test_busy_machine_refused(self) -> None:
refused = checkout(self.tmp / "refused")
code, _ = self.probe(["run", "--core", str(self.core), "--frames", "1", "--record",
str(self.tmp / "refused"), "--max-load", "-1"])
str(refused), "--max-load", "-1"])
self.assertEqual(code, 3)
self.assertFalse((self.tmp / "refused").exists())
self.assertFalse((refused / "measurements").exists())
def test_record_names_a_checkout_root(self) -> None:
# --record measurements wrote measurements/measurements/<emulator>.jsonl.
root = checkout(self.tmp / "rooted")
(root / "measurements").mkdir()
for wrong in (root / "measurements", self.tmp / "plain"):
wrong.mkdir(exist_ok=True)
err = io.StringIO()
with contextlib.redirect_stdout(io.StringIO()), contextlib.redirect_stderr(err):
code = core_probe.main(["run", "--core", str(self.core), "--frames", "1", "--no-trace",
"--record", str(wrong), "--work-dir", str(self.tmp / "work")])
self.assertEqual(code, 2)
self.assertIn("not a git checkout root", err.getvalue())
self.assertIn("--record .", err.getvalue())
self.assertFalse((wrong / "measurements" / "fake.jsonl").exists())
self.assertIsNone(core_probe.not_a_checkout_root(root))
self.assertIsNone(core_probe.not_a_checkout_root(REPO_ROOT))
def test_the_core_sees_only_the_env_it_was_given(self) -> None:
os.environ["CORE_PROBE_TEST_TAG"] = "from-the-host"
os.environ["GITHUB_TOKEN"] = "secret"
try:
code, record = self.probe(["run", "--core", str(self.core), "--frames", "1",
"--no-trace"])
finally:
del os.environ["CORE_PROBE_TEST_TAG"]
del os.environ["GITHUB_TOKEN"]
self.assertEqual(code, 0)
rep = record["variants"][0]["repetitions"][0]
self.assertEqual(rep["logs"][1]["text"], "tag unset")
self.assertTrue(rep["isolation"] == "bwrap" or rep["isolation"].startswith("environment only"))
class Sandbox(unittest.TestCase):
"""What a core run under bubblewrap can reach."""
def setUp(self) -> None:
if not core_probe.sandbox_argv([])[0]:
self.skipTest("no working bwrap on this host")
self.tmp = Path(tempfile.mkdtemp(dir=REPO_ROOT / "tmp" / "tests"))
self.home = self.tmp / "home"
for secret in (".config/gh/hosts.yml", ".ssh/id_ed25519"):
(self.home / secret).parent.mkdir(parents=True)
(self.home / secret).write_text("secret")
(self.home / ".git-credentials").write_text("https://user:secret@github.com")
self.out = self.tmp / "out"
self.elsewhere = self.tmp / "elsewhere"
self.elsewhere.mkdir()
def tearDown(self) -> None:
shutil.rmtree(self.tmp, ignore_errors=True)
def test_credentials_masked_tree_read_only_network_gone(self) -> None:
old_home = os.environ["HOME"]
os.environ["HOME"] = str(self.home)
try:
prefix, isolation = core_probe.sandbox_argv([self.out])
finally:
os.environ["HOME"] = old_home
self.assertEqual(isolation, "bwrap")
script = (f'cat {self.home}/.config/gh/hosts.yml {self.home}/.ssh/id_ed25519 '
f'{self.home}/.git-credentials 2>/dev/null; echo ok > {self.out}/w; '
f'echo no > {self.elsewhere}/w 2>/dev/null; tail -n +3 /proc/net/dev | cut -d: -f1')
proc = subprocess.run(prefix + ["/bin/sh", "-c", script], capture_output=True, text=True,
check=False, env={})
self.assertNotIn("secret", proc.stdout)
self.assertEqual((self.out / "w").read_text(), "ok\n")
self.assertFalse((self.elsewhere / "w").exists())
self.assertEqual(proc.stdout.split(), ["lo"])
if __name__ == "__main__":