Add caller-only elevated capability profiles #73

Open
blackbearreloaded wants to merge 5 commits from blackbearreloaded/feature/self-elevation into main
blackbearreloaded commented 2026-09-02 21:32:58 -05:00 (Migrated from github.com)

Note: support is intentionally limited to firmware versions already represented by kstuff-lite's offset sets, through 12.70. Firmware 6.02 and 12.70 have been validated on hardware.

Purpose

Native PS5 applications normally run inside a restricted sandbox. That is the correct default, but it prevents opt-in homebrew applications from performing legitimate operations such as managing files outside their application container, creating temporary mounts, or using privileged platform facilities. Without this proposal, an application needs a separate privileged payload or an application-specific out-of-process service. This PR instead adds a small, auditable, caller-only request interface to the already-running trusted kstuff component.

The feature is enabled by default and remains compile-time removable with KSTUFF_SELF_ELEVATION=0. Applications are never elevated automatically; the caller must issue a valid versioned request for one predefined profile.

Design

The target is always derived from the current syscall thread's td_proc; a request cannot 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. Kernel reads and writes are checked and the applied values are read back for verification.

Credential strategy

The initial implementation edited the credential already referenced by the process. This revision no longer does that. It invokes the firmware's native SYS_seteuid handler with the caller's existing effective UID, which makes the kernel perform its normal credential copy-on-write operation, including allocation, process locking, p_ucred replacement, and release of the old credential reference. The completion trap verifies that p_ucred changed before applying a profile to the new caller-private credential.

The implementation does not copy or replace cr_prison. It changes only the new private credential's identity fields, authority ID, capability bytes, and required attribute bit. Filesystem roots are adjusted separately on the calling process's file-descriptor state after credential cloning succeeds.

Request flow

sequenceDiagram
    participant App as Sandboxed native app
    participant API as kstuff.h
    participant Kstuff as kstuff-lite
    participant Kernel as Native kernel syscall path
    participant VFS as Normal kernel/VFS
    App->>API: kstuff_probe()
    API->>Kstuff: Versioned compatibility request
    Kstuff-->>API: Compatible or errno
    App->>API: kstuff_request_profile(DATA_ACCESS)
    API->>Kstuff: Versioned caller-only request
    Kstuff->>Kstuff: Derive caller from current thread
    Kstuff->>Kernel: SYS_seteuid(current effective UID)
    Kernel->>Kernel: Clone, lock, swap, and release ucred
    Kernel-->>Kstuff: Resume at completion trap
    Kstuff->>Kstuff: Verify private ucred and apply fixed profile
    Kstuff->>Kstuff: Update and verify caller filesystem roots
    Kstuff-->>App: Success or errno
    App->>VFS: sceKernelOpen("/data/example.txt")
    Note over App,VFS: Later operations use their normal syscall paths
    VFS-->>App: File descriptor or error

kstuff-lite changes the calling process state once; it does not proxy later file, network, mount, device, or debugging operations. Those calls continue through their normal kernel implementations, which evaluate the caller using the 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, and do not mutate the caller's errno.

Firmware handling

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

Validation

Check Result
Firmware 6.02 Fresh-reboot launch passed; the caller elevated, wrote and read /data/hello-from-sandbox.txt, and the console remained healthy
Firmware 12.70 Fresh-reboot launch passed; the caller elevated, wrote and read /data/hello-from-sandbox.txt, and the console remained healthy
File contents Exact bytes hello from the sandboxed app\n; SHA-256 05bd42b8472a73be683feeaeba5b83367fee9669b970479e08500c3fa7cffd94
Build configuration Full build passed with KSTUFF_SELF_ELEVATION=1 and KSTUFF_SELF_ELEVATION=0
Strict compile self_elevation.c passed -Wall -Wextra -Werror

The advanced profile tests documented by the companion example were completed during the earlier investigation. This table deliberately reports only the hardware checks repeated after switching to native credential copy-on-write.

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 fixed caller-only policy profiles for native applications running with a compatible kstuff build already active.

