#!/usr/bin/env python3 # SPDX-License-Identifier: GPL-3.0-or-later """Audit the pinned SDK startup/loader chain without executing a PS5 ELF.""" from __future__ import annotations import argparse import json import subprocess from pathlib import Path EXPECTED_SDK_COMMIT = "d2e2e585740362976a39fdd5ccf390f199a7bc37" def require_in_order(text: str, snippets: tuple[str, ...], source: Path) -> None: position = -1 for snippet in snippets: position = text.find(snippet, position + 1) if position < 0: raise ValueError(f"{source}: missing or reordered evidence: {snippet}") def read(source: Path, relative: str) -> str: path = source / relative return path.read_text(encoding="utf-8") def git_head(source: Path) -> str: result = subprocess.run( ["git", "-C", str(source), "rev-parse", "HEAD"], check=True, capture_output=True, text=True, ) return result.stdout.strip() def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--sdk-source", type=Path, required=True) parser.add_argument("--project-root", type=Path, required=True) parser.add_argument("--output", type=Path, required=True) args = parser.parse_args() sdk = args.sdk_source.resolve(strict=True) project = args.project_root.resolve(strict=True) if git_head(sdk) != EXPECTED_SDK_COMMIT: raise ValueError("SDK source checkout differs from the pinned v0.41 commit") crt = read(sdk, "crt/crt.c") patch = read(sdk, "crt/patch.c") rtld = read(sdk, "crt/rtld.c") dlfcn = read(sdk, "crt/rtld_dlfcn.c") sprx = read(sdk, "crt/rtld_sprx.c") kernel = read(sdk, "crt/kernel.c") probe_main = read(project, "samples/capability_probe/main.c") probe_platform = read(project, "src/backends/ps5/probe_platform.c") require_in_order( crt, ( "__crt_syscall_init(args)", "__kernel_init(args)", "__klog_init()", "__patch_init()", "__rtld_init()", "*payload_args->payloadout = main(argc, argv, environ)", ), sdk / "crt/crt.c", ) require_in_order( patch, ( "patch_kernel_ucred()", "patch_syscall_permissions()", ), sdk / "crt/patch.c", ) for snippet in ( "kernel_set_ucred_caps(pid, caps)", "kernel_set_ucred_attrs(pid, attrs)", "kernel_copyin(&uaddr, kaddr + 0xf0, sizeof(uaddr))", "kernel_copyin(&uaddr, kaddr + 0xf8, sizeof(uaddr))", ): if snippet not in patch: raise ValueError(f"crt/patch.c: missing expected write: {snippet}") require_in_order( rtld, ("__rtld_sprx_init()", "__rtld_dlfcn_init()"), sdk / "crt/rtld.c", ) for snippet in ( "sceKernelLoadStartModule(\"/system/common/lib/libSceSysmodule.sprx\"", "sceKernelLoadStartModule(path, 0, 0, 0, 0, 0)", "sceKernelStopUnloadModule(lib->handle, 0, 0, 0, 0, 0)", ): if snippet not in sprx: raise ValueError(f"crt/rtld_sprx.c: missing loader evidence: {snippet}") require_in_order( dlfcn, ("__rtld_lib_open(lib)", "__rtld_lib_init(lib, getargc(), getargv(), environ)"), sdk / "crt/rtld_dlfcn.c", ) require_in_order( dlfcn, ("__rtld_lib_fini(lib)", "__rtld_lib_close(lib)", "__rtld_lib_destroy(lib)"), sdk / "crt/rtld_dlfcn.c", ) for snippet in ("int\nkernel_copyin", "int\nkernel_copyout"): if snippet not in kernel: raise ValueError(f"crt/kernel.c: missing kernel I/O primitive: {snippet}") require_in_order( probe_main, ( "chimera_gfx_firmware_gate_allows", "chimera_gfx_ps5_make_loader_ops", "chimera_gfx_ps5_probe_symbols", ), project / "samples/capability_probe/main.c", ) for snippet in ( "dlopen(module_name, RTLD_LAZY | RTLD_LOCAL)", "address = dlsym(loader->module, symbol_name)", "address = NULL;", "dlclose(loader->module)", ): if snippet not in probe_platform: raise ValueError(f"probe_platform.c: missing loader boundary: {snippet}") document = { "schema_version": 1, "sdk": { "release": "v0.41", "commit": EXPECTED_SDK_COMMIT, }, "execution_eligible_under_project_policy": False, "blocking_side_effects_before_main": [ "__patch_init calls patch_kernel_ucred", "patch_kernel_ucred writes process capability and attribute fields", "__patch_init calls patch_syscall_permissions", "patch_syscall_permissions writes the process syscall-address bounds", ], "startup_calls_before_main": [ "__crt_syscall_init", "__kernel_init", "__klog_init", "__patch_init", "__rtld_init", "__rtld_sprx_init", "__rtld_dlfcn_init", "payload constructors", ], "project_requested_calls_after_firmware_gate": [ "fprintf", "chimera_gfx_ps5_make_loader_ops", "dlopen", "dlerror", "dlsym (21 bounded lookups; returned addresses discarded)", "snprintf", "dlclose", ], "loader_side_effects": [ "SDK rtld startup may load and start libSceSysmodule.sprx", "probe dlopen may load and start libSceGnmDriver.sprx", "module open allocates user memory and copies symbol/string tables", ], "cleanup_side_effects": [ "dlclose invokes rtld fini, close, and destroy paths", "a newly loaded SPRX is stopped/unloaded with sceKernelStopUnloadModule", "SDK sprx_init and sprx_fini are empty at the pinned commit", "cleanup is not guaranteed after a hang, crash, or loader failure", ], "conclusion": ( "Project code requests no GNM call, rendering, or GPU mutation, but the " "linked SDK payload CRT performs prohibited kernel writes before main. " "The resulting ELF must not be transferred or executed." ), } args.output.parent.mkdir(parents=True, exist_ok=True) args.output.write_text( json.dumps(document, indent=2, sort_keys=True) + "\n", encoding="utf-8" ) print("SDK runtime audit completed: execution blocked by pre-main kernel writes") return 0 if __name__ == "__main__": try: raise SystemExit(main()) except (OSError, subprocess.CalledProcessError, ValueError) as error: print(f"SDK runtime audit failed: {error}") raise SystemExit(1) from error