[][src]Module sunrise_libuser::caps

Kernel Capabilities declaration

Every program loaded by Sunrise has to declare the kernel capabilities it wishes to use. Upon doing a privileged action (such as using a syscall, or creating an event for an IRQ), the kernel will check that the process was allowed to take this action.

The main use-case is to make privilege escalation more complicated. In Sunrise, an exploit only grants the capabilities of the process that was vulnerable, requiring more pivoting in order to gain better accesses. For instance, a vulnerability in the browser does not give rights to access the filesystem.

Programs declare their capabilities by putting them in the .kernel_caps section of their ELF executable. Each capability is encoded on an u32. We provide convenience functions to generate those capabilities. Most programs will want to use the capabilities! macro in order to generate this section.

The capabilities macro takes two arrays: the first contains a list of syscall numbers, and the second contains a list of raw capabilities. Syscalls are handled specially in order to make them easier to declare.

In addition, programs are expected to provide a KipHeader, telling the kernel various information about how to start the process - such as how much memory it should allocate for the stack, or what the default priority of the process is. Those are provided by the kip_header macro.

Example

extern crate sunrise_libuser;
use sunrise_libuser::{syscalls, caps, capabilities, kip_header};
use sunrise_libuser::caps::ProcessCategory;
kip_header!(HEADER = caps::KipHeader {
    magic: *b"KIP1",
    name: *b"test\0\0\0\0\0\0\0\0",
    title_id: 0x0200000000001000,
    process_category: ProcessCategory::KernelBuiltin,
    main_thread_priority: 0,
    default_cpu_core: 0,
    reserved: 0,
    flags: 0,
    stack_page_count: 16,
});

capabilities!(CAPABILITIES = Capabilities {
    svcs: [
        syscalls::nr::SetHeapSize,
        syscalls::nr::QueryMemory,
        syscalls::nr::ExitProcess,
        syscalls::nr::CreateThread,
        syscalls::nr::StartThread,
        syscalls::nr::ExitThread,
        syscalls::nr::MapSharedMemory,
        syscalls::nr::UnmapSharedMemory,
        syscalls::nr::CloseHandle,
        syscalls::nr::WaitSynchronization,
        syscalls::nr::ConnectToNamedPort,
        syscalls::nr::SendSyncRequestWithUserBuffer,
        syscalls::nr::OutputDebugString,
        syscalls::nr::CreateSharedMemory,
        syscalls::nr::CreateInterruptEvent,
        syscalls::nr::SleepThread
    ],
    raw_caps: [caps::ioport(0x60), caps::ioport(0x64), caps::irq_pair(1, 0x3FF)],
});

Structs

KipHeader

Header for Kernel Builtins. Can be found in the .kip_header section of our ELFs. Nintendo KIPs start with a (slightly different, but functionally equivalent) header.

ProcessCategory

Category of the process.

Functions

application_type

Declare the type of the application. 0 is a sysmodule, 1 is an application, 2 is an applet. Only one application can run at a time.

debug_flags

Declares whether this application can be debugged (e.g. it allows the use of the debug syscalls on it), and whether it can debug other processes.

handle_table_size

Declare the maximum number of live handles this process is allowed to have open.

ioport

Allows the process to use the given IO Ports directly (through the in/out).

irq_pair

Allows the process to create an IRQEvent for those IRQs. Each IRQ should be under or equal to 0xFF, or equal to 0x3FF, in which case the IRQ will be ignored.

kernel_flags

Create a kernel flag capability. Specifies the lowest/highest priority this process is allowed to take, and which CPUs it is allowed to access.

kernel_release_version

The minimum kernel version this process expects.

map_normal_page

Maps the given physical memory page at a random address on process startup.