Publish Chimera GFX source
phase0-ci / build-and-audit (push) Successful in 2m14s

This commit is contained in:
Chimera GFX release export
2026-09-03 03:27:14 +02:00
commit a6037502d7
828 changed files with 100454 additions and 0 deletions
+87
View File
@@ -0,0 +1,87 @@
# Controlled PS5 runtime profile
`manifests/controlled-runtime-profile.schema.json` defines the mandatory
machine boundary for hardened-runtime deployment preparation. Missing metadata
is a denial, not an invitation to infer a value.
## Required invariants
- exact firmware `9.60`, supported by Jens's explicit confirmation;
- exact hardened Payload Manager, hardened elfldr, SDK, and artifact source
commits, sizes, and SHA-256 values;
- byte-identical double clean builds for every ELF;
- lifecycle artifact filename, byte size, SHA-256, and clean source commit
equal in artifact manifest, runtime profile, audit, and local bytes;
- persistent writes limited to removable controlled application artifacts;
- filesystem writes limited to the controlled artifact directory;
- payload network access `none`;
- maximum payload runtime 2000 ms;
- automatic retry disabled;
- no effect classified `PERSISTENT_WRITE` or `UNBOUNDED_OR_UNKNOWN`;
- no hard blocker and decision
`READY_FOR_HARDENED_RUNTIME_DEPLOYMENT`;
- explicit `execution_eligible=true`;
- profile name exactly `controlled-ps5-runtime`;
- `expected_volatile_effects` exactly equal to the IDs classified
`EXPECTED_VOLATILE_RUNTIME_EFFECT`;
- explicit top-level `execution_authorized=false`;
- deployment fields remain `installed=false`,
`ready_for_installation=true`, and `rollback_prepared=true`.
The static pass means the exact bytes are eligible for a later, separate
installation approval. It does not authorize a PS5 connection, transfer,
installation, or execution.
`rollback_prepared=true` means only that the offline review and rollback
packages exist. It does not claim that byte-exact stock backups are already
present on the console. Phase 0.8 keeps installation hard-blocked until those
current on-device rollback preconditions are proven through an admissible
collector.
## Current exact profile
`manifests/runtime/controlled-ps5-runtime-profile.json` binds:
- lifecycle probe
`bfb4a5cc768e162fe4c2fddf41c3978e152722918a39085277fd172cb95a7182`,
112680 bytes, source
`fe08300339a13f899fb78ea404ada381a5cba87c`;
- hardened elfldr
`63e810982471eb40cae3a20aa9df9a0a02892f420e429874fae4e99aa400b561`,
397000 bytes, source
`197623058f509eddde18868dafcb92fdcac66464`;
- controlled Payload Manager
`8fecf8241a46246eddbd21e8bb4d875f5d76f1f4f4c6a11384df1f131aa5e5b1`,
99560 bytes, source
`e23d94ff91233aa770e2342800c1467875bdef44`;
- SDK v0.41 commit
`d2e2e585740362976a39fdd5ccf390f199a7bc37`.
The profile records `installed=false`, `execution_authorized=false`,
`transferred=false`, and `executed=false`. Firmware was not queried from the
device because this phase was offline; the evidence string records Jens's
exact 9.60 confirmation.
## Static gate
`tools/check_artifact_execution_policy.py` verifies the profile, artifact
manifest, local lifecycle bytes, firmware argument, and permanent denylist. It
returns `PASS_STATIC_DEPLOYMENT_ELIGIBILITY_GATE` only for the exact reviewed
set and still emits `execution_authorized=false`.
The gate rejects a blocked decision, altered bytes, wrong firmware, an
uninstalled-identity claim, a widened budget, a hard effect, missing hardened
runtime identity, any authorization/transfer/execution claim, or a permanent
denylist match.
## Historical boundary
Phase 0.5's freestanding startup and Phase 0.6's unmodified public loader chain
remain blocked historical records. Phase 0.7 does not weaken or overwrite
those findings; it builds new hardened binaries that close the Phase-0.6
implementation blockers.
Phase 0.8 is a separate operational preflight gate. Its current decision is
`READ_ONLY_PREFLIGHT_BLOCKED`; it neither revokes the exact Phase-0.7 static
build evidence nor promotes it into connection, installation, transfer, or
execution authority.
+93
View File
@@ -0,0 +1,93 @@
# Kernelwrite proof matrix
Statuses mean: `SAFE` is proven only for the named scope, `UNSAFE` has a proven
policy violation, and `UNPROVEN` lacks necessary primary evidence. Absence of
an import is never used as the sole proof because SDK code is statically
combined in `crt1.o`.
| Component or behavior | Source | Linked in stock `crt1.o` | Reachable from stock `_start` | Status | Basis |
|---|---|---:|---:|---|---|
| `payload_args_t` order/offsets | public header + disassembly | yes | yes | `SAFE` | six x86-64 fields; `payloadout` at `0x28` |
| stock SDK startup | `crt/crt.c` | yes | yes | `UNSAFE` | invokes patch and rtld paths |
| `__patch_init` | `crt/patch.c` | yes | yes | `UNSAFE` | relocation and callgraph edge from `_start` |
| `kernel_copyin/out` | `crt/kernel.c` | yes | yes | `UNSAFE` | reachable read/write transport |
| `kernel_set_ucred_caps` | `crt/kernel.c` | yes | yes | `UNSAFE` | reaches `kernel_copyin` |
| `kernel_set_ucred_attrs` | `crt/kernel.c` | yes | yes | `UNSAFE` | reaches `kernel_copyin` |
| syscall address lower/upper bounds | `crt/patch.c` | yes | yes | `UNSAFE` | writes offsets `0xf0` and `0xf8` |
| JIT capability change | `crt/patch.c` | yes | yes | `UNSAFE` | `caps[15] |= 0x40` before credential write |
| ptrace attribute change | `crt/patch.c` | yes | yes | `UNSAFE` | `attrs[3] |= 0x80` before attribute write |
| runtime symbol discovery | `syscall.c`, `crt.c`, rtld | yes | yes | `UNSAFE` for minimal profile | multiple reachable dynamic resolutions |
| `__dlopen`/`__dlsym` facade | `rtld_dlfcn.c` | yes | no static startup edge | `UNSAFE` linked capability | absence from imports is not absence from bytes |
| Sce module load/start | `rtld_sprx.c` | yes | yes | `UNSAFE` | `__rtld_sprx_init` reaches function-pointer call |
| Sce module stop/unload | `rtld_sprx.c` | yes | cleanup-dependent | `UNPROVEN` cleanup | no guarantee after crash or partial init |
| SO mapping/`mprotect` | `rtld_so.c` | yes | path-dependent | `UNSAFE` linked capability | forbidden for minimal profile |
| socket-overlap helper | `kernel.c` | yes | no static startup edge | `UNSAFE` linked capability | still present in monolithic startup object |
| new network initialization | driver adds `libSceNet` | dependency present in stock links | module-init internals unknown | `UNPROVEN` | no caller/module initialization contract |
| GNM calls | no Phase-0.5 candidate source | no candidate | no candidate | `SAFE` source scope only | no custom source or artifact created |
| VideoOut calls | no Phase-0.5 candidate source | no candidate | no candidate | `SAFE` source scope only | no custom source or artifact created |
| SDL calls | no Phase-0.5 candidate source | no candidate | no candidate | `SAFE` source scope only | no custom source or artifact created |
| direct MMIO/register writes | audited project source | no candidate | no candidate | `SAFE` source scope only | none added |
| `-nostartfiles -nodefaultlibs` suppression | compiler `-###` | not linked in trace | n/a | `SAFE` driver fact | no CRT or default library added |
| loader stack/return contract | exact caller absent | n/a | n/a | `UNPROVEN` | callee cannot prove caller |
| pre-entry loader changes | exact caller absent | n/a | before entry | `UNPROVEN` | incoming kernel access exists; origin unknown |
The full source hashes, stock-object hashes, relocation-table hash,
disassembly hash, all reachable edges, and linked-but-unreachable prohibited
functions are in `manifests/runtime/phase-0.5-startup-audit.json`.
## Phase 0.6 controlled-runtime classification
The table above preserves the stricter Phase-0.5 "kernelwrite-free" question.
Phase 0.6 uses the user's corrected policy: a documented temporary runtime
write is not automatically unsafe. Only `PERSISTENT_WRITE` and
`UNBOUNDED_OR_UNKNOWN` are hard blockers.
| Component/effect | Classification | Review status | Basis |
|---|---|---|---|
| first-stage QA flag enable | `EXPECTED_VOLATILE_RUNTIME_EFFECT` | `SAFE` only as exact-source classification | loader bootstrap, before payload |
| child creation with `rfork_thread`/`execve` | `PAYLOAD_PROCESS_LOCAL` | `SAFE` source fact | separate SceSpZeroConf child |
| ptrace service authid, normal path | `RESTORED_BY_LOADER` | `SAFE` success path | authid backed up and restored |
| ptrace authid restore failure | `UNBOUNDED_OR_UNKNOWN` | `UNSAFE` for controlled profile | returns without a second restore |
| `pt_call`/`pt_syscall` completion | `UNBOUNDED_OR_UNKNOWN` | `UNSAFE` | no step or time bound |
| breakpoint byte | `RESTORED_BY_LOADER` | `SAFE` source fact | original byte copied back |
| breakpoint page RWX permission | `PAYLOAD_PROCESS_LOCAL` | `UNPROVEN` cleanup | permission not restored; relies on child exit |
| child root/jail/caps/authid | `RESTORED_BY_LOADER` on success | `UNPROVEN` partial | UID is not restored |
| payload mapping, argument page, sockets, pipe | `UNBOUNDED_OR_UNKNOWN` | `UNSAFE` for controlled profile | no success-path cleanup before detach |
| SDK `__patch_init` | `PAYLOAD_PROCESS_LOCAL` | `SAFE` classification, not execution proof | affects payload child; not an automatic blocker |
| SDK terminate branch | `UNBOUNDED_OR_UNKNOWN` | `UNSAFE` for controlled profile | return/exit/trap branch unresolved |
| detached payload runtime | `UNBOUNDED_OR_UNKNOWN` | `UNSAFE` | no two-second watchdog |
| child reaping | `UNBOUNDED_OR_UNKNOWN` | `UNSAFE` | SIGCHLD ignored; semantics undocumented |
| Manager load hash binding | `UNBOUNDED_OR_UNKNOWN` | `UNSAFE` | path streamed without SHA-256 check |
| Manager upload path | `PERSISTENT_WRITE` | `UNSAFE` | writes and commits under `/data/pldmgr/payloads` |
No source or binary evidence showed a GNM, VideoOut, SDL, direct MMIO, flash,
firmware, savegame, database, or system-configuration write in the proposed
payload path. Because no payload was built, that is a source-scope absence,
not an execution claim.
## Phase 0.7 hardened-runtime classification
The machine-readable counterpart is
`manifests/runtime/phase-0.7-kernelwrite-proof-matrix.json`.
| Component/effect | Phase-0.7 status | Classification | Evidence boundary |
|---|---|---|---|
| freestanding kernelwrite-free startup | `UNPROVEN` | historical blocked target | exact safe return contract still absent |
| stock SDK `__patch_init` | `UNSAFE` for a kernelwrite-free claim | `PAYLOAD_PROCESS_LOCAL` accepted effect | source, linker map, disassembly, reachable callgraph |
| stock SDK rtld module loading | `UNPROVEN` runtime branch; bounded externally | `PAYLOAD_PROCESS_LOCAL` accepted effect | linked module start/stop symbols, SDK source, child watchdog |
| ptrace step completion | `SAFE` offline | `BOUNDED_WATCHDOG` | source, unit/fuzz tests, disassembly |
| five-field credential restoration | `SAFE` offline | `RESTORED_BY_LOADER` | source, failure injection tests, callgraph |
| restoration failure | `SAFE` fail-closed logic | `FAIL_CLOSED_TERMINATION` | child killed/reaped; service disables ptrace |
| breakpoint byte/page | `SAFE` offline | `RESTORED_BY_LOADER` | source and disassembly |
| payload child lifetime | `SAFE` offline | `BOUNDED_WATCHDOG` | 2000 ms, SIGTERM, SIGKILL, reap |
| mapping/descriptor cleanup | `SAFE` offline | `OS_RECLAIMED_ON_EXIT` plus tracked cleanup | source, tests, callgraph |
| manager hash-to-stream binding | `SAFE` offline | `HASH_BOUND_SAME_FD` | source, TOCTOU and negative tests |
| receiver digest/denylist enforcement | `SAFE` offline | fail-closed | source, tests, disassembly |
| controlled artifact-directory write | `SAFE` for reviewed deployment budget | `ALLOWED_APPLICATION_WRITE` | exclusive temp, fsync, verify, atomic rename |
| GNM/VideoOut/SDL/MMIO/firmware mutation | `SAFE` absence claim | prohibited | source scan, imports, map, disassembly |
| firmware-9.60 runtime behavior | `UNPROVEN` | no execution evidence | no PS5 action occurred |
| installation, transfer, execution | `UNPROVEN` and unauthorized | action state false | manifests and offline audit |
The overall decision is
`READY_FOR_HARDENED_RUNTIME_DEPLOYMENT`, not `PROVEN KERNELWRITE-FREE`.
The known normal-CRT process-local write prevents the latter claim.
+220
View File
@@ -0,0 +1,220 @@
# PS5 payload loader contract audit
Audit date: 2026-07-17. Scope: pinned public PS5 Payload SDK v0.41 at
`d2e2e585740362976a39fdd5ccf390f199a7bc37`, inspected offline. No PS5 was
contacted and no ELF was built, transferred, or executed.
## Available primary evidence
The SDK README names three external loader families: `ps5-payload-dev/elfldr`,
`cryonumb/elfloader` through `ps5-jar-loader`, and
`shahrilnet/remote_lua_loader`. None of those caller repositories is present in
the pinned local evidence set. A `git grep` of every other local primary-source
checkout found no `payload_args_t` or `payloadout` caller implementation. The
only available contract is therefore the SDK callee side:
- `include/ps5/payload.h` defines the six-field `payload_args_t`;
- `crt/crt.c` defines `int _start(payload_args_t *args)` and labels it as the
entry invoked by the ELF loader;
- `crt1.o` disassembly shows the first argument consumed from `RDI` and
`payloadout` read at offset `0x28`;
- the SDK linker script defines image, BSS, constructor, destructor, and
dynamic-section boundaries.
These facts prove the callee layout. They do not prove how a particular loader
constructs the argument, stack, return address, or post-return state.
## Argument layout
For the audited x86-64 target the public fields are six eight-byte values in
this order:
| Offset | Field | Callee use |
|---:|---|---|
| `0x00` | `sys_dynlib_dlsym` | SDK syscall/symbol bootstrap |
| `0x08` | `rwpipe` | existing kernel read/write transport descriptors |
| `0x10` | `rwpair` | existing kernel read/write transport descriptors |
| `0x18` | `kpipe_addr` | existing kernel pipe address |
| `0x20` | `kdata_base_addr` | existing kernel data-base address |
| `0x28` | `payloadout` | result location written by the SDK CRT |
The 48-byte layout is `SAFE` as a source and disassembly fact. The lifetime,
writability, ownership, nullability, and post-return consumption of every
pointer are `UNPROVEN` because the caller is absent.
## Entry ABI and stack
The compiled SDK `_start` has a normal x86-64 function prologue, consumes the
argument from `RDI`, makes further calls without dynamically realigning `RSP`,
and ends one path with `ret`. This establishes what the callee expects, not what
the loader guarantees. In particular, the following remain `UNPROVEN`:
- the exact stack alignment at entry;
- whether a valid return address is present;
- which registers or floating-point state the loader expects preserved;
- whether the loader calls the entry as an ordinary function or transfers
control by another mechanism;
- whether the memory behind `payload_args_t` remains valid until return.
## BSS and image initialization
The SDK linker script provides `__bss_start` and `__bss_end`. The stock `_start`
explicitly zeros that range byte-by-byte before accessing its own BSS state.
The loop itself is freestanding and has no import, so a comparable loop is
technically possible. It is not evidence that the loader maps every segment
with the permissions, alignment, relocation state, or zero-fill behavior a new
artifact would require. Those caller/mapper properties are `UNPROVEN`.
## Return, exit, crash, and cleanup
The stock CRT does not define one universal return rule. Its
`payload_terminate()` first tries to detect a hijacked process with
`kernel_dynlib_dlsym(-1, 0x2001, "sceKernelDlsym")`. In that branch it returns
from `_start`. Otherwise it resolves and invokes `exit`; if that fails it
executes a trap. This heuristic itself depends on the syscall/kernel/rtld stack
that Phase 0.5 forbids.
Consequently, a custom `_start` that simply executes `ret` cannot be claimed
safe from the SDK callee alone. No local primary evidence proves:
- who consumes the integer return value;
- whether return resumes a hijacked process or exits a dedicated process;
- which mappings, descriptors, credentials, or signal state are restored;
- what happens after an invalid argument, fault, trap, or partial BSS clear;
- whether any cleanup exists after a crash.
All five are `UNPROVEN` and are build blockers.
## Loader state versus artifact-caused state
The argument fields show that kernel read/write descriptors and kernel
addresses already exist when the SDK entry is called. That is a fact about the
incoming state, not proof of how the loader created it. The exact loader may
have changed credentials, syscall bounds, mappings, modules, or other process
state before entry; the available callee source cannot distinguish those
possibilities.
The stock SDK artifact then independently causes additional writes through
`__patch_init`; those writes are attributable to `crt1.o` and are `UNSAFE`.
No Phase-0.5 candidate artifact exists, so it caused no new state changes.
## Contract decision
The public callee contract is insufficient for a safe-return artifact.
Decision: **BLOCKED**. The minimal missing evidence is the exact loader used for
firmware 9.60 at a pinned public commit, including its entry call site,
argument ownership, return path, pre-entry changes, cleanup, and crash path.
Machine evidence: `manifests/runtime/phase-0.5-startup-audit.json`.
## Phase 0.6 exact-loader addendum
The Phase-0.5 conclusion above is preserved as the evidence available at that
time. Phase 0.6 identified the installed loader exactly through the read-only
Payload Manager inventory and a byte-for-byte public release match:
- Payload Manager v0.3.1, commit
`cfbc70f30f419b09bf2b52283f7409e2d3117ee1`, SHA-256
`518740adbacccb9094fadb07dd424c53ee290f38306449ccc9d6957fdf813c0b`;
- `ps5-payload-dev/elfldr` v0.23, commit
`699e8bcff03e91e8d6ca6eba281af25c5a58d8c2`, SHA-256
`092d16ee0ede0c494947efd38d1a17bbd7cc4b022d3858ea898833c188c703e8`.
The proposed `itsPLK/ps5-elfldr` v0.23.2 candidate is not installed: its
release hash is
`2c28f847c859d3126b0f089ee23b72b84a733548da222ceafd91ae2f3df8f933`.
The exact exploit/autoloader that originally starts the first-stage loader
remains unidentified.
### Proven entry setup
The exact v0.23 source creates a new process using
`rfork_thread(RFPROC | RFCFDG | RFMEM)`. The child enables tracing and executes
`/system/vsh/app/NPXS40112/eboot.bin` (`SceSpZeroConf`). The parent stops at an
INT3 placed 58 bytes after the mapped eboot entry, restores that byte, maps the
payload, and then sets:
| Register/state | Exact loader operation | Status |
|---|---|---|
| `RSP` | writes observed `RIP` at `RSP - 8`, then subtracts 8 | `SAFE` source fact |
| `RIP` | payload ELF entry | `SAFE` source fact |
| `RDI` | loader-created `payload_args_t` page | `SAFE` source fact |
| breakpoint byte | original byte restored before injection | `RESTORED_BY_LOADER` |
| breakpoint page permission | changed to RWX and not restored | `PAYLOAD_PROCESS_LOCAL` |
This is a synthetic function-call frame. The public source does not establish
the meaning of the observed trap `RIP`, the exact original instruction
boundary, or the validity of resuming there after payload return. Therefore
the continuation is still `UNPROVEN`.
### Argument ownership and lifetime
`elfldr_payload_args()` maps one page into the child, creates two IPv6 sockets
and a pipe, overlaps the sockets through the SDK kernel helper, and populates
the six public fields. On successful detach the loader does not unmap that
page or close those child descriptors. They are process-local, but cleanup
depends on the child terminating. That termination and reaping path is not
bounded or proven.
### Return, exit, crash, and hang
The stock SDK v0.41 `_start` may return, resolve and call `exit`, or trap,
depending on `payload_terminate()`. Which branch applies to this injected
SceSpZeroConf child is not proven. Separately, elfldr:
- has no payload wall-clock deadline after `PT_DETACH`;
- has unbounded single-step loops in both `pt_call()` and `pt_syscall()`;
- ignores `SIGCHLD` in the service and documents no post-detach reaping
contract;
- kills the child on some preparation errors, but does not supervise normal
runtime, return, crash, or hang.
These are `UNBOUNDED_OR_UNKNOWN`, not objections to the mere presence of
temporary kernel/process writes. They block the requested controlled
two-second lifecycle.
### Existing loader state versus artifact-caused state
The first-stage loader enables QA flag bits and temporarily changes
credentials before the candidate payload exists. Those are existing-loader
effects. For each ptrace operation the service temporarily changes its authid
and normally restores it. The child receives process-local credentials,
mappings, sockets, pipes, executable permissions, and SDK `__patch_init`
changes. The artifact would cause SDK startup only after entry; it would not
cause the loader bootstrap.
The separation does not make the chain ready: UID restoration is absent,
authid restoration has an unrecovered failure path, and child lifetime is
unbounded. Full evidence is in
`manifests/runtime/phase-0.6-loader-runtime-audit.json`.
## Phase 0.7 hardened loader contract
Phase 0.7 does not depend on safely returning from `main`. The lifecycle
probe calls `_exit` after exactly one notification, so the unresolved SDK
`payload_terminate` return/exit/trap branch is outside the reachable
application path.
The hardened elfldr preserves the public `payload_args_t *` entry convention
and adds a controlled versioned transport header with exact artifact ID,
firmware 9.60, size, SHA-256, 2000 ms timeout, and no-retry fields. Both sender
and receiver validate the metadata; the receiver hashes the actual received
bytes and rejects the permanent denylist.
The loader's process mutations are exact and bounded:
- the initial QA flag change is an existing volatile bootstrap effect;
- ptrace service auth-ID and all child UID/jail/root/caps/auth fields are
backed up, restored, and checked;
- breakpoint byte and page protection are restored;
- single-step loops have independent time and step limits;
- every incomplete launch path terminates and reaps the child;
- the detached success path is replaced with a two-second supervised wait,
bounded termination escalation, and reap;
- an auth restoration failure permanently disables further ptrace work and
stops the service.
This is sufficient for the offline
`READY_FOR_HARDENED_RUNTIME_DEPLOYMENT` decision. Loader behavior on firmware
9.60 remains `UNPROVEN` until separately authorized installation and execution
produce on-device evidence.
+131
View File
@@ -0,0 +1,131 @@
# Minimal kernelwrite-free CRT feasibility
## Decision: BLOCKED
A compiler-driver trace proves that SDK v0.41 can be asked to omit its stock
CRT and default libraries. A freestanding BSS clear and ordinary x86-64 return
instruction are mechanically expressible. Those facts do not prove that the
actual PS5 loader safely calls or accepts return from such an entrypoint.
Because safe return was not proven, no custom `_start` source was added and no
PS5 ELF was built. This is the required fail-closed outcome, not an incomplete
artifact audit.
## Necessary versus convenience or patching
| Element | Minimal need | Classification | Evidence |
|---|---:|---|---|
| loader-recognized entry symbol | yes | `UNPROVEN` contract | SDK provides callee only |
| correct incoming stack/register ABI | yes | `UNPROVEN` caller | stock disassembly shows expectation only |
| mapped load segments and relocations | yes | `UNPROVEN` loader | linker script is not loader source |
| deterministic BSS state | yes when BSS exists | `SAFE` implementation primitive | linker symbols plus byte-zero loop |
| valid completion/return path | yes | `UNPROVEN` blocker | exact caller absent |
| `payloadout` write | unknown | `UNPROVEN` ownership | field exists; caller semantics absent |
| `__crt_syscall_init` | no for a no-call entry | convenience | stock SDK runtime only |
| `__kernel_init` | no | kernel transport convenience | consumes pre-existing kernel access |
| `__klog_init` | no | logging convenience | forbidden for minimal profile |
| `__patch_init` | no | prohibited patch | proven kernel writes |
| `__rtld_init` | no | dynamic-loader convenience | module loading and allocation |
| libc/stdio | no | convenience | omitted by `-nodefaultlibs` trace |
| constructors/destructors/TLS | no | convenience for this audit object | no artifact built |
## Exact blockers
The smallest evidence set needed before reconsidering a build is:
1. identification of the exact loader used with firmware 9.60 and a pinned,
public source commit;
2. the caller instructions establishing `RDI`, `RSP` alignment, the return
address, and any preserved state;
3. allocation and ownership of `payload_args_t`, including `payloadout`
lifetime and writability;
4. the complete caller path after `_start` returns, including restoration and
cleanup;
5. crash/fault behavior before and during entry;
6. all process, credential, syscall, module, and memory changes performed by
the loader before control reaches the artifact.
An SDK header, a function signature, or a successful link is not a substitute
for these caller facts.
## Verification disposition
| Requested check | Result |
|---|---|
| SDK source, Makefile, compiler and linker audit | passed offline |
| all stock startup objects/archives enumerated | passed offline |
| stock CRT disassembly and reachable callgraph | passed; stock CRT is `UNSAFE` |
| freestanding compiler-driver suppression | passed as no-output `-###` trace |
| custom source compile with warnings as errors | not performed; build blocked |
| custom linker map and full object/archive trace | not performed; build blocked |
| custom undefined symbols and `DT_NEEDED` | not performed; build blocked |
| custom relocations, arrays and TLS | not performed; build blocked |
| custom prohibited-code scan | not performed; no custom bytes exist |
| reproducible double clean cross-build and SHA-256 | not performed; no artifact exists |
| host tests and sanitizer tests | required by `TEST_PLAN.md` and run separately |
| negative build configuration | implemented; enabling the target must fail |
The non-build decision record is
`manifests/runtime/minimal-startup-artifact-decision.json`; it has
`execution_eligible=false` and deliberately has null filename, size, and hash.
## Safe alternatives
1. Continue `libchimera-gfx` through its deterministic mock and a separately
designed software backend. This advances API lifecycle, format conversion,
scaling, adapter contracts, and cleanup without PS5 startup or GPU risk.
2. Maintain a separate Linux-on-PS5 backend as a long-term track. Linux
`amdgpu`/RADV work can inform a Linux userspace backend, but it does not
establish a native PS5 userland ABI and must remain architecturally separate.
Neither alternative authorizes transfer or execution on the PS5.
## Phase 0.6 disposition
Phase 0.6 found the exact installed elfldr caller, so
`EXACT_LOADER_CALLER_SOURCE_ABSENT` is no longer the current blocker. The
Phase-0.5 non-build decision remains historically correct because that source
was not then available.
The corrected Phase-0.6 safety model does not reject normal SDK startup merely
because `__patch_init` performs documented temporary process/kernel runtime
changes. A lifecycle probe would therefore use the normal pinned SDK v0.41
startup rather than reopening the custom `-nostartfiles -nodefaultlibs` target.
No lifecycle source or ELF was created because the surrounding exact chain
still cannot enforce the required profile:
1. elfldr's ptrace single-step completion loops have no finite bound;
2. the detached child has no two-second loader watchdog;
3. SDK return/exit/trap selection for the injected child is unproven;
4. UID and some failure-path credential state are not restored;
5. child exit/reaping and mapping/descriptor cleanup are unproven;
6. Payload Manager launch is path-bound rather than SHA-256-bound;
7. its supported upload path performs persistent filesystem writes;
8. the exploit/autoloader identity and independent firmware attestation remain
unproven.
Decision: **BLOCKED_VERSION_OR_UNBOUNDED_EFFECT**. Building a normal-CRT
lifecycle probe would create bytes that cannot satisfy the mandatory runtime
profile, so Phase D was correctly skipped.
## Phase 0.7 disposition
The Phase-0.5 freestanding target remains blocked and was not bypassed.
Phase 0.7 instead resolves the lifecycle termination uncertainty with an
ordinary SDK v0.41 payload whose `main` calls `_exit` directly. This preserves
the public loader entry ABI and avoids relying on an unproven return to the
loader.
The resulting lifecycle ELF has exactly `_exit` and
`sceKernelSendNotificationRequest` as undefined imports and exactly
`libSceLibcInternal.sprx` and `libkernel_web.sprx` as `DT_NEEDED` modules.
There are no GNM, VideoOut, SDL, network, module-loader, thread, retry, or
autoload imports.
This does not prove a kernelwrite-free startup. The normal CRT is statically
linked and its reachable startup includes `__patch_init`. Phase 0.7 accepts
that exact process-local effect under ADR-0010/ADR-0011 and hardens the
surrounding loader lifecycle. The freestanding question remains `BLOCKED`;
the normal-CRT lifecycle is
`READY_FOR_HARDENED_RUNTIME_DEPLOYMENT` offline only.
+72
View File
@@ -0,0 +1,72 @@
# Chimera Payload Manager artifact policy contract
The controlled Phase-0.7 Payload Manager is maintained in the separate private
`chimera-ps5-payload-manager` repository. This repository supplies the
hash-bound artifact and runtime profile that the manager must enforce.
## Same-file-descriptor launch boundary
The controlled manager:
1. opens the selected artifact once with read-only, no-follow, close-on-exec
flags;
2. requires a regular file and exact compiled byte size;
3. hashes that same file descriptor;
4. rejects the permanent denylist and every metadata mismatch;
5. rewinds and streams that same descriptor;
6. checks descriptor identity and path identity after streaming;
7. sends an exact versioned header over loopback only;
8. uses a compiled exact artifact ID, SHA-256, size, firmware 9.60, 2000 ms
timeout, and `retry=false`.
There is no path reopen between hash and stream. A symlink, truncation,
replacement, digest mismatch, denylist match, wrong route, wrong firmware,
non-loopback destination, or post-stream identity change fails closed.
## Controlled upload boundary
The upload route accepts only the controlled directory, creates an exclusive
no-follow temporary file, writes and synchronizes it, verifies exact content,
then atomically renames it. Upload never autoloads or executes the artifact.
The removable application write is explicit in the Phase-0.7 budget; it is not
a firmware write.
## Receiver enforcement
The hardened elfldr independently hashes the received bytes, validates the
exact artifact ID/size/firmware/digest/timeout/no-retry header, and enforces the
permanent denylist. Sender metadata alone is therefore insufficient.
The legacy route is classified `UNVERIFIED_LEGACY` and is not a controlled
Chimera launch path.
## Repository static gate
Before preparing a later action, the exact lifecycle bytes must also pass:
```text
python3 tools/check_artifact_execution_policy.py \
--manifest <artifact-manifest.json> \
--denylist manifests/artifact-denylist.json \
--artifact <exact-local-artifact> \
--runtime-profile manifests/runtime/controlled-ps5-runtime-profile.json \
--firmware 9.60
```
Only `PASS_STATIC_DEPLOYMENT_ELIGIBILITY_GATE` is accepted. The result always
contains `execution_authorized=false`; it is preparation evidence, not
permission.
## Permanent denial
SHA-256 `4be1c17b4964f2b68c39b5145bc4af4619c32512d60269ecf5c39728b390fa63`
must always return `ARTIFACT_PERMANENTLY_DENYLISTED`, regardless of metadata,
runtime profile, or later generic approval. The entry is also copied into both
hardened consumers.
## Current action state
No hardened binary is installed. No lifecycle artifact has been transferred
or executed. A separate exact-hash installation approval is required first;
after successful installation verification, lifecycle transfer and one-time
execution require another artifact-specific approval.
+48
View File
@@ -0,0 +1,48 @@
# Phase 0.5 independent offline review
Date: 2026-07-17. Decision: **BLOCKED**.
## Review result
| Area | Status | Finding |
|---|---|---|
| SDK source pin and release | `SAFE` | local source is exact v0.41 commit |
| stock CRT object provenance | `SAFE` | all 12 sources and six empty archives enumerated and hashed |
| stock CRT execution | `UNSAFE` | reachable kernel credential and syscall-bound writes |
| stock rtld initialization | `UNSAFE` | reachable module load/start path and runtime allocation |
| freestanding flag suppression | `SAFE` | no-output driver trace removes CRT and default libraries |
| BSS byte-clear primitive | `SAFE` | implementable without imports using linker bounds |
| exact firmware-9.60 loader identity | `UNPROVEN` | not present in local pinned evidence |
| incoming stack/register contract | `UNPROVEN` | caller source absent |
| `payloadout` ownership/lifetime | `UNPROVEN` | only callee declaration exists |
| safe return and post-return cleanup | `UNPROVEN` | caller continuation absent |
| crash cleanup | `UNPROVEN` | loader fault path absent |
| pre-entry process modifications | `UNPROVEN` | kernel-access state is supplied but creation is absent |
| custom startup artifact | `SAFE` nonexistence | build gate stopped before source/link |
| permanent legacy artifact block | `SAFE` policy control | exact SHA-256 is denylisted and ineligible |
| Payload Manager integration surface | `SAFE` repository control | fail-closed JSON policy gate rejects false eligibility and denylisted hashes |
| external manager implementation | `UNPROVEN` outside repository | no Chimera Payload Manager source is in this project |
## Side-effect conclusion
The stock SDK startup is conclusively not kernelwrite-free. A hypothetical
freestanding entry could omit that startup, but safe loader return and cleanup
are not proven. It would be unsafe to turn a compiler/linker possibility into
an executable artifact without the caller evidence.
No PS5 connection, transfer, execution, VideoOut open, GNM call, framebuffer
write, network initialization, module load, credential change, syscall-bound
change, or new PS5 ELF occurred during this review.
## Artifact policy
The legacy capability-probe SHA-256
`4be1c17b4964f2b68c39b5145bc4af4619c32512d60269ecf5c39728b390fa63`
is permanently `BLOCKED`. `tools/check_artifact_execution_policy.py` returns a
nonzero decision for either `execution_eligible=false` or an exact denylist
match. A zero status means only that this static eligibility layer passed; its
JSON explicitly sets `execution_authorized=false`.
There is no approval package for transfer or one-time execution because the
task explicitly forbids asking for execution permission and the feasibility
decision is blocked.
+122
View File
@@ -0,0 +1,122 @@
# Phase 0.6 exact loader audit
Historical record: superseded for current deployment preparation by the new
Phase-0.7 hardened binaries. This blocked decision remains authoritative for
the unmodified public-release chain.
Audit date: 2026-07-17. Decision:
**BLOCKED_VERSION_OR_UNBOUNDED_EFFECT**.
No ELF was built, transferred, or executed. The PS5 was not contacted through
raw port 9021. Read-only Payload Manager status endpoints were used only to
identify the installed public components. A strict existing read-only status
client on port 744 could not connect, so firmware 9.60 remains user-attested,
not device-attested.
## Identity evidence
| Component | Observed identity | Public source/release match | Result |
|---|---|---|---|
| firmware | exact `9.60`, stated by Jens | no independent device response | `UNPROVEN` attestation |
| Payload Manager | `/version` = `0.3.1`; inventory SHA-256 `518740ad...3c0b` | v0.3.1, commit `cfbc70f30...` | exact |
| elfldr | inventory v0.23; SHA-256 `092d16ee...03e8` | `ps5-payload-dev/elfldr` v0.23, commit `699e8bcff0...` | exact |
| itsPLK elfldr candidate | SHA-256 `2c28f847...8f933` | differs from installed hash | excluded |
| SDK | v0.41 | commit `d2e2e58574...` | exact |
| exploit/autoloader | local backup candidate only | no installed identity proof | `UNPROVEN` |
The exact source and release pins are in `manifests/upstreams.lock.json`. The
machine audit normalizes source text to LF, hashes every reviewed file, hashes
the complete release-binary disassembly and readelf report, and asserts the
critical source tokens before generating its result.
## Exact release binary
The installed elfldr release asset is a stripped ELF64 PIE with entry `0x4700`.
Its complete import surface is:
```text
DT_NEEDED:
libSceLibcInternal.sprx
libSceNet.sprx
libkernel_web.sprx
Undefined dynamic symbols:
__error
close
execve
free
getpid
kevent
kill
kqueue
malloc
memcpy
memset
open
printf
puts
realloc
recv
rfork_thread
sceKernelSendNotificationRequest
strcmp
strerror
strlen
sysctl
vsnprintf
waitpid
```
It has 164 dynamic relocations, 140 of them `R_X86_64_RELATIVE`; zero-byte
preinit/init/fini arrays; and no TLS segment or TLS sections. The first load
segment is RWE. This import list does not prove absence of statically linked
kernel helpers, so the source and disassembly audits remain primary.
## Loader lifecycle
The loader uses a dedicated SceSpZeroConf child. It establishes a synthetic
call frame by placing the observed trap RIP at `RSP-8`, setting `RIP` to the
payload entry and `RDI` to a loader-created `payload_args_t`. It restores the
INT3 byte, jail/root/caps/authid on the child success path, and its own authid
after each ptrace syscall on the normal path.
It does not prove or enforce:
- the continuation reached when the payload returns;
- a finite step count in `pt_call()` or `pt_syscall()`;
- a two-second payload runtime;
- restoration after an authid-restore failure;
- child UID restoration;
- child mapping/socket/pipe cleanup after detach;
- child termination and reaping after normal return, crash, or hang.
The installed service's existing QA flag and bootstrap credential effects are
separate from new artifact effects. They are still documented because the
full lifecycle depends on them.
## Payload Manager lifecycle
The exact `/loadpayload:` handler resolves a filename/path and streams that
file to elfldr on loopback port 9021. It does not calculate or compare the file
SHA-256 at launch. The `/manage:upload` path creates
`/data/pldmgr/payloads/<filename>.tmp` and commits the upload into storage.
Consequently the current manager cannot simultaneously provide exact-hash
launch binding and the required zero-filesystem-write transfer budget.
No manager route was invoked to upload, load, kill, configure, retry, or
contact port 9021 during this audit.
## Minimum evidence needed to reopen Phase D
1. Exact exploit/autoloader identity and public-source lifecycle evidence.
2. Read-only, exact device attestation of firmware 9.60.
3. A bounded loader path whose ptrace and payload phases enforce a maximum of
2000 ms without automatic retry.
4. Proven payload return/exit/crash continuation and child cleanup/reaping.
5. Proven restoration or bounded termination on every credential-change
failure path, including UID.
6. A Payload Manager path that verifies the exact SHA-256 immediately before
launch and performs no filesystem write.
No workaround is authorized. The two safe development tracks remain the
mock/software backend and a separately scoped Linux-on-PS5 backend.
+58
View File
@@ -0,0 +1,58 @@
# Phase 0.6 independent review
Historical record: superseded for current deployment preparation by the new
Phase-0.7 hardened binaries. This blocked decision remains authoritative for
the unmodified public-release chain.
Date: 2026-07-17. Final decision:
**BLOCKED_VERSION_OR_UNBOUNDED_EFFECT**.
`SAFE` below means proven only for the stated offline/source scope. `UNSAFE`
means incompatible with the mandatory controlled profile. `UNPROVEN` means
required primary evidence is absent.
| Component | Status | Finding |
|---|---|---|
| private project isolation | `SAFE` | only `chimera-gfx` changed |
| firmware claim | `UNPROVEN` | exact 9.60 supplied by Jens; no device attestation |
| Payload Manager identity | `SAFE` | v0.3.1 asset hash matches commit/release |
| elfldr identity | `SAFE` | installed v0.23 asset hash matches exact public release |
| proposed itsPLK elfldr | `SAFE` exclusion | release hash differs; not audited as installed |
| exploit/autoloader identity | `UNPROVEN` | local backup is not installed-chain proof |
| separate payload process | `SAFE` source fact | rfork/exec creates SceSpZeroConf child |
| `RSP`/`RIP`/`RDI` setup | `SAFE` source fact | exact assignments identified |
| return continuation | `UNPROVEN` | trap RIP semantics and SDK terminate branch unresolved |
| ptrace completion | `UNSAFE` | single-step loops have no finite bound |
| maximum runtime | `UNSAFE` | detached child has no two-second watchdog |
| retry behavior | `SAFE` project policy | no project retry or execution path exists |
| normal authid restore | `SAFE` success path | loader backs up and restores |
| authid restore failure | `UNSAFE` | no recovery after failed restore |
| child credential restore | `UNPROVEN` partial | jail/root/caps/authid restored; UID not restored |
| breakpoint byte | `SAFE` | restored before payload detach |
| breakpoint permissions | `UNPROVEN` cleanup | page remains RWX until unproven child exit |
| payload args/resources | `UNPROVEN` cleanup | mappings, sockets and pipe rely on child exit |
| `__patch_init` | `SAFE` classification | known payload-process-local effect; not an automatic blocker |
| child exit/reaping | `UNPROVEN` | post-detach semantics not documented |
| manager launch hash | `UNSAFE` | path-bound stream; no launch-time SHA-256 verification |
| manager upload | `UNSAFE` | persistent `/data/pldmgr/payloads` write |
| GNM/VideoOut/SDL/MMIO | `SAFE` nonexistence | no lifecycle source or artifact was created |
| lifecycle artifact | `SAFE` nonexistence | Phase D stopped before source/build |
| legacy blocked artifact | `SAFE` policy | permanent denylist unchanged |
| transfer/execution | `SAFE` nonoccurrence | neither happened; no approval requested |
## Artifact disposition
There is no artifact path, artifact size, artifact SHA-256, or source commit
because no lifecycle probe was built. The machine profile contains null for
each of those fields and `execution_eligible=false`. No ELF is committed.
The permanent blocked SHA-256 remains:
```text
4be1c17b4964f2b68c39b5145bc4af4619c32512d60269ecf5c39728b390fa63
```
This review is not an approval package. Reopening Phase D requires resolving
every minimum-evidence item in `phase-0.6-loader-audit.md`, followed by a new
offline audit and a new decision. It does not require or request execution
permission now.
+79
View File
@@ -0,0 +1,79 @@
# Phase 0.7 hardened runtime — offline review
Decision: **READY_FOR_HARDENED_RUNTIME_DEPLOYMENT**.
This is an offline deployment-readiness decision. No PS5 connection,
installation, transfer, or execution occurred.
## Exact identities
| Component | Base | Hardened source | ELF SHA-256 | Size |
|---|---|---|---|---:|
| elfldr | `699e8bcff03e91e8d6ca6eba281af25c5a58d8c2` | `197623058f509eddde18868dafcb92fdcac66464` | `63e810982471eb40cae3a20aa9df9a0a02892f420e429874fae4e99aa400b561` | 397000 |
| controlled Payload Manager | `cfbc70f30f419b09bf2b52283f7409e2d3117ee1` | `e23d94ff91233aa770e2342800c1467875bdef44` | `8fecf8241a46246eddbd21e8bb4d875f5d76f1f4f4c6a11384df1f131aa5e5b1` | 99560 |
| lifecycle probe | Chimera GFX | `fe08300339a13f899fb78ea404ada381a5cba87c` | `bfb4a5cc768e162fe4c2fddf41c3978e152722918a39085277fd172cb95a7182` | 112680 |
All three pairs of clean builds are byte-identical. Complete disassembly,
symbol tables, relocations, normalized linker maps, and call-edge inventories
are in the ignored offline package under `outputs/phase07/audit/`; their
hashes and the complete call-edge lists are committed in
`manifests/runtime/phase-0.7-offline-audit.json`.
## Lifecycle binary boundary
The only undefined imports are:
- `_exit`
- `sceKernelSendNotificationRequest`
The only `DT_NEEDED` modules are:
- `libSceLibcInternal.sprx`
- `libkernel_web.sprx`
There are no GNM, VideoOut, SDL, SceNet, socket, download, thread, retry, or
autoload imports. The normal SDK startup object is statically present and
reaches its documented `__patch_init` and rtld initialization before `main`;
absence from imports is not used to hide that fact. The linker map also
contains `sceKernelLoadStartModule`/`sceKernelStopUnloadModule` through the
stock SDK rtld; its conditional module behavior is payload-process-local and
supervised by the external watchdog, but remains unobserved on firmware 9.60.
After one notification, `main` calls `_exit`, so the uncertain SDK
`main -> payload_terminate` return branch is not taken.
## Hardening closure
| Phase-0.6 finding | Phase-0.7 implementation | Review |
|---|---|---|
| unbounded ptrace loop | monotonic one-second deadline plus 65,536 steps | `SAFE` offline logic |
| incomplete child credential restore | UID, jaildir, rootdir, caps, auth-ID all restored and checked | `SAFE` offline logic |
| restore failure continues | fail-closed kill and deadline-bounded reap; no detach | `SAFE` offline logic |
| scattered cleanup | one tracked cleanup state machine for breakpoint, mappings, fds, child | `SAFE` offline logic |
| breakpoint page stays RWX | original byte restored and page reset RX | `SAFE` source fact |
| detached runtime unbounded | 2000 ms wait, SIGTERM grace, SIGKILL, reap | `SAFE` offline logic |
| ignored SIGCHLD/zombie risk | default SIGCHLD plus explicit reap | `SAFE` offline logic |
| path-based Manager load | one no-follow FD, fstat, hash, rewind, stream, post-check | `SAFE` offline logic |
| upload TOCTOU | exclusive temp, fsync, verify, atomic rename, inode check | `SAFE` offline logic |
| arbitrary controlled artifact | manager binary compiled for exact hash, size, and ID | `SAFE` offline configuration |
| sender-only hash | elfldr rehashes received bytes and checks denylist | `SAFE` offline logic |
`SAFE` here means source, test, map, and disassembly evidence agree. It is not
a hardware execution claim.
## Remaining risks
- No on-device observation exists yet; loader/firmware behavior remains
unverified at runtime.
- QA flags are an existing expected volatile loader bootstrap effect.
- Normal SDK startup performs known process-local credential/capability and
syscall-bound writes before `main`.
- The controlled manager listens for the later operator workflow, but accepts
only the compiled exact artifact identity; installation security and
network exposure still require a separate review.
- Abrupt platform failure can bypass userland reporting, though OS process
teardown should reclaim child mappings and descriptors.
- Rollback has only been prepared offline; its on-device paths and installed
hashes must be captured before any replacement.
These are deployment/execution residual risks, not unresolved compiler,
linker, or ABI blockers for preparing the hardened runtime.
@@ -0,0 +1,137 @@
# Phase 0.8 read-only on-device preflight
Audit date: 2026-07-18. Decision:
**READ_ONLY_PREFLIGHT_BLOCKED**.
This is an offline admissibility audit. No on-device preflight session was
started, no connection to the PS5 was made, and no collector was run against
the PS5. No file, configuration, service, process, artifact, autoload setting,
or retry state on the console was touched. Local documentation and manifest
changes are outside that console-action statement.
The attached preflight form requires both an exact permission record and a
collector whose reads demonstrably cannot change atime, audit logs, caches,
metadata, process state, or on-device logs. Neither condition can currently be
filled truthfully. The form's own fail-closed rule therefore requires
`STOP-RO`.
## Authorization record
| Field | Recorded value |
|---|---|
| explicit read-only preflight permission | absent; no exact text/reference was supplied |
| connection authorized | `false` |
| installation authorized | `false` |
| lifecycle authorized | `false` |
| execution authorized | `false` |
| automatic retry | `false` |
The request to read and act on a blank checklist is not recorded as an exact,
artifact-independent authorization sentence. This finding alone prevents an
on-device session. It does not prevent this offline source audit.
## Collector review
### Stock Payload Manager HTTP
The exact public v0.3.1 source is commit
`cfbc70f30f419b09bf2b52283f7409e2d3117ee1`.
This candidate is **UNSAFE for the Phase-0.8 read-only contract**:
- `src/http_server.c:131-152` calls `log_server_set_active()` for every
non-`OPTIONS` request before route dispatch;
- `src/log_server.c:20-23` implements that call by writing
`server_active_flag = 1`;
- `src/http_server.c:847-871` dispatches `/autoload_status` to
`pldmgr_autoload_get_status()` and opens
`/data/pldmgr/autoload.txt`;
- `src/autoload.c:44-48` writes `autoload_triggered = 1`; the worker at
`src/autoload.c:78-93` uses that flag to leave its frontend-wait state and
start the countdown;
- `src/http_server.c:911-930` also opens the autoload file for `/get_config`;
- non-noisy routes call `pldmgr_log()` at `src/http_server.c:479-481`;
`src/log_server.c:25-55` prints to stdout and mutates the in-process ring,
log version, mutex/condition state, and waiting clients.
Even `/version`, which is filtered from the explicit request log, first calls
`log_server_set_active()`. Therefore an apparently informational endpoint is
not sufficient evidence of a no-side-effect collector. `/autoload_status`
must not be used at all under this contract.
Pinned source-file SHA-256 values:
| File | SHA-256 |
|---|---|
| `src/http_server.c` | `35cf5d8f0dd44cf64ceab5e4b0ecc09413c82d7e9946ba9de2ca4b1898631fdd` |
| `src/autoload.c` | `7051cab3ee1a3e0b9f6498000565eb9e160b9c63efa1771f250e98ec3aa4ae67` |
| `src/log_server.c` | `659095f43df1bbe8eb24acb165f027edc277af1e60aabb26ba9e3920b233d6f1` |
### Direct filesystem or process collector
No exact collector, version, source, transport, or operation set was supplied.
No evidence proves `noatime` behavior, suppression of audit records, absence
of caches, absence of network/service counters, or absence of on-device
logging. Classifying these effects as “probably harmless” would contradict the
required `Onbekend -> STOP-RO` rule.
Historical Phase-0.6 endpoint observations are not reused as current
Phase-0.8 evidence. They lack current pre/post identity and were gathered
under a different, less strict observation boundary.
## Gate state
| Preflight section | Review | Reason |
|---|---|---|
| permission | `STOP-RO` | exact permission text/reference absent |
| collector | `STOP-RO` | side-effect freedom unproven |
| stock HTTP collector | `STOP-RO` | proven process-state mutations |
| two-source firmware 9.60 | `STOP-GATE` | one user attestation, no two current device sources |
| live elfldr path/object/hash | `STOP-GATE` | no current admissible observation |
| live Payload Manager path/object/hash | `STOP-GATE` | no current admissible observation |
| processes/services/listeners | `STOP-GATE` | current topology and ownership absent |
| autoload/startup/retry | `STOP-GATE` | authoritative sources not collected |
| separate backup destination | `STOP-GATE` | device, space, and reserve unproven |
| stock elfldr rollback backup | `STOP-GATE` | exact separate backup unproven |
| stock Payload Manager rollback backup | `HARD STOP-GATE` | exact separate on-device backup unproven |
The expected stock identities remain reference values only:
- elfldr: 397000 bytes,
`092d16ee0ede0c494947efd38d1a17bbd7cc4b022d3858ea898833c188c703e8`;
- Payload Manager: 2050320 bytes,
`518740adbacccb9094fadb07dd424c53ee290f38306449ccc9d6957fdf813c0b`.
They are not claims about the console's current state.
## Minimum evidence to reopen
1. Exact permission text and a stable task reference authorizing only this
read-only preflight, while leaving installation, lifecycle execution,
transfer, artifact execution, and automatic retry unauthorized.
2. A pinned public collector and transport with a complete source and
environment proof excluding file, atime, metadata, audit-log, cache,
process-state, service-state, network-state, and on-device-log mutation.
3. Two authoritative current firmware sources that agree exactly on `9.60`.
4. A side-effect-free collection plan for current object identities, full
metadata, hashes, process/service ownership, ports 8084/8085/9021, and all
autoload/startup/retry sources, including stable pre/post observations.
5. Proof that separate, already-present, byte-exact rollback objects exist.
The stock Payload Manager backup is a hard gate.
The stock Payload Manager HTTP interface cannot satisfy item 2 without a
different, separately reviewed implementation. No workaround is attempted.
## Final state
- dataset complete: `false`;
- open STOP-RO: `true`;
- open STOP-GATE: `true`;
- Payload Manager backup exact/current: `UNPROVEN`;
- installation approval: **NOT AUTHORIZED**;
- lifecycle approval: **NOT AUTHORIZED**;
- execution authorized: `false`;
- automatic retry: `false`.
The complete machine-readable record is
`manifests/runtime/phase-0.8-read-only-preflight.json`.
+289
View File
@@ -0,0 +1,289 @@
# Phase 0.8R offline remediation and evidence contract
Decision: **READ_ONLY_PREFLIGHT_BLOCKED**.
## Scope
Phase 0.8R is documentation, evidence-contract design, and host-only
regression protection. It does not contact a PS5, observe hardware, implement
a collector, build a target artifact, transfer a file, install a component, or
execute code on a target.
It grants no authority. `installation_authorized=false`,
`lifecycle_authorized=false`, `execution_authorized=false`,
`transfer_authorized=false`, and `automatic_retry=false`.
The absolute read-only rule used by historical Phase 0.8 is unchanged.
Possible future bounded observation would be a separate phase with a new name,
effect budget, exact permission, and review. This document does not approve
such a phase.
## Immutable historical identity
The Phase-0.8 record is anchored to repository commit
`2c944d6d65a08f7e1c02f518721cde061b999329`.
| Immutable file | Role | SHA-256 |
|---|---|---|
| `docs/runtime/phase-0.8-read-only-preflight.md` | human-readable historical record | `3fbe086175a6048176075f447ec1482074928e3b5282db97ea2169395fe1d508` |
| `manifests/runtime/phase-0.8-read-only-preflight.json` | machine-readable historical record | `47d7f452f8799979fe99b3e6d56859f03544112725bf7e5b349eba5ed81b3322` |
| `tests/test_phase08_preflight.py` | original fail-closed regression | `8a4ad7c70de28ffe3148fd3fd1f68c36a872c53c691c9068e1ff163970863c48` |
Historical reporting dated 2026-07-18 recorded 17/17 host tests passing,
manifest and safety checks passing, and a secret scan passing across 558 text
files. Those results are historical repository evidence. They are not current
hardware observations or proof of firmware behavior.
The immutable result remains `READ_ONLY_PREFLIGHT_BLOCKED`. Firmware 9.60
runtime behavior remains `UNPROVEN`. The stock elfldr and Payload Manager
sizes and hashes remain reference values only; their current on-device
identity is not established.
## Schema boundary
The existing artifact schema describes built target artifacts, while the
controlled-runtime schema describes the separate Phase-0.7 hardened runtime.
Neither can represent an offline remediation dossier without implying
inapplicable artifact or deployment semantics. No shared schema is widened.
The remediation manifest therefore names the dedicated
`chimera-gfx-phase-0.8-remediation-v1` contract and is validated semantically
by `tools/validate_phase08_remediation.py`.
## Side-effect classification
- **A — persistent mutation:** file create/write/delete/rename, configuration
or autoload change, metadata change, or persistent platform-state change.
- **B — process- or service-wide mutation:** functional global flags and
counters, `server_active_flag`, `autoload_triggered`, process/service state,
signals, or retry state.
- **C — volatile technical effect:** socket acceptance, temporary buffers,
allocations, scheduler activity, kernel counters, caches, audit or logging
paths, and temporary process-local state.
- **D — observation:** firmware fields, file metadata and hashes, process and
listener lists, configuration, rollback identities, and storage conditions.
No persistent write found is not equivalent to side-effect-free. Category C
is not claimed absent. Missing observations are unknown, never evidence of
safe absence.
## Pinned Payload Manager source
The reviewed local source is public Payload Manager v0.3.1 commit
`cfbc70f30f419b09bf2b52283f7409e2d3117ee1`. Relevant source identities are
recorded in `manifests/runtime/phase-0.8-remediation.json`.
The three confirmed root findings are:
1. `http_on_request()` returns early for `OPTIONS`, then calls
`log_server_set_active()` for every other request at
`work/upstream/pldmgr-v0.3.1/src/http_server.c:131-152`.
`log_server_set_active()` writes the process-global
`server_active_flag = 1` at
`work/upstream/pldmgr-v0.3.1/src/log_server.c:20-23`.
2. `/autoload_status` calls `pldmgr_autoload_get_status()` at
`work/upstream/pldmgr-v0.3.1/src/http_server.c:847-852`.
That function writes `autoload_triggered = 1` at
`work/upstream/pldmgr-v0.3.1/src/autoload.c:44-48`. The worker reads that
flag when deciding whether to leave its frontend wait and begin the
countdown at `src/autoload.c:78-93`.
3. The same handler opens `/data/pldmgr/autoload.txt` and calls
`config_read()` at `src/http_server.c:854-871`. `config_read()` opens
`/data/pldmgr/pldmgr_config.txt` at `src/config.c:12-49`.
### Request side-effect matrix
All handlers below are rooted in `http_on_request()`. “Filesystem/config”
means project source performs such a read; it does not assert that no other
read or technical effect occurs.
| Method | Endpoint | Handler path | `server_active_flag` | `autoload_triggered` | Filesystem/config | Other proven or unproven effects | Strict read-only |
|---|---|---|---:|---:|---:|---|---:|
| `OPTIONS` | `*` | `http_on_request` | no | no | no | response/transport allocations; network, cache, audit, scheduler and kernel effects unproven | **no** |
| `GET` | `/version` | `http_on_request` | yes | no | no | B: global flag; C: transport effects | **no** |
| `GET` | `/log` | `http_on_request -> log_build_json` | yes | no | no | B: global flag; C: allocation and mutex; D: ring observation | **no** |
| `GET` | `/autoload_status` | `http_on_request -> pldmgr_autoload_get_status -> config_read` | yes | yes | yes | B: functional autoload change; C: read/transport effects; D: config observation | **no** |
| `GET` | `/get_config` | `http_on_request -> config_read` | yes | no | yes | B: global flag; C: atime/audit/cache/metadata unproven; D: config observation | **no** |
| `GET` | `/list_payloads` | `http_on_request -> payload_mgr_list_json` | yes | no | yes | directory and sidecar scans; possible USB enumeration; technical effects unproven | **no** |
| `GET` | `/processes_list` | `http_on_request -> process_list_json` | yes | no | no | `sysctl` snapshot and allocation; kernel/audit/scheduler effects unproven | **no** |
| `GET` | `/sources_list` | `http_on_request -> sources_list_json` | yes | no | yes | not excluded by `is_noisy_route`, so `pldmgr_log()` also writes stdout and the log ring | **no** |
| `GET` | `/getip` | `http_on_request -> pldmgr_get_local_ip` | yes | no | no | network-interface query; kernel/cache/audit effects unproven | **no** |
Supporting locations:
- route constants: `include/pldmgr.h:7-44`;
- noisy-route list and generic request entry:
`src/http_server.c:108-152`;
- non-noisy request logging: `src/http_server.c:479-481`;
- payload and process lists: `src/http_server.c:601-616`;
- sources list: `src/http_server.c:706-713`;
- version, log, IP, autoload and config handlers:
`src/http_server.c:826-954`;
- ring and stdout mutation: `src/log_server.c:12-55`;
- payload scan: `src/payload_mgr.c:114-153,196-238`;
- sources file read: `src/sources.c:28-84,112-134`;
- process snapshot: `src/process_mgr.c:43-88`.
`OPTIONS` is not promoted merely because it returns before the two proven
flag writes. It provides none of the required device evidence, and network,
allocation, logging below the reviewed layer, cache, audit, scheduling, and
kernel-counter effects are still unproven.
## Root-cause analysis
The current HTTP interface is a frontend-control interface, not an evidence
collector. A request is treated as evidence that the frontend is active, so
the server deliberately changes functional process state. The autoload route
goes further and changes a flag consumed by the autoload worker. This makes
the interface incompatible with the historical absolute read-only contract
even where the response body appears informational.
A filesystem open using mode `"r"` prevents application-level content writes;
it does not prove absence of atime, audit records, page-cache activity,
metadata/cache updates, scheduling, kernel counters, or platform-specific
effects. Those effects require an exact collector and environment contract.
Unavailable data cannot be interpreted as a negative observation. No current
firmware query, file identity, process/service inventory, listener inventory,
autoload snapshot, or rollback identity exists in this dossier.
A missing Payload Manager backup cannot be created in an absolute read-only
phase. Creating it necessarily writes a new persistent object and may change
filesystem allocation and metadata. Backup creation therefore belongs to a
separate mutating rollback-preparation phase with separate authorization.
## Evidence contract for a possible future method
No collector is selected. Every timeout below is deliberately unset until the
collector implementation, transport, and cleanup contract are reviewed. An
unset timeout, timeout expiry, unknown result, identity drift, or partial
dataset yields `STOP`.
| Observation | Needed fact | Possible source class | Confidence | Known mutations | Unknown effects | Required identity | Timeout | Reviewer return |
|---|---|---|---|---|---|---|---|---|
| firmware | two authoritative current values agree exactly | two independently reviewed authoritative sources | `UNPROVEN` | none established | UI/transport/audit/cache/platform query | tool/source/operation identity | unset → `STOP` | raw values, times, identities, agreement |
| live paths | literal paths, mounts, types, no symlink | reviewed no-follow metadata operation | `UNPROVEN` | none established | atime/audit/cache/namespace | tool, source, no-follow and mount semantics | unset → `STOP` | raw paths, mounts, types, symlink decision |
| object identities | stable pre/post object/device IDs and full metadata | same reviewed object collector | `UNPROVEN` | none established | cache/audit/race/concurrency | lookup, race, symlink policy | unset → `STOP` | complete pre/post records and errors |
| file sizes | exact current live byte sizes | same bound object handles | `UNPROVEN` | none established | cache/audit/concurrent modification | same-object and race policy | unset → `STOP` | sizes, references, bindings |
| SHA-256 | digest of exact current bytes | no-follow same-object streaming hash | `UNPROVEN` | none established | atime/audit/page cache/scheduling | implementation, version, commit, binary hash, open policy | unset → `STOP` | bytes, times, digest, identity, errors |
| processes/services | all relevant owners, paths, parents, starts and startup modes | reviewed process/service snapshot | `UNPROVEN` | none established | counters/audit/scheduling/locks/cache | tool/API/source/snapshot semantics | unset → `STOP` | raw snapshot and unmapped entries |
| listeners | owners and binding for 8084/8085/9021 | reviewed listener snapshot | `UNPROVEN` | none established | stack counters/audit/cache/locks/races | tool/API/source/owner mapping | unset → `STOP` | protocol/address/port/owner/exposure |
| autoload/startup/retry | complete authoritative state; artifacts absent; retry off | collector distinct from stock `/autoload_status` | `UNPROVEN` | stock route mutates `autoload_triggered` | atime/audit/cache/metadata/service/race | tool/source plus complete source list and no-functional-mutation proof | unset → `STOP` | safe raw representations, identities, hashes, decisions |
| rollback files | separate existing exact backups and restore mappings | same admissible object/hash collector | `UNPROVEN` | none established | atime/audit/cache/metadata/mount/race | hash, object and separation semantics | unset → `STOP` | paths, IDs, hashes, separation and mapping |
| storage condition | separate target, 2447320 content bytes plus reserve | reviewed capacity/mount operation | `UNPROVEN` | none established | mount/audit/cache/accounting/concurrency | tool/API and capacity semantics | unset → `STOP` | IDs, available bytes, reserve and separation |
Any code-bearing collector would additionally require its exact name, version,
origin, source commit, byte size, SHA-256, complete operation set, imports,
transitive effects, output channel, cleanup, and fail-closed timeout behavior.
## Architecture options — design only
| Option | Can prove | Cannot prove | Transfer/execution needed | Persistent effects | Volatile effects | Required permission | Remaining blockers |
|---|---|---|---|---|---|---|---|
| A. Current Payload Manager endpoints | limited in-memory version/config/list responses | strict side-effect freedom, complete files/listeners/rollback identity | no new target transfer; requires a network request to an existing process | reads may affect metadata; no content write proven for selected GETs | proven global flags; autoload flag on status; sockets, allocation, logs, caches and audit | new bounded-observation permission would still be required | current interface violates the absolute read-only contract |
| B. Future one-shot observation method | potentially a purpose-built complete bounded dataset | nothing until source, ABI, transport and cleanup are reviewed | likely transfer and execution, both currently unspecified and unauthorized | must be forbidden by contract but absence is unproven | startup, loader, transport, allocation, scheduling, cache, audit and logs | new exact artifact- and method-bound permission | no design, binary, hash, ABI, timeout or cleanup proof exists |
| C. Manual/external firmware observation | one user-visible firmware value, possibly an independent second value | live files, processes, listeners, autoload and rollback state | no code transfer or execution if strictly manual | UI/platform persistence is unreviewed | UI, audit, cache and human transcription | new exact observation permission if used as formal evidence | insufficient for the complete preflight |
| D. Split observation from rollback preparation | observation can be reviewed before any backup write; later backup phase can prove rollback objects | observation alone cannot create missing backups | observation method unknown; backup preparation necessarily performs writes | backup creation, allocation and metadata are expected persistent effects | tool, storage, cache, scheduling and audit effects | separate observation permission, then separate mutating rollback permission | exact live identity and admissible backup procedure remain absent |
None of these options is implemented by Phase 0.8R.
## Hard gates
The active blockers are:
1. `exact_permission_quote_absent``STOP-RO`;
2. `collector_identity_absent``STOP-RO`;
3. `collector_side_effect_contract_absent``STOP-RO`;
4. `two_current_firmware_sources_absent``STOP-GATE`;
5. `live_object_identities_absent``STOP-GATE`;
6. `listeners_absent``STOP-GATE`;
7. `autoload_status_absent``STOP-GATE`;
8. `rollback_backups_absent``STOP-GATE`;
9. `payload_manager_backup_not_byte_exact_on_device``HARD_STOP-GATE`;
10. `unknown_result_is_stop``STOP`;
11. `timeout_is_stop``STOP`;
12. `deviation_is_stop``STOP`;
13. `automatic_retry_forbidden``STOP`.
No general `READY`, `COMPLETE`, or deployment status may override any one of
these gates. The Payload Manager backup gate can be closed only by
artifact-specific, current, on-device evidence gathered under a separately
approved method, not by changing this manifest.
## Phase separation
Authority never flows forward. Each step requires its own completed review and
new permission where it involves a target:
1. this offline remediation;
2. a possible later bounded-observation design;
3. separate permission for any observation transfer or execution;
4. review of the returned observations;
5. separate mutating rollback preparation if a backup must be created;
6. separate installation approval for only hardened elfldr and controlled
Payload Manager;
7. installation verification and complete rollback proof;
8. separate lifecycle approval;
9. non-graphical capability probes;
10. much later, a graphics backend and RetroArch.
Installation permission does not grant lifecycle permission. Observation
permission does not grant rollback preparation. No earlier wording may be
reused for a later artifact, method, or phase.
## Relationship to RetroArch
RetroArch is a long-term goal, not an active Phase-0.8R workstream. The
dependency chain is:
```text
offline evidence integrity
-> admissible bounded observation
-> verified rollback and installation boundary
-> separately approved lifecycle
-> non-graphical capability evidence
-> later graphics/runtime contracts
-> later adapters
-> eventual RetroArch port
```
Phase 0.8R implements none of GNM, VideoOut, SDL, hardware acceleration,
input, audio, RetroArch frontend behavior, cores, or content launching.
## Machine-readable consistency record
The validator compares this block structurally with the remediation manifest.
<!-- BEGIN PHASE08R_CONTRACT -->
```json
{
"status": "READ_ONLY_PREFLIGHT_BLOCKED",
"authorization": {
"authorized": false,
"installation_authorized": false,
"lifecycle_authorized": false,
"execution_authorized": false,
"transfer_authorized": false,
"automatic_retry": false
},
"blockers": [
"exact_permission_quote_absent",
"collector_identity_absent",
"collector_side_effect_contract_absent",
"two_current_firmware_sources_absent",
"live_object_identities_absent",
"listeners_absent",
"autoload_status_absent",
"rollback_backups_absent",
"payload_manager_backup_not_byte_exact_on_device",
"unknown_result_is_stop",
"timeout_is_stop",
"deviation_is_stop",
"automatic_retry_forbidden"
],
"firmware_runtime_behavior": "UNPROVEN",
"stock_identity_classification": "reference_only",
"payload_manager_backup_classification": "hard_blocker",
"retroarch_active_phase": false
}
```
<!-- END PHASE08R_CONTRACT -->
@@ -0,0 +1,188 @@
# Phase 0.9A offline anti-brick threat model
Status: **DESIGN_ONLY**. Historical operational status:
**READ_ONLY_PREFLIGHT_BLOCKED**.
This is an offline design review. It does not describe a proven PS5
filesystem, installation method, recovery method, path, syscall or switch
primitive. No PS5 was contacted; no file was transferred, installed or
executed; no target artifact was created. Host simulation is not hardware
evidence.
## Evidence boundary
The review uses only existing repository evidence:
- immutable Phase-0.8 record and Phase-0.8R remediation contract;
- the permanent artifact denylist;
- Phase-0.7 offline identities for the hardened elfldr and controlled Payload
Manager candidates;
- stock elfldr and Payload Manager sizes and hashes as `reference_only`;
- the offline rollback and installation review documents;
- clean local source identities for hardened elfldr, controlled Payload
Manager and the unchanged lifecycle-probe source.
Current on-device paths, mounts, object IDs, hashes, firmware behavior,
processes, services, listeners, autoload state, backups and recovery paths
remain unobserved. The byte-exact on-device Payload Manager backup remains a
hard STOP gate.
Severity means:
- `CATASTROPHIC`: can remove the only working launch/recovery path, destroy
both live and rollback identities, run unverified code automatically, or
make recovery depend on a failed component;
- `HIGH`: can select or persist wrong/partial bytes, invalidate the evidence
binding, or prevent controlled recovery;
- `MEDIUM`: disrupts control or observation but does not alone prove loss of
both live and recovery objects;
- `LOW`: occurs before live mutation and should leave the old object intact,
but still needs platform evidence.
## Control profiles
### A — wrong target
Possible damage is replacement of an unrelated or critical object. Before any
future mutation, one no-follow stable object must bind literal path, mount ID,
object ID, type, size and SHA-256, and the identity must be repeated
immediately before mutation. AB-001, AB-003, AB-004 and AB-007 prevent the
write. Recovery would require a separate verified backup and independent
executor; neither is proven. Namespace and object-identity semantics remain
`UNPROVEN`, so Phase 0.9A blocks.
| ID | Scenario | Severity |
|---|---|---|
| TM-A-01 | wrong path | CATASTROPHIC |
| TM-A-02 | wrong mountpoint | CATASTROPHIC |
| TM-A-03 | symlink, junction or other redirect | CATASTROPHIC |
| TM-A-04 | path resolves to another object after preflight | CATASTROPHIC |
| TM-A-05 | case or path normalization changes identity | HIGH |
| TM-A-06 | target is replaced between check and write | CATASTROPHIC |
### B — wrong pre-image
Possible damage is treating modified or firmware-incompatible bytes as stock.
The future evidence must bind firmware, manifest, stable object, size and
digest in one current observation. AB-001 through AB-004 reject every partial
match. Detection must happen before mutation; rollback is not a substitute.
Current device identities and firmware runtime behavior remain `UNPROVEN`.
| ID | Scenario | Severity |
|---|---|---|
| TM-B-01 | live hash differs from stock reference | HIGH |
| TM-B-02 | live size differs | HIGH |
| TM-B-03 | object ID changes | CATASTROPHIC |
| TM-B-04 | firmware differs | HIGH |
| TM-B-05 | manifest belongs to another build | HIGH |
| TM-B-06 | modified installation is treated as stock | CATASTROPHIC |
### C — backup failure
Possible damage is loss of all trusted rollback bytes. A backup must be
created before staging, on a separate identity, then closed, reopened,
re-identified and rehashed. Capacity, mapping and an independent recovery
executor must be proven. AB-005, AB-006, AB-016 and AB-017 block mutation
until this holds. The Payload Manager backup is currently a
`CATASTROPHIC` hard blocker.
| ID | Scenario | Severity |
|---|---|---|
| TM-C-01 | backup missing | CATASTROPHIC |
| TM-C-02 | backup is the same object as live | CATASTROPHIC |
| TM-C-03 | backup is on the same vulnerable path | CATASTROPHIC |
| TM-C-04 | backup is partial | CATASTROPHIC |
| TM-C-05 | backup hash differs | CATASTROPHIC |
| TM-C-06 | backup cannot be reopened | HIGH |
| TM-C-07 | backup-to-target mapping is ambiguous | CATASTROPHIC |
| TM-C-08 | recovery tool depends on the replaced component | CATASTROPHIC |
| TM-C-09 | storage or metadata capacity is insufficient | HIGH |
| TM-C-10 | backup is created only after live mutation | CATASTROPHIC |
### D — write and power loss
Possible damage is a missing, partial or ambiguous live identity. A safe design
needs isolated staging, durable files and directory metadata, and one
old-or-new atomic switch. AB-007 through AB-013 reject in-place overwrite and
unproven switch semantics. No such PS5 primitive is proven.
| ID | Scenario | Severity |
|---|---|---|
| TM-D-01 | power loss before staging | LOW |
| TM-D-02 | power loss during staging | HIGH |
| TM-D-03 | power loss after staging before verification | HIGH |
| TM-D-04 | power loss during live switch | CATASTROPHIC |
| TM-D-05 | power loss immediately after live switch | CATASTROPHIC |
| TM-D-06 | power loss before directory metadata is durable | CATASTROPHIC |
| TM-D-07 | partial write | CATASTROPHIC |
| TM-D-08 | short write | HIGH |
| TM-D-09 | write error | HIGH |
| TM-D-10 | flush or fsync error | CATASTROPHIC |
| TM-D-11 | file bytes correct but directory not durable | CATASTROPHIC |
| TM-D-12 | new file has wrong ownership, mode or metadata | HIGH |
### E — process and lifecycle
Possible damage is automatic launch of unverified bytes, stale mappings or a
crash loop. A future observation must establish all relevant owners,
instances, mappings, listeners, supervisors and authoritative autoload/retry
state. AB-010, AB-013, AB-014 and AB-020 require quiescence and a later
one-shot approval. Unknown topology blocks before switch.
| ID | Scenario | Severity |
|---|---|---|
| TM-E-01 | target executable is active | HIGH |
| TM-E-02 | multiple instances exist | HIGH |
| TM-E-03 | service restarts itself | CATASTROPHIC |
| TM-E-04 | listener conflict | MEDIUM |
| TM-E-05 | process holds old file or mappings | HIGH |
| TM-E-06 | watchdog or supervisor automatically restarts | CATASTROPHIC |
| TM-E-07 | autoload starts the candidate before verification | CATASTROPHIC |
| TM-E-08 | automatic retry creates a crash loop | CATASTROPHIC |
### F — rollback failure
Possible damage is restoring wrong bytes to a wrong path, automatic execution
or loss of the recovery executor. Rollback must bind the preverified backup,
exact target mapping and independent executor. AB-006 and AB-015 through
AB-017 require a separate approval and post-rollback identity proof. A failed
rollback verification is `CATASTROPHIC/BLOCKED`, never a retry.
| ID | Scenario | Severity |
|---|---|---|
| TM-F-01 | wrong backup selected | CATASTROPHIC |
| TM-F-02 | wrong rollback target path | CATASTROPHIC |
| TM-F-03 | rollback interrupted | CATASTROPHIC |
| TM-F-04 | restored hash is wrong | CATASTROPHIC |
| TM-F-05 | rollback automatically starts a service | CATASTROPHIC |
| TM-F-06 | rollback works only if Payload Manager works | CATASTROPHIC |
| TM-F-07 | rollback works only if elfldr works | CATASTROPHIC |
### G — operator error
Possible damage is a role swap, reused authority or combined loss of both
runtime components. Component manifests and approvals must be bound to one
device, firmware, action, hash, size and expiration. AB-018 through AB-020
prohibit a combined transaction, exclude the lifecycle probe and stop phase
carryover. Component order is not guessed.
| ID | Scenario | Severity |
|---|---|---|
| TM-G-01 | hardened elfldr and Payload Manager are swapped | CATASTROPHIC |
| TM-G-02 | lifecycle probe is treated as installation candidate | CATASTROPHIC |
| TM-G-03 | wrong firmware or build is selected | HIGH |
| TM-G-04 | two installation phases are combined | CATASTROPHIC |
| TM-G-05 | approval for one component is reused for another | HIGH |
| TM-G-06 | stale manifest is used | HIGH |
| TM-G-07 | general READY overrides a specific blocker | CATASTROPHIC |
The item-specific reasons and machine bindings are in
`manifests/runtime/phase-0.9-anti-brick-design.json`.
## Decision
Every threat is detectable only under evidence contracts that are not yet
satisfied on the PS5. The design is fail-closed and suitable for host review,
but not for installation engineering on a device.
**BLOCKER: NO PROVEN POWER-LOSS-SAFE SWITCH.**
@@ -0,0 +1,201 @@
# Phase 0.9A installation transaction design
Status: **DESIGN_ONLY — NOT INSTALLATION READY**.
This document defines a future evidence and state contract. It contains no
PS5 path, install command, device write implementation, lifecycle transition,
autoload, retry, graphics code or RetroArch transition. All approval values
remain false.
## Anti-brick invariants
| ID | Mandatory invariant |
|---|---|
| AB-001 | Never write without exact stable path, mount ID, object ID, type, size and pre-image SHA-256. |
| AB-002 | A stock hash remains `reference_only` until observed on one stable on-device object. |
| AB-003 | Hash match without object identity is insufficient. |
| AB-004 | Object identity without hash match is insufficient. |
| AB-005 | Before staging, a separate backup survives close, reopen, identity, size and hash verification. |
| AB-006 | Backup and recovery do not depend on the candidate or replaced component. |
| AB-007 | Never overwrite a live executable in place. |
| AB-008 | Stage under a separate inactive identity. |
| AB-009 | Reopen and hash the candidate before activation; bytes equal the approved artifact. |
| AB-010 | No autoload, retry, service restart or boot starts the candidate. |
| AB-011 | Switch only with a separately proven transactional or atomic primitive. |
| AB-012 | Unproven atomicity or durability blocks installation. |
| AB-013 | Verify the new live identity; execution is a later approval. |
| AB-014 | At most one manual execution and zero automatic retries. |
| AB-015 | Failed post-switch verification enters `ROLLBACK_REQUIRED`, never execution. |
| AB-016 | Rollback uses only the verified backup and exact target mapping. |
| AB-017 | After rollback, re-establish size, hash, object identity and metadata. |
| AB-018 | elfldr and Payload Manager are never replaced in one uninterrupted transaction. |
| AB-019 | The lifecycle probe is not an installation candidate. |
| AB-020 | No later phase begins without separate human permission. |
## State machine
The complete ordered state set is:
```text
OFFLINE_ONLY
-> OBSERVATION_NOT_AUTHORIZED
-> OBSERVATION_AUTHORIZED
-> DEVICE_IDENTITY_OBSERVED
-> LIVE_OBJECTS_VERIFIED
-> BACKUP_NOT_PRESENT
-> BACKUP_CREATION_NOT_AUTHORIZED
-> BACKUP_CREATION_AUTHORIZED
-> BACKUP_CREATED
-> BACKUP_REOPENED_AND_VERIFIED
-> RECOVERY_PATH_VERIFIED
-> CANDIDATE_NOT_AUTHORIZED
-> CANDIDATE_APPROVED_OFFLINE
-> STAGING_NOT_AUTHORIZED
-> STAGING_AUTHORIZED
-> CANDIDATE_STAGED
-> CANDIDATE_REOPENED_AND_VERIFIED
-> TARGET_NOT_QUIESCENT
-> TARGET_QUIESCENT
-> SWITCH_NOT_AUTHORIZED
-> SWITCH_AUTHORIZED
-> SWITCH_IN_PROGRESS
-> POST_SWITCH_VERIFY
-> MANUAL_EXECUTION_NOT_AUTHORIZED
-> MANUAL_EXECUTION_AUTHORIZED
-> ONE_SHOT_EXECUTION
-> ACCEPTED
```
The only recovery branch is:
```text
POST_SWITCH_VERIFY
-> ROLLBACK_REQUIRED
-> ROLLBACK_AUTHORIZED
-> ROLLBACK_IN_PROGRESS
-> ROLLBACK_VERIFIED
```
Any error, mismatch, timeout, unknown or object change goes to `BLOCKED`.
No state automatically crosses an authorization state. There is no automatic
retry, autoload, lifecycle, graphics or RetroArch transition. A general READY
value cannot bypass a specific gate.
The current real state is `OFFLINE_ONLY`; the repository templates do not move
it.
## Approval separation
Observation, backup creation, staging, switch, one-shot execution and rollback
each require a different active-task authorization. An authorization must bind
one component, device, exact firmware, live pre-image, candidate hash and
size, action count, runtime, expiration and stop conditions. Reuse for another
hash, action or component fails.
Phase 0.9A grants none of these authorizations. The simulator uses explicitly
labelled synthetic authorization objects only to test state-machine logic.
Those objects always report `installation_authorized=false` and
`execution_authorized=false`.
## Component-separated models
### Hardened elfldr
- stock reference: 397000 bytes,
`092d16ee0ede0c494947efd38d1a17bbd7cc4b022d3858ea898833c188c703e8`;
- candidate reference: 397000 bytes,
`63e810982471eb40cae3a20aa9df9a0a02892f420e429874fae4e99aa400b561`;
- live path, mount, object ID and current hash: `UNPROVEN`;
- separate on-device backup: `UNPROVEN`;
- process, service, listener, autoload and quiescence: `UNPROVEN`;
- target mapping, recovery independence and switch primitive: `UNPROVEN`;
- approval, staging, switch, execution, acceptance and rollback: not
authorized or performed.
### Controlled Payload Manager
- stock reference: 2050320 bytes,
`518740adbacccb9094fadb07dd424c53ee290f38306449ccc9d6957fdf813c0b`;
- candidate reference: 99560 bytes,
`8fecf8241a46246eddbd21e8bb4d875f5d76f1f4f4c6a11384df1f131aa5e5b1`;
- live path, mount, object ID and current hash: `UNPROVEN`;
- byte-exact, separate, reopened on-device backup: **HARD_BLOCKER**;
- process, service, listener, autoload and quiescence: `UNPROVEN`;
- target mapping, recovery independence and switch primitive: `UNPROVEN`;
- approval, staging, switch, execution, acceptance and rollback: not
authorized or performed.
There is no “install all” operation and no shared approval. Component B may be
considered only after component A is separately accepted or fully rolled back,
but Phase 0.9A does not infer which component is A. Order requires proven
dependency and recovery evidence. The lifecycle probe belongs to neither
model.
## Switch contract
Design preference, without assuming platform support:
1. side-by-side or dual-slot activation without deleting stock;
2. proven atomic exchange;
3. proven transactional snapshot;
4. another method only after separate evidence.
An in-place copy-overwrite is always forbidden. The sequence `rename live ->
backup; rename candidate -> live` is forbidden while a power-loss interval can
leave the live name absent.
Before a future switch, evidence must establish:
- filesystem type, mount identity and read/write state;
- atomic rename or exchange behavior and replacement semantics;
- file-flush and directory-flush durability;
- interruption and power-loss behavior;
- no-follow behavior and stable open-object identity;
- ownership, mode and metadata preservation;
- capacity, metadata reserve and maximum file size;
- behavior while the target executable is open.
None is proven for the PS5 in this phase.
**BLOCKER: NO PROVEN POWER-LOSS-SAFE SWITCH.**
## Power-loss boundary table
All results are `UNPROVEN` for PS5. The host simulator can prove only its own
virtual atomic primitive.
| # | Boundary | Possible state | Live visibility | Backup | Auto-start | Recovery | Result |
|---:|---|---|---|---|---:|---|---|
| 1 | before backup write | old live only | old | absent | no | no mutation yet | UNPROVEN |
| 2 | during backup write | old plus partial backup | old | invalid partial | no | old must remain | UNPROVEN |
| 3 | after backup write before flush | volatile backup | old | not durable | no | old must remain | UNPROVEN |
| 4 | after flush before reopen/hash | unverified backup | old | not reverified | no | old must remain | UNPROVEN |
| 5 | during candidate staging | partial candidate | old | verified if contract holds | no | independent | UNPROVEN |
| 6 | after staging before verification | unverified candidate | old | verified if contract holds | no | independent | UNPROVEN |
| 7 | immediately before switch | three verified logical objects | old | verified | no | independent | UNPROVEN |
| 8 | during switch | must be complete old or complete new | unknown | must remain verified | no | independent | UNPROVEN |
| 9 | immediately after switch | namespace/durability uncertain | unknown | must remain verified | no | independent | UNPROVEN |
| 10 | after switch before live hash | nominal new live unverified | unverified | verified | no | independent | UNPROVEN |
| 11 | after live hash before execution | nominal verified new | new | verified | no | independent | UNPROVEN |
| 12 | during first manual execution | new plus backup | new | verified | no automatic start | must work without new component | UNPROVEN |
| 13 | during rollback | must be complete new or complete old | unknown | must remain verified | no | independent | UNPROVEN |
| 14 | after rollback before verification | nominal restored old | unverified old | verified | no | independent | UNPROVEN |
Because at least one boundary is `UNPROVEN`, the model is not
installation-suitable. Here all fourteen are `UNPROVEN`.
## Host simulator
`tools/simulate_phase09_transaction.py` models logical objects, identities,
hashes, mounts, approvals, transitions, failures and all fourteen power-loss
boundaries in memory. It has no device path, network operation, cross-compiler
call, target artifact open, production installer or output-file option.
The default scenario stops at
`NO_PROVEN_POWER_LOSS_SAFE_SWITCH`. A special in-memory primitive can be
treated as atomic for fault-testing, but every report marks it
`host_simulation_only=true` and `hardware_evidence=false`. Even that synthetic
happy path stops at `MANUAL_EXECUTION_NOT_AUTHORIZED`.
The machine-readable contract is
`manifests/runtime/phase-0.9-anti-brick-design.json`.
@@ -0,0 +1,106 @@
# Phase 0.9A recovery and rollback contract
Status: **DESIGN_ONLY — RECOVERY UNPROVEN**.
This contract states what future evidence must prove. It does not authorize or
implement backup creation, transfer, installation, switch, rollback or
execution.
## Valid backup contract
A future backup is valid only when all conditions hold:
1. it is created before staging or any live mutation;
2. the source object and exact restoration target are recorded;
3. the source stays the same stable object throughout the read;
4. every byte is read and the exact size is recorded;
5. SHA-256 equals the current observed pre-image;
6. the backup is a distinct object, not an alias of live;
7. it is closed, reopened without redirection, re-identified and rehashed;
8. its storage medium and mount are recorded;
9. content and metadata capacity plus reserve are proven;
10. autoload, cleanup and packaging cannot delete it;
11. it is never replaced by candidate bytes;
12. mapping is literal and not selected by a glob, basename or guess;
13. rollback does not guess the live target;
14. recovery can use it without the component being replaced.
A second byte-exact off-device copy with its own manifest and SHA-256 is
strongly recommended. Creating or transferring that copy is a later,
separately authorized phase and is not permitted here.
For the controlled Payload Manager, an absent, differing, unstable,
non-reopenable or recovery-dependent byte-exact on-device backup remains a
**HARD STOP-GATE**.
## Recovery independence
Before any component transaction, evidence must answer all rows without
inference:
| Question | Hardened elfldr | Controlled Payload Manager |
|---|---|---|
| How is recovery started? | UNPROVEN | UNPROVEN |
| Which exact component executes recovery? | UNPROVEN | UNPROVEN |
| Is that executor outside the component being replaced? | UNPROVEN | UNPROVEN |
| Does recovery work when elfldr does not start? | UNPROVEN | UNPROVEN |
| Does recovery work when Payload Manager does not start? | UNPROVEN | UNPROVEN |
| Does recovery work without autoload? | UNPROVEN | UNPROVEN |
| Does recovery work without the replaced listener? | UNPROVEN | UNPROVEN |
| Is a second independent recovery path proven? | UNPROVEN | UNPROVEN |
A generic console recovery mode is not counted. No public evidence in this
repository proves that it restores custom project files.
If rollback depends on the component being replaced, the result is:
**CATASTROPHIC BLOCKER.**
## Rollback transition
Rollback is not an automatic exception path. It requires:
```text
POST_SWITCH_VERIFY failure
-> ROLLBACK_REQUIRED
-> separate human ROLLBACK_AUTHORIZED
-> ROLLBACK_IN_PROGRESS
-> ROLLBACK_VERIFIED
```
The rollback action may use only the already reopened and verified backup and
the fixed target mapping. It may not autoload, start or retry either component.
After the switch, path, mount, object ID, type, size, SHA-256, ownership, mode
and relevant metadata are re-established before any later decision.
An interrupted rollback is acceptable only if a proven atomic primitive leaves
exactly one complete live identity and preserves the verified backup. That
primitive is not proven on PS5. A wrong post-rollback hash is
`CATASTROPHIC/BLOCKED`; there is no retry.
## Component isolation
The hardened elfldr and controlled Payload Manager have separate live
pre-images, backups, candidates, target mappings, recovery dependencies,
process/service/listener states, autoload evidence, approvals, staging,
switches, post-switch checks, executions, acceptances and rollbacks.
There is no shared approval and no combined transaction. A second component
cannot begin until the first is separately accepted or fully rolled back.
Which component comes first is `UNPROVEN`; order must follow demonstrated
dependencies rather than convenience. The lifecycle probe is outside both
installation and rollback models.
## Current blockers
- historical `READ_ONLY_PREFLIGHT_BLOCKED`;
- current live identities and firmware behavior are unproven;
- exact Payload Manager backup is absent as proven evidence;
- filesystem atomicity, exchange, file durability and directory durability are
unproven;
- process, supervisor, listener, autoload and retry topology is unproven;
- no independent recovery executor or second recovery path is proven;
- no component order is proven;
- every device authorization remains false.
No blocker is lifted by this design, manifest, host simulator or test result.
@@ -0,0 +1,133 @@
# Phase 0.9B bounded observer design
Status: **BLOCKED — OFFLINE AUDIT ONLY**.
No observer source, PS5 target, ELF, installation package, lifecycle package or
execution package was created. No PS5 connection, scan, transfer or execution
occurred. This document describes the rejected design boundary and the exact
evidence needed before implementation may start.
## Canonical boundary
- Historical Phase 0.8 remains `READ_ONLY_PREFLIGHT_BLOCKED`.
- Phase 0.9A remains `DESIGN_ONLY`.
- Firmware 9.60 runtime behavior remains `UNPROVEN`.
- Stock sizes and hashes remain `reference_only`.
- The byte-exact on-device Payload Manager backup remains a `HARD_BLOCKER`.
- Every authorization field remains `false`; automatic retry remains `false`.
- SHA-256
`4be1c17b4964f2b68c39b5145bc4af4619c32512d60269ecf5c39728b390fa63`
remains permanently denied and execution-ineligible.
## Source identities
| Source | Commit | Tree |
|---|---|---|
| hardened elfldr | `197623058f509eddde18868dafcb92fdcac66464` | clean |
| controlled Payload Manager | `e23d94ff91233aa770e2342800c1467875bdef44` | clean |
| public elfldr v0.23 base | `699e8bcff03e91e8d6ca6eba281af25c5a58d8c2` | clean |
| public Payload Manager v0.3.1 base | `cfbc70f30f419b09bf2b52283f7409e2d3117ee1` | clean |
| PS5 Payload SDK v0.41 | `d2e2e585740362976a39fdd5ccf390f199a7bc37` | clean |
| lifecycle-probe source | `fe08300339a13f899fb78ea404ada381a5cba87c` | byte identity checked |
The public bases establish provenance and the pre-hardening behavior. The
hardened source commits establish the only controlled route considered here.
No external source was contacted during this audit.
## Mandatory gates
| Gate | Required | Evidence | Result |
|---|---|---|---|
| kernelwrite-free startup | complete reachable startup path excludes kernel/process patch writes | SDK `crt/crt.c:48-80,193-220`, `crt/patch.c:25-101`, `crt/Makefile:19-26` | **FAIL** for normal CRT |
| custom entry ABI | entry register, BSS, stack, return, exit and cleanup are all proven | elfldr `elfldr.c:273-415`; prior Phase-0.5 audit | **UNPROVEN** |
| non-persistent output | payload bytes return over the hash-bound route without a device file, listener or global-state mutation | elfldr `socksrv.c:129-145,361-365`, `elfldr.c:499-520`; manager `verified_launcher.c:119-185`, `ps5_launcher.c:18-70` | **FAIL** |
| bounded exit | successful and failing observer paths terminate without relying on an unproven ABI | SDK `crt/crt.c:150-220`; hardened loader watchdog | **UNPROVEN** |
Both implementation gates fail independently. The build gate therefore stops
before observer source or target creation.
## Capability matrix
“Source present” does not mean firmware-9.60 behavior is proven. “Implement”
is `no` for every row because startup/exit and output fail first.
| Needed fact | Available local API | Source | Evidence | Implement |
|---|---|---|---|---|
| firmware source 1 | `kernel_get_fw_version()` reads `sdk_ps5_ver` | SDK `crt/kernel.c:148-171` | source present; runtime unproven | no |
| firmware source 2 | none established | — | unproven | no |
| file metadata | `open(O_RDONLY\|O_NOFOLLOW\|O_CLOEXEC)`, `fstat`, `lstat`, `close` | manager `verified_launcher.c:76-115,174-184` | source/host evidence only | no |
| object identity | pre/post `st_dev`, `st_ino`, `st_size` | manager `verified_launcher.c:26-29,87-101` | source/host evidence only | no |
| SHA-256 | bounded descriptor read plus local SHA-256 | manager `verified_launcher.c:31-55`, `src/sha256.c` | source/host evidence only | no |
| mount information | `getmntinfo()` / `getfsstat()` sample | SDK `samples/mntinfo/main.c`, `libc/getmntinfo.c` | sample present; runtime unproven | no |
| processes/services | `sysctl(KERN_PROC)` sample; no complete service map | SDK `samples/ps/main.c` | partial and runtime unproven | no |
| listeners | none established | — | unproven | no |
| autoload configuration | stock file readers and mutating HTTP handlers | manager `config.c`, `autoload.c`, `http_server.c` | unsafe or unproven | no |
| output channel | controlled route suppresses payload stdio and manager has no receive operation | elfldr `socksrv.c`, manager `ps5_launcher.c` | proven absent on controlled route | no |
| monotonic deadline | `clock_gettime(CLOCK_MONOTONIC)` in loader watchdog | elfldr `ps5_controlled.c:26-59` | source/host evidence only | no |
| process exit | normal CRT terminate path or custom return | SDK `crt/crt.c:150-220`, elfldr `elfldr.c:380-415` | observer ABI unproven | no |
Unknown capabilities remain unknown. There is no FreeBSD, PS4 or other
firmware fallback.
## Rejected runtime designs
### Normal SDK CRT
The installed compiler wrapper adds `crt1.o` unless `-nostartfiles` is used.
That object transitively contains `patch.o`. `_start()` calls
`payload_init()`, which calls `__patch_init()` before `main`.
`__patch_init()` changes credential capabilities/attributes and syscall
permission bounds. This violates the Phase-0.9B kernelwrite-free requirement.
### Freestanding custom `_start`
The loader places its `payload_args_t *` in `RDI`, stores the old instruction
pointer at `RSP-8`, and enters the ELF. Those operations show how control is
transferred; they do not prove that a bare `ret`, a direct process-exit import,
or another custom termination path performs every required cleanup safely.
The prior minimal-startup gate remains blocked. It was not bypassed.
### Controlled stdout/stderr
The controlled route passes `-1` as `stdio`. The elfldr duplicates the request
socket into standard descriptors only when `stdio > 0`. The manager transport
exposes connect, send and close callbacks but no receive callback. The fixed
`Controlled payload exited` response carries no observer data. The legacy
stdio route is not the hash-bound controlled route and is inadmissible.
### Notifications, klog and manager HTTP
A system notification is not a complete deterministic machine-readable return
channel. Klog is not proven to be a bounded host-return channel. The Payload
Manager HTTP service is a persistent listener, and ordinary routes change
process-global state; `/autoload_status` also changes autoload state. None is
admissible.
## Intended observer shape if gates are later proven
This is a non-implemented contract:
1. enter once through a source-bound, kernelwrite-free ABI;
2. emit a fixed offline-bound artifact identity;
3. initialize bounded in-memory results;
4. execute each explicitly authorized read at most once;
5. emit raw value or explicit error;
6. emit a final status;
7. terminate through a proven exit/cleanup path.
It would have no event loop, server, thread, callback, retry, sleep, process
signal, subprocess, module load, file mutation, lifecycle action, graphics,
SDL, RetroArch, GNM or VideoOut behavior.
## Decision
**BLOCKED — OBSERVER STARTUP OR EXIT ABI UNPROVEN; NO PROVEN
NON-PERSISTENT OUTPUT CHANNEL.**
The minimum missing evidence is:
1. a commit-bound, kernelwrite-free entry and termination contract that covers
BSS, stack, return/exit, crash paths and loader cleanup; and
2. a commit-bound controlled response route that carries bounded observer
bytes without a device file, new listener, persistent state or Payload
Manager global-state mutation.
@@ -0,0 +1,108 @@
# Phase 0.9B observer limitations
Status: **BLOCKED**.
## What was established
- Exact local commits and relevant source-file identities were recorded.
- Normal SDK v0.41 startup is **UNSAFE** for this phase because
`__patch_init()` is reachable before `main` and performs prohibited writes.
- A `-nostartfiles` link can omit that CRT, but safe observer entry,
return/exit, crash cleanup and resource cleanup remain **UNPROVEN**.
- The hardened controlled route is hash-bound but passes `stdio=-1`.
- The controlled manager transport sends and closes; it has no receive
callback for observer data.
- The fixed loader exit response cannot carry the requested observation set.
- Stock Payload Manager HTTP routes and log state are not an admissible
replacement output collector.
## What was not built
- no observer source;
- no target declaration;
- no PS5 object or ELF;
- no linker map;
- no disassembly or reachable callgraph;
- no artifact import, relocation, string or open-flag report;
- no double clean target build;
- no artifact manifest;
- no install, lifecycle or execution package; and
- no transfer or execution instructions.
These are intentional consequences of the pre-build hard gates, not omitted
positive evidence.
## Unsupported or unproven observations
All target observations remain unimplemented. In particular:
- only one possible firmware source exists in the reviewed SDK source;
- no independent second firmware source is established;
- firmware 9.60 runtime behavior of the first source is untested;
- mount layouts and semantics are not runtime-proven;
- a process sample exists, but complete service mapping does not;
- no exact listener snapshot and owner-mapping API was established;
- live and backup paths are absent;
- live and backup objects, sizes, identities and hashes are absent;
- authoritative autoload/startup/retry source completeness is absent;
- stable no-follow behavior on the target filesystem is unproven;
- atime, audit, cache, counter and scheduler effects remain possible; and
- output and exit remain blocked.
## Remaining anti-brick blockers
1. two current firmware sources;
2. literal live paths;
3. live mount and object identities;
4. live sizes and SHA-256;
5. mount and filesystem properties;
6. process and service inventory;
7. listener inventory and ownership;
8. complete autoload/startup/retry state;
9. existing separate rollback objects;
10. byte-exact on-device Payload Manager backup (`HARD_BLOCKER`);
11. independent recovery;
12. power-loss-safe switch semantics;
13. component order;
14. observer startup/exit ABI; and
15. non-persistent output.
No offline test may promote a stock hash, clear a device blocker, prove
firmware behavior, or authorize a later action.
## Risk of a later one-shot run
Even if a future artifact were approved, unresolved risks would include:
- the existing loaders ptrace, credential, mapping, breakpoint and
socket-overlap operations before payload entry;
- loader cleanup failure or a child that does not terminate;
- crash or return behavior different from the source-reviewed expectation;
- kernel, audit, cache, atime, scheduler and counter effects from reads;
- stale or conflicting path plans;
- concurrent object replacement during observation;
- incomplete process/service/listener snapshots;
- output truncation or loss;
- a false inference from an unsupported result; and
- operator confusion between observation evidence and installation approval.
One observation could not prove atomic switch semantics, write durability,
power-loss behavior, recovery independence under actual failure, component
order, future runtime stability, graphics safety, RetroArch compatibility or
the absence of every platform side effect.
## Minimum evidence to resume engineering
Resume target engineering only after both items are available in local,
commit-bound public source and accepted by a new review:
1. a kernelwrite-free startup and termination ABI covering BSS, stack,
return/exit, crash behavior and loader cleanup; and
2. a one-shot response channel that returns bounded observer bytes over the
controlled route without a device file, new listener, persistent state,
global Payload Manager mutation or post-exit activity.
Until then the exact decision is:
**BLOCKED — OBSERVER STARTUP OR EXIT ABI UNPROVEN; NO PROVEN
NON-PERSISTENT OUTPUT CHANNEL.**
@@ -0,0 +1,114 @@
# Phase 0.9B observer result contract
Status: **HOST CONTRACT ONLY — NO TARGET IMPLEMENTATION**.
This contract defines how a future observer result would be represented after
startup, exit and output gates are separately proven. It does not establish
those capabilities and does not authorize transfer or execution.
## Framing
The preferred representation is bounded JSON Lines because every entry can be
validated independently and a final entry can mark truncation or failure.
Whether JSON Lines is feasible without unacceptable target dependencies
remains unproven.
Every future entry must contain:
```json
{
"schema_version": 1,
"observer_build_id": "offline-bound identifier",
"observation_id": "unique bounded identifier",
"category": "firmware",
"source": "exact source identity",
"raw_value": null,
"raw_error": "UNSUPPORTED_OR_UNPROVEN",
"normalized_value": null,
"confidence": "UNPROVEN",
"persistent_mutation_performed": false,
"retry_performed": false,
"monotonic_offset_ms": null,
"truncation": false,
"fail_closed": true
}
```
Allowed confidence values are `OBSERVED`, `PARTIAL`, `UNSUPPORTED`,
`UNPROVEN`, `CONFLICT`, and `ERROR`.
`raw_value` and `raw_error` are mutually exclusive. A normalized value may be
present only when it cannot hide a raw discrepancy. The raw values from two
firmware sources are always returned separately.
## Fixed limits
No target constants are selected while the build is blocked. A future
observation plan must bind all of these to finite positive values:
- maximum complete output bytes;
- maximum entry bytes;
- maximum path bytes;
- maximum observations;
- maximum objects;
- maximum processes;
- maximum services;
- maximum listeners;
- maximum errors; and
- maximum monotonic runtime.
An exceeded limit produces one final bounded error when the output channel
still works, sets `truncation=true` and `fail_closed=true`, performs no retry,
and exits through the proven termination path.
## Per-category rules
| Category | Success evidence | Required failure form |
|---|---|---|
| observer identity | offline manifest identity repeated unchanged | `UNPROVEN` if runtime self-binding is not available |
| firmware | two separately sourced raw values and exact comparison | `UNPROVEN` for a missing source; `CONFLICT` for mismatch |
| mount | only fields with exact ABI evidence | `UNSUPPORTED` for unproven layouts or semantics |
| object metadata | literal authorized path, no-follow open, stable pre/post same-object metadata | explicit symlink, path, object-ID or size error |
| SHA-256 | exact planned size, complete bounded read, stable post-read object | short read, read error, drift or hash mismatch |
| rollback object | same rules plus a distinct available identity from live | backup missing or same-object conflict |
| processes/services | bounded read-only snapshot with exact structures | `UNSUPPORTED` when service mapping is incomplete |
| listeners | bounded read-only snapshot with exact owner mapping | `UNSUPPORTED` when API or ownership is unproven |
| autoload | minimal fields from complete authoritative sources | missing source, parse error or incomplete-source `UNPROVEN` |
No file content unrelated to the minimal autoload/retry decision may be
returned. Secrets and full configuration contents are excluded.
## Filesystem contract
A future target may read an object only when its compiled and audited path is:
```text
authorized literal path
-> open read-only + no-follow + close-on-exec
-> fstat same descriptor
-> validate regular object and planned size
-> one bounded read stream
-> fstat same descriptor
-> compare identity and size
-> no-follow path metadata comparison
-> close
```
If no-follow is not source- and artifact-proven, the result is
`PATH_SYMLINK_SAFETY_UNPROVEN` and the object is not hashed. No path is
hardcoded by Phase 0.9B. The default observation plan contains no paths.
Reads may affect atime, caches, audit records, counters or scheduling. Those
volatile or unknown effects must be reported; this contract does not call them
absent and does not authorize persistent writes.
## Terminal behavior
Every future path, including output failure, deadline, unsupported query,
parse error, read error, limit exhaustion and conflict, must reach the proven
termination path. No retry, sleep-and-retry, callback, background thread,
listener, process signal, service action or subprocess may occur.
The host-only model in `tests/phase09b_observer_model.py` exercises these
contract decisions without filesystem or network I/O. It is a guardrail, not
PS5 code or hardware evidence.
@@ -0,0 +1,152 @@
# Phase 0.9B observer static audit
Status: **NOT PERFORMED — BLOCKED BEFORE SOURCE AND BUILD**.
This is a truthful negative audit record. No observer artifact exists, so no
ELF property can be reported as passing. Absence of imports or strings is not
used as a substitute for a reachable-code proof.
## Build decision
The source audit stopped the target build because:
- normal SDK startup reaches `__patch_init()` and performs prohibited writes;
- a freestanding observer return/exit and cleanup contract remains unproven;
- the hash-bound controlled route suppresses payload stdout/stderr; and
- the controlled manager sends the ELF and closes without receiving observer
output.
No observer source path or CMake target was added. The existing
`CHIMERA_GFX_BUILD_PS5_MINIMAL_STARTUP` configure-time blocker remains intact.
## Required artifact audit status
| Audit | Status | Reason |
|---|---|---|
| SHA-256 and size | `NOT_APPLICABLE_NO_ARTIFACT` | no binary |
| source commit binding | `NOT_APPLICABLE_NO_ARTIFACT` | no target source |
| toolchain identity | `PARTIAL_OFFLINE_REFERENCE_ONLY` | SDK v0.41 pinned; no observer link |
| double clean build | `NOT_PERFORMED_BLOCKED_BEFORE_BUILD` | hard gates failed |
| ELF header | `NOT_APPLICABLE_NO_ARTIFACT` | no ELF |
| program headers | `NOT_APPLICABLE_NO_ARTIFACT` | no ELF |
| section headers | `NOT_APPLICABLE_NO_ARTIFACT` | no ELF |
| dynamic dependencies | `NOT_APPLICABLE_NO_ARTIFACT` | no ELF |
| imported/undefined symbols | `NOT_APPLICABLE_NO_ARTIFACT` | no ELF |
| exported symbols | `NOT_APPLICABLE_NO_ARTIFACT` | no ELF |
| relocations | `NOT_APPLICABLE_NO_ARTIFACT` | no ELF |
| linker map | `NOT_CREATED` | no link |
| reachable callgraph | `NOT_CREATED` | no code |
| disassembly | `NOT_CREATED` | no code |
| strings | `NOT_APPLICABLE_NO_ARTIFACT` | no ELF |
| denied capabilities | `NOT_APPLICABLE_NO_ARTIFACT` | no ELF |
| filesystem open flags | `NOT_APPLICABLE_NO_ARTIFACT` | no ELF |
| network functions | `NOT_APPLICABLE_NO_ARTIFACT` | no ELF |
| threads/loops | `NOT_APPLICABLE_NO_ARTIFACT` | no ELF |
| kernelwrites | `NOT_APPLICABLE_NO_ARTIFACT` | no ELF |
The validator fails if a Phase-0.9B ELF, map, observer target, observer source
directory, installation package or lifecycle package appears while the
manifest remains blocked.
## Transitive startup audit
### Normal SDK link
The SDK compiler wrapper at commit
`d2e2e585740362976a39fdd5ccf390f199a7bc37` selects
`target/lib/crt1.o` unless `-nostartfiles` is present. The CRT Makefile links:
`crt.o`, `syscall.o`, `klog.o`, `nid.o`, `kernel.o`, `rtld.o`, `rtld_so.o`,
`rtld_sprx.o`, `rtld_payload.o`, `rtld_dlfcn.o`, `mdbg.o`, and `patch.o`.
The installed `crt1.o` is 112256 bytes with SHA-256
`0e4c1e5e38f22026580e856238a53e75d9e112f99a34bfe5495a3a0ffac15238`.
It was inspected as source-bound evidence and was not linked into a new
artifact.
Reachable sequence from normal `_start`:
```text
_start
-> clear BSS
-> payload_init
-> __crt_syscall_init
-> __kernel_init
-> __klog_init
-> write __isthreaded
-> __patch_init
-> patch_kernel_ucred
-> kernel_set_ucred_caps
-> kernel_set_ucred_attrs
-> patch_syscall_permissions
-> kernel_copyin syscall low bound
-> kernel_copyin syscall high bound
-> __rtld_init
-> payload_run
-> constructors
-> main
-> destructors
-> payload_terminate
```
Result: **UNSAFE** for the Phase-0.9B kernelwrite-free contract.
### Custom entry
`-nostartfiles -nodefaultlibs` can remove `crt1.o` and default libraries.
However, compile/link capability alone does not establish safe behavior.
elfldr `elfldr_prepare_exec()` shows `RDI=args`, `RIP=entry`, and the old RIP
stored on the adjusted stack. No source establishes the complete observer
post-return cleanup, process-exit, crash, or resource-lifetime contract for a
new bare entry. Result: **UNPROVEN**.
## Output audit
Controlled elfldr call path:
```text
controlled manager
-> connect_loopback
-> send_all(control header)
-> send_all(ELF bytes)
-> close_socket
elfldr controlled route
-> payload_read_controlled
-> payload_spawn
-> elfldr_spawn(stdio = -1)
-> no stdio duplication
-> watchdog/reap
-> fixed "Controlled payload exited" loader response
```
There is no manager receive callback and no payload-provided response body.
Result: **NO PROVEN NON-PERSISTENT OUTPUT CHANNEL**.
## Existing loader effects versus observer effects
The hardened loader performs ptrace, credential, mapping, socket-overlap,
breakpoint, protection and cleanup operations before and around entry. Those
are existing loader effects, not code introduced by an observer artifact.
They are still relevant to the risk of a later execution and do not make the
observers own startup kernelwrite-free.
Because no observer was built:
- observer imports: none to report;
- observer filesystem reads: none implemented;
- observer network functions: none implemented;
- observer threads or loops: none implemented;
- observer prohibited capabilities: none implemented; and
- absence of an artifact is not hardware-safety proof.
## Reproducibility
Build 1 hash: `null`.
Build 2 hash: `null`.
Final artifact hash/size: `null` / `null`.
Result: `NOT_PERFORMED_BLOCKED_BEFORE_BUILD`, not
`REPRODUCIBILITY_PASSED`.
@@ -0,0 +1,103 @@
# Phase 0.9C capability closure
Status: **NO TARGET CAPABILITY CLOSED**.
“Host evidence” below means a deterministic model or source validator. It is
not PS5 evidence. `implementation allowed` and `execution allowed` are false
for every capability because the startup/exit, output, firmware-source, and
side-effect gates fail before target implementation.
## Closure matrix
| Capability | Source evidence | Host evidence | Target evidence | Implement allowed | Execute allowed | Remaining blocker |
|---|---|---|---|---:|---:|---|
| runtime self-identity | future protocol binds observer version and artifact SHA-256 | framing validates both | absent | false | false | no target artifact or runtime self-binding |
| firmware source 1 | SDK `kernel_get_fw_version`, `crt/kernel.c:148-170` | protocol binds raw value | absent | false | false | depends on prohibited runtime and is not independent system identity |
| firmware source 2 | export-stub name only, no accepted signature/semantics | missing/conflict tests fail closed | absent | false | false | independent accepted source absent |
| mount query | SDK `samples/mntinfo` and libc wrapper | unsupported can be represented | absent | false | false | ABI, completeness, runtime behavior and effects unproven |
| metadata | controlled manager no-follow pattern | result framing can represent error | absent | false | false | target metadata/no-follow semantics and effects unproven |
| object ID | manager compares `st_dev/st_ino` | completeness rules modeled | absent | false | false | stable target identity and race contract unproven |
| size | manager compares exact `st_size` | checked result length modeled | absent | false | false | current object and stable-read evidence absent |
| SHA-256 | bounded same-FD manager implementation | checksum corruption is rejected | absent | false | false | target read effects, current paths and stable object absent |
| processes | SDK `samples/ps` partial snapshot | unsupported result modeled | absent | false | false | complete ABI, bounds and semantics absent |
| services | no complete source/API mapping | unsupported result modeled | absent | false | false | service inventory and ownership semantics absent |
| listeners | no accepted snapshot/owner API | unsupported result modeled | absent | false | false | listener API, ownership and side effects absent |
| autoload/startup/retry | stock manager readers/HTTP are incomplete or side-effecting | missing source remains blocked | absent | false | false | complete authoritative sources and safe collector absent |
| rollback objects | Phase 0.8R/0.9A evidence contract only | no false promotion in validators | absent | false | false | current exact backups absent; manager backup is hard blocker |
| monotonic time | hardened loader uses `CLOCK_MONOTONIC` | deadline expiry is rejected | absent in observer ABI | false | false | loader exposes no clock callback; freestanding callable ABI absent |
| startup | SDK and hardened loader callgraphs | startup classifications validated | absent | false | false | normal CRT writes; freestanding dependency closure incomplete |
| output | current route proven send-only; D1 host contract defined | 4096-byte framing and negative tests | absent | false | false | no caller-owned target buffer/copy-out/manager delivery |
| normal exit | loader has wait/reap; status discarded | no safe exit terminal modeled | absent | false | false | return/exit semantics and teardown unproven |
| error exit | CRT error/longjmp/trap and loader reap reviewed | observer error cannot equal empty success | absent | false | false | partial unwind, status and cleanup unproven |
| timeout | loader SIGTERM/SIGKILL watchdog reviewed | timeout record is rejected | absent | false | false | kill/timeout is not an admissible safe exit |
| cleanup | pre-detach cleanup state exists; post-detach relies on process lifetime | failed/incomplete cleanup rejected | absent | false | false | mappings, FDs, buffers, loader and manager cleanup not jointly proven |
| recovery independence | Phase 0.9A contract | blocker preserved | absent | false | false | recovery executor and exact rollback objects unproven |
## Firmware-source closure
Current source 1 reads a process-parameter field associated with
`libSceLibcInternal`; its own comment says it is chosen because some payloads
modify the kernel-reported value. That makes it useful source evidence, but
not an independent second current device identity.
The SDK stubs contain
`sceKernelGetProsperoSystemSwVersion`, but a stub exports only a name/NID
surface. The repository has no reviewed public prototype, result layout,
return semantics, side-effect contract, or firmware-9.60 observation. It is
not callable evidence and is not source 2.
A future source 2 must:
1. be official/reproducible public platform evidence or a separately reviewed
locally obtained runtime value;
2. have exact function/data ABI and side-effect evidence;
3. identify the current system, not the observer's compiled SDK requirement;
4. produce an exact raw value under the same deadline;
5. be independent of source 1's data origin;
6. bind source identity, raw result, nonce, request ID, observer artifact hash
and deadline into the result record; and
7. fail closed if absent, ambiguous, stale, or conflicting.
The host protocol returns
`BLOCKED_FIRMWARE_SOURCE_2_ABSENT` for absence and
`BLOCKED_FIRMWARE_CONFLICT` for disagreement. It never normalizes a conflict
away or prefers one source.
## Cross-gate closure
The following dependencies form one conjunctive gate:
```text
kernelwrite-free usable startup
+ proven stack/relocation/BSS/TLS closure
+ callable bounded observation primitives
+ two bound firmware sources
+ bounded transient output
+ normal/error/deadline exit without kill
+ complete cleanup and unambiguous status
+ bounded accepted observation effects
= target implementation may be reconsidered
```
Every term is required. A passing host protocol cannot compensate for a
missing exit ABI. A proven read algorithm cannot compensate for an absent
output channel. Two firmware strings cannot compensate for an unreviewed ABI
or stale execution binding.
## Decision
Closed for host design:
- startup graph classifications are explicit;
- the freestanding missing dependencies are explicit;
- D1 framing is fixed at 4096 bytes and fails closed;
- stale, duplicate, incomplete, corrupt, timed-out and conflicting records
are rejected; and
- every capability has an explicit blocker.
Not closed for target implementation:
- all 21 capabilities in the matrix.
The capability result contributes to
`BLOCKED_MULTIPLE_FOUNDATIONAL_CONTRACTS`.
@@ -0,0 +1,268 @@
# Phase 0.9C output-channel feasibility
Status: **HOST CONTRACT ONLY — NO CURRENT OUTPUT CHANNEL**.
This document evaluates the four requested architectures in order. It defines
a finite host protocol because D1 is conceptually coherent, but it does not
claim that hardened elfldr, the controlled Payload Manager, or any target
implements that protocol. No production runtime was changed.
## D1 — caller-owned bounded result buffer
### Current architecture
The current `payload_args_t.payloadout` is not a caller-owned observer result
buffer:
1. hardened elfldr maps the argument page **inside the child process**
(`elfldr.c:273-287`);
2. `payloadout` is `args_mapping + 0x300`
(`elfldr.c:349-367`);
3. after detach, elfldr clears its tracked cleanup bitmap and does not read
`payloadout` (`elfldr.c:538-545`);
4. on process exit, the controlled waiter discards the `waitpid` status
(`ps5_controlled.c:36-59`); and
5. the controlled connection writes only fixed loader text
(`socksrv.c:361-365`).
The current field is therefore child-owned mapped storage whose useful
post-exit lifetime and consumption are absent. It cannot be relabelled as D1.
### Future concept
A D1 implementation could be reviewed only if a future loader revision:
- allocates exactly 4096 bytes under caller ownership;
- zero-initializes that buffer;
- makes one bounded view available for one execution;
- retains ownership outside the observer process;
- binds it to a 128-bit execution nonce and 128-bit request ID;
- prevents concurrent or reused writers;
- obtains a proven normal return/exit indication;
- validates the observer body before accepting it;
- records cleanup outcome after the observer can no longer write;
- writes the final checksum and completion marker last;
- reads it once and rejects duplicate consumption; and
- destroys the transient object without filesystem, listener, log, or
persistent shared-memory state.
That design requires a loader ABI and implementation change in a later phase.
It also depends on the startup/exit contract that Phase 0.9C did not prove.
Classification:
`CONCEPT_FEASIBLE_REQUIRES_LOADER_CHANGE_AND_EXIT_PROOF`.
## D2 — existing request/response channel
The controlled manager's transport interface contains exactly:
```text
connect_loopback
send_all
close_socket
```
Source: controlled manager `include/verified_launcher.h:38-42` and
`src/ps5_launcher.c:18-69`. `verified_launcher.c:153-183` sends the header and
artifact bytes, then closes the socket. There is no receive callback, response
buffer, length framing, result deadline, or result validation.
The elfldr side can write a fixed text line after the child is reaped, but the
controlled manager has already closed and never reads it. The text carries no
nonce, request ID, process status, capability data, checksum, truncation flag,
or cleanup status. It also cannot distinguish a normal exit from a reaped
crash because the waiter discards status.
Classification: `REJECTED_SEND_ONLY_NO_RESULT_RECEIVE`.
## D3 — loader-owned fixed status record
Hardened elfldr has transient local variables for child PID, watchdog return,
and `waitpid` status, but no persistent or returned per-request status record.
The current `wait_reaped` discards the status and the connection response is
fixed.
A small loader-owned record would still require:
- per-request storage and nonce binding;
- preservation of actual wait status;
- an exact normal/error/crash mapping;
- a proven way for the observer to supply bounded data;
- a manager receive operation and response framing; and
- lifecycle rules preventing stale reuse or a race between completion and
cleanup.
Those are production loader/manager changes and were forbidden in this task.
Classification:
`UNPROVEN_REQUIRES_LOADER_STATE_AND_PROPAGATION_CHANGE`.
## D4 — process exit status
`waitpid` supplies an integer status to the loader, but
`ps5_controlled.c:36-59` does not retain or return it. The manager receives no
status. The same fixed text can follow a normal exit or a crash, and the
watchdog result distinguishes only its own high-level completion/timeout path.
Even if later propagated, a conventional exit status has too little space for
the required observations and needs an exact mapping for success, unsupported,
observer error, crash, signal, timeout, and cleanup failure. None exists.
Classification: `REJECTED_WAIT_STATUS_DISCARDED_AND_AMBIGUOUS`.
## Rejected output mechanisms
The following remain inadmissible:
- target filesystem or target logs;
- a new socket, listener, server, debug service, or callback;
- notification, klog, stdout, stderr, crash dump, or audit log;
- kernel buffer or persistent shared memory;
- autoload or service state;
- graphics, VideoOut, SDL, GNM, or RetroArch;
- timing or another covert channel; and
- the legacy stdio route.
The controlled route passes `stdio=-1` at `socksrv.c:139-145`. Stdio
duplication occurs only for `stdio > 0` at `elfldr.c:499-520`.
## Host-only D1 protocol
The protocol model is `tests/phase09c_feasibility_model.py`. It performs no
filesystem, network, compiler, or target operation.
### Ownership and completion
The conceptual write sequence is:
```text
caller:
allocate and zero exactly 4096 bytes
bind nonce, request ID, exact artifact hash and deadline
observer:
fill fixed fields and at most 3840 body bytes
write explicit status and observed/unsupported bitmaps
write body SHA-256
return through the still-unproven safe ABI
caller after proven return and cleanup:
validate request binding and body
write cleanup status
compute final result SHA-256
write completion marker last
consumer:
validate once
reject stale, duplicate, incomplete, timed-out or inconsistent records
```
The caller-finalization step is essential: an observer cannot truthfully
attest loader cleanup that occurs only after it returns. The current loader has
no such step.
### Fixed framing
All integers are unsigned big-endian. There are no pointers, offsets supplied
by the observer, variable headers, dynamic growth, or nested lengths.
| Offset | Size | Field |
|---:|---:|---|
| 0 | 8 | magic `CHG09C01` |
| 8 | 2 | protocol version `1` |
| 10 | 2 | header size `256` |
| 12 | 4 | maximum output size `4096` |
| 16 | 4 | actual output size, inclusive of header |
| 20 | 4 | observer version |
| 24 | 4 | status |
| 28 | 4 | flags; bit 0 means truncation |
| 32 | 4 | caller-recorded cleanup status |
| 36 | 4 | reserved zero |
| 40 | 8 | requested capability bitmap |
| 48 | 8 | observed capability bitmap |
| 56 | 8 | unsupported capability bitmap |
| 64 | 8 | monotonic deadline in nanoseconds |
| 72 | 16 | execution nonce |
| 88 | 16 | request ID |
| 104 | 8 | firmware source 1, canonical NUL-padded ASCII |
| 112 | 8 | firmware source 2, canonical NUL-padded ASCII |
| 120 | 32 | exact future observer artifact SHA-256 |
| 152 | 32 | SHA-256 of body bytes |
| 184 | 32 | SHA-256 of header and body with this field and completion zero |
| 216 | 8 | completion marker `COMPLETE`, written last |
| 224 | 32 | reserved zero |
| 256 | 03840 | bounded body |
| actual4096 | remainder | required zero |
`actual_output_size` must be in `[256, 4096]`; subtraction and addition are
checked before any slice is accepted. The body size is exactly
`actual_output_size - 256`. A body larger than 3840 bytes is rejected unless
the model deliberately produces a truncated record, and every truncated
record is blocked.
### Status and bitmap rules
- only explicit `SUCCESS` can yield a valid completed record;
- observer error, timeout, firmware conflict, or any unknown status is
blocked;
- `observed & unsupported` must be zero;
- `observed | unsupported` must exactly equal the requested bitmap;
- unrequested bits are forbidden;
- explicit unsupported bits preserve evidence but do not prove the
corresponding capability;
- an empty successful body is valid only when the requested bitmap is also
fully accounted for;
- an empty observer-error body is still failure, never empty success.
### Fail-closed validation
The consumer rejects:
- wrong magic, unknown protocol version, header size, or maximum;
- invalid or overflowed actual size;
- nonzero reserved or unused bytes;
- missing completion marker;
- stale nonce or request ID;
- duplicate consumption;
- observer version, deadline, artifact hash, or firmware binding mismatch;
- absent second firmware source or conflicting firmware sources;
- expired deadline;
- body or final checksum failure;
- unknown flags or truncation;
- incomplete or failed cleanup;
- observer failure;
- incomplete, overlapping, or unrequested capability bitmaps.
The completion marker is not itself an integrity proof. It is accepted only
after both checksums and every binding validate.
## Firmware binding
Source 1 is SDK `kernel_get_fw_version()` at `crt/kernel.c:148-170`. It reads
the `sdk_ps5_ver` field from the `libSceLibcInternal` process parameter and is
not independent device evidence. The SDK export stubs contain the symbol name
`sceKernelGetProsperoSystemSwVersion` at
`sce_stubs/libkernel_web.c:2358-2360`, but no reviewed public header,
signature, layout, semantics, side-effect contract, or firmware-9.60 runtime
evidence accompanies that name. A symbol name is not an ABI and is not source
2.
A future source 2 must be independently sourced, publicly reviewable or
locally cryptographically bound, current for the same execution, exact rather
than normalized from an ambiguous value, and bound into the same nonce and
request record. Absence yields `BLOCKED_FIRMWARE_SOURCE_2_ABSENT`; disagreement
yields `BLOCKED_FIRMWARE_CONFLICT`. Source 1 is never silently preferred.
## Feasibility decision
The 4096-byte D1 framing is internally closed and host-testable. That proves
only the data contract. It does not prove:
- a caller-owned target buffer;
- a shared mapping or copy-out ABI;
- an observer write boundary;
- a safe return or process exit;
- caller finalization after real cleanup;
- manager delivery; or
- firmware 9.60 runtime behavior.
No current bounded non-persistent output channel exists. The output result is
therefore `BLOCKED_NO_BOUNDED_OUTPUT_CHANNEL` despite the passing host model.
@@ -0,0 +1,108 @@
# Phase 0.9C observation side-effect model
Status: **OBSERVATION SIDE EFFECTS UNBOUNDED**.
This is an offline classification. No observation ran on a PS5. A source-level
`read`, `O_RDONLY`, metadata query, syscall, or manager request is never
promoted to side-effect-free merely because project code does not write file
content.
## Distinct effect dimensions
| Dimension | Meaning in this review | Required proof for absence |
|---|---|---|
| content | bytes of the observed object do not change | exact operation and all callees contain no content mutation |
| metadata | timestamps, flags, ownership, allocation or namespace state do not change | target filesystem and syscall semantics for the exact mount |
| atime | access time is not updated immediately or lazily | exact mount policy plus operation semantics |
| audit | platform audit/security/logging does not record the access | complete platform policy and service path |
| cache | page, name, attribute, service or network caches do not change | complete kernel/service implementation or an accepted bounded effect |
| counters | syscall, network, service, kernel or security counters do not change | complete implementation and counter inventory |
| service state | flags, wakeups, queues, worker state or functional service state do not change | exact service source and all invoked dependencies |
| security monitoring | access does not trigger security/accounting observation | exact policy and monitor implementation |
| open bookkeeping | descriptor tables, vnode references, locks, access records and reference counts remain unchanged | exact open/query semantics and close cleanup |
| process accounting | CPU time, scheduler data, resource usage and process records remain unchanged | platform accounting contract |
| object lifetime | an open/reference cannot delay deletion, replacement, unmount or cleanup | exact reference and namespace semantics |
| races | the observed identity cannot change between validation and read | stable-handle and concurrent-mutation contract |
Absence of a persistent content write proves none of the other rows.
## Classification vocabulary
Every proposed observation is labelled with one or more of:
- `SEMANTICALLY_READONLY`;
- `METADATA_EFFECT_POSSIBLE`;
- `ATIME_EFFECT_POSSIBLE`;
- `AUDIT_EFFECT_POSSIBLE`;
- `CACHE_EFFECT_POSSIBLE`;
- `COUNTER_EFFECT_POSSIBLE`;
- `SERVICE_STATE_EFFECT_POSSIBLE`;
- `SECURITY_MONITORING_EFFECT_POSSIBLE`;
- `OPEN_BOOKKEEPING_EFFECT_POSSIBLE`;
- `PROCESS_ACCOUNTING_EFFECT_POSSIBLE`;
- `OBJECT_LIFETIME_EFFECT_POSSIBLE`;
- `OBJECT_RACE_POSSIBLE`;
- `NOT_PROVABLY_SIDE_EFFECT_FREE`.
`SEMANTICALLY_READONLY` means only that the requested information flow does
not intentionally alter the observed value. Every row below remains
`NOT_PROVABLY_SIDE_EFFECT_FREE`.
## Observation matrix
| Observation | Application intent | Possible effects | Source boundary | Result |
|---|---|---|---|---|
| runtime self-identity | compare in-memory fixed identity | cache, audit, process accounting, loader mapping already exists | no target implementation | `NOT_PROVABLY_SIDE_EFFECT_FREE` |
| firmware source 1 | read `sdk_ps5_ver` process parameter | syscall/dynamic-member lookup, cache, audit, counters, process accounting | SDK `crt/kernel.c:148-170`; requires prohibited normal runtime dependencies | `NOT_PROVABLY_SIDE_EFFECT_FREE` |
| firmware source 2 | independently query current system firmware | all query ABI and effects unknown | only an export name exists; no accepted ABI | `UNPROVEN` |
| mount query | enumerate mount state | cache, audit, counters, locks, reference lifetime, snapshot races | SDK sample only; runtime semantics unproven | `NOT_PROVABLY_SIDE_EFFECT_FREE` |
| file metadata | no-follow stable-object metadata | metadata/access bookkeeping, cache, audit, reference lifetime, races | manager host/source pattern only | `NOT_PROVABLY_SIDE_EFFECT_FREE` |
| object ID and size | compare pre/post identity | same as metadata plus concurrent replacement race | manager `verified_launcher.c:26-29,83-115,174-176` | `NOT_PROVABLY_SIDE_EFFECT_FREE` |
| file SHA-256 | bounded descriptor read | atime, metadata, page cache, audit, counters, open bookkeeping, lifetime, races | manager `verified_launcher.c:31-55`; PS5 semantics unproven | `NOT_PROVABLY_SIDE_EFFECT_FREE` |
| process snapshot | enumerate process records | kernel allocation/cache/counters, scheduler/accounting, snapshot races | SDK process sample is partial | `NOT_PROVABLY_SIDE_EFFECT_FREE` |
| service snapshot | map services and supervisors | service queries, queues/counters/cache/audit and races | no complete API or mapping | `UNPROVEN` |
| listener snapshot | enumerate sockets and owners | network counters/cache/locks, service state, owner mapping races | no accepted API | `UNPROVEN` |
| autoload/startup/retry | read all authoritative sources | atime/metadata/cache/audit/open state; stock HTTP also changes global/autoload state | Phase 0.8R source audit | `NOT_PROVABLY_SIDE_EFFECT_FREE`; stock route is side-effecting |
| rollback objects | metadata and hash existing backups | same filesystem effects plus object lifetime and target/backup race | no current paths or objects | `UNPROVEN` |
| monotonic time | enforce deadline | clock/syscall counters, vDSO/runtime dependencies, accounting | only loader-owned clock use is source-proven | `NOT_PROVABLY_SIDE_EFFECT_FREE` for a future observer |
| result publication | write caller-owned transient buffer | caller memory mutation, cache, accounting, synchronization and lifetime | host-only concept; no target owner | `UNPROVEN` |
## Stock Payload Manager remains inadmissible
Phase 0.8R already proves that non-`OPTIONS` requests set
`server_active_flag`, `/autoload_status` sets `autoload_triggered`, and several
routes read configuration or mutate logging state. `OPTIONS` does not provide
the needed data and still has unproven network, allocation, audit, cache,
scheduler and counter effects.
Phase 0.9C does not reinterpret those endpoints as a collector. A persistent
listener or HTTP response is also forbidden as observer output.
## Filesystem-specific conclusion
The controlled manager demonstrates a useful source pattern:
```text
open(O_RDONLY | O_NOFOLLOW | O_CLOEXEC)
-> fstat
-> bounded read
-> fstat
-> lstat path
-> compare identity/size
-> close
```
That pattern can detect several races in the reviewed source. It does not
prove no atime update, no audit record, no page-cache fill, no vnode/reference
bookkeeping, no process accounting, or no platform-specific service effect.
It also cannot make a hash atomic with respect to every target namespace race
without proven filesystem and stable-object semantics.
## Decision
No planned observation is proven side-effect-free on firmware 9.60. A later
phase would need an explicit bounded-effect budget rather than an absolute
zero-effect claim, plus exact public ABI/source evidence and separately
authorized runtime observation. Phase 0.9C grants neither.
Current blocker: `BLOCKED_OBSERVATION_SIDE_EFFECTS_UNBOUNDED`.
@@ -0,0 +1,289 @@
# Phase 0.9C startup and exit feasibility
Status: **BLOCKED**. This is a source-bound offline analysis. It does not add
an observer, target source, PS5 object, ELF, linker map, installation package,
lifecycle package, transfer path, or execution authority.
## Evidence boundary
The exact reviewed sources are:
| Component | Commit | Relevant file identity |
|---|---|---|
| hardened elfldr | `197623058f509eddde18868dafcb92fdcac66464` | `elfldr.c` SHA-256 `9949f8e4037984d10f1f5aa498e4665593d1fac8a33614d7f2141349839bb803` |
| hardened elfldr controlled route | same | `socksrv.c` SHA-256 `d642ced3e9b4a296dd15e355050ebe956f53a6dfdaa6ac10109cd067a3bba3d7` |
| hardened cleanup model | same | `controlled_runtime.c` SHA-256 `10145f3bbb3b54e3d715b1667e45c6f12d3c7f52a04342ab104ec8dd49e384c9` |
| hardened PS5 cleanup adapter | same | `ps5_controlled.c` SHA-256 `68717ef1cc31c483743c5af325c59e73a90f66e93b880b989e349a4ddc748772` |
| controlled Payload Manager | `e23d94ff91233aa770e2342800c1467875bdef44` | `verified_launcher.c` SHA-256 `066100ca4917c7acc560e2e85666ca136cd7ccfd9094417377048f41106dd56e` |
| controlled manager adapter | same | `ps5_launcher.c` SHA-256 `29c1a5fd01784a59e88b3698940f120cb03020071bc2b7d74a1da1a51524ef59` |
| PS5 Payload SDK v0.41 | `d2e2e585740362976a39fdd5ccf390f199a7bc37` | `crt/crt.c` SHA-256 `3875f4739ec40b33f1f4967a1acbb585a527d2c281a360153e1f69c8b945932a` |
| SDK patch implementation | same | `crt/patch.c` SHA-256 `4f76a677bba54f4641e1cf2755768c29afb7464a35b2f21e85db2aa2785eceac` |
| SDK CRT object set | same | `crt/Makefile` SHA-256 `6a62f777f32ab05cbe7bff81c00cfd6639ba8bf440aba611a40ff0b62732568b` |
| SDK compiler wrapper | same | `host/bin/prospero-clang` SHA-256 `0cf49ae43d6110a7606c0ee4d702fc4b5d5e1c3ae9a722945a48b80294e295ba` |
| SDK linker script | same | `host/elf_x86_64.x` SHA-256 `169b80d01da601ef96bbc584986608dec1d9c01397eae81eccd4e1a66b0a6c6a` |
The public bases remain elfldr
`699e8bcff03e91e8d6ca6eba281af25c5a58d8c2` and Payload Manager
`cfbc70f30f419b09bf2b52283f7409e2d3117ee1`. The lifecycle source remains
bound to commit `fe08300339a13f899fb78ea404ada381a5cba87c`; its unchanged
`samples/lifecycle_probe/main.c` is
`1ae7df1fe921ccab2a252f77975d3d441ef7725e34535b024580c0d4a242d766`.
None of these historical target sources was modified.
Classifications in this document mean:
- `PROVEN_SAFE`: the cited source proves the narrow property stated;
- `PROVEN_SIDE_EFFECTING`: the cited source proves a state change or external
operation, whether or not an earlier phase accepted it;
- `UNPROVEN`: evidence required for the claimed contract is absent;
- `NOT_APPLICABLE`: the path deliberately excludes the facility.
`PROVEN_SAFE` never means hardware-tested.
## Loader-to-entry call graph
The controlled route has this source-proven graph:
```text
controlled manager
|- open_verified
| |- open(O_RDONLY | O_NOFOLLOW | O_CLOEXEC)
| |- fstat -> bounded read/SHA-256 -> fstat
| `- lseek(fd, 0)
|- connect_loopback
|- send_all(control header)
|- send_all(exact ELF bytes)
`- close_socket
hardened elfldr on_connection
|- recv/validate controlled header
|- recv exact payload bytes -> independent SHA-256
|- payload_spawn(route=CONTROLLED)
| `- elfldr_spawn(stdio=-1)
| |- rfork_thread -> child execve(SceSpZeroConf)
| |- wait for exec/stop under finite preparation waits
| |- pt_syscall(process-needed-and-relocate)
| |- change child heap-size parameter
| |- make entry page RWX
| |- install INT3 -> continue -> stop
| |- restore byte and RX protection
| |- map payload PT_LOAD image
| |- apply R_X86_64_RELATIVE relocations
| |- map payload_args_t page
| |- create two IPv6 sockets, overlap them, and create a pipe
| |- back up child credentials
| |- raise child credentials
| |- write saved RIP to [RSP-8]
| |- set RSP=RSP-8, RIP=ELF entry, RDI=payload_args_t*
| |- restore all five credential fields
| `- ptrace detach
|- watchdog wait/reap
| `- on timeout: SIGTERM -> grace -> SIGKILL -> reap
`- write fixed loader-generated exit text
```
Sources: hardened elfldr `socksrv.c:129-157,162-215,289-375`;
`elfldr.c:80-265,273-415,480-545,643-769`;
`controlled_runtime.c:60-92,95-143,146-220,223-250`; and
`ps5_controlled.c:26-59,132-220`. The manager side is
`verified_launcher.c:31-184`, `include/verified_launcher.h:38-42`, and
`ps5_launcher.c:18-69`.
### Entry contract classification
| Property | Classification | Evidence and consequence |
|---|---|---|
| entry symbol comes from `e_entry` | `PROVEN_SAFE` | `elfldr.c:143-265` returns `base + e_entry`. |
| first argument in `RDI` | `PROVEN_SAFE` | `elfldr.c:401-409` sets `r_rdi` to the loader-created argument page. |
| synthetic return address | `PROVEN_SIDE_EFFECTING` | `elfldr.c:401-407` writes the observed RIP at `RSP-8` and moves `RSP`; the child stack is changed. |
| x86-64 stack alignment at entry | `UNPROVEN` | the loader subtracts eight but never validates the trapped `RSP` alignment. |
| meaning and safety of saved RIP | `UNPROVEN` | it is the RIP observed at the breakpoint; no reviewed contract proves the post-`ret` continuation. |
| preserved general/SIMD register set | `UNPROVEN` | source changes `RSP`, `RIP`, and `RDI` but defines no caller/callee preservation contract for a custom entry. |
| argument layout | `PROVEN_SAFE` | SDK `include/ps5/payload.h:27-36` and elfldr `elfldr.c:349-367` agree on six x86-64 fields. |
| argument ownership | `PROVEN_SIDE_EFFECTING` | elfldr maps and populates the page in the child at `elfldr.c:273-372`. |
| argument lifetime after return or exit | `UNPROVEN` | success clears the loader cleanup bitmap at `elfldr.c:538-545`; the mapping then relies on child lifetime/OS teardown. |
| image mapping | `PROVEN_SIDE_EFFECTING` | elfldr allocates child mappings, copies bytes, changes protection, and calls `msync` at `elfldr.c:143-265`. |
| relocation support | `PROVEN_SAFE` only for `R_X86_64_RELATIVE` | `elfldr.c:208-222`; no complete freestanding artifact exists whose relocations can be checked. |
| BSS zero-fill by loader | `UNPROVEN` and source-negative | `base_mirror` comes from `malloc`; `data_load` copies only `p_filesz`, then the entire mirror is copied. No zero-fill is visible at `elfldr.c:96-109,183-224`. |
| TLS setup | `UNPROVEN` | elfldr has no reviewed TLS setup in this path; no future observer layout exists. |
| constructors/destructors | `NOT_APPLICABLE` to a proposed freestanding entry | they are a stock CRT facility and are forbidden for the proposed path. |
## Normal SDK v0.41 startup
The exact normal graph is:
```text
_start(payload_args_t *)
|- clear [__bss_start, __bss_end)
|- store payload_args
|- payload_init
| |- __crt_syscall_init
| |- __kernel_init
| |- __klog_init
| |- resolve __isthreaded and write 1
| |- __patch_init
| | |- get process/ucred state
| | |- write credential capability bytes
| | |- write credential attribute bytes
| | |- write syscall lower bound 0
| | `- write syscall upper bound -1
| `- __rtld_init
|- setjmp
|- payload_run
| |- resolve argc/argv/environ/progname
| |- create/open payload rtld object
| |- load DT_NEEDED dependencies and relocate
| |- run init array
| |- main
| |- run fini array
| `- close/destroy rtld object
`- payload_terminate
|- return 0 for the runtime's detected hijacked-process case
|- resolve and call exit(payloadout)
`- trap if exit resolution/call returns
```
Sources: SDK `crt/crt.c:30-44,51-80,88-146,154-180,197-220`;
`crt/patch.c:27-100`; `crt/rtld_payload.c:51-60,203-260`; and
`crt/Makefile:19-26,50-54`.
| Step | Classification | Reason |
|---|---|---|
| BSS clear | `PROVEN_SIDE_EFFECTING` | writes every byte in the payload BSS; deterministic and process-local, but still a mutation. |
| global argument/setjmp state | `PROVEN_SIDE_EFFECTING` | writes CRT BSS state. |
| syscall/kernel/klog bootstrap | `PROVEN_SIDE_EFFECTING` | consumes loader-provided kernel transport and initializes global function/state. |
| `__isthreaded = 1` | `PROVEN_SIDE_EFFECTING` | writes resolved libc state at `crt.c:65-69`. |
| `__patch_init` | `PROVEN_SIDE_EFFECTING` and prohibited | exact capability, attribute, and syscall-bound kernel writes occur before `main`. |
| rtld initialization | `PROVEN_SIDE_EFFECTING` | resolves functions, allocates bookkeeping, and can load/start Sce modules. |
| relocation and `DT_NEEDED` processing | `PROVEN_SIDE_EFFECTING` | writes relocations and opens dependencies. |
| constructors | `PROVEN_SIDE_EFFECTING` | arbitrary linked constructor effects are permitted by this path. |
| heap use | `PROVEN_SIDE_EFFECTING` | stock rtld resolves and uses allocation functions. |
| `main` | `UNPROVEN` for an observer | no Phase-0.9C target implementation exists. |
| destructors and rtld close | `PROVEN_SAFE` only as attempted normal-path calls | no proof covers partial initialization, longjmp, trap, crash, or module-internal cleanup. |
| `payload_terminate` branch selection | `UNPROVEN` | the actual branch and its platform semantics are not bound to an observer execution. |
The normal SDK startup is therefore **not kernelwrite-free** and is unsuitable
for Phase 0.9C. The fact that Phase 0.7 accepted its bounded, process-local
effects for a different lifecycle profile does not satisfy this phase's
stricter contract.
## Error and abnormal paths
### Initialization error
`_start` writes the error to `payloadout` and calls `payload_terminate`
(`crt.c:207-210`). A failure after credential capabilities were written but
before all patch writes finish has no CRT restoration path. A failure during
rtld initialization has no demonstrated full unwind in `_start`.
Classification: `PROVEN_SIDE_EFFECTING` for partial startup and `UNPROVEN` for
complete restoration and termination.
### Runtime error
`payload_run` attempts close/destroy on some open/init/fini failures
(`crt.c:116-146`). These are source-proven calls, not proof of module, heap,
TLS, file-descriptor, or process cleanup on firmware 9.60.
Classification: `PROVEN_SAFE` for the presence of the attempted calls;
`UNPROVEN` for complete cleanup.
### `payload_exit`
`payload_exit` writes `payloadout` and longjmps to `_start`
(`crt.c:175-180`). The longjmp leaves `payload_run`; `_start` proceeds directly
to `payload_terminate`, so the normal fini/close/destroy sequence is not on
that control path.
Classification: `PROVEN_SIDE_EFFECTING`; full cleanup is `UNPROVEN`.
### Trap, crash, unexpected return, and timeout
- `payload_terminate` deliberately traps if its resolved `exit` path returns
or cannot be used (`crt.c:162-170`).
- The controlled watchdog treats any reaped child as completion but discards
the `waitpid` status (`ps5_controlled.c:36-59`).
- If the child remains alive, the watchdog uses `SIGTERM`, then `SIGKILL`, and
reaps it (`controlled_runtime.c:223-250`).
- The connection handler emits the same fixed success text after
`payload_spawn` returns a nonnegative value (`socksrv.c:361-365`).
A trap/crash can therefore be indistinguishable from a normal exit to the
manager, and timeout termination is not a safe exit under the Phase-0.9C
rules. Classification: `UNPROVEN` for crash cleanup and status meaning;
`PROVEN_SIDE_EFFECTING` and **inadmissible** for signal termination.
## Freestanding feasibility without target implementation
`prospero-clang` omits `crt1.o` for `-nostartfiles` and omits libc,
`libkernel_web`, `libSceLibcInternal`, and `libSceNet` for `-nodefaultlibs`
(`host/bin/prospero-clang:25-46,69-84`). This proves driver suppression only.
No custom entry source or target was assembled or linked.
| Required facility | Theoretical availability | Classification |
|---|---|---|
| entry address | ELF `e_entry` is transferred to `RIP` | `PROVEN_SAFE` narrow loader fact |
| valid stack memory | an existing child stack is used | `UNPROVEN` size, alignment, guard, and post-return contract |
| small automatic buffers | mechanically possible if the stack contract holds | `UNPROVEN` |
| read-only constants | PT_LOAD bytes can be mapped and protected | `PROVEN_SAFE` only for loader mapping; relocation closure is artifact-dependent |
| BSS | loader does not prove zero-fill; a custom clear is mechanically possible | `UNPROVEN` until a reviewed entry and map exist |
| TLS | no freestanding TLS contract | `UNPROVEN` |
| constructors/destructors | excluded | `NOT_APPLICABLE` |
| heap | excluded | `NOT_APPLICABLE` |
| libc/stdio | excluded by design | `NOT_APPLICABLE` |
| raw syscalls | no callable observer syscall ABI is supplied by `payload_args_t` | `UNPROVEN` |
| system calls from injected text | SDK patch widens permitted syscall address bounds | `UNPROVEN` without the prohibited patch |
| monotonic time | hardened loader has a clock, but exposes no clock callback to the payload | `UNPROVEN` in the entry |
| filesystem `open/read/fstat/close` | requires unresolved imports, a proven raw-syscall ABI, or another supplied callback | `UNPROVEN` |
| process/service/listener queries | no freestanding callable ABI is supplied | `UNPROVEN` |
| normal `ret` | mechanically reaches the saved RIP | `UNPROVEN` continuation and cleanup |
| direct process exit | would require a proven import/raw syscall and exact teardown contract | `UNPROVEN` |
| exit status | current waiter discards it | `UNPROVEN` delivery |
| output | current `payloadout` is inside the child mapping and never read by the controlled caller | `UNPROVEN` |
The important closure result is negative: removing the CRT also removes the
only reviewed syscall, kernel, rtld, import, time, and libc initialization
machinery. The loader supplies a dynamic-symbol function pointer and kernel
transport fields, but using them would reintroduce dynamic resolution or
kernel-access dependencies that this phase excludes. No useful observation
primitive is proven available to a zero-import freestanding entry.
## Return, exit, and cleanup contract
| Resource/state | Normal `ret` | process exit | error/crash | timeout |
|---|---|---|---|---|
| saved stack continuation | resumes the observed RIP; meaning unproven | not used | may be bypassed | bypassed |
| ELF and argument mappings | remain in child after detach | OS reclamation expected but not source-proven for this exact contract | unproven | child is killed/reaped, which is not safe exit |
| loader-created pipe/sockets | remain in child after detach | same unproven teardown dependency | unproven | same inadmissible kill path |
| observer local buffers | stack lifetime follows unproven continuation/process semantics | teardown semantics unproven | unproven | forcibly discarded |
| file descriptors opened by a future observer | no implementation or cleanup contract | no implementation or exact teardown proof | unproven | forcibly discarded |
| threads | a future observer forbids them; existing child/runtime state remains | no target observer exists | unproven | signals affect the whole child |
| credentials | loader restores five fields before detach | source-proven attempted and checked restore | pre-detach cleanup is tracked; post-detach crash remains dependent on process teardown | watchdog does not prove observer cleanup |
| breakpoint/page | restored before payload entry | already restored | preparation failures use cleanup | already restored |
| loader bookkeeping | returns from watchdog on reap | `waitpid` status is discarded | status is ambiguous | returns timeout/failure |
| manager bookkeeping | send-only function closes its socket before a result | no result is received | indistinguishable | no result is received |
| exit status | no defined status | locally available to `waitpid` but discarded | discarded | timeout result is loader-local |
| output availability | none | child mapping gone; no copy-out | none | none |
The current normal return path is especially unsuitable: `ret` resumes the
SceSpZeroConf continuation rather than proving process termination. The
controlled watchdog waits for process exit; if that continuation remains
alive, the only bounded endpoint is signal termination. The user explicitly
forbids treating kill, crash, timeout, or disconnect as a safe exit.
## Decision
No reviewed path proves all of:
1. kernelwrite-free entry with usable observation dependencies;
2. correct stack and register ABI;
3. deterministic BSS/relocation/TLS closure;
4. normal return or process exit with exact status semantics;
5. cleanup of mappings, descriptors, stack, loader and manager state;
6. a safe error path;
7. a safe deadline path that does not rely on kill; and
8. result availability after cleanup.
Startup is therefore `BLOCKED_STARTUP_ABI_UNPROVEN`, exit and cleanup are
`BLOCKED_EXIT_CLEANUP_UNPROVEN`, and the combined Phase-0.9C decision cannot be
positive.
+147
View File
@@ -0,0 +1,147 @@
# Phase 0.9C static audit
Date: 2026-07-18. Final classification:
**BLOCKED_MULTIPLE_FOUNDATIONAL_CONTRACTS**.
This audit stops before target implementation. No observer source, assembly,
object, ELF, map, target build, lifecycle package, installation package,
autoload package, transfer template, device address, device path, or
authorization exists.
## Exact source basis
| Source | Commit | Tree |
|---|---|---|
| hardened elfldr | `197623058f509eddde18868dafcb92fdcac66464` | clean |
| controlled Payload Manager | `e23d94ff91233aa770e2342800c1467875bdef44` | clean |
| public elfldr v0.23 | `699e8bcff03e91e8d6ca6eba281af25c5a58d8c2` | clean |
| public Payload Manager v0.3.1 | `cfbc70f30f419b09bf2b52283f7409e2d3117ee1` | clean |
| PS5 Payload SDK v0.41 | `d2e2e585740362976a39fdd5ccf390f199a7bc37` | clean |
| lifecycle source identity | `fe08300339a13f899fb78ea404ada381a5cba87c` | unchanged file hash |
Every reviewed file hash is recorded in
`manifests/runtime/phase-0.9c-feasibility.json`. The validator rehashes the
files and verifies all five external Git trees without network access.
## Immutable evidence
| Evidence | SHA-256 |
|---|---|
| Phase-0.8 document | `3fbe086175a6048176075f447ec1482074928e3b5282db97ea2169395fe1d508` |
| Phase-0.8 manifest | `47d7f452f8799979fe99b3e6d56859f03544112725bf7e5b349eba5ed81b3322` |
| Phase-0.8 original test | `8a4ad7c70de28ffe3148fd3fd1f68c36a872c53c691c9068e1ff163970863c48` |
| Phase-0.9A manifest | `39fd7c70cae998d9d74e7caf1ff3c19f9f76f7de2e5a50bc09baede4ba53e9e9` |
| Phase-0.9B manifest | `104c4a667ad17f9827fc7276852c6faeef96effb8e3561a5ebc19a62c7d51634` |
| Phase-0.9B schema | `efcea3b0001ef5b2da65c372ceb93ee2fec09c9331b2e4cbb6008212504c0918` |
Phase 0.9B remains a truthful historical blocked audit. It was not rewritten
as if Phase 0.9C evidence existed earlier.
## Startup and transitive code result
### Normal SDK path
`crt1.o` transitively includes `crt`, `syscall`, `klog`, `nid`, `kernel`,
`rtld`, `rtld_so`, `rtld_sprx`, `rtld_payload`, `rtld_dlfcn`, `mdbg`, and
`patch`. `_start` reaches `__patch_init` before `main`; credential
capabilities/attributes and syscall bounds are written. It also initializes
rtld, permits DT_NEEDED processing, relocations, constructors, heap
bookkeeping and module loading.
Result: `PROVEN_SIDE_EFFECTING`, unsuitable for the kernelwrite-free contract.
### Freestanding theoretical path
The compiler can suppress CRT/default libraries, and the loader can transfer
`e_entry` and `RDI`. The reviewed source does not close:
- stack alignment and saved-RIP continuation;
- BSS zero-fill, complete relocations, TLS, or register preservation;
- a callable read/syscall ABI without prohibited patch/runtime setup;
- monotonic time in the observer;
- normal return or process exit;
- error/deadline exit without crash/kill;
- mapping, descriptor, buffer, loader and manager cleanup; or
- result copy-out.
Result: `BLOCKED_STARTUP_ABI_UNPROVEN` and
`BLOCKED_EXIT_CLEANUP_UNPROVEN`.
## Output result
| Architecture | Audit result |
|---|---|
| D1 caller-owned buffer | coherent 4096-byte host contract; no current loader buffer, return finalizer, copy-out, or manager delivery |
| D2 existing request/response | rejected; manager is connect/send/close only |
| D3 loader-owned status | unproven; wait status is discarded and no record propagates |
| D4 process status | rejected; ambiguous, discarded, and too small |
The D1 host model validates magic/version, nonce, request ID, two firmware
fields, observer version, fixed/actual sizes, status, requested/observed/
unsupported bitmaps, truncation, artifact hash, body/final checksums, deadline,
completion, cleanup, zero padding and one-time consumption. No target code
implements it.
Result: `BLOCKED_NO_BOUNDED_OUTPUT_CHANNEL`.
## Firmware and side-effect result
SDK `kernel_get_fw_version()` is source 1 but reads a process-parameter SDK
field and is runtime-unobserved. A system-version export name in the SDK stub
has no accepted prototype or semantics and is not source 2. Result:
`BLOCKED_FIRMWARE_SOURCE_INCOMPLETE`.
No planned observation is proven free of metadata, atime, audit, cache,
counter, service/security, open-bookkeeping, process-accounting,
object-lifetime, or race effects. Result:
`BLOCKED_OBSERVATION_SIDE_EFFECTS_UNBOUNDED`.
## Target artifact audit disposition
| Audit item | Result |
|---|---|
| target source/assembly | `NOT_CREATED` |
| target compile/link | `NOT_PERFORMED` |
| ELF headers/program headers/sections | `NOT_APPLICABLE_NO_ARTIFACT` |
| imports/undefined symbols/DT_NEEDED | `NOT_APPLICABLE_NO_ARTIFACT` |
| relocations/init/fini/TLS | `NOT_APPLICABLE_NO_ARTIFACT` |
| linker map | `NOT_CREATED` |
| target reachable callgraph | `NOT_CREATED` |
| target disassembly | `NOT_CREATED` |
| double target build/hash | `NOT_PERFORMED` |
| lifecycle/install/autoload package | `NOT_CREATED` |
| execution eligibility | `false` |
| execution authority | `false` |
These are nonexistence results, not evidence that hypothetical bytes would be
safe.
## Offline verification
The final verification run is recorded as:
| Check | Result |
|---|---|
| Phase-0.9A host tests | `PASS` — 41 guardrails, 33 fault types for each of 2 components, and 14 power-loss boundaries |
| Phase-0.9A hardened-elfldr virtual fault suite | `PASS` — 33 fault results and 14 power-loss results; host simulation only, no hardware evidence, connection, or execution |
| Phase-0.9A controlled-manager virtual fault suite | `PASS` — 33 fault results and 14 power-loss results; host simulation only, no hardware evidence, connection, or execution |
| Phase-0.9B validator and host tests | `PASS` — blocked-audit validator and artifact guardrails |
| Phase-0.9C protocol cases | `PASS` — 21/21 |
| Phase-0.9C feasibility cases | `PASS` — 12/12 |
| full host configure/build/CTest | `PASS` — 22/22 |
| manifests/schema/safety/denylist/secrets/immutable/checksums | `PASS` — all dedicated validators and regression guards |
| `git diff --check` | `PASS` — no output |
The committed version of this document must contain no pending result.
## Decision
The only permitted positive classification required every foundational
contract to be proven. Five independent blocker families remain. The exact
decision is:
`BLOCKED_MULTIPLE_FOUNDATIONAL_CONTRACTS`
No automatic Phase 0.9D transition is permitted. Reconsideration requires new
public, commit-bound evidence; it does not authorize an experimental target
run to discover the missing contracts.
@@ -0,0 +1,107 @@
# Phase 0.9D bootstrap and recovery chain
Date: 2026-07-18
Status: `DESIGN_ONLY`
This is an offline source audit. It does not establish current device state,
firmware behavior, persistence, a live path, or recovery success.
No PS5 was contacted.
## Source-bound chain
```mermaid
flowchart LR
A["External jailbreak / exploit host<br/>source absent from audited trees"]
B["Rudimentary exploit ELF loader<br/>port 9020 per elfldr README"]
C["elfldr bootstrap<br/>bdj.elf -> SceRedisServer"]
D["elfldr socket service<br/>elfldr.elf, port 9021"]
E["Payload Manager ELF<br/>manual or external autoloader"]
F["Payload Manager HTTP service"]
A --> B --> C --> D --> E --> F
```
The public and hardened elfldr `README.md:3-19` describe host-to-console
delivery to a rudimentary exploit loader on port 9020. The exploit and its host
implementation are not present in any audited tree, so its repeatability and
recovery behavior are unproven. Hardened elfldr `main.c:28-89` enters through
`bdj.elf`, temporarily attaches to `SceRedisServer`, and
`bootstrap.c:38-81` starts the socket server. `socksrv.c:477-507` names that
service `elfldr.elf`, removes an already running process with that name, and
listens on port 9021.
The Payload Manager README describes either manual loading or placement by an
external autoloader. Its `deploy.sh` only sends an ELF to elfldr; it does not
install, read back, or recover a device file. The external autoloader,
jailbreak host, browser exploit, and any USB recovery implementation are absent
from the audited sources.
## Dependency and recovery graph
| Component | Commit | Persistence | Start mechanism | Boot critical | Failure impact | Recovery executor | Self-dependent | Depends on elfldr | Depends on Manager | After reboot | Evidence / classification |
|---|---|---|---|---|---|---|---:|---:|---:|---|---|
| Jailbreak/exploit host | not present | `UNPROVEN` | user/browser/host, details absent | `UNPROVEN` | bootstrap unavailable if absent | itself/external | unknown | no | no | `UNPROVEN` | README description only; `UNPROVEN` |
| Rudimentary port-9020 loader | not present | session behavior `UNPROVEN` | exploit chain | `UNPROVEN` | elfldr cannot be bootstrapped through the described route | external exploit chain | unknown | no | no | `UNPROVEN` | README description only; `UNPROVEN` |
| Hardened elfldr bootstrap | `197623058f509eddde18868dafcb92fdcac66464` | source shows process injection, not filesystem installation | sent to port 9020 | no source proof | no port-9021 service | port-9020 chain, if still available | no | no | no | `UNPROVEN` | source plus missing upstream executor; `PARTIAL` |
| elfldr socket service | same | process-local in source | bootstrap creates `elfldr.elf` | no source proof | no normal Payload Manager launch transport | bootstrap | no | no | no | `UNPROVEN` | source; `PARTIAL` |
| Public/full Payload Manager | public base `cfbc70f30f419b09bf2b52283f7409e2d3117ee1` | external autoloader or manual, exact current deployment unknown | elfldr or external autoloader | `UNPROVEN` | management UI/listener unavailable | elfldr/manual route | no | yes | no | `UNPROVEN` | README/source; `PARTIAL` |
| Controlled minimal Manager source | `e23d94ff91233aa770e2342800c1467875bdef44` | explicitly not installed by the Phase-0.7 record | would require a separately authorized transfer and launch | no | no impact on current device because installation is unproven | none in this phase | no | yes | no | not installed | source/offline record; `UNPROVEN` as device runtime |
## Bootstrap questions
1. **Original exploit start:** only described as a BD-J or WebKit-style host
route to a rudimentary loader; implementation and current operator sequence
are absent. `UNPROVEN`.
2. **Direct browser/exploit delivery:** the elfldr README proves only that an
elfldr ELF is sent host-to-console. Exact browser assets are absent.
3. **elfldr storage:** source proves a process service, not a persistent
filesystem installation. Current storage is `UNPROVEN`.
4. **Payload Manager storage:** README permits manual or external-autoloader
use; actual current storage is `UNPROVEN`.
5. **Automatic start:** controlled by an external autoloader and/or Manager
configuration not present as current device evidence.
6. **Manual-only files:** any ELF sent to elfldr can be manually launched in
principle; current availability is not proven.
7. **Gone after reboot:** process state and volatile flags are source-local,
but device restart behavior of the complete chain is `UNPROVEN`.
8. **Persistent after reboot:** no current artifact or configuration is proven
persistent.
9. **Exploit after broken elfldr:** conceptually independent in the README,
but source and current operability of the original exploit are absent:
`PARTIAL`.
10. **Exploit after broken Manager:** same `PARTIAL` result.
11. **Independent recovery payload:** the README permits sending another ELF
through port 9020, but neither the executor nor a recovery payload is
audited: `PARTIAL`, not recovery proof.
12. **Write-back through original chain:** no source-bound file-write contract
is present: `UNPROVEN`.
13. **Ignore a wrong non-autoload file:** plausible, but live path and
configuration are unobserved: `UNPROVEN`.
14. **Boot-loop potential:** depends on unknown persistent autoload state:
`UNPROVEN`.
15. **Automatic-start configuration:** external autoloader configuration is
absent. Manager uses `/data/pldmgr/autoload.txt` and
`/data/pldmgr/pldmgr_config.txt`, but this does not prove the current
bootstrap configuration.
16. **Keep automatic start disabled:** design policy requires it; actual
current state has no non-mutating source-bound attestation.
17. **Recovery after reboot:** external exploit restart is only described:
`PARTIAL`.
18. **Recovery after crash/hang:** elfldr source restarts its accept loop and
uses a controlled watchdog, but recovery of a broken persistent file is
absent.
19. **USB/browser/host independent path:** upload and launch paths exist;
no audited PS5-to-host readback or independent restore path exists.
20. **Unproven answers:** current persistence, live paths, installed versions,
autoload state, exploit repeatability, boot-loop behavior, write-back,
power-loss recovery, and post-reboot recovery all remain hardware facts.
## Recovery classification
- elfldr: `PARTIAL`. The described port-9020 bootstrap does not depend on the
port-9021 elfldr service, but its implementation and current operability are
missing.
- Payload Manager: `PARTIAL` with a `CROSS_DEPENDENT` restore shape. Manual
launch through elfldr is described, but durable restoration and verification
are absent.
- Byte-exact file recovery for either component: `UNPROVEN`.
@@ -0,0 +1,123 @@
# Phase 0.9D existing-stack endpoint matrix
Date: 2026-07-18
Status: `DESIGN_ONLY`
## Scope and common behavior
The full-profile matrix is bound to controlled Payload Manager commit
`e23d94ff91233aa770e2342800c1467875bdef44`,
`include/pldmgr.h:8-40` and `src/http_server.c:188-1181`. Its public-base
equivalent is commit `cfbc70f30f419b09bf2b52283f7409e2d3117ee1`;
the public base lacks the two `chimera` routes. The separately compiled minimal
controlled profile is in `src/controlled_manager.c:181-334`.
Unless a row says otherwise:
- authentication is absent and full-profile responses add permissive CORS;
- every non-`OPTIONS` full-profile request writes the process-local
`server_active_flag` (`http_server.c:207-208`);
- non-noisy requests also append stdout/ring log state
(`http_server.c:638-641`);
- handler responses are bounded in-memory text/JSON/static assets, not an
arbitrary-file response;
- there is no automatic server-side retry, but client/UI retry is not a safe
property of the route;
- exact timeouts and maximum request/response sizes are `UNPROVEN` unless
explicitly bounded in the handler;
- no row is a readback candidate.
`ANY` means the handler branch itself does not enforce a verb. This is not a
recommendation to call it.
## Full-profile routes
| Method | Exact endpoint | Handler lines | Parameters / response | File and functional effects | Classification |
|---|---|---:|---|---|---|
| `OPTIONS` | any | 193-205 | empty CORS preflight | no active flag; sockets/counters only | observation false; not file readback |
| `ANY` | `/`, `/index.html`, `/cache.appcache`, `/favicon.svg`, `/icon.png` | 709-733 | compiled static bytes | no file open; active flag | `LOW_VOLATILE`, observation partial |
| `POST` | `/chimera:upload-controlled` | 212-252, 481-537 | query filename plus identity headers; text | exclusive write flags, then verified `O_RDONLY|O_NOFOLLOW|O_CLOEXEC` reopen/hash, fsync, rename, metadata write | forbidden: create/write/rename |
| `ANY` | `/manage:upload` | 254-286, 540-585 | query filename, request body; text | `fopen("wb")`, write, rename/import, metadata | forbidden: create/truncate/write/rename |
| `POST` | `/set_config` | 288-295, 363-398 | form body; text | reads current config, then config/autoload files can use `fopen("w")` | forbidden: configuration write |
| `POST` | `/repository_push` | 297-304, 401-443 | JSON body; text | temp/cache write, remove on error, rename, config timestamp | forbidden: write/remove/rename |
| `POST` | `/sources_set` | 306-313, 446-478 | JSON body; text | sources file replacement | forbidden: configuration write |
| `POST` | `/repository_install_push` | 315-356, 588-636 | filename/repo URL plus body; text | `fopen("wb")`, write, install rename/metadata | forbidden: create/truncate/write/rename |
| `ANY` | `/usb_move_check` | 648-674 | query `path`; JSON includes USB size | directory/stat reads only; path resolve | not binary response; observation partial |
| `ANY` | `/usb_move_perform` | 676-706 | path, overwrite, keep; JSON | reads USB, writes internal copy, optionally removes source | forbidden: write/remove |
| `ANY` | `/manage:check` | 735-759 | filename; existence JSON | `stat` directory and file | no bytes/size/hash; observation partial |
| `ANY` | `/list_payloads` | 760-767 | JSON list | directory traversal, `stat`, metadata-sidecar reads | no file bytes/size/hash attestation; observation partial |
| `ANY` | `/processes_list` | 768-775 | process JSON | process enumeration | functional observation only; not readback |
| `ANY` | `/process_kill` | 776-796 | pid query; text | sends process signal | forbidden: process action |
| `ANY` | `/repository_payloads` | 797-810 | JSON cache/list | cache/config reads; multi-source path can refresh/write | forbidden: possible network/cache write |
| `ANY` | `/repository_refresh` | 811-824 | JSON | network download, cache/temp/config writes and renames | forbidden: network/write/rename |
| `ANY` | `/repository_install` | 825-865 | filename/source/detail; JSON | network or cache reads, temp/final write and rename | forbidden: install/write/rename |
| `ANY` | `/sources_list` | 866-873 | JSON | reads sources configuration | configuration disclosure; no binary file framing |
| `ANY` | `/sources_add` | 874-900 | URL query; JSON | sources configuration write | forbidden: configuration write |
| `ANY` | `/sources_remove` | 901-921 | index query; JSON | sources configuration write | forbidden: configuration write |
| `ANY` | `/chimera:load-controlled` | 922-951 | filename plus identity headers; text | `O_RDONLY|O_NOFOLLOW|O_CLOEXEC`, stat/hash/read, sends to elfldr and launches | forbidden: payload launch |
| `ANY` | `/loadpayload:<path>` | 952-983 | path suffix; text | `open(O_RDONLY)`, stat/read, sends to elfldr and launches | forbidden: payload launch |
| `ANY` | `/manage:delete` | 984-1008 | filename query; text | unlinks payload/metadata, may update autoload | forbidden: delete/configuration |
| `ANY` | `/shutdown` | 1009-1015 | text | changes server run state | forbidden: service action |
| `ANY` | `/log` | 1016-1024 | log JSON | reads ring; active flag and connection state | observation partial |
| `ANY` | `/version` | 1025-1028 | text version | no file open; active flag | observation partial |
| `ANY` | `/getip` | 1029-1036 | text address | interface/socket query; active flag | observation partial; device/network metadata |
| `ANY` | `/autoload_status` | 1037-1091 | JSON | reads config/autoload; **sets `autoload_triggered=1`** | forbidden in Windows 1 and 2 |
| `ANY` | `/autoload_clear` | 1092-1097 | text | resets process-local autoload counters/trigger state; no file write in this call | forbidden: functional autoload mutation |
| `ANY` | `/abort` | 1098-1103 | text | changes autoload abort state | forbidden: functional mutation |
| unreachable | `/autoload_status` | 1104-1111 | short JSON | duplicate branch shadowed by 1037 | never independently callable |
| `ANY` | `/get_config` | 1112-1155 | JSON | `fopen("r")` config/autoload | no arbitrary file bytes; observation partial |
| `ANY` | `/events` | 1156-1165 | server-sent log stream | connection allocation and log reads | indefinite stream; not file readback |
## Minimal controlled-profile routes
This source defines a different listener/profile, not extra routes proven to be
installed beside the full profile.
| Method | Exact endpoint | Handler lines | Parameters / response | Effects | Classification |
|---|---|---:|---|---|---|
| `POST` | `/chimera/upload` | 181-303, 322-324 | required identity headers and filename; text status | exclusive temp create/write, then verified read/hash, fsync/rename | forbidden: device write |
| `POST` | `/chimera/launch` | 305-309, 324-326 | filename and identity headers; text status | verified local read/hash, sends and launches | forbidden: payload launch |
| `DELETE` | `/chimera/artifact` | 311-327 | filename; text status | unlink | forbidden: delete |
## Requested capability inventory
| Capability | Existing route | Result |
|---|---|---|
| Directory listing | `/list_payloads` | yes, filtered payload listing |
| File stat | `/manage:check`, `/usb_move_check`, listing internals | partial/fixed-purpose; no general stat identity |
| File read | internal only | no arbitrary bytes returned |
| File download | none | absent |
| File hash | internal controlled-launch verification only | no hash response route |
| File size | `/usb_move_check` for allowed USB source | no general live component size route |
| Upload | both upload routes and minimal `/chimera/upload` | present and forbidden |
| Rename | internal upload/install commits | present and forbidden; no standalone route |
| Delete | `/manage:delete`, minimal `/chimera/artifact` | present and forbidden |
| Process listing | `/processes_list` | present |
| Service listing | none | absent |
| Listener listing | none | absent |
| Firmware | none | absent |
| Configuration | `/get_config` | present, but request has functional active-flag effect |
| Autoload | status/clear/config routes | present and excluded |
| Payload launch | both load routes and minimal `/chimera/launch` | present and forbidden |
## File-open evidence
Filesystem reads occur in listing, configuration, repository/source handling,
USB checking, self-update discovery, and launch verification. The only
launch-side exact flags are controlled
`O_RDONLY|O_NOFOLLOW|O_CLOEXEC` (`verified_launcher.c:83-99`) and legacy
`O_RDONLY` (`ps5_launcher.c:77-84`). Upload paths use the write/create flags
shown above. None of these internal reads is wired to an HTTP binary-body
response.
Consequently:
- `readback_candidate=false` for every existing route;
- binary framing, remote EOF, returned byte count, partial-transfer detection,
and end-to-end integrity are absent;
- a local file read for launch is not evidence of host readback;
- a general HTTP response is not evidence of file streaming.
The machine-readable matrix in
`manifests/runtime/phase-0.9d-existing-stack-readback.json` records the
per-route booleans and hard-stop reasons used by the validator.
@@ -0,0 +1,71 @@
# Phase 0.9D independent recovery analysis
Date: 2026-07-18
Status: `UNPROVEN`
## elfldr
| Question | Source-bound answer |
|---|---|
| Write mechanism | none in audited source |
| Executor | original external exploit/rudimentary loader could launch an ELF, but its source is absent |
| Works if elfldr is broken | bootstrap independence is described, not demonstrated: `PARTIAL` |
| Works if Manager is broken | bootstrap path does not name Manager: `PARTIAL` |
| Works after reboot | `UNPROVEN` |
| Works without autoload | manual host send is described: `PARTIAL` |
| Works without defective listener | port 9020 is described as distinct from elfldr port 9021: `PARTIAL` |
| Exact restore target selectable | no live target mapping or write contract |
| Write then verify | absent |
| Old file remains intact | no restore transaction exists |
| Power-loss behavior | `UNPROVEN`; no atomic restoration contract |
| Second route | none source-bound |
Top-level required classification: `PARTIAL`. Detailed restore classifications:
`UNPROVEN` and `ABSENT`; no `INDEPENDENT_RECOVERY_CANDIDATE` is established.
## Payload Manager
| Question | Source-bound answer |
|---|---|
| Write mechanism | full Manager upload/install routes write files, but using a Manager to restore that same Manager is self-dependent and is not authorized |
| Executor | elfldr can launch a Manager ELF sent from a host, according to README/deploy source |
| Works if elfldr is broken | no; described manual Manager route depends on elfldr: `CROSS_DEPENDENT` |
| Works if Manager is broken | a separately supplied candidate could be launched through elfldr, but persistent restoration is absent: `PARTIAL` |
| Works after reboot | original exploit and elfldr repeatability are `UNPROVEN` |
| Works without autoload | manual send is described: `PARTIAL` |
| Works without normal Manager listener | host-to-elfldr launch is structurally separate: `PARTIAL` |
| Exact restore target selectable | no current live mapping |
| Write then verify | absent |
| Old file remains intact | upload/install paths are not an audited self-recovery transaction |
| Power-loss behavior | existing writes/renames are not proven safe for the current live Manager object |
| Second route | absent |
Top-level required classification: `PARTIAL`. Detailed classifications:
`CROSS_DEPENDENT`, `SELF_DEPENDENT`, and `POWER_LOSS_UNSAFE` for the available
shapes. None is recovery proof.
## Failure matrix
| Failed component | Still source-plausible | Not proven / unavailable |
|---|---|---|
| elfldr | original port-9020 exploit bootstrap, if the absent external chain remains usable | current exploit availability, persistent rewrite, exact target, verification, power-loss recovery |
| Payload Manager | elfldr remains capable of accepting and launching a separately supplied ELF in source | Manager live path, durable replacement, independent verification, recovery when elfldr also fails |
The current byte-exact Payload Manager backup remains
`HARD_BLOCKER_FOR_INSTALLATION`. Lack of independent recovery remains
`HARD_BLOCKER_FOR_EVERY_DEVICE_WRITE`.
## Side-by-side feasibility
elfldr `socksrv.c:477-507` terminates an already running `elfldr.elf` service
before creating another one. Payload Manager `main.c:81-103` terminates another
`pldmgr.elf` instance during startup. Both therefore have process/listener
overlap and global-state risks.
The controlled Manager source uses a separate profile/port but is not installed
or runtime-proven. Any candidate would require transfer and execution, a
source-bound non-live path, collision review, a timeout/cleanup contract, and
independent recovery. None exists here.
Classification: `BLOCKED` / `RECOVERY_UNPROVEN`. This is not staging,
installation, or execution approval.
@@ -0,0 +1,81 @@
# Phase 0.9D off-device backup contract
Date: 2026-07-18
Status: `DESIGN_ONLY`; no readback route currently satisfies this contract.
## Invariants
A future host workflow shall process one component per separately authorized
session. It shall contain no upload, create-on-device, rename, unlink, delete,
chmod, chown, launch, process/service action, mount action, configuration
change, `/autoload_status`, automatic resume, or automatic retry.
The host must:
1. record an approved literal source path without inference;
2. record non-secret device identity, session identity, route, raw
request/response metadata, and exact client source commit;
3. create a new local temporary output exclusively and refuse overwrite;
4. receive in binary mode while counting every byte;
5. reject timeout, protocol error, unexpected EOF, short transfer, surplus
bytes, missing expected length, or any partial output as
`TRANSFER_INCOMPLETE` then `INVALID`;
6. close the file, reopen it, record its exact size, and compute SHA-256;
7. start a new connection and session for a second new exclusive local
temporary file, with no reused partial bytes;
8. close, reopen, size, and hash the second file;
9. compare exact sizes, SHA-256 values, and every byte;
10. make no automatic third attempt when the copies differ.
If a transport cannot provide a trustworthy expected byte count, the host may
save an exploratory copy only as `SOURCE_MAPPING_PARTIAL`; it cannot classify
the transfer as byte-exact source attestation. The current stack has the
stronger blocker that it does not return arbitrary file bytes at all.
## State machine
```mermaid
stateDiagram-v2
[*] --> TRANSFER_NOT_STARTED
TRANSFER_NOT_STARTED --> TRANSFER_INCOMPLETE: first byte accepted
TRANSFER_INCOMPLETE --> INVALID: timeout / short read / framing error
TRANSFER_INCOMPLETE --> HOST_COPY_RECEIVED: exact complete response
HOST_COPY_RECEIVED --> HOST_COPY_REOPENED: close + reopen
HOST_COPY_REOPENED --> HOST_COPY_HASHED: size + SHA-256
HOST_COPY_HASHED --> SECOND_COPY_CREATED: new session/output
SECOND_COPY_CREATED --> SECOND_COPY_REOPENED: exact receive + close/reopen
SECOND_COPY_REOPENED --> SECOND_COPY_HASHED: size + SHA-256
SECOND_COPY_HASHED --> INVALID: size/hash/byte mismatch
SECOND_COPY_HASHED --> COPIES_MATCH: size/hash/all bytes equal
COPIES_MATCH --> SOURCE_MAPPING_PARTIAL: path/object identity incomplete
COPIES_MATCH --> SOURCE_MAPPING_VERIFIED: independent source mapping proven
```
Required status vocabulary:
- `TRANSFER_NOT_STARTED`
- `TRANSFER_INCOMPLETE`
- `HOST_COPY_RECEIVED`
- `HOST_COPY_REOPENED`
- `HOST_COPY_HASHED`
- `SECOND_COPY_CREATED`
- `SECOND_COPY_REOPENED`
- `SECOND_COPY_HASHED`
- `COPIES_MATCH`
- `SOURCE_MAPPING_PARTIAL`
- `SOURCE_MAPPING_VERIFIED`
- `INVALID`
## Classification boundaries
`OFF_DEVICE_BACKUP_VALID` is allowed only after the two closed-and-reopened
local copies have identical sizes, SHA-256 values, and bytes. It says nothing
about the current live source path unless source mapping was independently
proven.
`RECOVERY_PROVEN` is forbidden in this phase. A matching host backup is not
proof that any actor can safely restore it, survive power loss, retain the old
live file, or recover without the component being replaced.
The contract is intentionally descriptive. Phase 0.9D creates no client,
script, device command, backup, or transfer package.
@@ -0,0 +1,91 @@
# Phase 0.9D operational windows
Date: 2026-07-18
Status: future review design only
No window is authorized by this document. Because the existing stack has no
file readback route, Window 2 is currently blocked and the later windows cannot
open.
## Window 1 — manual fact collection
Proposed content:
- firmware text exactly as displayed in the PS5 interface;
- visible exploit, loader, and Manager status/version strings;
- non-secret device/session identifier;
- operator photograph or literal transcript;
- autoload state only if it is visible without a request or mutation.
Prohibitions: network request to Manager unless separately justified, file
transfer, `/autoload_status`, payload launch, configuration change, USB
operation, retry.
Current outcome: `PARTIAL`, then `BLOCKED_WINDOW1` until a concrete
non-mutating operator procedure is reviewed. It can become
`READY_FOR_WINDOW2_REVIEW` only through a new exact authorization.
## Window 2 — single off-device readback
Intended constraints:
- one existing component and one literal proven live source path;
- PS5-to-host only;
- no write/create/truncate/rename/unlink/delete/upload/launch/autoload/config,
no automatic retry or resume;
- new exclusive local output, binary framing, exact byte count, short-read and
timeout rejection;
- any accepted `server_active_flag`, logging, socket, buffer, counter, cache,
atime, scheduling, audit, accounting, or network-counter effect must be named
by the future permission.
Current outcome: `BLOCKED_NO_READBACK_PATH`. There is no first component to
recommend. No route satisfies binary response, exact length, EOF, short-read,
and partial-output rejection.
## Window 3 — independent repeat readback
Would require a new connection/session and output, no reused bytes, no
resume/retry, full size/hash/byte comparison, and no automatic third attempt.
A mismatch means `SOURCE_UNSTABLE_OR_READBACK_INVALID`.
Current outcome: `BLOCKED` because Window 2 is blocked.
## Window 4 — second component
Would require separate permission, session, and files after successful Windows
2 and 3. A combined backup-all operation is forbidden.
Current outcome: `BLOCKED`.
## Window 5 — recovery contract review
Offline only. A matching pair of host copies may establish
`OFF_DEVICE_BACKUP_VALID`, never `RECOVERY_PROVEN`. Exact write executor,
non-self-dependence, target selection, write-then-verify, old-file retention,
and power-loss behavior must be proven.
Current outcome: `UNPROVEN`.
## Window 6 — non-live staging
Outside Phase 0.9D and blocked until both readbacks match, live target mapping
is proven, independent recovery is sufficient, a non-live staging path is
proven, and a separate permission exists.
## Window 7 — side-by-side execution
Outside Phase 0.9D. No autoload, retry, live replacement, or combined lifecycle
probe is permitted. Current classification: `BLOCKED`.
## Hard stops
- no existing PS5-to-host file transport;
- no runtime-observed live component path;
- current installed identity and persistence are unproven;
- exploit/port-9020 executor source and repeatability are absent;
- independent byte-exact restore is absent;
- power-loss-safe restore is unproven;
- current Payload Manager backup is still the installation blocker;
- every device write is blocked by missing independent recovery;
- all authorization fields remain false.
@@ -0,0 +1,115 @@
# Phase 0.9D existing-stack readback feasibility
Date: 2026-07-18
Decision: `BLOCKED_NO_READBACK_PATH`
## Route search, in required order
| Order | Candidate | Source result | Binary framing | Short-read / EOF / size | Decision |
|---:|---|---|---|---|---|
| 1 | Payload Manager download | no endpoint exists | absent | absent | `ABSENT` |
| 2 | Payload Manager file read | internal reads are not returned to HTTP client | absent | absent | `ABSENT` |
| 3 | elfldr response or host pipe | controlled route returns fixed status text and disables payload stdio; legacy stdio requires a payload process | no file protocol | no file completeness contract | rejected |
| 4 | exploit host | README sends host-to-PS5; implementation absent | no reverse framing | unproven | rejected |
| 5 | browser/USB host | browser uploads toward PS5; USB move writes device storage | reverse direction or mutating | no host-copy contract | rejected |
| 6 | repository tools | deploy scripts send through port 9021 only | no reverse framing | absent | rejected |
| 7 | no route | all audited paths exhausted | — | — | selected |
Hardened elfldr `socksrv.c:288-375` sends only rejection, error, or
`Controlled payload exited` status. The payload data is discarded after
loading and controlled stdio is `-1`. Controlled Manager
`verified_launcher.c:31-184` verifies and sends a descriptor to elfldr and then
closes; `ps5_launcher.c:18-69` exposes connect/send/close only. Neither side
contains a receive path for component bytes.
## Flag semantics
### `server_active_flag`
- Declaration and initial value: static volatile integer initialized to zero,
`src/log_server.c:20-23`.
- Sole writer: `log_server_set_active()` assigns one.
- Sole reader: `pldmgr_server_is_active()`, used by
`src/autoload.c:101` only to suppress fallback notification behavior while a
browser/server request has occurred.
- Reset: none in the process.
- Lifetime: process-local; it cannot persist as this variable after process
exit or reboot. Exact manager process lifetime on hardware is unobserved.
- No source path connects it to filesystem writes, autoload enablement,
payload launch, request authorization, shutdown, or boot configuration.
- Disconnect does not reset it; a crash/process exit destroys the process
state.
Classification: `LOW_VOLATILE`, not `ANTI_BRICK_CRITICAL`. Because there is no
reset semantic within the running process, any otherwise observational route
remains `PARTIAL` and a future permission must explicitly accept this effect,
log-ring changes, connection state, buffers, sockets, and counters.
### `autoload_triggered`
- Declaration/initial value: static volatile integer zero,
`src/autoload.c:31`.
- Writers: `pldmgr_autoload_get_status()` sets one (`:45`);
`pldmgr_autoload_reset()` sets zero (`:235`).
- Readers: autoload worker wait logic at `:82-86`.
- `/autoload_status` calls the mutating getter before building its response
(`src/http_server.c:1037-1041`).
- Reset is explicit clear/resume logic, not disconnect cleanup.
- It is process-local, but can change worker timing and therefore launch
behavior while that process exists.
Classification: `HIGH_FUNCTIONAL`. `/autoload_status` is excluded from
Windows 1 and 2. The later duplicate route at `http_server.c:1104-1111` is
unreachable because the first identical comparison already matches.
## Path inventory
| Literal path | Source | Meaning | Live status | Evidence |
|---|---|---|---|---|
| `/data/pldmgr` | controlled Manager `include/pldmgr.h:8` | base device directory | configured default only | source literal |
| `/data/pldmgr/payloads` | same `:12` | payload storage | configured default only | source literal |
| `/data/pldmgr/autoload.txt` | same `:9` | Manager autoload list | configured default only | source literal |
| `/data/pldmgr/pldmgr_config.txt` | same `:10` | Manager config | configured default only | source literal |
| `/data/pldmgr/repository_cache.json` | same `:11` | repository cache | configured default only | source literal |
| `/data/pldmgr/sources.json` | same `:14` | repository sources | configured default only | source literal |
| `/mnt/usb0/pldmgr``/mnt/usb7/pldmgr` | `payload_mgr.c:201-218` | USB scan roots | possible source directories | source literal/pattern |
| `/data/pldmgr/payloads/chimera-controlled` | controlled Manager source/profile | controlled staging directory | explicitly not installed | offline candidate only |
| `/data/pldmgr/payloads/elfldr/elfldr_v0.23.elf` | historical Phase-0.6 manifest/tool input | stock identity reference | not runtime-observed | `reference_only` |
| `/data/pldmgr/payloads/pldmgr/pldmgr_v0.3.1.elf` | historical Phase-0.6 manifest/tool input | stock identity reference | not runtime-observed | `reference_only` |
| `/data/payload.elf` | elfldr README example | generic manual launch example | not a current mapping | documentation example |
| `/user/temp/payload_<pid>.self` | elfldr self-loader source | temporary converted image | runtime-generated, not component live path | source template |
| `/system/vsh/app/NPXS40112/eboot.bin` | elfldr bootstrap source | injection victim executable | not an elfldr installation path | source literal |
No audited input binds an actual live elfldr or Manager object to a current
path. The package/reference paths and configured defaults therefore produce
`PATH_CONFLICT`; no future readback window may guess.
## Readback decision matrix
- `NEW_OBSERVER_FEASIBILITY`: `BLOCKED`
- `EXISTING_STACK_MANUAL_FACT_COLLECTION`: `PARTIAL`
- `EXISTING_STACK_SINGLE_READBACK`: `BLOCKED_NO_READBACK_PATH`
- `EXISTING_STACK_REPEAT_READBACK`: `BLOCKED`
- `ELFLDR_INDEPENDENT_RECOVERY`: `PARTIAL`
- `PAYLOAD_MANAGER_INDEPENDENT_RECOVERY`: `PARTIAL`
- `SIDE_BY_SIDE_FEASIBILITY`: `BLOCKED`
- `DEVICE_WRITE`: `NOT_AUTHORIZED`
- `TARGET_EXECUTION`: `NOT_AUTHORIZED`
- `INSTALLATION`: `NOT_AUTHORIZED`
There is no possible first readback component: the component-risk order cannot
override an absent transport. A missing metadata query would merely reduce a
copy to `SOURCE_MAPPING_PARTIAL`; here the earlier condition—getting complete
binary bytes—already fails.
## Explicitly acceptable only after later consent
A future read-only request could reasonably entail sockets, temporary buffers,
heap allocation, connection/request counters, scheduler activity, cache or
atime effects, audit/process/network accounting, stdout logging, ring logging,
and a process-local `server_active_flag=1`. These effects are not claimed
absent. They are acceptable only if the chosen route has no device-file write,
launch, autoload, service, or persistent configuration effect and the
artifact-specific permission names them.
No such permission is requested in Phase 0.9D.
@@ -0,0 +1,109 @@
# Phase 0.9E bootstrap provenance
Date: 2026-07-18
Status: `BOOTSTRAP_IMPLEMENTATION_MISSING`
This is an offline inventory. No internet operation, package installation,
target build, device request, transfer, execution, or PS5 connection occurred.
Y2JB was used only as a filename/search hint.
## Search boundary
The search was limited to:
- this `chimera-gfx` tree and its existing `work/upstream` trees;
- the existing `chimera-elfldr` and `chimera-ps5-payload-manager` siblings;
- exact-name checks in the user Downloads directory and supplied Codex
attachments;
- existing repository manifests, scripts, audit records, and ignored local
Phase-0.6/0.7 evidence.
No other sibling project exists in the dated project directory. No BD-J SDK,
WebKit exploit tree, Y2JB source tree, 9020-loader tree, or external-autoloader
tree is present under the allowed source roots.
## Candidate archive
`~/Downloads/Y2JB-Autoloader-403-1240.zip` exactly matches the candidate
recorded by Phase 0.6:
- size: `504159435`;
- SHA-256:
`805e3f87f0c371223619ffc7d3a7b3c0d41a1fae8a8b1171d9e2f162659e8291`;
- ZIP integrity: valid central directory and CRC;
- entries: four directories plus
`PS5/EXPORT/BACKUP/202606102126_00/archive.dat`;
- no ZIP comment and no source/version manifest.
The inner object has:
- size: `504365056`;
- SHA-256:
`6439834e8856d45b6d6fe699b74c35ca6985a199ea8ecf3e398c018d37be2d55`;
- leading bytes: `SIECAF`;
- measured byte entropy: `7.999987` bits/byte;
- zero literal matches for `Y2JB`, `y2jb`, `9020`, `elfldr`, `autoload`,
`<html`, `.wasm`, or ELF magic.
The container is not a standard nested archive and no acceptable local parser
or source definition exists. It was not decrypted, unpacked through
proprietary tooling, or treated as source. Its filename and equal hash prove
only that this is the same local backup candidate as Phase 0.6. They do not
prove that it is deployed, that its opaque content is Y2JB, or that it is the
package currently used on the PS5.
## Artifact inventory
| Logical artifact | Size | SHA-256 | Provenance | Use evidence |
|---|---:|---|---|---|
| Y2JB-named outer ZIP | 504159435 | `805e3f87...659e8291` | `POSSIBLE` | historical local candidate only |
| inner `archive.dat` | 504365056 | `6439834e...37be2d55` | `UNKNOWN` | opaque `SIECAF` object |
| hardened `elfldr-ps5.elf` | 397000 | `63e81098...400b561` | `REFERENCE_ONLY` for this device chain | exact local Phase-0.7 build; manifest says not transferred/executed |
| hardened elfldr map | 142905 | `2ea5ff73...813124f` | `REFERENCE_ONLY` | local build evidence |
| embedded bootstrap map | 143081 | `ec4ae17a...5b3323` | `REFERENCE_ONLY` | source/build design only; intermediate ELF absent |
| embedded socket-service map | 145072 | `bf74db6e...5447c1` | `REFERENCE_ONLY` | source/build design only; intermediate ELF absent |
| hardened elfldr `Makefile` | 1902 | `3df93b48...783384` | `REFERENCE_ONLY` | exact commit-bound build source |
| hardened elfldr `README.md` | 2821 | `372aeb28...1eadb` | `REFERENCE_ONLY` | describes, but does not implement, port 9020 |
| hardened elfldr `main.c` | 2473 | `876389a2...2b4d1` | `REFERENCE_ONLY` | exact post-9020 bootstrap source |
| hardened elfldr `bootstrap.c` | 2081 | `5a8072ec...45381` | `REFERENCE_ONLY` | exact embedded-stage source |
| hardened elfldr `socksrv.c` | 11556 | `d642ced3...ba3d7` | `REFERENCE_ONLY` | exact port-9021 source, not port 9020 |
| public elfldr v0.23 asset | 397000 | `092d16ee...703e8` | `REFERENCE_ONLY` | historical public release identity |
| controlled Manager ELF | 99560 | `8fecf824...e5e5b1` | `REFERENCE_ONLY` | exact offline build, explicitly not installed |
Full hashes and source/build fields are in
`manifests/runtime/phase-0.9e-bootstrap-provenance.json`.
## Confidence decision
No artifact is classified `EXACT_USED` or `STRONG_MATCH`.
- The Y2JB-named ZIP is `POSSIBLE`: exact local identity, no deployed-use
identity.
- The opaque inner container is `UNKNOWN`.
- elfldr/Manager binaries and source are `REFERENCE_ONLY` for the external
pre-elfldr bootstrap question.
- public URLs in the elfldr README are architectural references only. No
public upstream was silently substituted for the used implementation.
Therefore:
- `actual_bootstrap_package_available=false`;
- `actual_bootstrap_identity=null`;
- `bootstrap_provenance=POSSIBLE`;
- exact used artifact set: empty.
## Missing exact objects
The minimum missing evidence is:
1. the actual Y2JB/exploit host directory or exported package with readable
HTML, JavaScript, WebAssembly, payload data, configuration, cache/service
worker, manifest, and version identity;
2. the port-9020 listener source or exact binary plus a source/release or
reproducible build match;
3. its build script and linker input;
4. the exact host sender/client and configuration used by the operator;
5. the external autoloader source/configuration, if one exists;
6. non-secret operator evidence binding those exact hashes to the current
firmware-9.60 workflow.
@@ -0,0 +1,64 @@
# Phase 0.9E future rescue payload contract
Date: 2026-07-18
This is a contract for a possible later Phase 0.9F. It is not target source,
build authorization, transfer authorization, or execution authorization.
Phase 0.9F design remains blocked while the exact bootstrap implementation and
output contract are missing.
## Requirements
| # | Requirement | Bootstrap support now |
|---:|---|---|
| 1 | loaded only through an independently proven bootstrap | `UNPROVEN` |
| 2 | never installed | payload policy can require it; bootstrap staging unknown |
| 3 | never added to autoload | payload policy can require it; actual trigger config unknown |
| 4 | never modifies elfldr or Manager | payload policy can require it |
| 5 | creates no device file | bootstrap behavior `UNKNOWN` |
| 6 | opens targets read-only | future payload requirement |
| 7 | sends only PS5-to-host file bytes | no current output channel |
| 8 | binary-safe framing | must be designed |
| 9 | exact byte count | must be designed |
| 10 | SHA-256 or complete host hashing | must be designed |
| 11 | rejects partial transfer | must be designed |
| 12 | no automatic retry | mandatory; current authorization false |
| 13 | one file per session | mandatory |
| 14 | no rename/unlink/upload/install/other-launch/autoload/mount/reboot/service control | mandatory |
| 15 | hard deadline | missing |
| 16 | host abort | missing |
| 17 | live installation untouched | bootstrap and payload both must prove this |
| 18 | separate output derived from exact bootstrap | missing |
| 19 | explicit crash/hang model | missing |
| 20 | no side-effect-free execution claim | mandatory disclosure |
## Required framing properties
A future design must bind:
- protocol version and request identifier;
- literal source path and component identity;
- expected exact byte count before accepting output;
- monotonically increasing chunk offset and bounded chunk length;
- final byte count and SHA-256;
- explicit success, rejection, timeout, abort, and short-read terminal states;
- no resume, reconnect retry, or third attempt;
- one connection/session and one component;
- host-side exclusive temporary output, close, reopen, size/hash, and partial
deletion/quarantine policy.
## Safety gates before any target source
Target source may not be created merely from this contract. A new phase must
first provide:
1. exact used bootstrap package and source/binary identity;
2. proof of independence from both components being recovered;
3. source-backed host-to-memory or safe temporary-staging semantics;
4. a bounded, binary-safe result channel;
5. a restart/reboot model;
6. a reviewed startup, deadline, abort, crash, and cleanup contract;
7. separate explicit authority to design target code.
Current machine decision:
`phase09f_rescue_payload_design_allowed=false`.
@@ -0,0 +1,80 @@
# Phase 0.9E independent rescue chain
Date: 2026-07-18
Decision: `BOOTSTRAP_IMPLEMENTATION_MISSING`
## Dependency graph
```mermaid
flowchart LR
A["Operator trigger<br/>exact artifact missing"]
B["Y2JB/browser exploit host<br/>opaque candidate only"]
C["Rudimentary port-9020 listener<br/>implementation missing"]
D["Host sender<br/>README concept only"]
E["hardened elfldr-ps5.elf<br/>local reference build"]
F["embedded bootstrap<br/>source design"]
G["elfldr service :9021<br/>source design"]
H["controlled Payload Manager<br/>offline reference build"]
A --> B --> C
D --> C
C --> E --> F --> G --> H
```
| Node | Environment / side | State | Start/input/output | Dependencies | Device file / autoload | Recovery role | Evidence |
|---|---|---|---|---|---|---|---|
| operator trigger | host/browser | unknown | unknown | exact package | unknown | begins jailbreak session | `UNKNOWN` |
| Y2JB/exploit host | browser/host | unknown | opaque backup candidate | trigger/package | unknown | could recreate 9020 state | `POSSIBLE` |
| rudimentary loader | PS5 process/kernel context unknown | unknown | presumed listener on 9020 | exploit | unknown | candidate rescue executor | implementation missing |
| conceptual sender | host | temporary | host connects and streams an ELF per README | working listener | no sender-side device path | sends elfldr | architecture only |
| hardened elfldr bootstrap | PS5 | temporary entry, then background service design | final ELF embeds bootstrap and service | 9020 execution | source itself does not install, but performs documented process/kernel changes | creates port 9021 | exact local source, not deployed-use proof |
| elfldr service | PS5 process | background design | listens TCP 9021 | hardened bootstrap | no autoload source path | later payload executor | exact source, hardware unproven |
| controlled Manager | PS5 process | not installed in evidence | separate launch via elfldr | elfldr 9021 | controlled storage if used; no autoload | management layer | offline reference only |
No node before hardened elfldr has a source-bound executable identity.
## Required questions
1. **Who listens on 9020?** Unknown. The elfldr README calls it a
“rudimentary ELF loader”; no implementation is present.
2. **Who starts it?** Presumably the exploit chain, but exact trigger and
process are unknown.
3. **Before elfldr?** Architecturally yes; exact implementation proof is
absent.
4. **Available again after reboot?** Plausible for a repeatable jailbreak, not
proven for the used package.
5. **Requires working elfldr on filesystem?** Architecture says no; exact
loader proof is absent, so `independent_from_elfldr=unproven`.
6. **Requires Payload Manager?** Architecture says no; exact proof is absent,
so `independent_from_payload_manager=unproven`.
7. **Can it receive a payload directly?** The README assumes an elfldr ELF can
be sent; limits and exact acceptance are unknown.
8. **Accepted format?** The sender streams ELF bytes. Server validation,
container rules, and truncation behavior are unknown.
9. **Automatic execution?** Required by the described bootstrap, but no server
source proves it.
10. **Writes a device file first?** Unknown.
11. **Can it execute without live replacement?** Plausible, not proven.
12. **Restart after a payload crash?** Unknown.
13. **Does reboot remove temporary state?** Plausible, not proven.
14. **Depends on autoload?** No architectural requirement is documented, but
actual configuration is absent.
15. **Works with both later components absent?** Conceptual chain says yes;
exact implementation is missing.
16. **Rescue without filesystem write?** Unknown.
17. **Independent result channel?** No exact result/output contract exists.
18. **Hardware-unproven aspects:** all process identities, boot persistence,
port behavior, parser behavior, mapping/entry, file writes, cleanup,
crash/hang response, and reboot recovery.
## Independence decision
An architectural diagram alone permits at most
`PARTIAL_RESCUE_EXECUTOR`. Here, the actual executable implementation itself
is unavailable, so the more precise required classification is:
`BOOTSTRAP_IMPLEMENTATION_MISSING`
This does not mean the chain is dependent; it means independence cannot be
audited. `phase09f_rescue_payload_design_allowed=false`.
@@ -0,0 +1,63 @@
# Phase 0.9E port-9020 protocol
Date: 2026-07-18
Protocol status: `UNPROVEN_IMPLEMENTATION_MISSING`
## Available evidence
Hardened elfldr `README.md:11-19` describes a host connecting to port 9020 and
piping `elfldr-ps5.elf` bytes through a generic TCP stream tool. Its Makefile
defines `PS5_PORT ?= 9020`, but contains no deploy target or protocol client.
The README names external BD-J and WebKit projects; neither project nor the
used Y2JB implementation exists in the allowed local source trees.
This proves only the expected sender shape. It does not prove the listener
implementation or actual deployed package.
| Field | Offline result |
|---|---|
| server role | PS5-side rudimentary loader, description only |
| client role | host-side generic stream sender, no exact client artifact |
| transport | TCP is strongly indicated by the documented stream tool |
| port | 9020 in README/Makefile |
| bind address | unknown |
| direction | host connects to PS5 |
| handshake / magic / version | unknown |
| endianness / headers / length fields | unknown |
| maximum payload size | unknown |
| chunking | TCP fragmentation behavior only; application contract unknown |
| EOF | sender closes after input; listener EOF semantics unknown |
| acknowledgement / error frame | unknown |
| checksum / hash | none documented; listener behavior unknown |
| timeout / retry / reconnect | unknown |
| upload direction | host to PS5 |
| response direction | unknown |
| accepted object | ELF assumed by documentation; validation unknown |
| parser / bounds / overflow | implementation missing |
| partial recv/send detection | implementation missing |
| allocation / mapping / permissions | implementation missing |
| entrypoint selection | implementation missing |
| filesystem staging | implementation missing |
| cleanup / crash behavior | implementation missing |
The exact source-backed port-9021 protocol is deliberately not substituted for
port 9020. Port 9021 belongs to `socksrv.c`; it has different parser and
lifecycle code.
## Host model decision
No parser/emulator was created. A model derived from the README would invent
server framing, maximum length, EOF, mapping, and error semantics. The
machine-readable result is
`manifests/runtime/phase-0.9e-loader-protocol.json`.
Minimum input needed to build a host-only model:
- exact 9020 listener source or a fully audited exact binary;
- exact sender/client implementation;
- maximum length and allocation rules;
- complete recv/EOF/short-read state machine;
- accepted format and entrypoint validation;
- response/error/close behavior;
- timeout and retry rules.
@@ -0,0 +1,30 @@
# Phase 0.9E output architecture options
Date: 2026-07-18
No output architecture is selected. The actual bootstrap implementation is
missing, so `output_channel_for_future_rescue=UNKNOWN`.
| Option | Exists now | Changes required | Device file | Cleanup/crash model | Risk / feasibility |
|---|---|---|---|---|---|
| A. same 9020 connection, duplex | unknown | exact server and host protocol may need change; payload result propagation required | not inherently | unknown socket ownership, EOF and abort | potentially low persistent risk, feasibility unknown |
| B. temporary PS5-to-approved-host outbound connection | absent | host receiver and target payload required | no | bounded connect/send/close and deadline required | temporary socket is not automatically brick-relevant; network policy and cleanup unproven |
| C. temporary one-connection listener | absent | target listener and host client required | no | bind/listen/accept deadline and guaranteed close required | listener lifetime/session collision risk; not automatically a brick risk |
| D. caller-owned host buffer | absent | exact loader ABI, buffer ownership, copy-out and post-exit delivery required | no | caller finalization and crash-safe ownership required | Phase-0.9C already shows current elfldr has no such output path |
| E. no usable output | consistent with current evidence | none | no | no recovery result possible | only defensible current operational assumption |
Options A through D are designs, not claims. A generic TCP connection can be
duplex at transport level, but that does not prove that the 9020 listener keeps
the socket, passes it to a payload, accepts response bytes, or returns them to
the host.
No option may:
- create or replace a live device file;
- enable autoload;
- retry automatically;
- combine recovery of both components;
- persist a listener or configuration across sessions.
The missing exact listener source prevents selection and prevents a
source-derived host-only emulator.
@@ -0,0 +1,56 @@
# Phase 0.9E-R official Y2JB host sender audit
Date: 2026-07-18
Official sender:
`Gezine/Y2JB@0dbbf4e7e0203af7e5d101a3256c634edf4e3ba2:payload_sender.py`
Identity:
- size: 1064 bytes;
- SHA-256:
`8c87920c41dbdbd66b9f36ca9509f0d6bef9170f351dd97ff831cfb98e642ec6`;
- Git blob: `4ad80085bd8f2cf9ca3520d8ff1353b9c764fb75`;
- same blob in all five official tags;
- originating commit:
`edf0d631dd6e4dbd5a3db54ebdae47934d8bd994`.
The file was inspected statically and was never run against any network
target.
## Contract
| Lines | Behavior |
|---|---|
| 2 | `send_payload(path, host, port=50000)` |
| 34 | opens the selected local file `rb` and reads it completely |
| 6 | creates IPv4 TCP socket |
| 7 | blocking connect to caller-supplied host/port |
| 8 | `sendall(data)`; CPython manages short sends or raises |
| 9 | closes after successful `sendall` |
| 10 | reports local byte count, not peer acknowledgement |
| 1422 | accepts `host file` or `host port file`; explicit port uses `int()` |
| 2329 | prints usage/examples, including non-binding 9020 example |
Findings:
- binary mode: yes;
- default port: 50000;
- explicit port selection: yes;
- maximum input size: absent;
- timeout: absent;
- automatic retry/resume: absent;
- response read: absent;
- acknowledgement, remote byte count, checksum, or hash: absent;
- exception handling: absent; file/socket errors propagate;
- success exit: implicit zero;
- usage error exit: also implicit zero;
- local mutation: none; selected file is read-only;
- duplex classification: false.
The server added same-connection log writes in Y2JB 1.4, but this official
sender closes after `sendall` and never reads. Transport-level duplex
capability is not an end-to-end duplex sender contract.
No claim is made that this official sender is the one actually used by the
operator. That requires the separate operator attestation.
@@ -0,0 +1,125 @@
# Phase 0.9E-R official Y2JB release correlation
Date: 2026-07-18
Result: `OFFICIAL_RELEASE_NO_MATCH`
Overall classification: `LOCAL_BACKUP_NOT_CORRELATED`
This was a bounded host-side investigation. Public network access was limited
to official `Gezine/Y2JB` GitHub repository, API, tag, release, asset metadata,
and source-archive URLs. No PS5 address, request, connection, transfer,
payload, target build, restore, or execution was used.
## Local evidence captured before network access
| Field | Value |
|---|---|
| path | `<local-download>/Y2JB-Autoloader-403-1240.zip` |
| size | `504159435` |
| SHA-256 | `805e3f87f0c371223619ffc7d3a7b3c0d41a1fae8a8b1171d9e2f162659e8291` |
| creation UTC | `2026-06-23T14:10:39.0466596Z` |
| modification UTC | `2026-06-23T14:11:10.6992328Z` |
| ZIP comment | empty |
| first 64 bytes | `504b030414000000000041abca5c000000000000000000000000040000005053352f504b030414000000000041abca5c0000000000000000000000000b000000` |
| last 64 bytes | `76652e6461740a0020000000000001001800c065678d17f9dc0100000000000000000000000000000000504b050600000000050005000a020000abda0c1e0000` |
| Zone.Identifier | 327 bytes; SHA-256 `70928a3d66cbb9f584596414c4fe535b498dd5ed7c5f55bbeae4efeb146ea841` |
| local download indication | `ReferrerUrl` and `HostUrl` are MediaFire; exact volatile signed URL is retained only in the original ADS |
| browser records | exact filename absent from five bounded Chrome/Edge/Brave/Firefox history candidates |
The MediaFire marker is local provenance evidence, not evidence about the
bytes hosted there and not an official-source match.
### ZIP entries
The four directory entries use method 0, CRC `00000000`, flag bits 0, and
zero sizes. Central-directory metadata was captured without normalization:
| Name | Method | Compressed | Uncompressed | CRC32 | DOS timestamp | Header offset | External attr |
|---|---:|---:|---:|---|---|---:|---:|
| `PS5/` | 0 | 0 | 0 | `00000000` | `2026-06-10 21:26:02` | 0 | 16 |
| `PS5/EXPORT/` | 0 | 0 | 0 | `00000000` | `2026-06-10 21:26:02` | 34 | 16 |
| `PS5/EXPORT/BACKUP/` | 0 | 0 | 0 | `00000000` | `2026-06-10 21:26:54` | 75 | 16 |
| `PS5/EXPORT/BACKUP/202606102126_00/` | 0 | 0 | 0 | `00000000` | `2026-06-10 21:27:24` | 123 | 16 |
| `PS5/EXPORT/BACKUP/202606102126_00/archive.dat` | 8 | 504158629 | 504365056 | `522808c8` | `2026-06-10 21:27:28` | 187 | 32 |
All five entries use general-purpose flag bits 0. The archive entry reports
create system 0, create version 63, and extraction version 20.
The inner first 64 bytes are
`5349454341460000010000000000000001000000000000000300000000000000c6ff138694ca1d2701779aae67de1525e5158700e6158700e715870000000000`.
Only the `SIECAF` magic and bounded header were inspected. No new parsing,
decryption, or reverse engineering was attempted. Its previously established
SHA-256 remains
`6439834e8856d45b6d6fe699b74c35ca6985a199ea8ecf3e398c018d37be2d55`.
## Official inventory
Metadata came from:
- `https://api.github.com/repos/Gezine/Y2JB`;
- `https://api.github.com/repos/Gezine/Y2JB/releases?per_page=100`;
- `https://api.github.com/repos/Gezine/Y2JB/tags?per_page=100`.
The official API returned three releases and five tags.
| Version | Official state | Tag commit | Release publication | Source tree |
|---|---|---|---|---|
| 1.2 | changelog text only; no current tag or release | unknown; not guessed | none | no exact release tree |
| 1.2.1 | tag `Y2JB-1.2.1`; no current release | `6210f98c23552e6eb3c4c8981f72a200bb6121b2` | none | `928ceb979881a063457270dde4961ea4a06bc1fa` |
| 1.3 | release `Y2JB 1.3 (deprecated)`, tag `1.3` | `82e6bbf1935d5f41c3bd5bd9e6598cf90bb2e022` | `2026-05-25T14:29:41Z` | `df29ffe4d8131b5f8b0da1874e34b95a41f0660d` |
| 1.4 | tag `1.4`; no current release | `02eda2e772df629ecfe5a46459769bd8c994ef3e` | none | `ec06403b45f7b68e01eb5053f81277dee4910dd2` |
| 1.5 | release `Y2JB 1.5 (deprecated)`, tag `1.5` | `5fa556e6281229057dace3254b099f95261df386` | `2026-05-22T15:06:30Z` | `db364529c347f34b8ddb186f57bb61dab91113db` |
| 1.6 | release `Y2JB 1.6`, tag `1.6` | `0dbbf4e7e0203af7e5d101a3256c634edf4e3ba2` | `2026-06-09T14:54:35Z` | `c4344f43af7c268337437e6419548dba6f6bc211` |
The 1.6 release body contains the historical 1.2 through 1.5 changelogs. That
does not create missing release objects or identify an exact 1.2 commit.
## Metadata-first asset comparison
GitHub supplied SHA-256 digests for every current official asset. Each digest
and size excludes the local outer ZIP, so no large release asset was
downloaded.
| Tag | Asset ID | Official asset | Official size | Size delta vs local | Official SHA-256 | Result |
|---|---:|---|---:|---:|---|---|
| 1.6 | 442805805 | `Y2JB_backup_1.6.12.20.zip` | 498991521 | -5167914 | `9c097ed9000792507bcf307eff0802f40ee64dc047ab6de3d38acccc62d39dcc` | `NO_MATCH` |
| 1.6 | 442358421 | `Y2JB_backup_1.6.4.03.zip` | 504395044 | +235609 | `b01b4f442327f9eca90ffc4506dfa58249e4ac70cb9d7488c856c9e8dfaf37b4` | `NO_MATCH` |
| 1.6 | 442358388 | `Y2JB_download0_1.6.zip` | 315229037 | -188930398 | `d032954033c17acda47c41179a22fa09016ddd40a274f4e9afbb051e5d08d3bd` | `NO_MATCH` |
| 1.5 | 429350761 | `Y2JB_backup_1.5.zip` | 503863926 | -295509 | `91bc9fb38e62d2b34d0009dbfd6a46dffb379277eef3915dd0a1956f65462a45` | `NO_MATCH` |
| 1.5 | 429351154 | `Y2JB_download0_1.5.zip` | 336514975 | -167644460 | `f7e5debb2e4c6b3fe7224e549c4aaf9b273a178543cd0bfe84e37bc0521d590a` | `NO_MATCH` |
| 1.3 | 429415428 | `Y2JB_backup_1.3.7z` | 488117068 | -16042367 | `e63a6b8fe134ad93b8a6a3b332b98810598aff7dfb6703a226523143c3844dfb` | `NO_MATCH` |
| 1.3 | 429415862 | `Y2JB_download0_1.3.zip` | 336789664 | -167369771 | `c64ef5bc508e4d81395928a8a54b2832f2b37c9cd1603ec9e7e3bd6f5ad6b526` | `NO_MATCH` |
Asset creation/update times recorded by GitHub were:
- 1.6 `12.20`: `2026-06-09T14:52:35Z` / `14:53:10Z`;
- 1.6 `4.03`: `2026-06-09T03:33:57Z` / `03:34:40Z`;
- 1.6 `download0`: `2026-06-09T03:33:55Z` / `03:34:30Z`;
- 1.5 backup: `2026-05-25T12:46:49Z` / `12:47:34Z`;
- 1.5 `download0`: `2026-05-25T12:47:34Z` / `12:47:56Z`;
- 1.3 backup: `2026-05-25T14:27:41Z` / `14:28:29Z`;
- 1.3 `download0`: `2026-05-25T14:28:29Z` / `14:29:18Z`.
The 1.6 release labels its `4.03` backup for firmware 4.03 through 12.40 and
its `12.20`-named backup for 12.60 and later. Releases 1.3 and 1.5 are marked
deprecated. Their release bodies, and the 1.6 historical changelog, were
retained as descriptive metadata only; they do not establish local identity.
No asset has the local name, size, or SHA-256. An exact byte match is therefore
mathematically impossible for the inventoried assets without downloading
them. Downloading a digest-excluded 315504 MB object would add no evidence and
would violate the metadata-first rule.
## Decision
- correlation: `OFFICIAL_RELEASE_NO_MATCH`;
- identified local release: none;
- local outer-to-release association: none;
- large backup assets downloaded: zero;
- local backup classification: `LOCAL_BACKUP_NOT_CORRELATED`;
- Phase 0.9F offline design allowed: `false`.
This does not prove that the local package contains no official-derived
content. It proves that its outer bytes are not any current official
`Gezine/Y2JB` release asset.
@@ -0,0 +1,148 @@
# Phase 0.9E-R official Y2JB port audit
Date: 2026-07-18
Port-9020 classification: `PORT_9020_REFERENCE_ONLY`
## Exact 9020 search
Every official tag (`Y2JB-1.2.1`, `1.3`, `1.4`, `1.5`, `1.6`) has exactly two
9020 text references:
- `README.md`: a `payload_sender.py ... 9020 payload.bin` example;
- `payload_sender.py:29`: the same usage example.
No tag contains a socket bind, listen, connect target, parser, mapper, ELF
loader, or dispatch function fixed to port 9020. Therefore the example cannot
be promoted to an implementation.
## Actual Remote JS Loader
At release 1.6 commit
`0dbbf4e7e0203af7e5d101a3256c634edf4e3ba2`, the implementation is
`download0/cache/splash_screen/aHR0cHM6Ly93d3cueW91dHViZS5jb20vdHY=/remotejsloader.js`.
| Lines | Function / block | Contract |
|---|---|---|
| 28 | allocation | fixed `MAXSIZE = 500 * 1024`; one 512000-byte receive buffer |
| 1039 | `create_socket` | TCP/IPv4, `SO_REUSEADDR`, `INADDR_ANY`, port 0, backlog 3 |
| 4147 | `get_port` | reads assigned ephemeral port |
| 4988 | `setup_socket_until_port_50000` | creates/closes up to 60000 sockets seeking assigned port 50000; falls back to last port |
| 90105 | `recreate_socket` | creates a new ephemeral listener after accept failure |
| 107119 | initial setup | reports actual IP and port |
| 122209 | accept loop | infinite accept/read/decode/eval loop |
| 145164 | receive loop | reads until EOF or 512000 bytes; partial reads accumulate |
| 168188 | validation | rejects empty/error; 1.6 rejects ELF magic only |
| 190203 | dispatch | UTF-8 decode, `eval`, same-connection log writes, close in `finally` |
Protocol properties:
- server: PS5-side JavaScript listener;
- expected port: normally 50000, but explicitly dynamic;
- framing: TCP connection close/EOF;
- maximum accepted prefix: 512000 bytes;
- content: JavaScript; 1.6 rejects only `7f 45 4c 46`;
- authentication: none;
- declared length, version, checksum, or hash: none;
- timeout: none;
- full-limit rejection: absent; reaching 512000 bytes can dispatch the prefix
without proving EOF;
- native mapping/entrypoint: absent; received bytes are text-decoded and
evaluated;
- filesystem write: none in this receive function;
- retry behavior: internal listener allocation/recreation loops exist;
- crash/hang risk: untrusted JavaScript evaluation, unbounded accept lifetime,
blocking reads, and no deadline.
The 1.2.1/1.3 loader uses Git blob
`21663be4a0fab6b6a829824946f54706fb1be839`; 1.4/1.5 use
`decb42ba0bbd2bdc8d1568d33b6d772f9fe24d8e`; 1.6 uses
`dd4957530e7a88c889877a7dcb3433642a71e019`. Release 1.6 added ELF-magic
rejection. Release 1.4 added streaming logs over the accepted connection.
This is a concrete official implementation, but it is not a port-9020
implementation.
## Lapse and port 9021
The official chain is:
`Remote JS Loader (~50000) → lapse.js → load_aioshellcode → embedded kexp + elfldr bytes → elfldr listener 9021`
Relevant source:
- `payloads/lapse.js:1707-1717` requires `load_aioshellcode` and rejects
firmware above 10.01;
- `payloads/lapse.js:1725-1734` creates a per-run `lapse.fail` marker;
- `payloads/lapse.js:1639` calls `load_aioshellcode` after exploit setup;
- `aioshellcode.js:12-24` locates embedded files in sandbox slots;
- `aioshellcode.js:26-45` maps the kexp binary with JIT shared executable
memory;
- `aioshellcode.js:47-76` starts and joins its thread;
- `aioshellcode.js:78-90` reads the embedded elfldr into process memory;
- `aioshellcode.js:107-117` passes pipe state, `allproc`, elfldr address, and
size to the embedded binary;
- `misc.js:262-302` treats a successful loopback connection to 9021 as a
jailbroken/elfldr-running signal;
- `README.md:127-137` tells the host to send an ELF to 9021 after Lapse.
The port-9021 listener itself is contained in an ELF binary. Y2JB contains no
generator or listener source for the 1.6 ELF. Release 1.5 embeds the already
pinned public elfldr v0.23 asset byte-for-byte; release 1.6 embeds a distinct
binary. No 1.6 elfldr source commit is invented.
## Safety classification
The Remote JS Loader is independent of an already running elfldr and Payload
Manager at source-architecture level, but deployed use is unbound because the
local backup is not an official outer asset. It also uses ~50000, not 9020.
Consequently:
- `PORT_9020_IMPLEMENTATION_FOUND`: false;
- `PORT_9020_IMPLEMENTATION_PARTIAL`: false;
- `PORT_9020_REFERENCE_ONLY`: true;
- Phase 0.9F offline design allowed: false.
## Security and robustness findings
| Finding | Classification | Evidence and consequence |
|---|---|---|
| Receiver dispatches UTF-8 through `eval` | `SESSION_CRASH_RISK` | arbitrary JavaScript can hang or terminate the current exploit session |
| No receiver deadline; infinite accept loop | `SESSION_CRASH_RISK` | blocked reads and repeated listener lifetime have no bounded cleanup |
| Buffer limit can dispatch without proven EOF | `PROTOCOL_INTEGRITY_RISK` | a 512000-byte prefix can be treated as complete |
| No length, authentication, checksum, or hash | `PROTOCOL_INTEGRITY_RISK` | source does not bind received bytes to an intended request |
| Sender has no timeout, acknowledgement, response read, or hash | `PROTOCOL_INTEGRITY_RISK` | local `sendall` completion is not peer receipt or execution proof |
| Lapse creates `common_temp/lapse.fail` | `UNKNOWN` | source proves a filesystem side effect, but deployed persistence and reboot semantics remain unobserved |
| Lapse/kexp intentionally changes kernel state | `BRICK_RELEVANT` | it is outside every authorization in this phase and cannot be treated as read-only |
| Embedded 1.6 elfldr has no source/generator | `UNKNOWN` | listener bounds, parser, mapping, cleanup, and crash behavior cannot be source-audited here |
| Sender usage errors return implicit success | `HOST_ONLY` | automation could misread a local invocation error; no device action occurred |
A session crash is not automatically a brick: the reviewed Remote JS receive
function does not itself replace a live file or enable autoload. However, the
local backup is unbound and the subsequent Lapse path contains explicit kernel
and filesystem effects, so no device-risk conclusion or recovery guarantee is
promoted from that source architecture.
## Firmware selection and reboot boundary
At release 1.6:
- `main.js:681-729` identifies supported YouTube app layouts and labels
versions `01.000.003`, `01.000.030`, and `01.009.202` with minimum firmware
4.03, 12.20, and 13.20 respectively;
- `misc.js:92-108` obtains `kern.sdk_version` and formats the firmware value;
- `main.js:967-971` assigns and reports that value;
- `payloads/lapse.js:1707-1717` requires `load_aioshellcode` and rejects
versions above 10.01.
Thus 9.60 passes the release-source comparison in Lapse. It does not prove
that release 1.6 is deployed, that its masks match the device, or that the
runtime chain succeeds.
Listener sockets, JavaScript state, mappings, threads, and loaded code are
process- or kernel-resident in source architecture. The Y2JB cache and
`lapse.fail` path are filesystem state. Source alone does not prove which
state a reboot removes, whether the original trigger remains usable, or
whether a crash permits clean restart. The classification stays
`REBOOT_RECOVERY_UNPROVEN`.
@@ -0,0 +1,63 @@
# Phase 0.9E-R remaining provenance gaps
Date: 2026-07-18
Overall decision: `LOCAL_BACKUP_NOT_CORRELATED`
## Closed questions
- The local outer ZIP retains its Phase-0.9E size and SHA-256.
- The official current inventory consists of releases 1.3, 1.5, and 1.6 and
tags `Y2JB-1.2.1`, 1.3, 1.4, 1.5, and 1.6.
- All seven current official release assets have official SHA-256 digests,
names, and sizes different from the local outer ZIP.
- Official tag commits, trees, source archives, and host sender are bound.
- Official Y2JB does not implement a port-9020 listener in the inspected tags.
- Its Remote JS Loader is a dynamic port listener normally seeking 50000.
- Port 9021 belongs to an embedded elfldr path reached after Lapse/kexp.
## Remaining gaps
1. The source, author, version, and construction procedure for
`Y2JB-Autoloader-403-1240.zip` are unknown.
2. The MediaFire download marker does not identify an official release asset.
3. The local opaque `SIECAF` content cannot be matched to official source.
4. No evidence binds the local outer ZIP to what was restored on the PS5.
5. No evidence shows whether `download0.dat` or app data was later replaced.
6. No evidence identifies the operator's actual host sender.
7. No evidence explains the previously assumed port-9020 listener.
8. The source/generator identity of the 1.6 embedded elfldr and kexp blobs is
not present in Y2JB.
9. Runtime behavior on firmware 9.60 remains unobserved.
10. Independent recovery and the current Payload Manager backup remain
unresolved installation blockers.
11. The exact requested official source-archive URLs are recorded, but the
transient GitHub redirect URLs were not retained.
The official sender is one-way. The JavaScript server can write log bytes on
its accepted socket, but `payload_sender.py` never receives them. Therefore no
existing end-to-end duplex result channel is established. Reusing that
connection would require a different host contract; an outbound connection or
temporary listener would require new target design. No output architecture is
selected while the exact-used bootstrap remains unbound.
## Phase 0.9F gate
`phase09f_offline_design_allowed=false`.
The mandatory official outer-asset byte match is absent and the inspected
official source has only a 9020 reference, not a found or partial 9020
implementation. Device observation cannot be used to repair these facts in
this phase.
Minimum safe next evidence:
- a verifiable publisher/provenance record for the exact MediaFire-marked
outer ZIP, or a different operator-provided exact outer ZIP that matches an
official asset;
- a completed non-runtime operator attestation;
- exact identification of any external autoloader or 9020 implementation and
sender used in the real workflow.
Supplying evidence grants no connection, transfer, installation, execution,
autoload, device-write, or retry authority.
@@ -0,0 +1,93 @@
# Phase 0.9E-R Y2JB release-to-source binding
Date: 2026-07-18
## Official source acquisition
The official repository was acquired from
`https://github.com/Gezine/Y2JB.git` into ignored host-only path
`work/upstream/Y2JB-official`. It is detached at tag `1.6`:
- commit: `0dbbf4e7e0203af7e5d101a3256c634edf4e3ba2`;
- tree: `c4344f43af7c268337437e6419548dba6f6bc211`;
- status: clean;
- submodules: none;
- Git LFS pointers: none;
- tracked files at 1.6: 19;
- license: MIT.
No project file from that tree was executed and no dependency was installed.
The upstream tree remains ignored and is not vendored.
## Source archives
Each official GitHub tag source archive was downloaded outside tracked paths,
closed, hashed locally, and compared byte-for-byte by pathname with the exact
Git tree. All regular files match their tag tree.
The requested URLs were the official GitHub API form
`https://api.github.com/repos/Gezine/Y2JB/zipball/<tag>` for each exact tag in
the table. GitHub's redirect target was not retained as provenance and is
listed as a gap rather than reconstructed.
| Tag | Commit | Tree | Archive bytes | Locally computed SHA-256 | Archive ↔ tree |
|---|---|---|---:|---|---|
| `Y2JB-1.2.1` | `6210f98c23552e6eb3c4c8981f72a200bb6121b2` | `928ceb979881a063457270dde4961ea4a06bc1fa` | 142038 | `dd7b05234aec35696b6d00ea4420f7bc1e09d57a4fe64363fdaa6728a37b7201` | 20/20 files exact |
| `1.3` | `82e6bbf1935d5f41c3bd5bd9e6598cf90bb2e022` | `df29ffe4d8131b5f8b0da1874e34b95a41f0660d` | 185243 | `661993fbeec566bdfc0c5d9b89eeddc4a1f21f4a8c0b7392fddea4f73ce636d6` | 22/22 files exact |
| `1.4` | `02eda2e772df629ecfe5a46459769bd8c994ef3e` | `ec06403b45f7b68e01eb5053f81277dee4910dd2` | 151619 | `53d7fb1e665d0534d446cfe980841a0b8eed7eda35424c2f9c4abad32d5aaec5` | 19/19 files exact |
| `1.5` | `5fa556e6281229057dace3254b099f95261df386` | `db364529c347f34b8ddb186f57bb61dab91113db` | 149934 | `5d964faaf1b941c2fc8a006b10ae909b15d8f2c27d120e08b37196f1e464ad6d` | 19/19 files exact |
| `1.6` | `0dbbf4e7e0203af7e5d101a3256c634edf4e3ba2` | `c4344f43af7c268337437e6419548dba6f6bc211` | 150964 | `8385c439458c6954fd1198760ab0ef8245543235c83db90d041591362027cae4` | 19/19 files exact |
This establishes `REPRODUCIBLE_CONTENT_BINDING` between each downloaded source
archive and its official Git tree. It establishes no relationship between the
local MediaFire-marked backup and any tag.
## Static 1.6 inventory
The 1.6 tree contains one HTML file, ten JavaScript files, three Python host
tools, one embedded kexp binary, and one embedded ELF. It contains no WASM,
service worker, web manifest, submodule, LFS pointer, loader generator, or
build script for the embedded blobs.
Important 1.6 file identities:
| Path | Bytes | SHA-256 |
|---|---:|---|
| `README.md` | 7500 | `16bfdaa624b8b04f4a6a4a7d512ca8473ad2db73e80df39a974267403e34f751` |
| `payload_sender.py` | 1064 | `8c87920c41dbdbd66b9f36ca9509f0d6bef9170f351dd97ff831cfb98e642ec6` |
| `log_server.py` | 929 | `463114fd46479a7286706de13beb3f52221f36f3cbe37dc5a27bdb6104787a98` |
| `appinfo_editor.py` | 2008 | `c1bcb453660f597cbc9026dba76519a4929fc3e967c183deec8a1ca56912e2e8` |
| `splash.html` | 596 | `0060fce48b104d57025399814e29e9db83923068e7fce899c6235ff7da2e72ef` |
| `main.js` | 44909 | `4f2a87a4550e453b13ada660136d9e7019230bf8fdf7016e855911bd38f0e3d5` |
| `global.js` | 8760 | `1b39c3fe7576f80f6ff3cd32fcb5eef2cbb972b574897f80a28370fb1afceb1d` |
| `kernel.js` | 9113 | `631aac816ed674dce6460cea49fa62961b06ed9446b14f6340416bb98d0326de` |
| `misc.js` | 16308 | `05df5102239af19a9f5a28fb6994dc213db8ab54c7bd7120243b92409c8f8407` |
| `remotejsloader.js` | 7132 | `30cc6d1535549b2a49b47a9e0c85a3444cf84177be54398691694b7c6505f38e` |
| `aioshellcode.js` | 3870 | `feb50f1a7596dfde61611ae347fc7d2ec2ca34e75d05fa5d91340df2d762d310` |
| `kexp_2026_05_25.bin` | 18912 | `618f4b121cd26f2b259ade4fc3a69b3bdb631667758ae63fb9d316b4362015eb` |
| `elfldr-ps5-1340.elf` | 397000 | `30478bcadb6439e1247451c4ac706b6e1385044dd0f12d6486b6d7057929453b` |
The embedded 1.6 ELF is an x86-64 PIE with entry `0x4700` and `DT_NEEDED`
entries for `libkernel_web.sprx`, `libSceLibcInternal.sprx`, and
`libSceNet.sprx`. It has no source or generator in Y2JB; its commit identity is
therefore the containing Y2JB blob only, not a claimed elfldr source commit.
Across tags the embedded elfldr identities are:
| Tag | Embedded file | SHA-256 | Binding |
|---|---|---|---|
| 1.2.1 / 1.3 | `elfldr.elf` | `00ce93eb217b3720f40f18f47221ed25702847c570593e468823abffbcadd562` | binary only |
| 1.4 | `elfldr_1320_v5.elf` | `5839049ca949462c9e8cb40be35afd783ac07d50a290857a5558ceeb81fb90fe` | binary only |
| 1.5 | `elfldr-ps5-0.23.elf` | `092d16ee0ede0c494947efd38d1a17bbd7cc4b022d3858ea898833c188c703e8` | byte-equal to the already pinned public v0.23 asset |
| 1.6 | `elfldr-ps5-1340.elf` | `30478bcadb6439e1247451c4ac706b6e1385044dd0f12d6486b6d7057929453b` | binary only |
## Binding decision
- official tag source archive → Git tree:
`REPRODUCIBLE_CONTENT_BINDING`;
- official release → same-tag source: `OFFICIAL_RELEASE_ASSOCIATION`;
- local outer ZIP → official release: no association;
- local inner `SIECAF` → source: `UNBOUND`;
- local backup overall: `LOCAL_BACKUP_NOT_CORRELATED`.
No official source association was promoted into a local inner-content match.
@@ -0,0 +1,70 @@
# Phase 0.9E-R2 community backup correlation
Date: 2026-07-19
Only the three named official GitHub repositories and their release metadata
were inspected. No mirror or general scene download was used. Metadata,
source trees, and release assets were read statically; downloaded archives
were not executed.
## Candidate matrix
| Family | Relevant release identity | Firmware statement | Public system backup | Components/autoload | Decision |
|---|---|---|---|---|---|
| `itsPLK/ps5-y2jb-autoloader` | `v0.8-a0146a2`, commit `a0146a2a9229fa5df5b5127257bf2e11ffc6d2de` | 4.0312.70 | no; README explicitly says the project does not distribute preconfigured system backups | Lapse blob `190996c…`, P2JB blob `510bf4b…`, elfldr submodule `148b71c…`, Payload Manager submodule `5d33ce1…`; exploit and localhost elfldr auto-load, later payloads use `autoload.txt` | `THIRD_PARTY_BUILD_FROM_PUBLIC_SOURCE_POSSIBLE`, but unbound |
| `owendswang/Y2JB-P2JB-bdj_unpatch` | `v1.4-autoloader`, commit `9990e917cdb24c249ce24f4ff18e6e869e99cf51` | tag README says 9.0012.40 disc; downloaded backup name says 7.61 | yes | Gezine Y2JB base declared; Lapse/P2JB blobs and embedded elfldr are identifiable; no Payload Manager identity at this tag | downloaded candidate inner and structure do not match |
| `lz-anonz/Y2X` | `v1.3`, commit `2ae881259be647738713b83a6a91ffe693ccf9af` | 4.0312.70 | no current large release asset despite README backup wording | P2JB/Lapse, v1/v2 embedded elfldr, Payload Manager 0.3.1 and FTP; v2 auto-loads Manager/FTP and warns against kstuff in autoload | excluded by asset inventory; no large download |
## itsPLK
The relevant tag was published 2026-06-10 09:05:51Z, before the local inner
ZIP timestamp. Its official assets are only:
- `download0.dat`, 336789504 bytes,
SHA-256 `268c82f7a8f581c804949a86c259c982953ff479c13a3dc9f9da02c354b32d6e`;
- `y2jb_update.zip`, 1152857 bytes,
SHA-256 `301599b05e7eb7224025ef9ed6ebc896d86d2c14bba5c32ced5a88bdf2c3517e`.
Its README's firmware range, “Autoloader” naming, timing, and credit to Rush
for creating a backup make the family plausible. The same README explicitly
says itsPLK does not distribute such backups. No public hash, backup asset,
MediaFire link, or maker attestation binds this source to the local bytes.
Accordingly it is not an official itsPLK release and is not promoted to
`THIRD_PARTY_REPACK_PROVENANCE_BOUND`.
## owendswang
Release `v1.4-autoloader` published 2026-06-10 09:01:19Z includes:
- `download0_Y2JB+autoloader-20260609.zip`, 333151616 bytes;
- `PS5-12.20-backup-Y2JB+autoloader-20260609-en.zip`, 498991549 bytes;
- `PS5-7.61-backup-Y2JB+autoloader-20260609-en.zip`, 504425435 bytes.
The 7.61 backup was the sole downloaded community candidate because its
family, date, and size were concrete matches. Its local download exactly
matched GitHub size and SHA-256
`8552d7c3c7bb3f078d967f56dfe1b488b37e3ed13e10c5fe97ae222482d56897`.
Its inner is 504627200 bytes with SHA-256
`d4f9b1ba4e32af175a3431a7734085d5420370ebb79f9a32852eb824a90e190e`.
The local inner is 262144 bytes smaller, has a different full hash, differs
byte-for-byte, and has version/count 3/62 rather than 6/58. Normalized
segment layout and section hashes also differ.
Classification: no `COMMUNITY_INNER_BYTE_MATCH`.
## lz-anonz
Release `v1.3` published 2026-06-10 21:58:27Z has only:
- `USB-ps5_autoloader.rar`, 904337 bytes;
- `v1.3-download0-Y2X-P2JB+Lapse.rar`, 521801 bytes.
The source contains autoload and embedded components, but the current release
does not expose a system-backup object to compare. README language is not a
byte identity. No large asset was downloaded.
## Download bound
One of the maximum three allowed community backups was downloaded. It used one
attempt, no resume, and no retry. The other two families had no public large
candidate justified by their own release metadata.
@@ -0,0 +1,67 @@
# Phase 0.9E-R2 final provenance decision
Date: 2026-07-19
Primary classification: `LOCAL_BACKUP_UNCORRELATED`
## Decision chain
1. The complete local ADS establishes `MEDIAFIRE_URL_EXACT` for file key
`jq3fcutuwbb1mrb` and the exact local filename.
2. The exact MediaFire page is still present and establishes
`MEDIAFIRE_OBJECT_METADATA_BOUND`, but exposes no server digest, exact byte
count, public uploader, maker, tutorial, or source.
3. The mandatory official Gezine/Y2JB 1.6 4.03 inner differs in size,
SHA-256, complete bytes, normalized layout, and section hashes.
4. The one justified community backup from owendswang also differs on every
inner and structural measure.
5. itsPLK is a plausible public source family, but explicitly does not publish
system backups and supplies no binding to this MediaFire object.
6. Y2X has no current large system-backup asset at its relevant release.
Therefore:
- `OFFICIAL_INNER_BYTE_MATCH`: false;
- `COMMUNITY_INNER_BYTE_MATCH`: false;
- `THIRD_PARTY_REPACK_PROVENANCE_BOUND`: false;
- `SIECAF_STRUCTURAL_RELATION_ONLY`: false;
- `LOCAL_BACKUP_UNCORRELATED`: true.
`LOCAL_BACKUP_NOT_CORRELATED` from Phase 0.9E-R remains historically correct
for the outer-asset analysis. R2 refines the current fail-closed result after
inner, structure, origin, and community correlation; it does not silently
replace the prior record.
## Separate identities
| Question | Result |
|---|---|
| Is the outer ZIP official? | no |
| Is the MediaFire object metadata-bound? | yes |
| Is its maker/source bound? | no |
| Is the inner official/community byte-bound? | no |
| Is even a normalized structural relation established? | no |
| Was this backup restored to the PS5? | `UNPROVEN` |
| Are current PS5 bytes known? | `UNPROVEN` |
| Is firmware-9.60 runtime behavior known? | `UNPROVEN` |
## Phase 0.9F
Phase 0.9F offline design may not be reconsidered. Neither of the entry
conditions is met:
- the inner is not byte-exactly bound to an auditable source family;
- the MediaFire backup is not bound to an auditable maker/release with a
complete actual bootstrap implementation.
The actual deployed bootstrap, embedded listener closure, autoloader component
manifest, independent recovery, and current device contents remain unproven.
The byte-exact Payload Manager backup remains
`HARD_BLOCKER_FOR_INSTALLATION`.
## Authorization
All device, target-build, transfer, execution, installation, lifecycle,
autoload, device-write, rescue-design, and retry fields remain false. No PS5
action, target code, target artifact, payload, device client, restore, or
execution occurred.
@@ -0,0 +1,68 @@
# Phase 0.9E-R2 inner archive correlation
Date: 2026-07-19
Result: `INNER_ARCHIVE_HASH_MISMATCH`
Phase 0.9E-R excluded an outer byte match. R2 separately tests the plausible
repack case by comparing complete inner `archive.dat` bytes.
## Local identity
| Object | Size | SHA-256 |
|---|---:|---|
| local outer ZIP | 504159435 | `805e3f87f0c371223619ffc7d3a7b3c0d41a1fae8a8b1171d9e2f162659e8291` |
| local `PS5/EXPORT/BACKUP/202606102126_00/archive.dat` | 504365056 | `6439834e8856d45b6d6fe699b74c35ca6985a199ea8ecf3e398c018d37be2d55` |
## Mandatory official candidate
The exact official Gezine/Y2JB 1.6 asset
`Y2JB_backup_1.6.4.03.zip` was downloaded once from its GitHub release URL.
Resume and retry were disabled. The closed and reopened file was 504395044
bytes and its locally calculated SHA-256 was
`b01b4f442327f9eca90ffc4506dfa58249e4ac70cb9d7488c856c9e8dfaf37b4`,
equal to GitHub's official digest.
It was not executed or restored. Static ZIP inventory:
| Entry | Method | Compressed | Uncompressed | CRC32 | Timestamp | Entry SHA-256 |
|---|---:|---:|---:|---|---|---|
| `PS5/` | 0 | 0 | 0 | `00000000` | `2026-06-09 04:15:20` | empty SHA-256 |
| `PS5/EXPORT/` | 0 | 0 | 0 | `00000000` | `2026-06-09 04:15:20` | empty SHA-256 |
| `PS5/EXPORT/BACKUP/` | 0 | 0 | 0 | `00000000` | `2026-06-09 04:15:20` | empty SHA-256 |
| `PS5/EXPORT/BACKUP/202606090510_00/` | 0 | 0 | 0 | `00000000` | `2026-06-09 04:15:20` | empty SHA-256 |
| `PS5/EXPORT/BACKUP/202606090510_00/archive.dat` | 8 | 504394122 | 504496128 | `7db3b89a` | `2026-06-09 05:15:58` | `3e1f0867d5d8362cbf722d51d0e68c26243d6b33d78460d978580b510c854212` |
The four directory entries use Unix create-system 3, create/extract version
20, external attributes 1107230720, and empty comments. The inner entry uses
create system/version 3/20, extract version 20, flag bits 8, external
attributes 2176188416, header offset 315, and an empty comment.
## Full inner comparison
| Property | Local inner | Official inner |
|---|---:|---:|
| size | 504365056 | 504496128 |
| SHA-256 | `6439834e...37be2d55` | `3e1f0867...0c854212` |
| complete bytes equal | no | no |
The size differs by 131072 bytes. Complete streaming comparison and both
hashes disagree. Classification is `INNER_ARCHIVE_HASH_MISMATCH`, so the
local outer cannot be classified `REPACKAGED_OFFICIAL_BACKUP`.
## Community comparison performed
The one source-motivated community download was
owendswang/Y2JB-P2JB-bdj_unpatch release `v1.4-autoloader`,
`PS5-7.61-backup-Y2JB+autoloader-20260609-en.zip`. GitHub and local size were
504425435 bytes; both SHA-256 values were
`8552d7c3c7bb3f078d967f56dfe1b488b37e3ed13e10c5fe97ae222482d56897`.
Its inner `PS5/EXPORT/BACKUP/202606100638_00/archive.dat` is 504627200 bytes,
CRC32 `cf138df3`, and SHA-256
`d4f9b1ba4e32af175a3431a7734085d5420370ebb79f9a32852eb824a90e190e`.
It is neither the same size, hash, nor bytes as the local inner:
`INNER_ARCHIVE_HASH_MISMATCH`.
Outer mismatch did not substitute for inner analysis. The negative inner
results now independently exclude both downloaded candidates.
@@ -0,0 +1,78 @@
# Phase 0.9E-R2 local download provenance
Date: 2026-07-19
Result: `MEDIAFIRE_URL_EXACT`
This evidence is host-only. No PS5 address, request, connection, transfer,
restore, target build, or execution was used.
## Local object
| Field | Value |
|---|---|
| name | `Y2JB-Autoloader-403-1240.zip` |
| size | `504159435` |
| SHA-256 | `805e3f87f0c371223619ffc7d3a7b3c0d41a1fae8a8b1171d9e2f162659e8291` |
| creation UTC | `2026-06-23T14:10:39.0466596Z` |
| modification UTC | `2026-06-23T14:11:10.6992328Z` |
The file was read without changing it. Its `Zone.Identifier` alternate data
stream is 327 bytes and has SHA-256
`70928a3d66cbb9f584596414c4fe535b498dd5ed7c5f55bbeae4efeb146ea841`.
It contains exactly the `ZoneTransfer` section and these fields:
| Field | Safe evidence |
|---|---|
| `ZoneId` | `3` |
| `ReferrerUrl` | host `www.mediafire.com`, path `/`, no query; full-value SHA-256 `9a0ff5a3e34286b2e53192003fca8b6c7b00ad6df3c681765da04ccaa54c0919` |
| `HostUrl` | host `download2434.mediafire.com`, file key `jq3fcutuwbb1mrb`, filename `Y2JB-Autoloader-403-1240.zip`; full-value SHA-256 `a39f05923d0a5368ea5138c1974ac109bb09f8ab795c6edb8e470d8dfe4d784c` |
| `LastWriterPackageFamilyName` | absent |
| `AppZoneId` | absent |
| other fields | none |
The transient signed path component is deliberately redacted. It was neither
committed nor reproduced here. The complete value remains only in the
unchanged local ADS.
## Browser metadata
The bounded search covered existing Chrome Default, Chrome System Profile,
and Edge Default Chromium History databases. The query was limited to the
exact filename, size, filesystem-date window, MediaFire host, and file key.
Brave, standalone Chromium, Opera, and Opera GX profiles were absent.
Three read-only database copies were made because browser databases can be
live-locked. Chrome Default, Chrome System Profile, and Edge Default each
returned `NO_MATCH`; no download rows were exported and the originals were
not changed. The temporary copies were removed with the rest of the research
directory.
Browser classification: `NO_BROWSER_HISTORY_MATCH`.
## Exact MediaFire page
Only
`https://www.mediafire.com/file/jq3fcutuwbb1mrb/Y2JB-Autoloader-403-1240.zip/file`
was requested. Static HTML was 333321 bytes with SHA-256
`655e4c3c2e5c423019b0195ca863ee8906f7ca02601b773b39688a590bf7fcb7`.
It displayed:
- filename `Y2JB-Autoloader-403-1240.zip`;
- size `480.8MB`;
- uploaded value `2026-06-11 15:32:16`;
- upload country `United Kingdom`;
- the same MediaFire file key.
No public account/uploader, user description, tutorial, maker, server digest,
or exact server byte count was exposed. The download object was not
downloaded again. The local ADS plus page provide
`MEDIAFIRE_OBJECT_METADATA_BOUND`, not `MEDIAFIRE_OBJECT_BYTE_BOUND` and not
maker/source provenance.
## Boundary
The download-origin classification is `MEDIAFIRE_URL_EXACT`. That describes
where the local bytes were downloaded from. It does not prove who created
them, which public source generated them, whether they were restored, or what
is currently on the PS5.
@@ -0,0 +1,70 @@
# Phase 0.9E-R2 SIECAF structural analysis
Date: 2026-07-19
Result: all pairwise comparisons are `SIECAF_LAYOUT_DIFFERENT`.
## Evidence and scope
`tools/inspect_siecaf_header.py` is a host-only read-only parser. Its fixed
little-endian layouts are bound to:
- PS5 DevWiki `Archive.dat` structure documentation;
- `c0w-ar/ps5-bar-tool` commit
`36d014672bc87577a6e0d750c2cccadc3fae0854`, tree
`d3e973b60432fdc32bd16e3b7424e82dcc38a23f`;
- public `include/bar_file.h` blob
`fdbc368353a7797464873ada306f0297257eb95e`.
The public header names the 64-bit value after the magic `unknown`, and the
later signed 32-bit field `version`. Versions 3 and 6 were observed and are
parsed using that same public fixed-width layout. Other versions fail closed.
The parser reads only the 0x58-byte header, 0x40-byte metadata records, and
0x30-byte hash records. It never decrypts, guesses keys, extracts content,
executes `ps5-bar-tool`, writes output files, or opens a network connection.
The 16-byte header field named `key` by the public source and the complete raw
header are not emitted; only their SHA-256 fingerprints are recorded. This
preserves exact structural comparison without committing cryptographic header
material.
It checks exact magic, table arithmetic with uint64 overflow guards, table and
declared-data bounds, 64 KiB alignment, coherent aligned/unaligned sizes,
metadata `(section_id, part_number)` identity, hash-table index coverage,
duplicates, overlaps, gaps, and trailing data. Repeated section IDs with
different part numbers are reported but are valid multipart records.
## Header comparison
| Field | Local | Official Y2JB 1.6 4.03 | owendswang v1.4 autoloader 7.61 |
|---|---:|---:|---:|
| inner size | 504365056 | 504496128 | 504627200 |
| version | 3 | 3 | 6 |
| segment count | 62 | 64 | 58 |
| data offset | 65536 | 65536 | 65536 |
| declared data size | 504299520 | 504430592 | 504561664 |
| header SHA-256 | `4454809c9831770901491368f08b648129aef7ee3148aff17df8716ff3a5cd76` | `1af2bd937e5b6a2386331893f7ea1295661858cb91c90ee728141a4fec2dbf9b` | `db2a9677f051b372e208261d767ac45f653374426a5594ce3306568138ebd3ae` |
All three parse as `SIECAF_VALID_STRUCTURE`. None has gaps, overlaps, trailing
data, duplicate metadata composite keys, or duplicate hash-table IDs.
## Normalized fingerprints
| Object | Segment table SHA-256 | Hash blocks SHA-256 | Layout SHA-256 | Structural SHA-256 |
|---|---|---|---|---|
| local | `ee35a92fe5e46c307310715fc5bd0edb9ac46c2046b7d77e9c1c437446e399ea` | `6e052f186dc8e683d501e376d79dcec1ba0d3268c257b6071e96eae738a7be24` | `c6dac8313ef99accba68b4a36871f0d8ae99676df0b721d4447ecb05a12a6539` | `7bb1b70187d1f48370b9bae218429af79105585bd043307824c0d84982e6922f` |
| official | `d31def8e731d7bba0eaf23177f7c7245ef17f5d37ade53c9ca18744154bc8e25` | `c3236f5d85a4d7741be5a1fda5ce96d2bb7f005b0e48fed043af5ea48fb045d2` | `de6cc47686e5e301b725267b9b777c80a07a788e51f214cfb6e9d7f6e2e11110` | `9c453e1fa99ef1f1e6fe1d992f9b0a2ede4dbd4b9a2ad8551c08c8c61ed9be2a` |
| community | `f0aed4ae115866010902671a511983c3e6e21d1a7ab187bae7f36566979beb89` | `434b209865af8c5815b1277073db59348fddf65086908b2fd00dee5324459bcb` | `be7fdf87361c17fa52d3b4b263f4ee0cce69e924f8dab0ab66c554b4d9557549` | `4884c54e280969371ae1d0b84533be5a7c50a61dff6931cf595fdb5862655218` |
Pairwise outcomes:
- local versus official: `SIECAF_LAYOUT_DIFFERENT`;
- local versus community: `SIECAF_LAYOUT_DIFFERENT`;
- official versus community: `SIECAF_LAYOUT_DIFFERENT`.
`manifests/runtime/phase-0.9e-r2-siecaf-fingerprints.json` contains every
non-secret normalized input field, metadata record, section hash, redacted
header-field hashes, parser warning/error array, and comparison. Structural
hashes are non-authorizing fingerprints:
even `SIECAF_STRUCTURAL_EXACT` would not prove decrypted-content identity or
deployment. Here, not even normalized layout equality exists.
@@ -0,0 +1,57 @@
# Phase 0.9E reboot and crash model
Date: 2026-07-18
Classification: `REBOOT_RECOVERY_UNPROVEN`
## State model
| State | Evidence | Expected lifetime | Reboot statement |
|---|---|---|---|
| exact exploit/browser state | implementation absent | unknown | `UNPROVEN` |
| exact port-9020 listener state | implementation absent | unknown | `UNPROVEN` |
| hardened elfldr entry process | `main.c` source | temporary by design | hardware behavior unproven |
| embedded bootstrap in `SceRedisServer` | `main.c`/`bootstrap.c` | temporary injection stage | likely process/kernel state, not a proven recovery mechanism |
| `elfldr.elf` port-9021 service | `socksrv.c` | process-local background service by design | README says rest-mode resume, not reboot persistence |
| controlled Manager | source/offline artifact | process-local when launched | explicitly not installed in current controlled-runtime evidence |
| Manager configuration/autoload files | source paths only | filesystem-persistent if actually present | current device values and use unobserved |
| Y2JB-named `SIECAF` backup | host file | host-persistent | not proof of device installation |
The hardened elfldr README states that the port-9021 service survives payload
crashes and resumes after rest mode. It does not say that the service survives
a full reboot. Source creates process state and does not install a boot item,
but the complete device bootstrap/autoload environment is not available.
## Crash cases
- A payload crash under hardened port 9021 is isolated by design from the
service process. That is source architecture, not a tested firmware-9.60
guarantee.
- A crash in the unknown port-9020 listener may terminate a process, exploit
state, or more. No cleanup, watchdog, retry, or restart path is available for
audit.
- A malformed or truncated 9020 transfer has unknown allocation, mapping,
execution, and close behavior.
- A hang has no proven host abort, deadline, or recovery response.
- No source proves that a bad payload cannot create persistent state; a future
rescue contract must explicitly prohibit such writes.
## Anti-brick boundary
A session crash is not automatically brick-relevant if live files, autoload,
configuration, mounts, and boot state remain unchanged and a reboot or fresh
jailbreak session restores the executor. Those premises are not yet proven for
the actual chain.
Consequently:
- `restartable_after_reboot=unproven`;
- no guarantee is made that reboot always restores access;
- no automatic retry is permitted;
- no future device phase may rely on reboot recovery until the exact package
and its state transitions are audited.
Minimum evidence to promote to `REBOOT_RECOVERY_SUPPORTED_BY_DESIGN` is an
exact source-bound trigger/listener implementation proving that all bootstrap
state is session-local or safely reproducible, plus an exact operator procedure
that does not rely on a live component or autoload.
+198
View File
@@ -0,0 +1,198 @@
# SDK v0.41 startup call graph
This is an offline source, relocation, and disassembly audit of the installed
SDK v0.41 `target/lib/crt1.o`. It describes the unsafe stock startup, not a new
Chimera GFX artifact. The complete machine-readable reachable graph contains
31 functions and 182 call or tail-call edges in
`manifests/runtime/phase-0.5-startup-audit.json`.
## Transitive startup objects
`crt/Makefile` compiles and partially links exactly these objects into one
relocatable `crt1.o` with `prospero-lld -r`:
| Object | Public source | Role |
|---|---|---|
| `crt.o` | `crt/crt.c` | entry, BSS, init/run/terminate |
| `syscall.o` | `crt/syscall.c` | syscall bootstrap |
| `klog.o` | `crt/klog.c` | kernel log helpers |
| `nid.o` | `crt/nid.c` | symbol-name encoding |
| `kernel.o` | `crt/kernel.c` | kernel transport and process helpers |
| `rtld.o` | `crt/rtld.c` | runtime-loader core |
| `rtld_so.o` | `crt/rtld_so.c` | shared-object mapping and relocation |
| `rtld_sprx.o` | `crt/rtld_sprx.c` | Sce module load/start/stop/unload |
| `rtld_payload.o` | `crt/rtld_payload.c` | payload relocation and arrays |
| `rtld_dlfcn.o` | `crt/rtld_dlfcn.c` | `dlopen`/`dlsym` facade |
| `mdbg.o` | `crt/mdbg.c` | memory-debug transport helpers |
| `patch.o` | `crt/patch.c` | credentials and syscall-bound patches |
The files named `crti.o`, `crtn.o`, `crtbegin.o`, `crtend.o`, `crtbeginS.o`,
and `crtendS.o` are empty `ar` archives at the installed release. The audit
enumerates them rather than assuming their filename implies contents.
## Reachable startup paths
The important conservative paths from source, relocations, and disassembly are:
```text
_start
|- zero [__bss_start, __bss_end)
|- __crt_syscall_init
|- __kernel_init
| `- kernel_copyout (reachable in compiled object)
|- __klog_init
|- kernel_dynlib_dlsym -> set __isthreaded = 1
|- __patch_init UNSAFE
| |- kernel_get_ucred_caps -> kernel_copyout
| |- kernel_get_ucred_attrs -> kernel_copyout
| |- kernel_set_ucred_caps -> kernel_copyin KERNEL WRITE
| |- kernel_set_ucred_attrs -> kernel_copyin KERNEL WRITE
| `- kernel_copyin at process offsets 0xf0/0xf8 KERNEL WRITE
|- __rtld_init UNSAFE
| |- __rtld_sprx_init -> sceKernelLoadStartModule
| |- __rtld_so_init
| |- __rtld_payload_init
| `- __rtld_dlfcn_init
|- __rtld_payload_new/open/init
| `- constructors
|- main
|- __rtld_lib_fini/close/destroy
| `- destructors
`- payload_terminate
|- ret for the CRT's detected hijacked-process case
|- resolved exit for another case
`- trap when exit cannot be resolved
```
Indirect calls are retained as `INDIRECT:<operand>` in the JSON graph rather
than guessed. A relocation to the `sceKernelLoadStartModule` function-pointer
slot is retained explicitly. This makes the graph conservative without
inventing a firmware ABI.
## Linked but not startup-reachable
The monolithic `crt1.o` also contains `__dlopen`, `__dlsym`,
`kernel_mprotect`, `kernel_overlap_sockets`, and
`kernel_set_vmem_protection`, although the disassembly graph did not find them
reachable from the stock `_start`. Their presence demonstrates why an import
inventory alone would be insufficient: prohibited-capability code can be
statically linked without appearing as an undefined symbol.
## Driver and linker behavior
The `prospero-clang` wrapper normally adds `crt1.o`, `libc`, `libkernel_web`,
`libSceLibcInternal`, and `libSceNet`. A no-output `-###` trace with both
`-nostartfiles` and `-nodefaultlibs` adds none of them. The linker wrapper still
selects the public `elf_x86_64.x` script, PIE mode, an ELF x86-64 emulation,
0x4000 maximum page size, emulated TLS support, and GNU hashing unless the
caller overrides applicable options.
The linker script retains preinit/init/fini arrays and a dynamic segment. It
also declares the text load segment with flags `0x7`; that is a source fact,
not a claim about final loader-enforced permissions.
## Why there is no custom linker map
The loader return contract failed before the build gate. In accordance with
the task rule, no custom `_start` source or PS5 ELF was created. Therefore a
custom linker map, imports, `DT_NEEDED`, relocations, arrays, TLS inventory,
double-build hash, and artifact disassembly are all explicitly recorded as
`NOT_PERFORMED_BLOCKED_BEFORE_BUILD`, not silently treated as passing.
## Phase 0.6 exact runtime chain
This addendum is the reviewed source call graph for the installed chain. No new
probe artifact exists, so there is no probe disassembly call graph to report.
```text
Payload Manager /loadpayload:<path>
`- ps5_launch_elf(path)
|- open(path, O_RDONLY)
|- connect(127.0.0.1:9021)
`- send(ELF bytes)
elfldr serve_elfldr
`- elfldr_spawn
|- rfork_thread
| `- child: elfldr_rfork_entry
| |- sys_budget_set(0)
| |- open(/dev/deci_{stdin,stdout,stderr})
| |- ptrace(PT_TRACE_ME)
| `- execve(SceSpZeroConf)
|- parent: pt_syscall(599)
| `- pt_syscall -> unbounded pt_step loop
|- elfldr_set_heap_size(-1)
|- kernel_mprotect(eboot entry page, RWX)
|- install INT3 -> continue -> wait -> restore byte
`- elfldr_exec
|- backup jaildir/rootdir/caps/authid
|- elfldr_raise_privileges
| `- set rootdir/jaildir/UID/caps
|- elfldr_prepare_exec
| |- elfldr_load
| | |- mmap/copy/RELATIVE relocations
| | `- per-segment mprotect + msync
| |- elfldr_payload_args
| | |- mmap page
| | |- two IPv6 sockets + overlap
| | `- pipe + six payload_args_t fields
| `- [RSP-8]=old RIP; RIP=entry; RDI=args
|- restore jaildir/rootdir/caps/authid (not UID)
`- ptrace(PT_DETACH)
SDK v0.41 payload _start
|- clear BSS
|- initialize syscall/kernel/klog
|- __patch_init
|- initialize rtld and constructors
|- main
|- destructors and rtld cleanup
`- payload_terminate
`- return OR exit OR trap (exact child branch unproven)
```
The exact elfldr release binary is stripped, so the source graph is bound to
the release by source commit and release-asset SHA-256. Static binary evidence
records entry `0x4700`, 164 relocations, 24 undefined dynamic symbols, three
`DT_NEEDED` modules, zero-byte init/fini arrays, no TLS, and hashes of the
complete readelf report and disassembly in
`manifests/runtime/phase-0.6-loader-runtime-audit.json`.
## Phase 0.7 hardened callgraph addendum
Phase 0.7 uses new hardened elfldr and controlled Payload Manager binaries;
the graph above remains the historical stock Phase-0.6 chain.
The lifecycle source-level action is deliberately narrow:
```text
SDK _start
|- BSS and stock SDK v0.41 runtime initialization
|- __patch_init
|- main
| |- sceKernelSendNotificationRequest
| `- _exit
`- payload_terminate [not reached from main]
```
The hardened loader retains its required first-stage and ptrace operations,
but each single-step operation now has both a one-second monotonic deadline
and a 65,536-step ceiling. Cleanup tracks the child, breakpoint, mappings, and
descriptors in one state. The success and failure paths restore all five
credential fields and verify every restoration. The runtime supervisor waits
at most 2000 ms, then uses a bounded SIGTERM/SIGKILL/reap sequence.
The controlled manager opens, hashes, rewinds, and streams one no-follow file
descriptor. The hardened receiver independently rehashes the received bytes
and checks the exact versioned header and permanent denylist.
The committed machine audit contains every extracted call edge, not a sample:
- lifecycle: 499 edges;
- hardened elfldr: 1032 edges;
- controlled manager: 478 edges.
Full disassembly, normalized linker maps, symbol/relocation/section reports,
and text callgraphs are in the ignored `outputs/phase07/audit/` package. Their
hashes and the complete edge arrays are committed in
`manifests/runtime/phase-0.7-offline-audit.json`.