3"""Focused hostile runtime cases for the privileged startup wrapper."""
5from __future__
import annotations
10from collections.abc
import Callable
11from dataclasses
import dataclass
12from pathlib
import Path
15@dataclass(frozen=True)
17 """One fully specified invocation of a private selftest script."""
19 command: tuple[str, ...]
21 environment: dict[str, str]
22 pass_fds: tuple[int, ...] = ()
24 preexec_fn: Callable[[],
None] |
None =
None
31@dataclass(frozen=True)
33 """One wrapper variant supplied by the single policy authority."""
36 prefix: tuple[str, ...]
37 close: tuple[str, ...]
40class PrivilegedRuntimeError(RuntimeError):
41 """One privileged wrapper runtime invariant failed."""
44def _fail(message: str) ->
None:
45 raise PrivilegedRuntimeError(message)
48def run_private(spec: PrivateRun) -> subprocess.CompletedProcess[str]:
49 """Run one fixed private startup fixture."""
50 return subprocess.run(
54 pass_fds=spec.pass_fds,
56 preexec_fn=spec.preexec_fn,
64def _write_wrapper(path: Path, variant: WrapperVariant, body: str) ->
None:
65 lines = [
"#!/bin/bash -p", *variant.prefix, *body.splitlines(), *variant.close]
66 path.write_text(
"\n".join(lines) +
"\n", encoding=
"ascii")
70def _hostile_environment() -> dict[str, str]:
71 environment = {
"LC_ALL":
"C",
"PATH":
"/usr/bin:/bin"}
72 environment[
"BASH_FUNC_ra8_probe%%"] =
"() { :; }"
73 environment[
"BASH_FUNC_ra8_legacy()"] =
"() { :; }"
77def _exec_failure_case(
79 variant: WrapperVariant,
82 body_marker = base / f
"{variant.name}-{failure}.body"
83 descendant_marker = base / f
"{variant.name}-{failure}.descendant"
84 script = base / f
"{variant.name}-{failure}.sh"
88 f
"printf 'body\\n' >{body_marker!s}\n"
89 f
"/bin/bash -c \"printf 'descendant\\\\n' >{descendant_marker!s}\"\n",
91 text = script.read_text(encoding=
"ascii")
92 if failure ==
"e2big":
94 'ra8_startup_e2big="$(/usr/bin/head -c 3000000 /dev/zero | '
95 "/usr/bin/tr '\\000' x)\"\n"
96 'ra8_startup_env_unset+=(-u "$ra8_startup_e2big")\n'
98 text = text.replace(
"if ! exec /usr/bin/env ", f
"{injection}if ! exec /usr/bin/env ", 1)
100 text = text.replace(
"exec /usr/bin/env ",
"exec /ra8-absent-env ", 1)
101 script.write_text(text, encoding=
"ascii")
103 (
"ordinary", (str(script),)),
104 (
"execfail", (
"/bin/bash",
"-O",
"execfail",
"-p", str(script))),
106 for mode, command
in commands:
107 result = run_private(PrivateRun(command, base, _hostile_environment()))
108 if result.returncode == 0
or body_marker.exists()
or descendant_marker.exists():
109 _fail(f
"{variant.name}/{failure}/{mode}: failed exec reached body")
110 if mode ==
"execfail" and "could not enter sanitized process" not in result.stderr:
111 _fail(f
"{variant.name}/{failure}: explicit refusal did not run")
114def _ignore_usr1() -> None:
115 signal.signal(signal.SIGUSR1, signal.SIG_IGN)
118def _preservation_findings(
119 result: subprocess.CompletedProcess[str], expected: tuple[str, ...]
121 findings = [line
for line
in expected
if f
"{line}\n" not in result.stdout]
122 if result.returncode != OWNER_STATUS:
123 findings.append(f
"status={OWNER_STATUS}")
127def _assert_preservation(
128 result: subprocess.CompletedProcess[str], expected: tuple[str, ...], variant: str
130 """Require every process-state observation and prove each check is live."""
131 if findings := _preservation_findings(result, expected):
132 _fail(f
"{variant}: changed process state: {findings!r}")
133 for line
in expected:
134 mutated = result.stdout.replace(f
"{line}\n",
"mutated\n", 1)
135 control = subprocess.CompletedProcess(result.args, OWNER_STATUS, mutated, result.stderr)
136 if not _preservation_findings(control, expected):
137 _fail(f
"{variant}: assertion missed {line!r}")
138 control = subprocess.CompletedProcess(result.args, 0, result.stdout, result.stderr)
139 if not _preservation_findings(control, expected):
140 _fail(f
"{variant}: assertion missed owner status")
143def _preservation_case(base: Path, variant: WrapperVariant) ->
None:
144 script = base / f
"{variant.name}-preserve.sh"
146printf 'cwd=%s\\n' "$PWD"
147printf 'umask=%s\\n' "$(umask)"
148IFS= read -r ra8_fd_payload <&"${RA8_TEST_FD:?}"
149printf 'fd=%s\\n' "$ra8_fd_payload"
151printf 'signal=ignored\\n'
153while IFS= read -r -d '' ra8_env_row; do
154 case "${ra8_env_row%%=*}" in
155 BASH_FUNC_*) ra8_function_rows=$((ra8_function_rows + 1)) ;;
157done < <(/usr/bin/env -0)
158printf 'function-rows=%s\\n' "$ra8_function_rows"
159printf 'argc=%s\\n' "$#"
161for ra8_arg in "$@"; do
162 printf 'arg%s=%s\\n' "$ra8_arg_index" "$ra8_arg"
163 ra8_arg_index=$((ra8_arg_index + 1))
166 _write_wrapper(script, variant, body)
167 read_fd, write_fd = os.pipe()
168 os.write(write_fd, b
"open-descriptor\n")
170 environment = _hostile_environment()
171 environment[
"RA8_TEST_FD"] = str(read_fd)
172 args = (
"plain",
"path with spaces",
"line-one_line-two")
174 result = run_private(
176 (str(script), *args),
181 preexec_fn=_ignore_usr1,
189 "fd=open-descriptor",
194 "arg1=path with spaces",
195 "arg2=line-one_line-two",
197 _assert_preservation(result, expected, variant.name)
200def run_privileged_wrapper_runtime_cases(base: Path, variants: tuple[WrapperVariant, ...]) -> int:
201 """Exercise all three live wrapper variants in both directions."""
202 for variant
in variants:
203 for failure
in (
"missing",
"e2big"):
204 _exec_failure_case(base, variant, failure)
205 _preservation_case(base, variant)
206 return 5 * len(variants)