Add caller-only elevated capability profiles #1

Closed
blackbearreloaded wants to merge 4 commits from feature/self-elevation into main
blackbearreloaded commented 2026-08-30 11:41:10 -05:00 (Migrated from github.com)

Purpose

Native PS5 applications normally run inside a restricted sandbox. That is the right default, but it prevents end-user homebrew applications from implementing legitimate features that require broader platform access, such as managing files outside their app container, creating temporary mounts, or opening privileged platform facilities.

Without this proposal, an application generally needs a separate privileged payload or an application-specific out-of-process service, as demonstrated by the earlier elfldr-based proof in ps5-native-app-boilerplate PR #1. This PR instead adds one small, auditable, opt-in request interface to the already-running trusted kstuff component. A native application requests one predefined profile for itself, checks the result, and continues running as a normal native title. Focused C++ usage examples are provided in ps5-native-app-boilerplate PR #2.

The feature is enabled by default but remains compile-time removable with KSTUFF_SELF_ELEVATION=0. It does not make applications privileged automatically: each caller must explicitly issue a valid versioned request.

Design

The target is always derived from the current syscall thread's td_proc; no request can select another process. Operation 7 accepts only one of three fixed profiles, and operation 8 is a bounded read-only inspection that returns only the caller's current authority ID. Neither operation accepts a PID, kernel pointer, arbitrary authority ID, capability mask, or structure offset.

Requests use the existing getppid kekcall bridge and require an exact magic value and ABI version. Unknown operations, versions, selectors, profiles, and unsupported firmware fail closed. The implementation captures the complete original credential and file-descriptor state, performs checked kernel copies, reads the result back for verification, and performs a verified rollback if an update fails.

Request flow

sequenceDiagram
    participant App as Sandboxed native app
    participant API as kstuff.h
    participant Kernel as kstuff-lite
    participant VFS as Normal kernel/VFS

    App->>API: kstuff_probe()
    API->>Kernel: Versioned compatibility request
    Kernel-->>API: Compatible or errno
    App->>API: kstuff_request_profile(DATA_ACCESS)
    API->>Kernel: Versioned caller-only request
    Kernel->>Kernel: Derive caller from current thread
    Kernel->>Kernel: Validate and snapshot process state
    Kernel->>Kernel: Update and verify credentials and filesystem roots
    Kernel-->>App: Success or errno
    App->>VFS: sceKernelOpen("/data/example.txt")
    Note over App,VFS: Subsequent calls use the normal syscall path
    VFS-->>App: File descriptor or error

The elevation request happens once. kstuff-lite changes the calling process's kernel-maintained credentials, authority, capabilities, prison, and filesystem-root references; it does not proxy later file, network, mount, or device operations. Those calls continue through their normal kernel implementations, which now evaluate the caller using its updated process state.

Request ABI

Operation Selector Result
7 profile 1 Elevate the caller for data, mount, and device access
7 profile 2 Select the fixed coredump authority used by platform mdbg
7 profile 3 Select the fixed debug authority used by platform ptrace
8 selector 1 Return only the caller's current kernel credential authority ID

Native-application API

include/kstuff.h is the canonical header-only C interface and is directly usable from C++. It adds no library or runtime dependency and keeps operation numbers, magic values, ABI versions, profiles, selectors, validation, and syscall transport in one shared definition.

#include <kstuff.h>

int error = kstuff_probe();
if (!error)
    error = kstuff_request_profile(KSTUFF_PROFILE_DATA_ACCESS);

The public calls are kstuff_probe(), kstuff_request_profile(), and kstuff_get_authority_id(). They return zero on success or a positive errno value on failure, reject invalid arguments locally, do not mutate the caller's errno, and make the process-lifetime scope explicit.

Firmware handling

The credential layout is selected only for an explicit firmware whitelist covering the firmware versions already represented by kstuff-lite's supported offset sets, including 6.02 and 12.70. Unsupported firmware returns EPROTONOSUPPORT. No application-supplied firmware value or credential offset is accepted.

