remove data_cave offset and use page alloc for sc args

This commit is contained in:
Mateico
2026-05-15 15:04:08 +02:00
parent e84dcbf281
commit 85a16afa80
9 changed files with 92 additions and 94 deletions

View File

@@ -18,9 +18,12 @@
#define hv_stack_size 0x1000ULL
// This is used as transitional storage from ProsperoOS to Kernel shellcode
#define kernel_cave_files 0xFFFF800000000000
#define kernel_cave 0xFFFF800000000000
#define kernel_cave_arguments kernel_cave
#define kernel_cave_files kernel_cave_arguments + PAGE_SIZE
#define kernel_cave_linux_info kernel_cave_files
#define kernel_cave_bzImage kernel_cave_linux_info + PAGE_SIZE
// #define kernel_cave_initrd // Allocated dynamically after bzImage
// Linux boot config

View File

@@ -3,7 +3,6 @@
#include "utils.h"
#include <stdint.h>
uint64_t alloc_page(void);
void install_page(uintptr_t pml4, vm_offset_t va, vm_paddr_t pa, int bits);
void pte_store(uintptr_t ptep, uint64_t pte);
int read_file(const char *path, void *buf, size_t bufsize);

View File

@@ -12,7 +12,6 @@ typedef struct _offset_list {
/* Shellcode Kernel */
uint64_t HOOK_ACPI_WAKEUP_MACHDEP;
uint64_t KERNEL_CODE_CAVE;
uint64_t KERNEL_DATA_CAVE;
uint64_t FUN_PRINTF;
uint64_t FUN_HV_IOMMU_SET_BUFFERS;
uint64_t FUN_HV_IOMM_WAIT_COMPLETION;

View File

@@ -5,8 +5,8 @@
extern struct linux_info linux_i;
int prepare_resume(void);
int update_sck_data_ptr(void *sc, uint64_t dest_text, uint64_t dest_data);
uint64_t prepare_sck_args(void);
int update_sck_args_ptr(uint64_t shellcode, uint64_t args);
void hook_call_near(uint64_t hook, uint64_t dst);
void prepare_sck_args(uint64_t dest_data);
#endif

View File

@@ -167,4 +167,10 @@ enum kit_type { KIT_RETAIL, KIT_TESTKIT, KIT_DEVKIT };
enum kit_type get_kit_type(void);
#define MINI_SYSCORE_PID 1
uint64_t alloc_page(void);
void pte_store(uintptr_t ptep, uint64_t pte);
void install_page(uintptr_t pml4, vm_offset_t va, vm_paddr_t pa, int bits);
void install_page_syscore(vm_offset_t va, vm_paddr_t pa, int bits);
#endif

View File

@@ -19,59 +19,6 @@
#include <sys/types.h>
#include <unistd.h>
#define MINI_SYSCORE_PID 1
uint64_t alloc_page(void) {
void *page = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
// Fault it to force physical allocation
*(uint8_t *)page = 0;
return vtophys_user((uintptr_t)page);
}
void install_page(uintptr_t pml4, vm_offset_t va, vm_paddr_t pa, int bits) {
uint64_t entry;
uintptr_t pml4e = pml4 + pmap_pml4e_index(va) * 8;
entry = kread64(pml4e);
if (!PAGE_P(entry)) {
uint64_t page = alloc_page();
entry = page | PG_B_RW | PG_B_P | bits;
kwrite64(pml4e, entry);
}
uintptr_t pdpe = pa_to_dmap(PAGE_PA(entry)) + pmap_pdpe_index(va) * 8;
entry = kread64(pdpe);
if (!(entry & PG_B_P)) {
uint64_t page = alloc_page();
entry = page | PG_B_RW | PG_B_P | bits;
kwrite64(pdpe, entry);
}
uintptr_t pde = pa_to_dmap(PAGE_PA(entry)) + pmap_pde_index(va) * 8;
entry = kread64(pde);
if (!(entry & PG_B_P)) {
uint64_t page = alloc_page();
entry = page | PG_B_RW | PG_B_P | bits;
kwrite64(pde, entry);
}
uintptr_t pte = pa_to_dmap(PAGE_PA(entry)) + pmap_pte_index(va) * 8;
entry = pa | PG_B_RW | PG_B_P | bits;
pte_store(pte, entry);
}
void pte_store(uintptr_t ptep, uint64_t pte) {
static_assert((PAGE_SIZE % 0x1000) == 0,
"PAGE_SIZE should be a multiple of 0x1000");
for (uint64_t i = 0; i < (PAGE_SIZE / 0x1000); i++) {
kwrite64(ptep + i * 8, pte + i * 0x1000);
}
}
const char *file_paths[] = {
"/mnt/usb0/", "/mnt/usb1/", "/mnt/usb2/",
"/mnt/usb3/", "/mnt/usb0/PS5/Linux/", "/mnt/usb1/PS5/Linux/",
@@ -179,9 +126,6 @@ void trim_newline(char *s) {
}
int fetch_linux(struct linux_info *info) {
uintptr_t syscore_pmap = getpmap(kernel_get_proc(MINI_SYSCORE_PID));
uintptr_t syscore_pml4 = kread64(syscore_pmap + 0x20);
char bzimage_path[256];
char initrd_path[256];
@@ -269,16 +213,16 @@ int fetch_linux(struct linux_info *info) {
uint64_t page = alloc_page();
kwrite(pa_to_dmap(page), info, sizeof(struct linux_info));
install_page(syscore_pml4, kernel_cave_linux_info, page, 0);
install_page_syscore(kernel_cave_linux_info, page, 0);
for (int i = 0; i < bzimage_size; i += PAGE_SIZE) {
install_page(syscore_pml4, info->bzimage + i,
vtophys_user((uintptr_t)bzimage + i), 0);
install_page_syscore(info->bzimage + i,
vtophys_user((uintptr_t)bzimage + i), 0);
}
for (int i = 0; i < initrd_size; i += PAGE_SIZE) {
install_page(syscore_pml4, info->initrd + i,
vtophys_user((uintptr_t)initrd + i), 0);
install_page_syscore(info->initrd + i, vtophys_user((uintptr_t)initrd + i),
0);
}
return 0;

View File

@@ -7,7 +7,6 @@ offset_list off_0300 = {
.DATA_BASE_GVMSPACE = 0x06423F80,
.HOOK_ACPI_WAKEUP_MACHDEP = 0x0390E73,
.KERNEL_CODE_CAVE = 0x500,
.KERNEL_DATA_CAVE = 0xC01300,
.FUN_PRINTF = 0x048B9A0,
.FUN_HV_IOMMU_SET_BUFFERS = 0x0B33E20,
.FUN_HV_IOMM_WAIT_COMPLETION = 0x0B33D50,
@@ -33,7 +32,6 @@ offset_list off_0310 = {
.DATA_BASE_GVMSPACE = 0x06423F80,
.HOOK_ACPI_WAKEUP_MACHDEP = 0x0390EB3,
.KERNEL_CODE_CAVE = 0x500,
.KERNEL_DATA_CAVE = 0xC01300,
.FUN_PRINTF = 0x048B9E0,
.FUN_HV_IOMMU_SET_BUFFERS = 0x0B33E60,
.FUN_HV_IOMM_WAIT_COMPLETION = 0x0B33D90,
@@ -59,7 +57,6 @@ offset_list off_0320 = {
.DATA_BASE_GVMSPACE = 0x06423F80,
.HOOK_ACPI_WAKEUP_MACHDEP = 0x391203,
.KERNEL_CODE_CAVE = 0x500,
.KERNEL_DATA_CAVE = 0xC01300,
.FUN_PRINTF = 0x48BD30,
.FUN_HV_IOMMU_SET_BUFFERS = 0xB34320,
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB34250,
@@ -85,7 +82,6 @@ offset_list off_0321 = {
.DATA_BASE_GVMSPACE = 0x06423F80,
.HOOK_ACPI_WAKEUP_MACHDEP = 0x391203,
.KERNEL_CODE_CAVE = 0x500,
.KERNEL_DATA_CAVE = 0xC01300,
.FUN_PRINTF = 0x48BD30,
.FUN_HV_IOMMU_SET_BUFFERS = 0xB34320,
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB34250,
@@ -112,7 +108,6 @@ offset_list off_0400 = {
.HOOK_ACPI_WAKEUP_MACHDEP = 0x3A7613,
.FUN_PRINTF = 0x4A3240,
.KERNEL_CODE_CAVE = 0x500,
.KERNEL_DATA_CAVE = 0xC01300,
.FUN_HV_IOMMU_SET_BUFFERS = 0xB638F0,
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB63830,
.FUN_SMP_RENDEZVOUS = 0xA6C920,
@@ -137,7 +132,6 @@ offset_list off_0402 = {
.DATA_BASE_GVMSPACE = 0x064C3F80,
.HOOK_ACPI_WAKEUP_MACHDEP = 0x3A7613,
.KERNEL_CODE_CAVE = 0x500,
.KERNEL_DATA_CAVE = 0xC01300,
.FUN_PRINTF = 0x4A3240,
.FUN_HV_IOMMU_SET_BUFFERS = 0xB63950,
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB63890,
@@ -163,7 +157,6 @@ offset_list off_0403 = {
.DATA_BASE_GVMSPACE = 0x064C3F80,
.HOOK_ACPI_WAKEUP_MACHDEP = 0x3A7613,
.KERNEL_CODE_CAVE = 0x500,
.KERNEL_DATA_CAVE = 0xC01300,
.FUN_PRINTF = 0x4A3240,
.FUN_HV_IOMMU_SET_BUFFERS = 0xB639F0,
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB63930,
@@ -189,7 +182,6 @@ offset_list off_0450 = {
.DATA_BASE_GVMSPACE = 0x064C3F80,
.HOOK_ACPI_WAKEUP_MACHDEP = 0x03A75E3,
.KERNEL_CODE_CAVE = 0x500,
.KERNEL_DATA_CAVE = 0xC01300,
.FUN_PRINTF = 0x04A3270,
.FUN_HV_IOMMU_SET_BUFFERS = 0xB63BB0,
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB63AF0,
@@ -215,7 +207,6 @@ offset_list off_0451 = {
.DATA_BASE_GVMSPACE = 0x64C3F80,
.HOOK_ACPI_WAKEUP_MACHDEP = 0x3A75E3,
.KERNEL_CODE_CAVE = 0x500,
.KERNEL_DATA_CAVE = 0xC01300,
.FUN_PRINTF = 0x4A3270,
.FUN_HV_IOMMU_SET_BUFFERS = 0xB63FE0,
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB63F20,

View File

@@ -1,6 +1,7 @@
#include "prepare_resume.h"
#include "../shellcode_kernel/shellcode_kernel.h"
#include "../shellcode_kernel/shellcode_kernel_args.h"
#include "config.h"
#include "iommu.h"
#include "offsets.h"
#include "utils.h"
@@ -14,21 +15,14 @@ int prepare_resume(void) {
return -1;
}
if (env_offset.KERNEL_DATA_CAVE == 0) {
printf("Error: missing data cave offset\n");
return -1;
}
uint64_t dest_text = ktext + env_offset.KERNEL_CODE_CAVE;
uint64_t dest_data = ktext + env_offset.KERNEL_DATA_CAVE;
kwrite_large(dest_text, shellcode_kernel_bin, shellcode_kernel_bin_len);
prepare_sck_args(dest_data);
if (update_sck_data_ptr(shellcode_kernel_bin, dest_text, dest_data))
uint64_t args_va = prepare_sck_args();
if (update_sck_args_ptr((uint64_t)shellcode_kernel_bin, args_va))
return -1;
hook_call_near(ktext + env_offset.HOOK_ACPI_WAKEUP_MACHDEP, dest_text);
uint64_t sck_va = ktext + env_offset.KERNEL_CODE_CAVE;
kwrite_large(sck_va, shellcode_kernel_bin, shellcode_kernel_bin_len);
hook_call_near(ktext + env_offset.HOOK_ACPI_WAKEUP_MACHDEP, sck_va);
kwrite8(ktext + env_offset.KERNEL_DEBUG_PATCH, 0xC3);
kwrite8(ktext + env_offset.KERNEL_CFI_CHECK, 0xC3);
@@ -36,11 +30,11 @@ int prepare_resume(void) {
return 0;
}
int update_sck_data_ptr(void *sc, uint64_t dest_text, uint64_t dest_data) {
int update_sck_args_ptr(uint64_t shellcode, uint64_t args) {
// Find the address 0x11AA11AA11AA11AA used as marker
int offset = -1;
for (int i = 0; i < 0x40; i++) {
if (*(uint64_t *)((uint64_t)sc + i) == 0x11AA11AA11AA11AA) {
for (uint64_t i = 0; i < 0x40; i++) {
if (*(uint64_t *)(shellcode + i) == 0x11AA11AA11AA11AA) {
offset = i;
break;
}
@@ -49,7 +43,7 @@ int update_sck_data_ptr(void *sc, uint64_t dest_text, uint64_t dest_data) {
notify("Could not find offset of args_ptr address - Aborting\n");
return -1;
}
kwrite64(dest_text + offset, dest_data);
*(uint64_t *)(shellcode + offset) = args;
return 0;
}
@@ -62,7 +56,7 @@ void hook_call_near(uint64_t hook, uint64_t dst) {
DEBUG_PRINT("Instruction patched\n");
}
void prepare_sck_args(uint64_t dest_data) {
uint64_t prepare_sck_args(void) {
shellcode_kernel_args args;
args.fw_version = fw;
args.ktext = ktext;
@@ -94,5 +88,9 @@ void prepare_sck_args(uint64_t dest_data) {
args.linux_info_va = linux_i.linux_info;
kernel_copyin(&args, dest_data, sizeof(args));
uint64_t args_cave = alloc_page();
kernel_copyin(&args, pa_to_dmap(args_cave), sizeof(args));
install_page_syscore(kernel_cave_arguments, args_cave, 0);
return kernel_cave_arguments;
}

View File

@@ -4,6 +4,7 @@
#include <ps5/kernel.h>
#include <stdio.h>
#include <sys/cpuset.h>
#include <sys/mman.h>
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/stat.h>
@@ -284,3 +285,60 @@ enum kit_type get_kit_type(void) {
notify("Retail console detected\n");
return KIT_RETAIL;
}
uint64_t alloc_page(void) {
void *page = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
// Fault it to force physical allocation
*(uint8_t *)page = 0;
return vtophys_user((uintptr_t)page);
}
void install_page(uintptr_t pml4, vm_offset_t va, vm_paddr_t pa, int bits) {
uint64_t entry;
uintptr_t pml4e = pml4 + pmap_pml4e_index(va) * 8;
entry = kread64(pml4e);
if (!PAGE_P(entry)) {
uint64_t page = alloc_page();
entry = page | PG_B_RW | PG_B_P | bits;
kwrite64(pml4e, entry);
}
uintptr_t pdpe = pa_to_dmap(PAGE_PA(entry)) + pmap_pdpe_index(va) * 8;
entry = kread64(pdpe);
if (!(entry & PG_B_P)) {
uint64_t page = alloc_page();
entry = page | PG_B_RW | PG_B_P | bits;
kwrite64(pdpe, entry);
}
uintptr_t pde = pa_to_dmap(PAGE_PA(entry)) + pmap_pde_index(va) * 8;
entry = kread64(pde);
if (!(entry & PG_B_P)) {
uint64_t page = alloc_page();
entry = page | PG_B_RW | PG_B_P | bits;
kwrite64(pde, entry);
}
uintptr_t pte = pa_to_dmap(PAGE_PA(entry)) + pmap_pte_index(va) * 8;
entry = pa | PG_B_RW | PG_B_P | bits;
pte_store(pte, entry);
}
void pte_store(uintptr_t ptep, uint64_t pte) {
static_assert((PAGE_SIZE % 0x1000) == 0,
"PAGE_SIZE should be a multiple of 0x1000");
for (uint64_t i = 0; i < (PAGE_SIZE / 0x1000); i++) {
kwrite64(ptep + i * 8, pte + i * 0x1000);
}
}
void install_page_syscore(vm_offset_t va, vm_paddr_t pa, int bits) {
uintptr_t syscore_pmap = getpmap(kernel_get_proc(MINI_SYSCORE_PID));
uintptr_t syscore_pml4 = kread64(syscore_pmap + 0x20);
install_page(syscore_pml4, va, pa, bits);
}