diff --git a/PUBLIC_SOURCE_EXPORT.md b/PUBLIC_SOURCE_EXPORT.md index 53c2914..41b1de2 100644 --- a/PUBLIC_SOURCE_EXPORT.md +++ b/PUBLIC_SOURCE_EXPORT.md @@ -1,3 +1,3 @@ # Public source export -This source snapshot was generated from the private canonical repository at revision `07800de5cf3d27b80dbdebc13025bddeb58a07e3`. It contains no private Git history or operational evidence. Changes are published from the canonical repository. +This source snapshot was generated from the private canonical repository at revision `2ff7105f7d3066d6c38825540340505233836a91`. It contains no private Git history or operational evidence. Changes are published from the canonical repository. diff --git a/PUBLIC_SOURCE_MANIFEST.json b/PUBLIC_SOURCE_MANIFEST.json index 49a5d2e..d8c9213 100644 --- a/PUBLIC_SOURCE_MANIFEST.json +++ b/PUBLIC_SOURCE_MANIFEST.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "sourceRevision": "07800de5cf3d27b80dbdebc13025bddeb58a07e3", + "sourceRevision": "2ff7105f7d3066d6c38825540340505233836a91", "files": [ { "path": ".dockerignore", @@ -949,8 +949,8 @@ }, { "path": "backend/tests/test_ci_job_docker.py", - "sha256": "1ca4e7c38a13a88840d412f203fe312a762fc8b2499bf3e3f004fe1fd3e78ea0", - "bytes": 30346 + "sha256": "3078c95e688699818a986448b761c3e967918b537e6e50673ad2df3bfd6d19a6", + "bytes": 31768 }, { "path": "backend/tests/test_container_restart.py", @@ -1659,8 +1659,8 @@ }, { "path": "backend/tests/test_runner_fleet_specialize.py", - "sha256": "4df95dc997d0ef9918209b233a470d70eadcb0ca62046be25a5bb399cbce8496", - "bytes": 200956 + "sha256": "6b4da6ed984a8c6741b1232f54f977521631ab6a3cc030284c1ea5c42ff99c47", + "bytes": 201815 }, { "path": "backend/tests/test_runner_fleet_v2_execution_surface.py", diff --git a/backend/tests/test_ci_job_docker.py b/backend/tests/test_ci_job_docker.py index f122ea3..5526df3 100644 --- a/backend/tests/test_ci_job_docker.py +++ b/backend/tests/test_ci_job_docker.py @@ -566,7 +566,7 @@ def test_nested_build_subordinate_ranges_cover_mapped_nonroot_ids_only(): @pytest.mark.skipif(os.name == "nt", reason="rootless Docker wrapper is Linux-only") -@pytest.mark.parametrize("bad", ["", "0 0 4294967295\n", "0 1000 1\n1 100000 65535\n", +@pytest.mark.parametrize("bad", ["", "0 0 4294967294\n", "0 1000 1\n1 100000 65535\n", "0 1000 1\n100000 100000 65536\n", "SECRET-CANARY\n", "0 1000 1\n1 100000 65536\n2 2 1\n", "x" * 257]) @pytest.mark.parametrize("kind", ["uid", "gid"]) @@ -589,14 +589,41 @@ def test_private_engine_refuses_wrong_parent_mapping_before_runtime_effects(tmp_ @pytest.mark.skipif(os.name == "nt", reason="rootless Docker wrapper is Linux-only") -def test_private_engine_accepts_own_supported_parent_maps_and_refuses_missing_map(tmp_path, monkeypatch): +@pytest.mark.parametrize("mapping", [" 0 1000 1\n 1 100000 65536\n", + " 0 0 4294967295\n"]) +def test_private_engine_accepts_own_supported_parent_maps_and_refuses_missing_map(tmp_path, monkeypatch, mapping): sys.path.insert(0, str(ROOT / "ops/runner-task-images/build")) import job_docker for kind in ("uid", "gid"): path = tmp_path / kind - path.write_text(" 0 1000 1\n 1 100000 65536\n") + path.write_text(mapping) monkeypatch.setattr(job_docker, kind.upper() + "_MAP_PATH", path) job_docker._validate_parent_id_maps() job_docker.GID_MAP_PATH.unlink() with pytest.raises(job_docker.WrapperError, match="mapping unavailable"): job_docker._validate_parent_id_maps() + + +@pytest.mark.skipif(os.name == "nt", reason="rootless Docker wrapper is Linux-only") +@pytest.mark.parametrize("rootful_kind", ["uid", "gid"]) +def test_private_engine_refuses_mixed_supported_parent_maps_before_effects(tmp_path, monkeypatch, rootful_kind): + sys.path.insert(0, str(ROOT / "ops/runner-task-images/build")) + import job_docker + for kind in ("uid", "gid"): + path = tmp_path / kind + path.write_text("0 0 4294967295\n" if kind == rootful_kind else "0 1000 1\n1 100000 65536\n") + monkeypatch.setattr(job_docker, kind.upper() + "_MAP_PATH", path) + effects = [] + monkeypatch.setattr(job_docker, "_ensure_runtime", lambda: effects.append("runtime")) + monkeypatch.setattr(job_docker, "_launch_daemon", lambda: effects.append("daemon")) + with pytest.raises(job_docker.WrapperError, match="mapping invalid"): + job_docker._ensure_daemon() + assert effects == [] + + +@pytest.mark.skipif(os.name == "nt", reason="rootless Docker wrapper is Linux-only") +def test_private_engine_accepts_actual_supported_runtime_parent_namespace(): + sys.path.insert(0, str(ROOT / "ops/runner-task-images/build")) + import job_docker + # Real own namespace from the Linux test container; no host /proc or effects. + job_docker._validate_parent_id_maps() diff --git a/backend/tests/test_runner_fleet_specialize.py b/backend/tests/test_runner_fleet_specialize.py index 0bfe562..bc40d3a 100644 --- a/backend/tests/test_runner_fleet_specialize.py +++ b/backend/tests/test_runner_fleet_specialize.py @@ -3248,6 +3248,22 @@ def _install_build_probe_cleanup_fakes(specialize, monkeypatch, record, item, id return removed +@pytest.mark.parametrize("running", [True, False]) +def test_build_probe_running_gate_distinguishes_owned_exit_and_preserves_identity(specialize, running): + record = _build_probe_record(specialize) + item, environment = _build_probe_inspect(specialize, record) + item["State"]["Running"] = running + item["State"]["Pid"] = 123 if running else 0 + if running: + specialize._require_running_build_probe(item, record, environment) + else: + with pytest.raises(specialize.RunnerFleetSpecializeError, match="build_probe_exited_early"): + specialize._require_running_build_probe(item, record, environment) + item["HostConfig"]["Privileged"] = True + with pytest.raises(specialize.RunnerFleetSpecializeError, match="build_probe_container_untrusted"): + specialize._require_running_build_probe(item, record, environment) + + def test_build_probe_recovery_cleans_only_intent_owned_container_after_create_crash( specialize, monkeypatch,