From 661cdb367c8ae6fb7c6310d4a808c73480cb7f45 Mon Sep 17 00:00:00 2001 From: MaxHearnden Date: Thu, 30 Nov 2023 21:29:45 +0000 Subject: [PATCH 1/2] Add syscalls needed for a simple sandbox --- aarch64/aarch64_defs.M1 | 7 ++++++ aarch64/linux/unistd.c | 47 ++++++++++++++++++++++++++++++++++++ amd64/amd64_defs.M1 | 3 +++ amd64/linux/unistd.c | 53 +++++++++++++++++++++++++++++++++++++++++ armv7l/linux/unistd.c | 48 +++++++++++++++++++++++++++++++++++++ riscv32/linux/unistd.c | 45 ++++++++++++++++++++++++++++++++++ riscv64/linux/unistd.c | 45 ++++++++++++++++++++++++++++++++++ uefi/uefi.c | 29 ++++++++++++++++++++-- uefi/unistd.c | 32 +++++++++++++++++++++++++ unistd.h | 11 +++++++++ x86/linux/unistd.c | 52 ++++++++++++++++++++++++++++++++++++++++ x86/x86_defs.M1 | 4 ++++ 12 files changed, 374 insertions(+), 2 deletions(-) diff --git a/aarch64/aarch64_defs.M1 b/aarch64/aarch64_defs.M1 index 691bca4..85ea0a1 100644 --- a/aarch64/aarch64_defs.M1 +++ b/aarch64/aarch64_defs.M1 @@ -117,6 +117,8 @@ DEFINE SUB_X0_X0_X1 000001cb DEFINE SUB_X0_8 002000d1 DEFINE SUB_X0_16 004000d1 DEFINE SUB_X0_24 006000d1 +DEFINE SUB_X0_32 008000d1 +DEFINE SUB_X0_40 00A000d1 DEFINE MSUB_X0_X0_X2_X1 0084029b DEFINE MUL_X0_X1_X0 207c009b @@ -160,4 +162,9 @@ DEFINE SET_X8_TO_SYS_WAIT4 882080d2 DEFINE SET_X8_TO_SYS_WRITE 080880d2 DEFINE SET_X8_TO_SYS_UNLINK 488080d2 DEFINE SET_X8_TO_SYS_UMASK c81480d2 +DEFINE SET_X8_TO_SYS_UNSHARE 280c80d2 +DEFINE SET_X8_TO_SYS_GETEUID e81580d2 +DEFINE SET_X8_TO_SYS_GETEGID 081680d2 +DEFINE SET_X8_TO_SYS_CHROOT 680680d2 +DEFINE SET_X8_TO_SYS_MOUNT 080580d2 DEFINE SYSCALL 010000d4 diff --git a/aarch64/linux/unistd.c b/aarch64/linux/unistd.c index 33c4337..aede9eb 100644 --- a/aarch64/linux/unistd.c +++ b/aarch64/linux/unistd.c @@ -197,4 +197,51 @@ int uname(struct utsname* unameData) "SYSCALL"); } +int unshare(int flags) { + asm ( + "SET_X0_FROM_BP" "SUB_X0_8" "DEREF_X0" + "SET_X8_TO_SYS_UNSHARE" + "SYSCALL" + ); +} + +int geteuid() { + asm ( + "SET_X8_TO_SYS_GETEUID" + "SYSCALL" + ); +} + +int getegid() { + asm ( + "SET_X8_TO_SYS_GETEGID" + "SYSCALL" + ); +} + +int chroot(char const *path) { + asm ( + "SET_X0_FROM_BP" "SUB_X0_8" "DEREF_X0" + "SET_X8_TO_SYS_CHROOT" + "SYSCALL" + ); +} + +int mount(char const *source, char const *target, char const *filesystemtype, + ulong mountflags, void const *data) { + asm ( + "SET_X0_FROM_BP" "SUB_X0_40" "DEREF_X0" + "SET_X4_FROM_X0" + "SET_X0_FROM_BP" "SUB_X0_32" "DEREF_X0" + "SET_X3_FROM_X0" + "SET_X0_FROM_BP" "SUB_X0_24" "DEREF_X0" + "SET_X2_FROM_X0" + "SET_X0_FROM_BP" "SUB_X0_16" "DEREF_X0" + "SET_X1_FROM_X0" + "SET_X0_FROM_BP" "SUB_X0_8" "DEREF_X0" + "SET_X8_TO_SYS_MOUNT" + "SYSCALL" + ); +} + #endif diff --git a/amd64/amd64_defs.M1 b/amd64/amd64_defs.M1 index c926583..7252852 100644 --- a/amd64/amd64_defs.M1 +++ b/amd64/amd64_defs.M1 @@ -41,7 +41,9 @@ DEFINE lea_rdx,[rsp+DWORD] 488D9424 DEFINE lea_rdx,[rbp+DWORD] 488D95 DEFINE lea_rsi,[rsp+DWORD] 488DB424 DEFINE lea_r8,[rbp+DWORD] 4C8D85 +DEFINE lea_r8,[rsp+DWORD] 4C8D8424 DEFINE lea_r9,[rbp+DWORD] 4C8D8D +DEFINE lea_r10,[rsp+DWORD] 4C8D9424 DEFINE mov_rax, 48C7C0 DEFINE mov_rbx, 48C7C3 DEFINE mov_rdi, 48C7C7 @@ -81,6 +83,7 @@ DEFINE mov_rbp,[rip+DWORD] 488B2D DEFINE mov_rsp,[rip+DWORD] 488B25 DEFINE mov_r8,[r8] 4D8B00 DEFINE mov_r9,[r9] 4D8B09 +DEFINE mov_r10,[r10] 4D8B12 DEFINE movzx_rax,al 480FB6C0 DEFINE movsxd_rax,eax 4863C0 DEFINE movsx_rax,BYTE_PTR_[rax] 480FBE00 diff --git a/amd64/linux/unistd.c b/amd64/linux/unistd.c index a1d4b76..c91ccd6 100644 --- a/amd64/linux/unistd.c +++ b/amd64/linux/unistd.c @@ -199,4 +199,57 @@ int uname(struct utsname* unameData) "mov_rax, %63" "syscall"); } + +int unshare(int flags) { + asm ( + "lea_rdi,[rsp+DWORD] %8" + "mov_rdi,[rdi]" + "mov_rax, %272" + "syscall" + ); +} + +int geteuid() { + asm ( + "mov_rax, %107" + "syscall" + ); +} + +int getegid() { + asm ( + "mov_rax, %108" + "syscall" + ); +} + +int mount( + char *source, char *target, char *filesystemtype, + ulong mountflags, void *data +) { + asm ( + "lea_rdi,[rsp+DWORD] %40" + "mov_rdi,[rdi]" + "lea_rsi,[rsp+DWORD] %32" + "mov_rsi,[rsi]" + "lea_rdx,[rsp+DWORD] %24" + "mov_rdx,[rdx]" + "lea_r10,[rsp+DWORD] %16" + "mov_r10,[r10]" + "lea_r8,[rsp+DWORD] %8" + "mov_r8,[r8]" + "mov_rax, %165" + "syscall" + ); +} + +int chroot(char *path) { + asm ( + "lea_rdi,[rsp+DWORD] %8" + "mov_rdi,[rdi]" + "mov_rax, %161" + "syscall" + ); +} + #endif diff --git a/armv7l/linux/unistd.c b/armv7l/linux/unistd.c index b587b3b..c86a8df 100644 --- a/armv7l/linux/unistd.c +++ b/armv7l/linux/unistd.c @@ -191,4 +191,52 @@ int uname(struct utsname* unameData) "!0 R0 LOAD32 R0 MEMORY" "SYSCALL_ALWAYS"); } + +int unshare(int flags) { + asm("!4 R0 SUB R12 ARITH_ALWAYS" + "!0 R0 LOAD32 R0 MEMORY" + "!337 R7 LOADI8_ALWAYS" + "SYSCALL_ALWAYS"); +} + +int geteuid() { + asm( + "!201 R7 LOADI8_ALWAYS" + "SYSCALL_ALWAYS" + ); +} + +int getegid() { + asm ( + "!202 R7 LOADI8_ALWAYS" + "SYSCALL_ALWAYS" + ); +} + +int chroot(char const *path) { + asm ( + "!4 R0 SUB R12 ARITH_ALWAYS" + "!61 R7 LOADI8_ALWAYS" + "SYSCALL_ALWAYS" + ); +} + +int mount(char const *source, char const *target, char const *filesystemtype, + ulong mountflags, void const *data) { + asm ( + "!4 R0 SUB R12 ARITH_ALWAYS" + "!0 R0 LOAD32 R0 MEMORY" + "!8 R1 SUB R12 ARITH_ALWAYS" + "!0 R1 LOAD32 R1 MEMORY" + "!12 R2 SUB R12 ARITH_ALWAYS" + "!0 R2 LOAD32 R2 MEMORY" + "!16 R3 SUB R12 ARITH_ALWAYS" + "!0 R3 LOAD32 R3 MEMORY" + "!20 R4 SUB R12 ARITH_ALWAYS" + "!0 R4 LOAD32 R4 MEMORY" + "!31 R7 LOADI8_ALWAYS" + "SYSCALL_ALWAYS" + ); +} + #endif diff --git a/riscv32/linux/unistd.c b/riscv32/linux/unistd.c index ac7d5ca..f431c33 100644 --- a/riscv32/linux/unistd.c +++ b/riscv32/linux/unistd.c @@ -235,4 +235,49 @@ int uname(struct utsname* unameData) "ecall"); } +int unshare(int flags) { + asm ( + "rd_a0 rs1_fp !-4 lw" + "rd_a7 !97 addi" + "ecall" + ); +} + +int geteuid() { + asm ( + "rd_a7 !175 addi" + "ecall" + ); +} + +int getegid() { + asm ( + "rd_a7 !177 addi" + "ecall" + ); +} + +int mount ( + char *source, char *target, char *filesystemtype, + ulong mountflags, void *data +) { + asm ( + "rd_a0 rs1_fp !-4 lw" + "rd_a1 rs1_fp !-8 lw" + "rd_a2 rs1_fp !-12 lw" + "rd_a3 rs1_fp !-16 lw" + "rd_a4 rs1_fp !-20 lw" + "rd_a7 !40 addi" + "ecall" + ); +} + +int chroot(char *path) { + asm ( + "rd_a0 rs1_fp !-4 lw" + "rd_a7 !51 addi" + "ecall" + ); +} + #endif diff --git a/riscv64/linux/unistd.c b/riscv64/linux/unistd.c index 87cb13b..ba7049f 100644 --- a/riscv64/linux/unistd.c +++ b/riscv64/linux/unistd.c @@ -179,4 +179,49 @@ int uname(struct utsname* unameData) "ecall"); } +int unshare(int flags) { + asm ( + "rd_a0 rs1_fp !-8 ld" + "rd_a7 !97 addi" + "ecall" + ); +} + +int geteuid() { + asm ( + "rd_a7 !175 addi" + "ecall" + ); +} + +int getegid() { + asm ( + "rd_a7 !177 addi" + "ecall" + ); +} + +int mount ( + char *source, char *target, char *filesystemtype, + ulong mountflags, void *data +) { + asm ( + "rd_a0 rs1_fp !-8 ld" + "rd_a1 rs1_fp !-16 ld" + "rd_a2 rs1_fp !-24 ld" + "rd_a3 rs1_fp !-32 ld" + "rd_a4 rs1_fp !-40 ld" + "rd_a7 !40 addi" + "ecall" + ); +} + +int chroot(char *path) { + asm ( + "rd_a0 rs1_fp !-8 ld" + "rd_a7 !51 addi" + "ecall" + ); +} + #endif diff --git a/uefi/uefi.c b/uefi/uefi.c index d6a2281..28b4b70 100644 --- a/uefi/uefi.c +++ b/uefi/uefi.c @@ -59,6 +59,7 @@ char** _argv; char** _envp; char* _cwd; +char* _root; struct efi_simple_text_output_protocol { @@ -491,8 +492,12 @@ char* _relative_path_to_absolute(char* narrow_string) char* absolute_path = calloc(__PATH_MAX, 1); if(narrow_string[0] != '/' && narrow_string[0] != '\\') { - strcpy(absolute_path, _cwd); + strcat(absolute_path, _cwd); } + else + { + strcat(absolute_path, _root); + } strcat(absolute_path, narrow_string); return absolute_path; @@ -704,6 +709,7 @@ char* strchr(char const* str, int ch); void _setup_current_working_directory(char** envp) { _cwd = calloc(__PATH_MAX, 1); + _root = calloc(__PATH_MAX, 1); unsigned i = 0; unsigned j; @@ -719,7 +725,26 @@ void _setup_current_working_directory(char** envp) j += 1; } envp[i][j] = 0; - if(strcmp(envp[i], "cwd") == 0) + if(strcmp(envp[i], "root") == 0) + { + value = envp[i] + j + 1; + match = strchr(value, ':'); /* strip uefi device, e.g. fs0: */ + if(match != NULL) + { + value = match + 1; + } + strcpy(_root, value); + k = 0; + while(_root[k] != '\0') + { + if(_root[k] == '\\') + { + _root[k] = '/'; + } + k += 1; + } + } + else if(strcmp(envp[i], "cwd") == 0) { value = envp[i] + j + 1; match = strchr(value, ':'); /* strip uefi device, e.g. fs0: */ diff --git a/uefi/unistd.c b/uefi/unistd.c index ce6c5d6..d52d422 100644 --- a/uefi/unistd.c +++ b/uefi/unistd.c @@ -166,6 +166,7 @@ int spawn(char* file_name, char** argv, char** envp) /* Setup environment for child process */ _set_environment(envp); _set_variable("cwd", _cwd); + _set_variable("root", _root); /* Run command */ rval = __uefi_3(child_ih, 0, 0, _system->boot_services->start_image); @@ -330,4 +331,35 @@ int uname(struct utsname* unameData) #endif } +int unshare(int flags) { + if (flags != 0) { + return -1; // Any unshare operation is invalid + } + return 0; +} + +int geteuid(int flags) { + return 0; +} + +int getegid(int flags) { + return 0; +} + +int chroot(char const *path) { + char *newroot = _relative_path_to_absolute(path); + free(_root); + _root = newroot; + if(_root[strlen(_root) - 1] != '\\') + { + strncat(_root, "/", __PATH_MAX); + } + return 0; +} + +int mount(char const *source, char const *target, char const *filesystemtype, + ulong mountflags, void const *data) { + return -1; +} + #endif diff --git a/unistd.h b/unistd.h index 865503e..b725688 100644 --- a/unistd.h +++ b/unistd.h @@ -71,5 +71,16 @@ struct utsname int uname(struct utsname* unameData); +int unshare(int flags); + +int geteuid(); + +int getegid(); + +int chroot(char const *path); + +int mount(char const *source, char const *target, char const *filesystemtype, + ulong mountflags, void const *data); + #endif #endif diff --git a/x86/linux/unistd.c b/x86/linux/unistd.c index 8d096da..a51e095 100644 --- a/x86/linux/unistd.c +++ b/x86/linux/unistd.c @@ -194,4 +194,56 @@ int uname(struct utsname* unameData) "int !0x80"); } +int unshare(int flags) { + asm ( + "lea_ebx,[esp+DWORD] %4" + "mov_ebx,[ebx]" + "mov_eax, %310" + "int !0x80" + ); +} + +int geteuid() { + asm ( + "mov_eax, %201" + "int !0x80" + ); +} + +int getegid() { + asm ( + "mov_eax, %202" + "int !0x80" + ); +} + +int mount( + char *source, char *target, char *filesystemtype, + ulong mountflags, void *data +) { + asm ( + "lea_ebx,[esp+DWORD] %20" + "mov_ebx,[ebx]" + "lea_ecx,[esp+DWORD] %16" + "mov_ecx,[ecx]" + "lea_edx,[esp+DWORD] %12" + "mov_edx,[edx]" + "lea_esi,[esp+DWORD] %8" + "mov_esi,[esi]" + "lea_edi,[esp+DWORD] %4" + "mov_edi,[edi]" + "mov_eax, %21" + "int !0x80" + ); +} + +int chroot(char *path) { + asm ( + "lea_ebx,[esp+DWORD] %4" + "mov_ebx,[ebx]" + "mov_eax, %61" + "int !0x80" + ); +} + #endif diff --git a/x86/x86_defs.M1 b/x86/x86_defs.M1 index bbd6a20..5e5961f 100644 --- a/x86/x86_defs.M1 +++ b/x86/x86_defs.M1 @@ -36,6 +36,8 @@ DEFINE lea_eax,[esp+DWORD] 8D8424 DEFINE lea_ebx,[esp+DWORD] 8D9C24 DEFINE lea_ecx,[esp+DWORD] 8D8C24 DEFINE lea_edx,[esp+DWORD] 8D9424 +DEFINE lea_esi,[esp+DWORD] 8DB424 +DEFINE lea_edi,[esp+DWORD] 8DBC24 DEFINE mov_eax,[esp+DWORD] 8B8424 DEFINE mov_eax,ebp 89E8 DEFINE mov_eax,ebx 89D8 @@ -54,6 +56,8 @@ DEFINE mov_eax,[eax] 8B00 DEFINE mov_ebx,[ebx] 8B1B DEFINE mov_ecx,[ecx] 8B09 DEFINE mov_edx,[edx] 8B12 +DEFINE mov_esi,[esi] 8B36 +DEFINE mov_edi,[edi] 8B3F DEFINE mov_[ebx],al 8803 DEFINE mov_[ebx],ax 668903 DEFINE mov_[ebx],eax 8903 From 6f8fda3792a16048129941b03b7e23731fbde1a5 Mon Sep 17 00:00:00 2001 From: MaxHearnden Date: Thu, 30 Nov 2023 22:25:00 +0000 Subject: [PATCH 2/2] ulong -> unsigned long --- unistd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unistd.h b/unistd.h index b725688..2745c7c 100644 --- a/unistd.h +++ b/unistd.h @@ -80,7 +80,7 @@ int getegid(); int chroot(char const *path); int mount(char const *source, char const *target, char const *filesystemtype, - ulong mountflags, void const *data); + unsigned long mountflags, void const *data); #endif #endif