Focused C++ usage examples are available in ps5-native-app-boilerplate PR #2.

Beta artifact

The corrected beta build is available as kstuff-self-escalation.elf. It was built from commit 33ec81e5e086837f54644d519ed0a90b16d5c1f5 and has SHA-256 88027ea317576cb0d087f455f3712972ef41484b158ba671838c1643a43cfa38.

Note: support is intentionally limited to firmware versions already represented by kstuff-lite's offset sets, through 12.70. Firmware 6.02 and 12.70 have been validated on hardware. ## Purpose Native PS5 applications normally run inside a restricted sandbox. That is the correct default, but it prevents opt-in homebrew applications from performing legitimate operations such as managing files outside their application container, creating temporary mounts, or using privileged platform facilities. Without this proposal, an application needs a separate privileged payload or an application-specific out-of-process service. This PR instead adds a small, auditable, caller-only request interface to the already-running trusted kstuff component. The feature is enabled by default and remains compile-time removable with `KSTUFF_SELF_ELEVATION=0`. Applications are never elevated automatically; the caller must issue a valid versioned request for one predefined profile. ## Design The target is always derived from the current syscall thread's `td_proc`; a request cannot 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. Kernel reads and writes are checked and the applied values are read back for verification. ## Credential strategy The initial implementation edited the credential already referenced by the process. This revision no longer does that. It invokes the firmware's native `SYS_seteuid` handler with the caller's existing effective UID, which makes the kernel perform its normal credential copy-on-write operation, including allocation, process locking, `p_ucred` replacement, and release of the old credential reference. The completion trap verifies that `p_ucred` changed before applying a profile to the new caller-private credential. The implementation does not copy or replace `cr_prison`. It changes only the new private credential's identity fields, authority ID, capability bytes, and required attribute bit. Filesystem roots are adjusted separately on the calling process's file-descriptor state after credential cloning succeeds. ## Request flow ```mermaid sequenceDiagram participant App as Sandboxed native app participant API as kstuff.h participant Kstuff as kstuff-lite participant Kernel as Native kernel syscall path participant VFS as Normal kernel/VFS App->>API: kstuff_probe() API->>Kstuff: Versioned compatibility request Kstuff-->>API: Compatible or errno App->>API: kstuff_request_profile(DATA_ACCESS) API->>Kstuff: Versioned caller-only request Kstuff->>Kstuff: Derive caller from current thread Kstuff->>Kernel: SYS_seteuid(current effective UID) Kernel->>Kernel: Clone, lock, swap, and release ucred Kernel-->>Kstuff: Resume at completion trap Kstuff->>Kstuff: Verify private ucred and apply fixed profile Kstuff->>Kstuff: Update and verify caller filesystem roots Kstuff-->>App: Success or errno App->>VFS: sceKernelOpen("/data/example.txt") Note over App,VFS: Later operations use their normal syscall paths VFS-->>App: File descriptor or error ``` kstuff-lite changes the calling process state once; it does not proxy later file, network, mount, device, or debugging operations. Those calls continue through their normal kernel implementations, which evaluate the caller using the 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, and do not mutate the caller's `errno`. ## Firmware handling The credential layout is selected only for an explicit firmware whitelist covering versions already represented by kstuff-lite's supported offset sets. Unsupported firmware returns `EPROTONOSUPPORT`. No firmware value or credential offset is supplied by the application. ## Validation | Check | Result | | --- | --- | | Firmware 6.02 | Fresh-reboot launch passed; the caller elevated, wrote and read `/data/hello-from-sandbox.txt`, and the console remained healthy | | Firmware 12.70 | Fresh-reboot launch passed; the caller elevated, wrote and read `/data/hello-from-sandbox.txt`, and the console remained healthy | | File contents | Exact bytes `hello from the sandboxed app\n`; SHA-256 `05bd42b8472a73be683feeaeba5b83367fee9669b970479e08500c3fa7cffd94` | | Build configuration | Full build passed with `KSTUFF_SELF_ELEVATION=1` and `KSTUFF_SELF_ELEVATION=0` | | Strict compile | `self_elevation.c` passed `-Wall -Wextra -Werror` | The advanced profile tests documented by the companion example were completed during the earlier investigation. This table deliberately reports only the hardware checks repeated after switching to native credential copy-on-write. ## 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 fixed caller-only policy profiles for native applications running with a compatible kstuff build already active. Focused C++ usage examples are available in [ps5-native-app-boilerplate PR #2](https://github.com/blackbearreloaded/ps5-native-app-boilerplate/pull/2). ## Beta artifact The corrected beta build is available as [kstuff-self-escalation.elf](https://github.com/blackbearreloaded/kstuff-lite/releases/download/self-elevation-beta.2/kstuff-self-escalation.elf). It was built from commit `33ec81e5e086837f54644d519ed0a90b16d5c1f5` and has SHA-256 `88027ea317576cb0d087f455f3712972ef41484b158ba671838c1643a43cfa38`.
blackbearreloaded commented 2026-09-06 11:50:06 -05:00 (Migrated from github.com)