Hardware validation

Firmware Results
6.02 Caller authority inspection, profile 1 data access, /data write/read verification, profile 2 direct mdbg read/write/restore, nullfs mount lifecycle, /dev/mdctl open/close, raw ICMP socket creation without transmission, and profile 3 bounded ptrace all passed
12.70 Caller authority inspection, profile 1 data access, nullfs mount lifecycle, /dev/mdctl open/close, raw ICMP socket creation without transmission, and profile 3 bounded ptrace passed; platform mdbg reads succeeded while writes returned EPERM

The 12.70 mdbg write result is treated as firmware-specific platform behavior rather than hidden by the API. The advanced example repository documents it explicitly. Ordinary end-user applications generally need profile 1 and do not need process tracing or process-memory access.

Completed hardware runs left the console and services healthy: the exact titles closed, and FTP 2121, klog 3232, and elfldr 9021 remained responsive.

Code impact

The change is limited to five files: include/kstuff.h, the ps5-kstuff Makefile, the existing kekcall dispatcher, and the new self_elevation.c and self_elevation.h implementation files. It does not modify prosper0gdb, the loader protocol, console settings, or unrelated kstuff behavior.

Scope boundary

This proposal does not add an exploit, generic kernel-memory interface, remote target selection, or network service. It provides a fixed caller-only policy mechanism for native applications running with a compatible kstuff build already active.

Beta artifact

A prerelease build from this PR's exact head commit is available as kstuff-self-escalation.elf. The beta release is self-elevation-beta.1, targets commit 714def2621028737f9a5a23b95f18bf9581d453c, and has SHA-256 c49ecf99ba483f1651944b41be594432c916857aa082eab44c6b1a1e429a451b.

