From e9e584149c3f7f9757b3535dc6d8be8b73ca4447 Mon Sep 17 00:00:00 2001 From: Mathieu Maret Date: Mon, 8 Nov 2021 23:22:03 +0100 Subject: [PATCH] Add support for syscall with more than 3 args --- arch/x86/cpu_context.c | 52 +++++++++++++++++++++++++++++++++++++- core/cpu_context.h | 23 +++++++++++++---- core/syscall.c | 8 +++++- core/syscall.h | 1 + userspace/kernel/syscall.h | 1 + userspace/libc.c | 19 ++++++++++++++ userspace/libc.h | 5 ++++ userspace/main_user.c | 5 ++++ 8 files changed, 107 insertions(+), 7 deletions(-) diff --git a/arch/x86/cpu_context.c b/arch/x86/cpu_context.c index eedd0f4..8cbd774 100644 --- a/arch/x86/cpu_context.c +++ b/arch/x86/cpu_context.c @@ -10,6 +10,7 @@ #include "gdt.h" #include "klibc.h" #include "segment.h" +#include "uaccess.h" /** * Here is the definition of a CPU context for IA32 processors. This @@ -512,7 +513,7 @@ int syscallGet1arg(const struct cpu_state *user_ctxt, } -int _syscallGet2args(const struct cpu_state *user_ctxt, +int syscallGet2args(const struct cpu_state *user_ctxt, /* out */unsigned int *arg1, /* out */unsigned int *arg2) { @@ -520,3 +521,52 @@ int _syscallGet2args(const struct cpu_state *user_ctxt, return syscallGet3args(user_ctxt, arg1, arg2, & unused); } +int syscallGet4args(const struct cpu_state *user_ctxt, + /* out */ unsigned int *arg1, + /* out */ unsigned int *arg2, + /* out */ unsigned int *arg3, + /* out */ unsigned int *arg4) +{ + uaddr_t userOtherArgs; + unsigned int otherArgs[2]; + int ret; + + ret = syscallGet3args(user_ctxt, arg1, arg2, (unsigned int *)&userOtherArgs); + if (ret) + return ret; + + ret = memcpyFromUser((vaddr_t)otherArgs, userOtherArgs, sizeof(otherArgs)); + + if (ret != sizeof(otherArgs)) + return -EFAULT; + + *arg3 = otherArgs[0]; + *arg4 = otherArgs[1]; + return 0; +} + +int syscallGet5args(const struct cpu_state *user_ctxt, + /* out */ unsigned int *arg1, + /* out */ unsigned int *arg2, + /* out */ unsigned int *arg3, + /* out */ unsigned int *arg4, + /* out */ unsigned int *arg5) +{ + uaddr_t userOtherArgs; + unsigned int otherArgs[3]; + int ret; + + ret = syscallGet3args(user_ctxt, arg1, arg2, (unsigned int *)&userOtherArgs); + if (ret) + return ret; + + ret = memcpyFromUser((vaddr_t)otherArgs, userOtherArgs, sizeof(otherArgs)); + + if (ret != sizeof(otherArgs)) + return -EFAULT; + + *arg3 = otherArgs[0]; + *arg4 = otherArgs[1]; + *arg5 = otherArgs[2]; + return 0; +} diff --git a/core/cpu_context.h b/core/cpu_context.h index 724b067..936eaa9 100644 --- a/core/cpu_context.h +++ b/core/cpu_context.h @@ -204,14 +204,27 @@ void cpu_state_detect_kernel_stack_overflow(const struct cpu_state *ctxt, int cpu_ustate_init(struct cpu_state **ctx, uaddr_t startPC, uint32_t arg1, uint32_t arg2, uaddr_t startSP, vaddr_t kernelStackBottom, size_t kernelStackSize); -int syscallGet3args(const struct cpu_state *user_ctxt, - /* out */ unsigned int *arg1, - /* out */ unsigned int *arg2, - /* out */ unsigned int *arg3); - int syscallGet1arg(const struct cpu_state *user_ctxt, /* out */ unsigned int *arg1); int syscallGet2args(const struct cpu_state *user_ctxt, /* out */ unsigned int *arg1, /* out */ unsigned int *arg2); + +int syscallGet3args(const struct cpu_state *user_ctxt, + /* out */ unsigned int *arg1, + /* out */ unsigned int *arg2, + /* out */ unsigned int *arg3); + +int syscallGet4args(const struct cpu_state *user_ctxt, + /* out */ unsigned int *arg1, + /* out */ unsigned int *arg2, + /* out */ unsigned int *arg3, + /* out */ unsigned int *arg4); + +int syscallGet5args(const struct cpu_state *user_ctxt, + /* out */ unsigned int *arg1, + /* out */ unsigned int *arg2, + /* out */ unsigned int *arg3, + /* out */ unsigned int *arg4, + /* out */ unsigned int *arg5); diff --git a/core/syscall.c b/core/syscall.c index 19b3a21..e904867 100644 --- a/core/syscall.c +++ b/core/syscall.c @@ -7,7 +7,7 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx) { - int ret; + int ret = 0; switch (syscallId) { case SYSCALL_ID_EXIT: { @@ -31,6 +31,12 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx) case SYSCALL_ID_READ: ret = keyboardRead(); break; + case SYSCALL_ID_TEST: { + unsigned int arg1, arg2, arg3, arg4, arg5; + ret = syscallGet5args(userCtx, &arg1, &arg2, &arg3, &arg4, &arg5); + printf("Got 5args from userspace %d %d %d %d %d\n", arg1, arg2, arg3, arg4, arg5); + break; + } default: printf("Unknon syscall id %d\n", syscallId); ret = -ENOENT; diff --git a/core/syscall.h b/core/syscall.h index 3eb77dc..6d846de 100644 --- a/core/syscall.h +++ b/core/syscall.h @@ -7,6 +7,7 @@ #define SYSCALL_ID_YOLO 2 #define SYSCALL_ID_PUTC 3 #define SYSCALL_ID_READ 4 +#define SYSCALL_ID_TEST 5 #ifdef __KERNEL__ int syscallExecute(int syscallId, const struct cpu_state *user_ctx); diff --git a/userspace/kernel/syscall.h b/userspace/kernel/syscall.h index 3eb77dc..6d846de 100644 --- a/userspace/kernel/syscall.h +++ b/userspace/kernel/syscall.h @@ -7,6 +7,7 @@ #define SYSCALL_ID_YOLO 2 #define SYSCALL_ID_PUTC 3 #define SYSCALL_ID_READ 4 +#define SYSCALL_ID_TEST 5 #ifdef __KERNEL__ int syscallExecute(int syscallId, const struct cpu_state *user_ctx); diff --git a/userspace/libc.c b/userspace/libc.c index b46f9fc..c029aab 100644 --- a/userspace/libc.c +++ b/userspace/libc.c @@ -467,6 +467,20 @@ int vasprintf(char **strp, const char *fmt, va_list ap) return size; } +int syscall5(int id, unsigned int arg1, unsigned int arg2, unsigned int arg3, + unsigned int arg4, unsigned int arg5) +{ + unsigned int args[] = {arg3, arg4, arg5}; + return syscall3(id, arg1, arg2, (unsigned)args); +} + +int syscall4(int id, unsigned int arg1, unsigned int arg2, unsigned int arg3, + unsigned int arg4) +{ + unsigned int args[] = {arg3, arg4}; + return syscall3(id, arg1, arg2, (unsigned)args); +} + int syscall3(int id, unsigned int arg1, unsigned int arg2, unsigned int arg3) { int ret; @@ -513,6 +527,11 @@ void yolo() syscall0(SYSCALL_ID_YOLO); } +int testSycall5(uint arg1, uint arg2, uint arg3, uint arg4, uint arg5) +{ + return syscall5(SYSCALL_ID_TEST, arg1, arg2, arg3, arg4, arg5); +} + char readc() { return syscall0(SYSCALL_ID_READ); diff --git a/userspace/libc.h b/userspace/libc.h index 91031e5..f877897 100644 --- a/userspace/libc.h +++ b/userspace/libc.h @@ -30,6 +30,10 @@ int printf(const char *format, ...); int asprintf(char **strp, const char *fmt, ...); int vasprintf(char **strp, const char *fmt, va_list ap); +int syscall5(int id, unsigned int arg1, unsigned int arg2, unsigned int arg3, + unsigned int arg4, unsigned int arg5); +int syscall4(int id, unsigned int arg1, unsigned int arg2, unsigned int arg3, + unsigned int arg4); int syscall3(int id, unsigned int arg1, unsigned int arg2, unsigned int arg3); int syscall2(int id, unsigned int arg1, unsigned int arg2); int syscall1(int id, unsigned int arg1); @@ -37,6 +41,7 @@ int syscall0(int id); void _exit(int status); void yolo(); +int testSycall5(uint arg1, uint arg2, uint arg3, uint arg4, uint arg5); char readc(); char readcBlock(); int readline(char *buf, int size); diff --git a/userspace/main_user.c b/userspace/main_user.c index fd8cd67..5dac99e 100644 --- a/userspace/main_user.c +++ b/userspace/main_user.c @@ -12,6 +12,7 @@ int func_help() printf(" yolo\n"); printf(" suicide\n"); printf(" help\n"); + printf(" syscall5\n"); return 0; } @@ -45,6 +46,10 @@ int main(int argc, char *argv[]) func_suicide(); continue; } + if (strcmp(buf, "syscall5") == 0) { + testSycall5(1, 2, 3, 4, 5); + continue; + } } return 0; }