The implementation no longer edits the process's existing ucred and no longer copies or replaces cr_prison. It now invokes the native SYS_seteuid handler with the caller's current effective UID, allowing the kernel to allocate a private credential, take the normal process locks, swap p_ucred, and release the old reference. A completion trap verifies that the credential pointer changed before the fixed profile is applied.

This exact source revision passed full builds with self-elevation enabled and disabled, and self_elevation.c passes -Wall -Wextra -Werror. The corrected flow was validated after fresh reboots on firmware 6.02 and 12.70 by elevating the native example and verifying an exact write/read of /data/hello-from-sandbox.txt; both consoles and their services remained healthy. The PR description and sequence diagram now reflect the new strategy, and beta 2 contains the build from commit 33ec81e5e086837f54644d519ed0a90b16d5c1f5.

The implementation no longer edits the process's existing `ucred` and no longer copies or replaces `cr_prison`. It now invokes the native `SYS_seteuid` handler with the caller's current effective UID, allowing the kernel to allocate a private credential, take the normal process locks, swap `p_ucred`, and release the old reference. A completion trap verifies that the credential pointer changed before the fixed profile is applied. This exact source revision passed full builds with self-elevation enabled and disabled, and `self_elevation.c` passes `-Wall -Wextra -Werror`. The corrected flow was validated after fresh reboots on firmware 6.02 and 12.70 by elevating the native example and verifying an exact write/read of `/data/hello-from-sandbox.txt`; both consoles and their services remained healthy. The PR description and sequence diagram now reflect the new strategy, and beta 2 contains the build from commit `33ec81e5e086837f54644d519ed0a90b16d5c1f5`.
This pull request has changes conflicting with the target branch.
  • ps5-kstuff/uelf/kekcall.c
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin 'blackbearreloaded/feature/self-elevation:blackbearreloaded/feature/self-elevation'
git switch 'blackbearreloaded/feature/self-elevation'

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch 'main'
git merge --no-ff 'blackbearreloaded/feature/self-elevation'
git switch 'blackbearreloaded/feature/self-elevation'
git rebase 'main'
git switch 'main'
git merge --ff-only 'blackbearreloaded/feature/self-elevation'
git switch 'blackbearreloaded/feature/self-elevation'
git rebase 'main'
git switch 'main'
git merge --no-ff 'blackbearreloaded/feature/self-elevation'
git switch 'main'
git merge --squash 'blackbearreloaded/feature/self-elevation'
git switch 'main'
git merge --ff-only 'blackbearreloaded/feature/self-elevation'
git switch 'main'
git merge 'blackbearreloaded/feature/self-elevation'
git push origin 'main'
Sign in to join this conversation.
No description provided.