ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
hil_convergence_safety_image_harness_policy.py
Go to the documentation of this file.
1# SPDX-License-Identifier: MIT
2# Copyright (c) 2026 Brighton Sikarskie
3"""Cross-language source policy for the devcontainer image selftest harness."""
4
5from __future__ import annotations
6
7import hil_convergence_safety_image_process_analysis as image_process_analysis
8
9_IMAGE_PROCESS_ANALYSIS_MODULE = "hil_convergence_safety_image_process_analysis"
10_IMAGE_PROCESS_ANALYSIS_IMPORT = (
11 "import " + _IMAGE_PROCESS_ANALYSIS_MODULE + " as image_process_analysis"
12)
13ModuleSpec = tuple[str, str, tuple[str, ...]]
14
15
16def _exact_shell_token_errors(source: str, label: str, tokens: tuple[str, ...]) -> list[str]:
17 """Require each security-sensitive shell token exactly once."""
18 return [
19 f"{label}: required process-authority token is not unique: {token}"
20 for token in tokens
21 if source.count(token) != 1
22 ]
23
24
25def _image_lifecycle_process_errors(lifecycle: str, bound_exit: str) -> list[str]:
26 """Require exact lifecycle allocation and child-process authorities."""
27 return _exact_shell_token_errors(
28 f"{lifecycle}\n{bound_exit}",
29 "devcontainer image lifecycle selftest",
30 (
31 "live_child_jobspec() {",
32 "done < <(jobs -r -l)",
33 'builtin kill -"$signal" "$child"',
34 "selftest_suite_root_is_safe() {",
35 "selftest_suite_anchor_is_safe() {",
36 "selftest_suite_path_is_safe() {",
37 "configure_selftest_suite_authority() {",
38 "configure_bound_exit_nested_suite() {",
39 "publish_bound_exit_nested_root() {",
40 "establish_selftest_suite_root() {",
41 "set_selftest_shell_identity() {",
42 'local destination="$1" value="$$:${BASH_SUBSHELL:-0}"',
43 "SELFTEST_DEADLINE_STEPS=200",
44 ': "$SELFTEST_DEADLINE_STEPS"',
45 "od -An -N16 -tx1 /dev/urandom",
46 'if (umask 077 && mkdir -m 0700 -- "$candidate"); then',
47 '"$suffix" =~ ^[0-9a-f]{32}$ && ! -L "$canonical"',
48 '"$(file_identity "$anchor")" == "$SELFTEST_SUITE_ANCHOR_IDENTITY"',
49 '"$SELFTEST_SUITE_ROOT_OWNER_UID" == "$SELFTEST_SUITE_ANCHOR_OWNER_UID"',
50 "run_bound_exit_supervisor() {",
51 'RA8_SELFTEST_BOUND_ENTRY="$1"',
52 '"${BASH_SOURCE[1]:-missing}" -ef "$SELFTEST_HELPER_PARENT"',
53 '"${DEVCONTAINER_SELFTEST_PARENT:-}" == '
54 '"$SELFTEST_HELPER_PARENT_DIR/devcontainer_image.sh"',
55 "selftest_descriptor_bound_entry() {",
56 'RA8_SELFTEST_BOUND_ENTRY="$wrong_entry"',
57 'RA8_SELFTEST_BOUND_ENTRY="$SCRIPT_DIR/devcontainer_image.sh"',
58 'select_selftest_group_id "$tmp" "$rejected" >/dev/null 2>&1 && return 1\n'
59 " done\n return 0",
60 "write_supervisor_stall_fixture() {",
61 ' "exec -a \\"\\$0\\" /bin/sleep 30" >"$destination") || return 1',
62 "selftest_bound_exit_supervisor_failures() {",
63 'run_bound_exit_supervisor --selftest-parent-death "$stall_entry" "$tmp"',
64 'run_bound_exit_supervisor --selftest-watchdog-expiry "$stall_entry" "$tmp"',
65 'run_bound_exit_supervisor --selftest-closed-death-fd "$stall_entry" "$tmp"',
66 'run_bound_exit_supervisor --selftest-closed-entry-fd "$stall_entry" "$tmp"',
67 'run_bound_exit_supervisor --selftest-hardlink-bound "$stall_entry" "$tmp"',
68 'RA8_SELFTEST_NESTED_PARENT_IDENTITY="$SELFTEST_TMP_IDENTITY"',
69 'RA8_SELFTEST_NESTED_ROOT_RECEIPT="$nested_receipt"',
70 'run_bound_exit_supervisor "$stall_entry" "$bound" "$outer"',
71 'run_bound_exit_supervisor --selftest-missing-entry "$tmp"',
72 'run_bound_exit_supervisor --selftest-entry-binding "$tmp"',
73 ),
74 )
75
76
77def _image_cases_process_errors(cases: str) -> list[str]:
78 """Require exact case-controller authorities."""
79 errors = _exact_shell_token_errors(
80 cases,
81 "devcontainer image cases selftest",
82 (
83 "configure_bound_exit_nested_suite || die",
84 "publish_bound_exit_nested_root || die",
85 'selftest_pre_isolation_exit_refusal "$tmp" ||',
86 'signal_owned_live_child KILL "$child" ||',
87 "stale allocation child PID retained signal authority",
88 'establish_selftest_suite_root || die "selftest: could not bind its suite root"',
89 'clear_selftest_suite_root || die "selftest: suite-root cleanup did not complete"',
90 '--selftest-allocation-checkpoint-child "$phase" "$receipt"',
91 '"${BASH_SOURCE[1]:-missing}" -ef "$SELFTEST_CASES_PARENT"',
92 '"${DEVCONTAINER_SELFTEST_PARENT:-}" == '
93 '"$SELFTEST_CASES_PARENT_DIR/devcontainer_image.sh"',
94 "selftest_temp_root_is_safe() {",
95 '"$SELFTEST_TMP_ROOT" == "$(cd -P /tmp && pwd)" &&',
96 '"$(file_special_mode "$SELFTEST_TMP_ROOT")" == "1777" ]]',
97 '"$SELFTEST_TMP_ROOT" == "$SELFTEST_SUITE_ROOT" &&',
98 (
99 '"$SELFTEST_TMP_ROOT_IDENTITY" == "$SELFTEST_SUITE_ROOT_IDENTITY" ]] &&\n'
100 " selftest_suite_root_is_safe"
101 ),
102 'selftest_temp_root_is_safe || die "selftest: allocation parent authority is unsafe"',
103 'selftest_descriptor_bound_entry "$tmp" ||',
104 'selftest_controller_persisted_ps_failure "$tmp"',
105 ),
106 )
107 errors += _exact_shell_token_errors(
108 cases, "devcontainer image cases selftest", ('selftest_ps_failure_cleanup "$tmp"',)
109 )
110 return errors
111
112
113def _image_signal_process_errors(signal_source: str) -> list[str]:
114 """Require exact isolated signal-controller authorities."""
115 return _exact_shell_token_errors(
116 signal_source,
117 "devcontainer image signal selftest",
118 (
119 'local launcher_mode="${5:-}" controller_pid pending '
120 'ready="$3/controller-launcher.ready"',
121 '--selftest-case-signal-child "$signal" "$tmp" "$SELFTEST_TMP_IDENTITY"',
122 'signal_owned_live_child TERM "$controller_pid" || controller_bound_spawn_signal 1',
123 "selftest_pre_isolation_exit_refusal() {",
124 '! signal_owned_live_child TERM "$child" || controller_bound_spawn_signal 1',
125 "signal_owned_controller_group() {",
126 'controller_group_signal_is_authorized "$controller" || return 1',
127 'builtin kill -"$signal" -- "-$controller"',
128 'signal_owned_controller_group "$signal" "$controller" ||',
129 'signal_owned_controller_group TERM "$controller" ||',
130 '"${BASH_SOURCE[1]:-missing}" -ef "$SELFTEST_SIGNAL_PARENT"',
131 '"${DEVCONTAINER_SELFTEST_PARENT:-}" == '
132 '"$SELFTEST_SIGNAL_PARENT_DIR/devcontainer_image.sh"',
133 'kill -KILL -- "-$controller" 2>/dev/null || bounded_group_gone "$controller"',
134 ),
135 )
136
137
138def _image_lock_process_errors(
139 lifecycle: str, cases: str, signal_source: str, lock: str
140) -> list[str]:
141 """Reject unsafe lock-helper PID and portability fallbacks."""
142 errors = _exact_shell_token_errors(
143 lock,
144 "devcontainer image-lock selftest",
145 (
146 "worker_group_signal_is_authorized() {",
147 "image_lock_ps_group_snapshot() {",
148 'signal_owned_controller_group TERM "$controller"',
149 "SELFTEST_CONTROLLER_CLEANUP_STEPS=1600",
150 'wait_for_worker_ack "$case_dir" "$$" || exit 124',
151 'if wait "$SELFTEST_BOUND_DIRECT_CHILD"; then child_status=0; else child_status=$?; fi',
152 "rebound numeric process group gained signal authority",
153 "pre-ready-hang | signal-controller | post-ready-build-hang) trap '' HUP INT TERM ;;",
154 "repeated ps failure left a signal-ignoring descendant",
155 '"${BASH_SOURCE[1]:-missing}" -ef "$SELFTEST_LOCK_HELPER_PARENT"',
156 '"${DEVCONTAINER_SELFTEST_PARENT:-}" == '
157 '"$SELFTEST_LOCK_HELPER_PARENT_DIR/devcontainer_image.sh"',
158 ),
159 )
160 forbidden = (
161 'kill -TERM "$controller"',
162 'kill -KILL "$controller"',
163 'signal_owned_live_child KILL "$controller"',
164 'signal_owned_live_child TERM "$controller"',
165 'kill -TERM "$SELFTEST_WORKER_PID"',
166 )
167 if any(token in lock for token in forbidden):
168 errors.append("devcontainer image-lock selftest: bare PID signal fallback returned")
169 if 'mktemp -d "$SELFTEST_TMP_ROOT/' in lifecycle:
170 errors.append("devcontainer image lifecycle selftest: allocation-before-binding returned")
171 if any("BASHPID" in source for source in (lifecycle, cases, signal_source, lock)):
172 errors.append("devcontainer image selftest: macOS Bash 3.2 BASHPID dependency returned")
173 return errors
174
175
176def _image_supervisor_token_errors(
177 supervisor: str, cases_source: str, process_source: str
178) -> list[str]:
179 """Delegate Python process-authority checking to its focused module."""
180 return image_process_analysis.supervisor_errors(supervisor, cases_source, process_source)
181
182
183def _semantic_aggregator_errors(source: str) -> list[str]:
184 """Require every split runtime selftest to remain imported and dispatched."""
185 return _exact_shell_token_errors(
186 source,
187 "hil convergence semantic selftest",
188 (
189 "import hil_convergence_safety_process_mutations as process_mutations",
190 _IMAGE_PROCESS_ANALYSIS_IMPORT,
191 "import hil_convergence_safety_raw_digest_runtime as raw_digest_runtime",
192 "import hil_convergence_safety_runtime_cleanup as runtime_cleanup",
193 "import hil_convergence_safety_runtime_escape as runtime_escape",
194 "import hil_convergence_safety_runtime_mutations as runtime_mutations",
195 "process_mutations.process_authority_mutations()",
196 "image_process_analysis.semantic_process_findings(label)",
197 "raw_digest_runtime.cases(inputs)",
198 "runtime_cleanup.cases(inputs)",
199 "runtime_escape.cases(inputs)",
200 "runtime_mutations.runtime_cases(inputs)",
201 ),
202 )
203
204
205def _runtime_module_specs(inputs: dict[str, str]) -> tuple[ModuleSpec, ...]:
206 """Return runtime cleanup, loader, mutation, and escape bindings."""
207 return (
208 (
209 "runtime cleanup",
210 inputs["runtime_cleanup"],
211 (
212 "import hil_convergence_safety_runtime_loader as runtime_loader",
213 "runtime_loader.cases(inputs)",
214 ),
215 ),
216 (
217 "runtime loader",
218 inputs["runtime_loader"],
219 (
220 "import hil_convergence_safety_runtime_loader_harness as loader_harness",
221 "loader_harness.run(",
222 ),
223 ),
224 (
225 "runtime mutations",
226 inputs["runtime_mutations"],
227 (
228 "import hil_convergence_safety_runtime_launcher as runtime_launcher",
229 "import hil_convergence_safety_runtime_sources as runtime_sources",
230 "import hil_convergence_safety_runtime_root_swap as runtime_root_swap",
231 "_write_sources = runtime_sources.publish",
232 "runtime_launcher.launch(",
233 ),
234 ),
235 (
236 "runtime escape",
237 inputs["runtime_escape"],
238 ("from hil_convergence_safety_runtime_mutations import (",),
239 ),
240 )
241
242
243def _image_module_specs(inputs: dict[str, str]) -> tuple[ModuleSpec, ...]:
244 """Return image analysis, harness, and mutation-catalog bindings."""
245 return (
246 (
247 "image process analysis",
248 inputs["image_process_analysis"],
249 (
250 "import hil_convergence_safety_image_process_policy as catalog",
251 "import hil_convergence_safety_image_subreaper_policy as subreaper_policy",
252 "CROSS_LANGUAGE_SCOPED_TOKENS = catalog.CROSS_LANGUAGE_SCOPED_TOKENS",
253 "subreaper_policy.errors(supervisor, process_source)",
254 ),
255 ),
256 (
257 "image harness policy",
258 inputs["image_harness_policy"],
259 (
260 _IMAGE_PROCESS_ANALYSIS_IMPORT,
261 "image_process_analysis."
262 "supervisor_errors("
263 "supervisor, cases_source, process_source)",
264 "image_process_analysis." + "source_errors(inputs)",
265 ),
266 ),
267 (
268 "process mutation catalog",
269 inputs["process_mutations"],
270 (
271 "import hil_convergence_safety_process_source_fixtures as process_source_fixtures",
272 "import hil_convergence_safety_runtime_fixtures as runtime_fixtures",
273 "import hil_convergence_safety_source_fixtures as source_fixtures",
274 "process_source_fixtures.process_authority_mutations()",
275 "runtime_fixtures.process_authority_mutations()",
276 "*source_fixtures.process_authority_mutations(),",
277 ),
278 ),
279 )
280
281
282def _image_dispatch_specs(inputs: dict[str, str]) -> tuple[ModuleSpec, ...]:
283 """Return the public checker and authenticated shell-loader bindings."""
284 return (
285 (
286 "image harness consumer",
287 inputs["hil_convergence_entry"],
288 (
289 "import hil_convergence_safety_image_harness_policy as image_harness_policy",
290 "image_harness_policy.errors(inputs)",
291 ),
292 ),
293 (
294 "bound-exit helper loader",
295 inputs["devcontainer_image"],
296 (
297 "SELFTEST_BOUND_EXIT_RAW_SHA256=",
298 'source_approved_selftest_helper "$SCRIPT_DIR/'
299 'devcontainer_image_bound_exit_selftest.bash"',
300 '"$SELFTEST_BOUND_EXIT_RAW_SHA256"',
301 ),
302 ),
303 )
304
305
306def _split_runtime_module_errors(inputs: dict[str, str]) -> list[str]:
307 """Bind every focused split helper to one exact production consumer."""
308 specifications = (
309 *_runtime_module_specs(inputs),
310 *_image_module_specs(inputs),
311 *_image_dispatch_specs(inputs),
312 )
313 errors = []
314 for label, source, tokens in specifications:
315 errors.extend(_exact_shell_token_errors(source, label, tokens))
316 return errors
317
318
319def errors(inputs: dict[str, str]) -> list[str]:
320 """Bind signal cleanup to live jobs and bounded process-enumeration failure."""
321 lifecycle = inputs["devcontainer_image_selftest"]
322 bound_exit = inputs["devcontainer_image_bound_exit_selftest"]
323 cases = inputs["devcontainer_image_selftest_cases"]
324 signal_source = inputs["devcontainer_image_signal_selftest"]
325 lock = inputs["devcontainer_image_lock_selftest"]
326 supervisor = inputs["devcontainer_image_selftest_supervisor"]
327 supervisor_cases = inputs["devcontainer_image_selftest_supervisor_cases"]
328 supervisor_process = inputs["devcontainer_image_selftest_process"]
329 return (
330 _image_lifecycle_process_errors(lifecycle, bound_exit)
331 + _image_cases_process_errors(cases)
332 + _image_signal_process_errors(signal_source)
333 + _image_lock_process_errors(lifecycle, cases, signal_source, lock)
334 + _image_supervisor_token_errors(supervisor, supervisor_cases, supervisor_process)
335 + image_process_analysis.source_errors(inputs)
336 + _semantic_aggregator_errors(inputs["semantic_mutations"])
337 + _split_runtime_module_errors(inputs)
338 )