## Purpose Native PS5 applications normally run inside a restricted sandbox. That is the right default, but it prevents end-user homebrew applications from implementing legitimate features that require broader platform access, such as managing files outside their app container, creating temporary mounts, or opening privileged platform facilities. Without this proposal, an application generally needs a separate privileged payload or an application-specific out-of-process service, as demonstrated by the earlier elfldr-based proof in [ps5-native-app-boilerplate PR #1](https://github.com/blackbearreloaded/ps5-native-app-boilerplate/pull/1). This PR instead adds one small, auditable, opt-in request interface to the already-running trusted kstuff component. A native application requests one predefined profile for itself, checks the result, and continues running as a normal native title. Focused C++ usage examples are provided in [ps5-native-app-boilerplate PR #2](https://github.com/blackbearreloaded/ps5-native-app-boilerplate/pull/2). The feature is enabled by default but remains compile-time removable with `KSTUFF_SELF_ELEVATION=0`. It does not make applications privileged automatically: each caller must explicitly issue a valid versioned request. ## Design The target is always derived from the current syscall thread's `td_proc`; no request can select another process. Operation 7 accepts only one of three fixed profiles, and operation 8 is a bounded read-only inspection that returns only the caller's current authority ID. Neither operation accepts a PID, kernel pointer, arbitrary authority ID, capability mask, or structure offset. Requests use the existing `getppid` kekcall bridge and require an exact magic value and ABI version. Unknown operations, versions, selectors, profiles, and unsupported firmware fail closed. The implementation captures the complete original credential and file-descriptor state, performs checked kernel copies, reads the result back for verification, and performs a verified rollback if an update fails. ## Request flow ```mermaid sequenceDiagram participant App as Sandboxed native app participant API as kstuff.h participant Kernel as kstuff-lite participant VFS as Normal kernel/VFS App->>API: kstuff_probe() API->>Kernel: Versioned compatibility request Kernel-->>API: Compatible or errno App->>API: kstuff_request_profile(DATA_ACCESS) API->>Kernel: Versioned caller-only request Kernel->>Kernel: Derive caller from current thread Kernel->>Kernel: Validate and snapshot process state Kernel->>Kernel: Update and verify credentials and filesystem roots Kernel-->>App: Success or errno App->>VFS: sceKernelOpen("/data/example.txt") Note over App,VFS: Subsequent calls use the normal syscall path VFS-->>App: File descriptor or error ``` The elevation request happens once. kstuff-lite changes the calling process's kernel-maintained credentials, authority, capabilities, prison, and filesystem-root references; it does not proxy later file, network, mount, or device operations. Those calls continue through their normal kernel implementations, which now evaluate the caller using its updated process state. ## Request ABI | Operation | Selector | Result | | --- | --- | --- | | `7` | profile `1` | Elevate the caller for data, mount, and device access | | `7` | profile `2` | Select the fixed coredump authority used by platform `mdbg` | | `7` | profile `3` | Select the fixed debug authority used by platform ptrace | | `8` | selector `1` | Return only the caller's current kernel credential authority ID | ## Native-application API `include/kstuff.h` is the canonical header-only C interface and is directly usable from C++. It adds no library or runtime dependency and keeps operation numbers, magic values, ABI versions, profiles, selectors, validation, and syscall transport in one shared definition. ```c #include <kstuff.h> int error = kstuff_probe(); if (!error) error = kstuff_request_profile(KSTUFF_PROFILE_DATA_ACCESS); ``` The public calls are `kstuff_probe()`, `kstuff_request_profile()`, and `kstuff_get_authority_id()`. They return zero on success or a positive `errno` value on failure, reject invalid arguments locally, do not mutate the caller's `errno`, and make the process-lifetime scope explicit. ## Firmware handling The credential layout is selected only for an explicit firmware whitelist covering the firmware versions already represented by kstuff-lite's supported offset sets, including 6.02 and 12.70. Unsupported firmware returns `EPROTONOSUPPORT`. No application-supplied firmware value or credential offset is accepted. ## Hardware validation | Firmware | Results | | --- | --- | | 6.02 | Caller authority inspection, profile 1 data access, `/data` write/read verification, profile 2 direct `mdbg` read/write/restore, nullfs mount lifecycle, `/dev/mdctl` open/close, raw ICMP socket creation without transmission, and profile 3 bounded ptrace all passed | | 12.70 | Caller authority inspection, profile 1 data access, nullfs mount lifecycle, `/dev/mdctl` open/close, raw ICMP socket creation without transmission, and profile 3 bounded ptrace passed; platform `mdbg` reads succeeded while writes returned `EPERM` | The 12.70 `mdbg` write result is treated as firmware-specific platform behavior rather than hidden by the API. The advanced example repository documents it explicitly. Ordinary end-user applications generally need profile 1 and do not need process tracing or process-memory access. Completed hardware runs left the console and services healthy: the exact titles closed, and FTP `2121`, klog `3232`, and elfldr `9021` remained responsive. ## Code impact The change is limited to five files: `include/kstuff.h`, the ps5-kstuff Makefile, the existing kekcall dispatcher, and the new `self_elevation.c` and `self_elevation.h` implementation files. It does not modify `prosper0gdb`, the loader protocol, console settings, or unrelated kstuff behavior. ## Scope boundary This proposal does not add an exploit, generic kernel-memory interface, remote target selection, or network service. It provides a fixed caller-only policy mechanism for native applications running with a compatible kstuff build already active. ## Beta artifact A prerelease build from this PR's exact head commit is available as [kstuff-self-escalation.elf](https://github.com/blackbearreloaded/kstuff-lite/releases/download/self-elevation-beta.1/kstuff-self-escalation.elf). The beta release is [self-elevation-beta.1](https://github.com/blackbearreloaded/kstuff-lite/releases/tag/self-elevation-beta.1), targets commit `714def2621028737f9a5a23b95f18bf9581d453c`, and has SHA-256 `c49ecf99ba483f1651944b41be594432c916857aa082eab44c6b1a1e429a451b`.

Pull request closed

Sign in to join this conversation.
No description provided.