Skip to content

Commit

Permalink
generate wrappers for syscalls
Browse files Browse the repository at this point in the history
  • Loading branch information
john-tornblom committed May 8, 2024
1 parent 334f1c4 commit 4888939
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 36 deletions.
2 changes: 2 additions & 0 deletions crt/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
syscalls.c

11 changes: 9 additions & 2 deletions crt/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

DESTDIR ?= /opt/ps5-payload-sdk

PYTHON ?= python3

CCS := clang-18 clang-17 clang-16 clang-15 clang
CCS := $(foreach CC,$(CCS),$(if $(shell command -v $(CC) 2> /dev/null),$(CC)))
CC := $(firstword $(CCS))
Expand All @@ -36,14 +38,19 @@ CFLAGS += -Wall -Werror

all: crt1.o

crt1.o: crt.o klog.o kernel.o rtld.o patch.o mdbg.o env.o
crt1.o: crt.o klog.o kernel.o rtld.o patch.o mdbg.o env.o syscalls.o
$(LD) -r -o $@ $^

syscalls.o: syscalls.c

syscalls.c: ../include/freebsd/sys/syscall.h
$(PYTHON) gen_syscall_funcs.py > $@

%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $^

clean:
rm -f *.o
rm -f *.o syscalls.c

install: crt1.o
install -d $(DESTDIR)/target/lib
Expand Down
38 changes: 4 additions & 34 deletions crt/crt.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,30 +40,7 @@ extern int main(int argc, char* argv[], char *envp[]);
int __klog_init(payload_args_t *args);
int __kernel_init(payload_args_t* args);
int __rtld_init(payload_args_t* args);


/**
* The PS5 does not allow syscalls from .text sections that are allocated in
* shared memory. Instead, we simply assign the approriate registers, and
* jump directly to a syscall instruction in libkernel (which is not in shared
* memory).
**/
static __attribute__ ((used)) long ptr_syscall = 0;
asm(".intel_syntax noprefix\n"
".global syscall\n"
".type syscall @function\n"
"syscall:\n"
" mov rax, rdi\n" // sysno
" mov rdi, rsi\n" // arg1
" mov rsi, rdx\n" // arg2
" mov rdx, rcx\n" // arg3
" mov r10, r8\n" // arg4
" mov r8, r9\n" // arg5
" mov r9, qword ptr [rsp + 8]\n" // arg6
" jmp qword ptr [rip + ptr_syscall]\n" // syscall
" ret\n"
);

int __syscall_init(payload_args_t* args);

static payload_args_t* payload_args = 0;

Expand All @@ -79,21 +56,14 @@ pre_init(payload_args_t *args) {
int *__isthreaded;
int error = 0;

if(args->sceKernelDlsym(0x1, "getpid", &ptr_syscall)) {
if((error=args->sceKernelDlsym(0x2001, "getpid", &ptr_syscall))) {
return error;
}
}

// jump directly to the syscall instruction
// in getpid (provided by libkernel)
ptr_syscall += 0xa;

if((error=args->sceKernelDlsym(0x2, "__isthreaded", &__isthreaded))) {
return error;
}
*__isthreaded = 1;

if((error=__syscall_init(args))) {
return error;
}
if((error=__klog_init(args))) {
return error;
}
Expand Down
100 changes: 100 additions & 0 deletions crt/gen_syscall_funcs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/usr/bin/env python3
# encoding: utf-8
# Copyright (C) 2024 John Törnblom
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not see
# <http://www.gnu.org/licenses/>.

import os
import string


print('''
static __attribute__ ((used)) long ptr_syscall = 0;
asm(".intel_syntax noprefix\\n"
".global syscall\\n"
".type syscall @function\\n"
"syscall:\\n"
" mov rax, rdi\\n"
" mov rdi, rsi\\n"
" mov rsi, rdx\\n"
" mov rdx, rcx\\n"
" mov r10, r8\\n"
" mov r8, r9\\n"
" mov r9, qword ptr [rsp + 8]\\n"
" jmp qword ptr [rip + ptr_syscall]\\n"
" ret\\n"
);
''')


syscall_tmpl = string.Template('''
asm(".intel_syntax noprefix\\n"
".global $sysname\\n"
".type $sysname @function\\n"
"$sysname:\\n"
" mov rax, $sysno\\n"
" mov r10, rcx\\n"
" jmp qword ptr [rip + ptr_syscall]\\n"
" ret\\n"
);
''')

header = os.path.dirname(__file__)
with open(f'{header}/../include/freebsd/sys/syscall.h') as f:
s = f.read()
for line in s.splitlines():
if not line.startswith('#define\tSYS'):
continue

line = line[12:].strip()
name, no = line.split()
name = name.strip()
no = int(no.strip())

if name.startswith('__acl'):
continue

if name.startswith('__cap'):
continue

if name.startswith('__'):
name = name[2:]

if name in ['syscall', 'pipe', 'MAXSYSCALL']:
continue

if name.startswith('freebsd'):
continue

print(syscall_tmpl.substitute(sysname=name, sysno=no))


print('''
#include "payload.h"
int __syscall_init(payload_args_t* args) {
int error;
if(args->sceKernelDlsym(0x1, "getpid", &ptr_syscall)) {
if((error=args->sceKernelDlsym(0x2001, "getpid", &ptr_syscall))) {
return error;
}
}
// jump directly to the syscall instruction
// in getpid (provided by libkernel)
ptr_syscall += 0xa;
return 0;
}
''')

0 comments on commit 4888939

Please sign in to comment.