Skip to content

Commit

Permalink
kernel: add function to lookup handle of a given sprx basename
Browse files Browse the repository at this point in the history
  • Loading branch information
john-tornblom committed May 26, 2024
1 parent 39bab18 commit a86fd19
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 22 deletions.
63 changes: 62 additions & 1 deletion crt/kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ typedef struct {
static void* (*malloc)(unsigned long) = 0;
static void (*free)(void*) = 0;
static int (*strncmp)(const char*, const char*, unsigned long) = 0;

static int (*strlen)(const char*) = 0;

/**
* public constants.
Expand Down Expand Up @@ -218,6 +218,10 @@ __kernel_init(payload_args_t* args) {
klog_perror("Unable to resolve 'free'");
return error;
}
if((error=args->sceKernelDlsym(0x2, "strlen", &strlen))) {
klog_perror("Unable to resolve 'strlen'");
return error;
}
if((error=args->sceKernelDlsym(0x2, "strncmp", &strncmp))) {
klog_perror("Unable to resolve 'strncmp'");
return error;
Expand Down Expand Up @@ -482,6 +486,63 @@ kernel_dynlib_obj(int pid, unsigned int handle, dynlib_obj_t* obj) {
}


int
kernel_dynlib_handle(int pid, const char* basename, unsigned int *handle) {
unsigned long kproc;
unsigned long kaddr;
unsigned long kpath;
unsigned long blen;
unsigned long plen;
char path[1024];
long temphandle;

if(!(kproc=kernel_get_proc(pid))) {
return -1;
}

if(kernel_copyout(kproc + 0x3e8, &kaddr, sizeof(kaddr)) < 0) {
return -1;
}

blen = strlen(basename);
do {
if(kernel_copyout(kaddr, &kaddr, sizeof(kaddr)) < 0) {
return -1;
}
if(!kaddr) {
return -1;
}
if(kernel_copyout(kaddr + __builtin_offsetof(dynlib_obj_t, path),
&kpath, sizeof(kpath)) < 0) {
return -1;
}
if(kernel_copyout(kpath, path, sizeof(path)) < 0) {
return -1;
}

if(kernel_copyout(kaddr + __builtin_offsetof(dynlib_obj_t, handle),
&temphandle, sizeof(temphandle)) < 0) {
return -1;
}

plen = strlen(path);
if(plen <= blen) {
continue;
}
if(path[plen-blen-1] != '/') {
continue;
}
if(strncmp(path + plen - blen, basename, blen)) {
continue;
}


*handle = (unsigned int)temphandle;
return 0;
} while(1);
}


unsigned long
kernel_dynlib_fini_addr(int pid, unsigned int handle) {
dynlib_obj_t obj;
Expand Down
1 change: 1 addition & 0 deletions crt/kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ unsigned long kernel_get_proc_rootdir(int pid);
int kernel_set_proc_rootdir(int pid, unsigned long vnode);

unsigned long kernel_dynlib_entry_addr(int pid, unsigned int handle);
int kernel_dynlib_handle(int pid, const char* basename, unsigned int *handle);
28 changes: 7 additions & 21 deletions crt/rtld.c
Original file line number Diff line number Diff line change
Expand Up @@ -546,31 +546,17 @@ rtld_load(void) {
**/
static int
rtld_load_sysmodule(payload_args_t *args) {
unsigned long nb_handles = 0;
int handles[256];
int handle;

// get handles for loaded modules
if(syscall(0x250, handles, sizeof(handles), &nb_handles)) {
return -1;
}
int pid = syscall(SYS_getpid);
unsigned int handle;

// try to load sceSysmoduleLoadModuleInternal from all of the handles
for(int i=0; i<nb_handles; i++) {
handle = handles[i];
if(!args->sceKernelDlsym(handle, "sceSysmoduleLoadModuleInternal",
&sceSysmoduleLoadModuleInternal)) {
return 0;
if(kernel_dynlib_handle(pid, "libSceSysmodule.sprx", &handle)) {
if((handle=sceKernelLoadStartModule("/system/common/lib/libSceSysmodule.sprx",
0, 0, 0, 0, 0)) <= 0) {
klog_libload_error("libSceSysmodule.sprx");
return -1;
}
}

// load libSceSysmodule
if((handle=sceKernelLoadStartModule("/system/common/lib/libSceSysmodule.sprx",
0, 0, 0, 0, 0)) <= 0) {
klog_libload_error("libSceSysmodule.sprx");
return -1;
}

// resolve sceSysmoduleLoadModuleInternal
return args->sceKernelDlsym(handle, "sceSysmoduleLoadModuleInternal",
&sceSysmoduleLoadModuleInternal);
Expand Down
1 change: 1 addition & 0 deletions include/ps5/kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ intptr_t kernel_get_proc_file(pid_t pid, int fd);

int kernel_overlap_sockets(pid_t pid, int master_sock, int victim_sock);

int kernel_dynlib_handle(pid_t pid, const char* basename, uint32_t *handle);
intptr_t kernel_dynlib_resolve(pid_t pid, uint32_t handle, const char *nid);
intptr_t kernel_dynlib_entry_addr(pid_t pid, uint32_t handle);
intptr_t kernel_dynlib_init_addr(pid_t pid, uint32_t handle);
Expand Down

0 comments on commit a86fd19

Please sign in to comment.