Spaces:
Running
Running
fix: prevent direct AI approval inheritance
Browse files- src/lumi_eggcracker/supervisor.py +22 -5
- tests/test_supervisor.py +27 -0
src/lumi_eggcracker/supervisor.py
CHANGED
|
@@ -708,16 +708,25 @@ class Supervisor:
|
|
| 708 |
return value
|
| 709 |
|
| 710 |
def _authorizes_protected_scope(
|
| 711 |
-
self,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 712 |
) -> bool:
|
| 713 |
-
"""Authorize
|
| 714 |
|
| 715 |
A topology launcher commonly execs or forks a worker whose PID/start
|
| 716 |
time was not present at the pre-exec gate. The root-owned provenance
|
| 717 |
record and exact delegated cgroup are the approval closure for that
|
| 718 |
-
worker
|
| 719 |
-
|
|
|
|
|
|
|
|
|
|
| 720 |
"""
|
|
|
|
|
|
|
| 721 |
if provenance is None or snapshot.uid != self.policy["workload_uid"]:
|
| 722 |
return False
|
| 723 |
selected = f"0::{provenance['cgroup']}"
|
|
@@ -1703,6 +1712,12 @@ class Supervisor:
|
|
| 1703 |
"",
|
| 1704 |
)
|
| 1705 |
scope_provenance = provenance_by_cgroup.get(candidate_cgroup)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1706 |
authorized = (
|
| 1707 |
provenance is not None
|
| 1708 |
and launch_authorizes(
|
|
@@ -1714,7 +1729,9 @@ class Supervisor:
|
|
| 1714 |
provenance,
|
| 1715 |
)
|
| 1716 |
) or self._authorizes_protected_scope(
|
| 1717 |
-
candidate.snapshot,
|
|
|
|
|
|
|
| 1718 |
)
|
| 1719 |
# An active local lockdown turns an exact protected
|
| 1720 |
# recurrence into an enforcement candidate even when a stale
|
|
|
|
| 708 |
return value
|
| 709 |
|
| 710 |
def _authorizes_protected_scope(
|
| 711 |
+
self,
|
| 712 |
+
snapshot: ProcessSnapshot,
|
| 713 |
+
provenance: dict[str, Any] | None,
|
| 714 |
+
*,
|
| 715 |
+
profile: str | None = None,
|
| 716 |
) -> bool:
|
| 717 |
+
"""Authorize a qualified topology worker in one approved cgroup.
|
| 718 |
|
| 719 |
A topology launcher commonly execs or forks a worker whose PID/start
|
| 720 |
time was not present at the pre-exec gate. The root-owned provenance
|
| 721 |
record and exact delegated cgroup are the approval closure for that
|
| 722 |
+
worker. Direct profiles deliberately do not receive this cgroup-wide
|
| 723 |
+
closure: an approved launcher must not shelter a separate direct AI
|
| 724 |
+
process. UID and cgroup identity remain mandatory, so the topology
|
| 725 |
+
exception does not broaden approval to a user, directory, process name
|
| 726 |
+
or wildcard.
|
| 727 |
"""
|
| 728 |
+
if profile not in {"content.gguf-ollama", "content.safetensors-vllm"}:
|
| 729 |
+
return False
|
| 730 |
if provenance is None or snapshot.uid != self.policy["workload_uid"]:
|
| 731 |
return False
|
| 732 |
selected = f"0::{provenance['cgroup']}"
|
|
|
|
| 1712 |
"",
|
| 1713 |
)
|
| 1714 |
scope_provenance = provenance_by_cgroup.get(candidate_cgroup)
|
| 1715 |
+
# A root-approved launch identity authorizes only that exact
|
| 1716 |
+
# process. Cgroup-wide approval is reserved for detector
|
| 1717 |
+
# profiles whose contract explicitly includes a qualified
|
| 1718 |
+
# launcher/worker topology. A direct profile (for example
|
| 1719 |
+
# GGUF+llama) must not let an approved Python launcher hide a
|
| 1720 |
+
# separate AI process in the same owned cgroup.
|
| 1721 |
authorized = (
|
| 1722 |
provenance is not None
|
| 1723 |
and launch_authorizes(
|
|
|
|
| 1729 |
provenance,
|
| 1730 |
)
|
| 1731 |
) or self._authorizes_protected_scope(
|
| 1732 |
+
candidate.snapshot,
|
| 1733 |
+
scope_provenance,
|
| 1734 |
+
profile=detected.profile,
|
| 1735 |
)
|
| 1736 |
# An active local lockdown turns an exact protected
|
| 1737 |
# recurrence into an enforcement candidate even when a stale
|
tests/test_supervisor.py
CHANGED
|
@@ -109,6 +109,33 @@ class SupervisorTests(unittest.TestCase):
|
|
| 109 |
self.assertTrue(supervisor._managed(snapshot))
|
| 110 |
self.assertFalse(supervisor._discovery_excluded(snapshot))
|
| 111 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
def test_group_refresh_replaces_preexec_gate_snapshot_without_losing_evidence(self) -> None:
|
| 113 |
identity = ProcessIdentity(10, 100)
|
| 114 |
stale = ProcessSnapshot(
|
|
|
|
| 109 |
self.assertTrue(supervisor._managed(snapshot))
|
| 110 |
self.assertFalse(supervisor._discovery_excluded(snapshot))
|
| 111 |
|
| 112 |
+
def test_approved_cgroup_closure_is_limited_to_topology_profiles(self) -> None:
|
| 113 |
+
supervisor = self._instance()
|
| 114 |
+
cgroup = "/system.slice/lumi-eggcracker-workload-" + "a" * 24 + ".service"
|
| 115 |
+
supervisor.active_cgroups = {cgroup}
|
| 116 |
+
snapshot = ProcessSnapshot(
|
| 117 |
+
ProcessIdentity(10, 100),
|
| 118 |
+
2001,
|
| 119 |
+
"/usr/bin/python3",
|
| 120 |
+
"python3",
|
| 121 |
+
("python3",),
|
| 122 |
+
("0::" + cgroup,),
|
| 123 |
+
(),
|
| 124 |
+
(),
|
| 125 |
+
)
|
| 126 |
+
provenance = {"cgroup": cgroup}
|
| 127 |
+
|
| 128 |
+
self.assertFalse(
|
| 129 |
+
supervisor._authorizes_protected_scope(
|
| 130 |
+
snapshot, provenance, profile="content.gguf-llama"
|
| 131 |
+
)
|
| 132 |
+
)
|
| 133 |
+
self.assertTrue(
|
| 134 |
+
supervisor._authorizes_protected_scope(
|
| 135 |
+
snapshot, provenance, profile="content.gguf-ollama"
|
| 136 |
+
)
|
| 137 |
+
)
|
| 138 |
+
|
| 139 |
def test_group_refresh_replaces_preexec_gate_snapshot_without_losing_evidence(self) -> None:
|
| 140 |
identity = ProcessIdentity(10, 100)
|
| 141 |
stale = ProcessSnapshot(
|