diff --git a/README.md b/README.md index 44d8bc4..47eeecf 100644 --- a/README.md +++ b/README.md @@ -267,6 +267,7 @@ with - x86_64 - aarch64 +- riscv64 (Only the trap mode and the seccomp mode are available) ## License diff --git a/docs/architecture.md b/docs/architecture.md index 4583c3b..1221d0e 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -174,6 +174,8 @@ host-kernel calls. `mmap` and `epoll_*` are deliberately excluded because they need W^X enforcement, shadow validation, or FD-table gating that the fast-path cannot perform. +On **riscv64**, the rewrite mode is not available now. + Each site is classified as WRAPPER (simple `syscall; ret` pattern, eligible for inline virtualized return: getpid=1, gettid=1, getppid=0) or COMPLEX (result consumed internally by helpers like `raise()` that diff --git a/mk/toolchain.mk b/mk/toolchain.mk index 2d4297d..bac91a2 100644 --- a/mk/toolchain.mk +++ b/mk/toolchain.mk @@ -29,6 +29,11 @@ CFLAGS += -Wno-unused-parameter CFLAGS += -Iinclude -Isrc LDFLAGS += -Wl,-z,noexecstack -Wl,-z,separate-code +# Disable link relaxation of riscv64 architecture to prevent long link time +ifeq ($(ARCH),riscv64) + LDFLAGS += -Wl,--no-relax +endif + # Build mode from Kconfig (fallback to BUILD= for unconfigured builds) ifeq ($(CONFIG_BUILD_RELEASE),y) CFLAGS += -O2 -DNDEBUG diff --git a/scripts/alpine-sha256.txt b/scripts/alpine-sha256.txt index 6259d19..346dec3 100644 --- a/scripts/alpine-sha256.txt +++ b/scripts/alpine-sha256.txt @@ -1,2 +1,3 @@ 55ea3e5a7c2c35e6268c5dcbb8e45a9cd5b0e372e7b4e798499a526834f7ed90 alpine-minirootfs-3.21.0-x86_64.tar.gz f31202c4070c4ef7de9e157e1bd01cb4da3a2150035d74ea5372c5e86f1efac1 alpine-minirootfs-3.21.0-aarch64.tar.gz +b2c5ed2be586aebd2da5dd13dbc96bc8cc41b72e517d0726dfbbb0a9810e66d6 alpine-minirootfs-3.21.0-riscv64.tar.gz diff --git a/src/dispatch-misc.c b/src/dispatch-misc.c index e6b4478..ffcac95 100644 --- a/src/dispatch-misc.c +++ b/src/dispatch-misc.c @@ -239,6 +239,8 @@ struct kbox_dispatch forward_uname(const struct kbox_syscall_request *req, snprintf(uts.machine, sizeof(uts.machine), "x86_64"); #elif defined(__aarch64__) snprintf(uts.machine, sizeof(uts.machine), "aarch64"); +#elif (defined(__riscv) && __riscv_xlen == 64) + snprintf(uts.machine, sizeof(uts.machine), "riscv64"); #else snprintf(uts.machine, sizeof(uts.machine), "unknown"); #endif diff --git a/src/elf.c b/src/elf.c index 5baebe5..0f1162e 100644 --- a/src/elf.c +++ b/src/elf.c @@ -417,7 +417,7 @@ int kbox_build_elf_load_plan(const unsigned char *buf, p_memsz = read_le64(buf + off + P_MEMSZ_OFF); p_align = read_le64(buf + off + P_ALIGN_OFF); - if (p_filesz > p_memsz) + if (p_memsz && p_filesz > p_memsz) return -1; /* Validate that p_offset + p_filesz does not overflow. We do diff --git a/src/image.c b/src/image.c index 635945e..e2cd277 100644 --- a/src/image.c +++ b/src/image.c @@ -490,8 +490,8 @@ static const struct kbox_host_nrs *select_host_nrs(void) { #if defined(__x86_64__) return &HOST_NRS_X86_64; -#elif defined(__aarch64__) - return &HOST_NRS_AARCH64; +#elif defined(__aarch64__) || (defined(__riscv) && (__riscv_xlen == 64)) + return &HOST_NRS_GENERIC; #else return NULL; #endif diff --git a/src/loader-entry.c b/src/loader-entry.c index faf77f1..171d453 100644 --- a/src/loader-entry.c +++ b/src/loader-entry.c @@ -17,6 +17,9 @@ static int machine_to_entry_arch(uint16_t machine, case 0xb7: *arch_out = KBOX_LOADER_ENTRY_ARCH_AARCH64; return 0; + case 0xf3: + *arch_out = KBOX_LOADER_ENTRY_ARCH_RISCV64; + return 0; default: return -1; } diff --git a/src/loader-entry.h b/src/loader-entry.h index 6747d59..e3cd7bb 100644 --- a/src/loader-entry.h +++ b/src/loader-entry.h @@ -9,6 +9,7 @@ enum kbox_loader_entry_arch { KBOX_LOADER_ENTRY_ARCH_X86_64, KBOX_LOADER_ENTRY_ARCH_AARCH64, + KBOX_LOADER_ENTRY_ARCH_RISCV64 }; struct kbox_loader_entry_state { diff --git a/src/loader-transfer.c b/src/loader-transfer.c index 192051d..0408706 100644 --- a/src/loader-transfer.c +++ b/src/loader-transfer.c @@ -89,6 +89,24 @@ kbox_loader_transfer_to_guest(const struct kbox_loader_transfer_state *state) : "r"(sp), "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4), "r"(x5), "r"(x16) : "memory"); +#elif defined(__riscv) && (__riscv_xlen == 64) + if (state->arch != KBOX_LOADER_ENTRY_ARCH_RISCV64) + __builtin_trap(); + register uint64_t a0 __asm__("a0") = state->regs[0]; + register uint64_t a1 __asm__("a1") = state->regs[1]; + register uint64_t a2 __asm__("a2") = state->regs[2]; + register uint64_t a3 __asm__("a3") = state->regs[3]; + register uint64_t a4 __asm__("a4") = state->regs[4]; + register uint64_t a5 __asm__("a5") = state->regs[5]; + register uint64_t t0 __asm__("t0") = state->pc; + uint64_t sp = state->sp; + + __asm__ volatile( + "mv sp, %0\n\t" + "jr t0\n\t" + : + : "r"(sp), "r"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(t0) + : "memory"); #else (void) state; __builtin_trap(); diff --git a/src/rewrite.c b/src/rewrite.c index 25b852a..77c276b 100644 --- a/src/rewrite.c +++ b/src/rewrite.c @@ -608,10 +608,10 @@ static int encode_aarch64_virtual_procinfo_patch( if (aarch64_prev_insn_syscall_nr(image, image_len, site_off, &nr) < 0) return -1; - if (nr == (uint32_t) HOST_NRS_AARCH64.getpid || - nr == (uint32_t) HOST_NRS_AARCH64.gettid) { + if (nr == (uint32_t) HOST_NRS_GENERIC.getpid || + nr == (uint32_t) HOST_NRS_GENERIC.gettid) { value = 1; - } else if (nr == (uint32_t) HOST_NRS_AARCH64.getppid) { + } else if (nr == (uint32_t) HOST_NRS_GENERIC.getppid) { value = 0; } else { return -1; diff --git a/src/seccomp-bpf.c b/src/seccomp-bpf.c index ad86b1d..8481eff 100644 --- a/src/seccomp-bpf.c +++ b/src/seccomp-bpf.c @@ -142,7 +142,7 @@ static const int deny_nrs[] = { 153, /* vhangup */ }; -#elif defined(__aarch64__) +#elif defined(__aarch64__) || (defined(__riscv) && __riscv_xlen == 64) static const int deny_nrs[] = { /* Seccomp manipulation */ 277, /* seccomp */ diff --git a/src/seccomp-defs.h b/src/seccomp-defs.h index 68a8874..948526f 100644 --- a/src/seccomp-defs.h +++ b/src/seccomp-defs.h @@ -34,6 +34,8 @@ #define KBOX_AUDIT_ARCH_CURRENT 0xc000003eU #elif defined(__aarch64__) #define KBOX_AUDIT_ARCH_CURRENT 0xc00000b7U +#elif defined(__riscv) && __riscv_xlen == 64 +#define KBOX_AUDIT_ARCH_CURRENT 0xc00000f3U #else #error "unsupported architecture" #endif diff --git a/src/seccomp-dispatch.c b/src/seccomp-dispatch.c index 3894750..1a5f3f9 100644 --- a/src/seccomp-dispatch.c +++ b/src/seccomp-dispatch.c @@ -33,28 +33,28 @@ #ifndef __NR_pidfd_open #if defined(__x86_64__) #define __NR_pidfd_open 434 -#elif defined(__aarch64__) +#elif defined(__aarch64__) || (defined(__riscv) && (__riscv_xlen == 64)) #define __NR_pidfd_open 434 #endif #endif #ifndef __NR_pidfd_getfd #if defined(__x86_64__) #define __NR_pidfd_getfd 438 -#elif defined(__aarch64__) +#elif defined(__aarch64__) || (defined(__riscv) && (__riscv_xlen == 64)) #define __NR_pidfd_getfd 438 #endif #endif #ifndef __NR_faccessat2 #if defined(__x86_64__) #define __NR_faccessat2 439 -#elif defined(__aarch64__) +#elif defined(__aarch64__) || (defined(__riscv) && (__riscv_xlen == 64)) #define __NR_faccessat2 439 #endif #endif #ifndef __NR_statx #if defined(__x86_64__) #define __NR_statx 332 -#elif defined(__aarch64__) +#elif defined(__aarch64__) || (defined(__riscv) && (__riscv_xlen == 64)) #define __NR_statx 291 #endif #endif diff --git a/src/seccomp-supervisor.c b/src/seccomp-supervisor.c index e506443..08ba24c 100644 --- a/src/seccomp-supervisor.c +++ b/src/seccomp-supervisor.c @@ -482,8 +482,8 @@ int kbox_run_supervisor(const struct kbox_sysnrs *sysnrs, /* Architecture-specific host syscall numbers for the BPF filter. */ #if defined(__x86_64__) const struct kbox_host_nrs *host_nrs = &HOST_NRS_X86_64; -#elif defined(__aarch64__) - const struct kbox_host_nrs *host_nrs = &HOST_NRS_AARCH64; +#elif defined(__aarch64__) || (defined(__riscv) && __riscv_xlen == 64) + const struct kbox_host_nrs *host_nrs = &HOST_NRS_GENERIC; #else #error "Unsupported architecture" #endif diff --git a/src/syscall-nr.c b/src/syscall-nr.c index 3368637..bfad4da 100644 --- a/src/syscall-nr.c +++ b/src/syscall-nr.c @@ -353,7 +353,7 @@ const struct kbox_host_nrs HOST_NRS_X86_64 = { .readlink = 89, }; -const struct kbox_host_nrs HOST_NRS_AARCH64 = { +const struct kbox_host_nrs HOST_NRS_GENERIC = { .openat = 56, .openat2 = 437, .open = -1, diff --git a/src/syscall-nr.h b/src/syscall-nr.h index ec7e902..d3dd90f 100644 --- a/src/syscall-nr.h +++ b/src/syscall-nr.h @@ -220,7 +220,7 @@ struct kbox_host_nrs { }; extern const struct kbox_host_nrs HOST_NRS_X86_64; -extern const struct kbox_host_nrs HOST_NRS_AARCH64; +extern const struct kbox_host_nrs HOST_NRS_GENERIC; const struct kbox_sysnrs *detect_sysnrs(void); const char *syscall_name_from_nr(const struct kbox_host_nrs *h, int nr); diff --git a/src/syscall-trap.c b/src/syscall-trap.c index c67710d..639c9d1 100644 --- a/src/syscall-trap.c +++ b/src/syscall-trap.c @@ -387,26 +387,6 @@ extern int64_t kbox_syscall_trap_host_rt_sigprocmask_unblock( const uint64_t *mask, size_t sigset_size); #elif defined(__aarch64__) -extern char kbox_syscall_trap_host_syscall_start[]; -extern char kbox_syscall_trap_host_syscall_ip_label[]; -extern char kbox_syscall_trap_host_syscall_end[]; -extern char kbox_syscall_trap_host_futex_wait_start[]; -extern char kbox_syscall_trap_host_futex_wait_end[]; -extern char kbox_syscall_trap_host_futex_wake_start[]; -extern char kbox_syscall_trap_host_futex_wake_end[]; -extern char kbox_syscall_trap_host_exit_group_start[]; -extern char kbox_syscall_trap_host_exit_group_end[]; -extern char kbox_syscall_trap_host_execve_start[]; -extern char kbox_syscall_trap_host_execve_end[]; -extern char kbox_syscall_trap_host_execveat_start[]; -extern char kbox_syscall_trap_host_execveat_end[]; -extern char kbox_syscall_trap_host_clone_start[]; -extern char kbox_syscall_trap_host_clone_end[]; -extern char kbox_syscall_trap_host_clone3_start[]; -extern char kbox_syscall_trap_host_clone3_end[]; -extern char kbox_syscall_trap_host_rt_sigprocmask_unblock_start[]; -extern char kbox_syscall_trap_host_rt_sigprocmask_unblock_end[]; - __asm__( ".text\n" ".globl kbox_syscall_trap_host_syscall6\n" @@ -549,6 +529,172 @@ __asm__( "ret\n" ".size kbox_syscall_trap_host_rt_sigprocmask_unblock, " ".-kbox_syscall_trap_host_rt_sigprocmask_unblock\n"); +#elif (defined(__riscv) && __riscv_xlen == 64) +__asm__( + ".text\n" + ".globl kbox_syscall_trap_host_syscall6\n" + ".type kbox_syscall_trap_host_syscall6,%function\n" + ".globl kbox_syscall_trap_host_syscall_start\n" + "kbox_syscall_trap_host_syscall_start:\n" + "kbox_syscall_trap_host_syscall6:\n" + "mv a7, a0\n" + "mv a0, a1\n" + "mv a1, a2\n" + "mv a2, a3\n" + "mv a3, a4\n" + "mv a4, a5\n" + "mv a5, a6\n" + ".globl kbox_syscall_trap_host_syscall_ip_label\n" + "kbox_syscall_trap_host_syscall_ip_label:\n" + "ecall\n" + ".globl kbox_syscall_trap_host_syscall_end\n" + "kbox_syscall_trap_host_syscall_end:\n" + "ret\n" + ".size kbox_syscall_trap_host_syscall6, " + ".-kbox_syscall_trap_host_syscall6\n" + + ".globl kbox_syscall_trap_host_futex_wait_private\n" + ".type kbox_syscall_trap_host_futex_wait_private,%function\n" + ".globl kbox_syscall_trap_host_futex_wait_start\n" + "kbox_syscall_trap_host_futex_wait_private:\n" + "kbox_syscall_trap_host_futex_wait_start:" + "li a7, " XSTR(__NR_futex) "\n" + "mv a2, a1\n" + "li a1, " XSTR(FUTEX_WAIT_PRIVATE) "\n" + "li a3, 0\n" + "li a4, 0\n" + "li a5, 0\n" + "ecall\n" + ".globl kbox_syscall_trap_host_futex_wait_end\n" + "kbox_syscall_trap_host_futex_wait_end:\n" + "ret\n" + ".size kbox_syscall_trap_host_futex_wait_private, " + ".-kbox_syscall_trap_host_futex_wait_private\n" + + ".globl kbox_syscall_trap_host_futex_wake_private\n" + ".type kbox_syscall_trap_host_futex_wake_private,%function\n" + ".globl kbox_syscall_trap_host_futex_wake_start\n" + "kbox_syscall_trap_host_futex_wake_start:\n" + "kbox_syscall_trap_host_futex_wake_private:\n" + "li a7, " XSTR(__NR_futex) "\n" + "mv a2, a1\n" + "li a1, " XSTR(FUTEX_WAKE_PRIVATE) "\n" + "li a3, 0\n" + "li a4, 0\n" + "li a5, 0\n" + "ecall\n" + ".globl kbox_syscall_trap_host_futex_wake_end\n" + "kbox_syscall_trap_host_futex_wake_end:\n" + "ret\n" + ".size kbox_syscall_trap_host_futex_wake_private, " + ".-kbox_syscall_trap_host_futex_wake_private\n" + + ".globl kbox_syscall_trap_host_exit_group_now\n" + ".type kbox_syscall_trap_host_exit_group_now,%function\n" + ".globl kbox_syscall_trap_host_exit_group_start\n" + "kbox_syscall_trap_host_exit_group_start:\n" + "kbox_syscall_trap_host_exit_group_now:\n" + "li a7, " XSTR(__NR_exit_group) "\n" + "ecall\n" + ".globl kbox_syscall_trap_host_exit_group_end\n" + "kbox_syscall_trap_host_exit_group_end:\n" + "ret\n" + ".size kbox_syscall_trap_host_exit_group_now, " + ".-kbox_syscall_trap_host_exit_group_now\n" + + ".globl kbox_syscall_trap_host_execve_now\n" + ".type kbox_syscall_trap_host_execve_now,%function\n" + ".globl kbox_syscall_trap_host_execve_start\n" + "kbox_syscall_trap_host_execve_start:\n" + "kbox_syscall_trap_host_execve_now:\n" + "li a7, " XSTR(__NR_execve) "\n" + "ecall\n" + ".globl kbox_syscall_trap_host_execve_end\n" + "kbox_syscall_trap_host_execve_end:\n" + "ret\n" + ".size kbox_syscall_trap_host_execve_now, " + ".-kbox_syscall_trap_host_execve_now\n" + + ".globl kbox_syscall_trap_host_execveat_now\n" + ".type kbox_syscall_trap_host_execveat_now,%function\n" + ".globl kbox_syscall_trap_host_execveat_start\n" + "kbox_syscall_trap_host_execveat_start:\n" + "kbox_syscall_trap_host_execveat_now:\n" + "li a7, " XSTR(__NR_execveat) "\n" + "ecall\n" + ".globl kbox_syscall_trap_host_execveat_end\n" + "kbox_syscall_trap_host_execveat_end:\n" + "ret\n" + ".size kbox_syscall_trap_host_execveat_now, " + ".-kbox_syscall_trap_host_execveat_now\n" + + ".globl kbox_syscall_trap_host_clone_now\n" + ".type kbox_syscall_trap_host_clone_now,%function\n" + ".globl kbox_syscall_trap_host_clone_start\n" + "kbox_syscall_trap_host_clone_start:\n" + "kbox_syscall_trap_host_clone_now:\n" + "li a7, " XSTR(__NR_clone) "\n" + "ecall\n" + ".globl kbox_syscall_trap_host_clone_end\n" + "kbox_syscall_trap_host_clone_end:\n" + "ret\n" + ".size kbox_syscall_trap_host_clone_now, " + ".-kbox_syscall_trap_host_clone_now\n" + + ".globl kbox_syscall_trap_host_clone3_now\n" + ".type kbox_syscall_trap_host_clone3_now,%function\n" + ".globl kbox_syscall_trap_host_clone3_start\n" + "kbox_syscall_trap_host_clone3_start:\n" + "kbox_syscall_trap_host_clone3_now:\n" + "li a7, " XSTR(__NR_clone3) "\n" + "ecall\n" + ".globl kbox_syscall_trap_host_clone3_end\n" + "kbox_syscall_trap_host_clone3_end:\n" + "ret\n" + ".size kbox_syscall_trap_host_clone3_now, " + ".-kbox_syscall_trap_host_clone3_now\n" + + ".globl kbox_syscall_trap_host_rt_sigprocmask_unblock\n" + ".type kbox_syscall_trap_host_rt_sigprocmask_unblock,%function\n" + ".globl kbox_syscall_trap_host_rt_sigprocmask_unblock_start\n" + "kbox_syscall_trap_host_rt_sigprocmask_unblock_start:\n" + "kbox_syscall_trap_host_rt_sigprocmask_unblock:\n" + "li a7, " XSTR(__NR_rt_sigprocmask) "\n" + "mv a3, a1\n" + "mv a1, a0\n" + "li a0, " XSTR(SIG_UNBLOCK) "\n" + "li a2, 0\n" + "li a4, 0\n" + "li a5, 0\n" + "ecall\n" + ".globl kbox_syscall_trap_host_rt_sigprocmask_unblock_end\n" + "kbox_syscall_trap_host_rt_sigprocmask_unblock_end:\n" + "ret\n" + ".size kbox_syscall_trap_host_rt_sigprocmask_unblock, " + ".-kbox_syscall_trap_host_rt_sigprocmask_unblock\n"); +#endif + +#if defined(__aarch64__) || (defined(__riscv) && __riscv_xlen == 64) +extern char kbox_syscall_trap_host_syscall_start[]; +extern char kbox_syscall_trap_host_syscall_ip_label[]; +extern char kbox_syscall_trap_host_syscall_end[]; +extern char kbox_syscall_trap_host_futex_wait_start[]; +extern char kbox_syscall_trap_host_futex_wait_end[]; +extern char kbox_syscall_trap_host_futex_wake_start[]; +extern char kbox_syscall_trap_host_futex_wake_end[]; +extern char kbox_syscall_trap_host_exit_group_start[]; +extern char kbox_syscall_trap_host_exit_group_end[]; +extern char kbox_syscall_trap_host_execve_start[]; +extern char kbox_syscall_trap_host_execve_end[]; +extern char kbox_syscall_trap_host_execveat_start[]; +extern char kbox_syscall_trap_host_execveat_end[]; +extern char kbox_syscall_trap_host_clone_start[]; +extern char kbox_syscall_trap_host_clone_end[]; +extern char kbox_syscall_trap_host_clone3_start[]; +extern char kbox_syscall_trap_host_clone3_end[]; +extern char kbox_syscall_trap_host_rt_sigprocmask_unblock_start[]; +extern char kbox_syscall_trap_host_rt_sigprocmask_unblock_end[]; + extern int64_t kbox_syscall_trap_host_syscall6(long nr, uint64_t a0, @@ -734,7 +880,8 @@ int kbox_syscall_trap_sigset_blocks_reserved(const void *mask, size_t len) uintptr_t kbox_syscall_trap_host_syscall_ip(void) { -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__aarch64__) || \ + (defined(__riscv) && __riscv_xlen == 64) return (uintptr_t) kbox_syscall_trap_host_syscall_ip_label; #else return 0; @@ -743,7 +890,8 @@ uintptr_t kbox_syscall_trap_host_syscall_ip(void) int kbox_syscall_trap_host_syscall_range(struct kbox_syscall_trap_ip_range *out) { -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__aarch64__) || \ + (defined(__riscv) && __riscv_xlen == 64) uintptr_t start = (uintptr_t) kbox_syscall_trap_host_syscall_start; uintptr_t end = (uintptr_t) kbox_syscall_trap_host_syscall_end; @@ -838,7 +986,7 @@ int kbox_syscall_trap_internal_ip_ranges(struct kbox_syscall_trap_ip_range *out, (uintptr_t) kbox_syscall_trap_host_rt_sigprocmask_unblock_start, (uintptr_t) kbox_syscall_trap_host_rt_sigprocmask_unblock_end) < 0) return -1; -#elif defined(__aarch64__) +#elif defined(__aarch64__) || (defined(__riscv) && __riscv_xlen == 64) if (append_ip_range(out, cap, &n, (uintptr_t) kbox_syscall_trap_host_futex_wait_start, (uintptr_t) kbox_syscall_trap_host_futex_wait_end) < 0) @@ -915,6 +1063,17 @@ int kbox_syscall_regs_from_sigsys(const siginfo_t *info, out->args[4] = (uint64_t) uc->uc_mcontext.regs[4]; out->args[5] = (uint64_t) uc->uc_mcontext.regs[5]; return 0; +#elif defined(__riscv) && __riscv_xlen == 64 + out->nr = (info->si_syscall != 0) ? info->si_syscall + : (int) uc->uc_mcontext.__gregs[17]; + out->instruction_pointer = (uint64_t) uc->uc_mcontext.__gregs[0]; + out->args[0] = (uint64_t) uc->uc_mcontext.__gregs[10]; + out->args[1] = (uint64_t) uc->uc_mcontext.__gregs[11]; + out->args[2] = (uint64_t) uc->uc_mcontext.__gregs[12]; + out->args[3] = (uint64_t) uc->uc_mcontext.__gregs[13]; + out->args[4] = (uint64_t) uc->uc_mcontext.__gregs[14]; + out->args[5] = (uint64_t) uc->uc_mcontext.__gregs[15]; + return 0; #else (void) uc; return -1; @@ -1390,6 +1549,43 @@ static int64_t host_syscall(const ucontext_t *uc) (uint64_t) uc->uc_mcontext.regs[1], (uint64_t) uc->uc_mcontext.regs[2], (uint64_t) uc->uc_mcontext.regs[3], (uint64_t) uc->uc_mcontext.regs[4], (uint64_t) uc->uc_mcontext.regs[5]); +#elif defined(__riscv) && (__riscv_xlen == 64) + long nr = (long) uc->uc_mcontext.__gregs[17]; + + if (nr == __NR_exit || nr == __NR_exit_group) + return kbox_syscall_trap_host_exit_group_now( + (int) uc->uc_mcontext.__gregs[10]); + if (nr == __NR_execve) + return kbox_syscall_trap_host_execve_now( + (const char *) (uintptr_t) uc->uc_mcontext.__gregs[10], + (char *const *) (uintptr_t) uc->uc_mcontext.__gregs[11], + (char *const *) (uintptr_t) uc->uc_mcontext.__gregs[12]); + if (nr == __NR_execveat) + return kbox_syscall_trap_host_execveat_now( + (int) uc->uc_mcontext.__gregs[10], + (const char *) (uintptr_t) uc->uc_mcontext.__gregs[11], + (char *const *) (uintptr_t) uc->uc_mcontext.__gregs[12], + (char *const *) (uintptr_t) uc->uc_mcontext.__gregs[13], + (int) uc->uc_mcontext.__gregs[14]); + if (nr == __NR_clone) + return kbox_syscall_trap_host_clone_now( + (uint64_t) uc->uc_mcontext.__gregs[10], + (uint64_t) uc->uc_mcontext.__gregs[11], + (uint64_t) uc->uc_mcontext.__gregs[12], + (uint64_t) uc->uc_mcontext.__gregs[13], + (uint64_t) uc->uc_mcontext.__gregs[14]); + if (nr == __NR_clone3) + return kbox_syscall_trap_host_clone3_now( + (const void *) (uintptr_t) uc->uc_mcontext.__gregs[10], + (size_t) uc->uc_mcontext.__gregs[11]); + + return kbox_syscall_trap_host_syscall6( + nr, (uint64_t) uc->uc_mcontext.__gregs[10], + (uint64_t) uc->uc_mcontext.__gregs[11], + (uint64_t) uc->uc_mcontext.__gregs[12], + (uint64_t) uc->uc_mcontext.__gregs[13], + (uint64_t) uc->uc_mcontext.__gregs[14], + (uint64_t) uc->uc_mcontext.__gregs[15]); #else (void) uc; return -ENOSYS; @@ -1425,6 +1621,9 @@ int kbox_syscall_result_to_sigsys(void *ucontext_ptr, #elif defined(__aarch64__) uc->uc_mcontext.regs[0] = (uint64_t) ret; return 0; +#elif defined(__riscv) && (__riscv_xlen == 64) + uc->uc_mcontext.__gregs[10] = (uint64_t) ret; + return 0; #else return -1; #endif diff --git a/tests/unit/test-syscall-nr.c b/tests/unit/test-syscall-nr.c index 7bd5c12..8c2da54 100644 --- a/tests/unit/test-syscall-nr.c +++ b/tests/unit/test-syscall-nr.c @@ -72,15 +72,15 @@ static void test_host_x86_64_sendmsg(void) static void test_host_aarch64_gettimeofday(void) { - ASSERT_EQ(HOST_NRS_AARCH64.gettimeofday, 169); + ASSERT_EQ(HOST_NRS_GENERIC.gettimeofday, 169); } static void test_host_aarch64_no_open(void) { /* aarch64 has no legacy open syscall */ - ASSERT_EQ(HOST_NRS_AARCH64.open, -1); - ASSERT_EQ(HOST_NRS_AARCH64.stat, -1); - ASSERT_EQ(HOST_NRS_AARCH64.lstat, -1); + ASSERT_EQ(HOST_NRS_GENERIC.open, -1); + ASSERT_EQ(HOST_NRS_GENERIC.stat, -1); + ASSERT_EQ(HOST_NRS_GENERIC.lstat, -1); } static void test_at_fdcwd(void) diff --git a/tests/unit/test-syscall-trap.c b/tests/unit/test-syscall-trap.c index 88a893c..36a418b 100644 --- a/tests/unit/test-syscall-trap.c +++ b/tests/unit/test-syscall-trap.c @@ -91,7 +91,8 @@ static void test_host_syscall_range_contains_ip(void) struct kbox_syscall_trap_ip_range range; uintptr_t ip = kbox_syscall_trap_host_syscall_ip(); -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__aarch64__) || \ + (defined(__riscv) && (__riscv_xlen == 64)) ASSERT_EQ(kbox_syscall_trap_host_syscall_range(&range), 0); ASSERT_TRUE(range.start < range.end); ASSERT_TRUE(ip >= range.start); @@ -150,6 +151,30 @@ static void test_sigsys_decode_aarch64_registers(void) ASSERT_EQ(regs.args[0], 101); ASSERT_EQ(regs.args[5], 606); } +#elif defined(__riscv) && (__riscv_xlen == 64) +static void test_sigsys_decode_riscv64_registers(void) +{ + siginfo_t info; + ucontext_t uc; + struct kbox_syscall_regs regs; + + memset(&uc, 0, sizeof(uc)); + init_sigsys(&info, 56); + uc.uc_mcontext.__gregs[0] = 0x4000; + uc.uc_mcontext.__gregs[10] = 101; + uc.uc_mcontext.__gregs[11] = 202; + uc.uc_mcontext.__gregs[12] = 303; + uc.uc_mcontext.__gregs[13] = 404; + uc.uc_mcontext.__gregs[14] = 505; + uc.uc_mcontext.__gregs[15] = 606; + uc.uc_mcontext.__gregs[16] = 999; + + ASSERT_EQ(kbox_syscall_regs_from_sigsys(&info, &uc, ®s), 0); + ASSERT_EQ(regs.nr, 56); + ASSERT_EQ(regs.instruction_pointer, 0x4000); + ASSERT_EQ(regs.args[0], 101); + ASSERT_EQ(regs.args[5], 606); +} #endif static void test_sigsys_request_builder_uses_trap_source(void) @@ -174,6 +199,11 @@ static void test_sigsys_request_builder_uses_trap_source(void) uc.uc_mcontext.pc = 0x5000; uc.uc_mcontext.regs[0] = 7; expected_rc = 0; +#elif defined(__riscv) && (__riscv_xlen == 64) + init_sigsys(&info, 93); + uc.uc_mcontext.__gregs[0] = 0x5000; + uc.uc_mcontext.__gregs[10] = 7; + expected_rc = 0; #else memset(&info, 0, sizeof(info)); info.si_signo = SIGSYS; @@ -182,7 +212,8 @@ static void test_sigsys_request_builder_uses_trap_source(void) ASSERT_EQ( kbox_syscall_request_from_sigsys(&req, 777, &info, &uc, &guest_mem), expected_rc); -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__aarch64__) || \ + (defined(__riscv) && (__riscv_xlen == 64)) ASSERT_EQ(req.source, KBOX_SYSCALL_SOURCE_TRAP); ASSERT_EQ(req.pid, 777); ASSERT_EQ(req.cookie, 0); @@ -209,6 +240,10 @@ static void test_sigsys_request_builder_defaults_current_guest_mem(void) init_sigsys(&info, 172); uc.uc_mcontext.pc = 0x6000; expected_rc = 0; +#elif defined(__riscv) && (__riscv_xlen == 64) + init_sigsys(&info, 172); + uc.uc_mcontext.__gregs[0] = 0x6000; + expected_rc = 0; #else memset(&info, 0, sizeof(info)); info.si_signo = SIGSYS; @@ -216,7 +251,8 @@ static void test_sigsys_request_builder_defaults_current_guest_mem(void) ASSERT_EQ(kbox_syscall_request_from_sigsys(&req, 123, &info, &uc, NULL), expected_rc); -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__aarch64__) || \ + (defined(__riscv) && (__riscv_xlen == 64)) ASSERT_EQ(req.guest_mem.ops, &kbox_current_guest_mem_ops); ASSERT_EQ(req.guest_mem.opaque, 0); #endif @@ -233,7 +269,8 @@ static void test_sigsys_result_writer(void) dispatch.val = 1234; dispatch.error = 0; -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__aarch64__) || \ + (defined(__riscv) && (__riscv_xlen == 64)) expected_rc = 0; #endif ASSERT_EQ(kbox_syscall_result_to_sigsys(&uc, &dispatch), expected_rc); @@ -241,6 +278,8 @@ static void test_sigsys_result_writer(void) ASSERT_EQ(uc.uc_mcontext.gregs[REG_RAX], 1234); #elif defined(__aarch64__) ASSERT_EQ(uc.uc_mcontext.regs[0], 1234); +#elif defined(__riscv) && (__riscv_xlen == 64) + ASSERT_EQ(uc.uc_mcontext.__gregs[10], 1234); #endif } @@ -259,7 +298,10 @@ static void test_sigsys_continue_executes_host_syscall(void) uc.uc_mcontext.gregs[REG_RAX] = HOST_NRS_X86_64.getpid; expected_rc = 0; #elif defined(__aarch64__) - uc.uc_mcontext.regs[8] = HOST_NRS_AARCH64.getpid; + uc.uc_mcontext.regs[8] = HOST_NRS_GENERIC.getpid; + expected_rc = 0; +#elif defined(__riscv) && (__riscv_xlen == 64) + uc.uc_mcontext.__gregs[17] = HOST_NRS_GENERIC.getpid; expected_rc = 0; #endif @@ -268,6 +310,8 @@ static void test_sigsys_continue_executes_host_syscall(void) ASSERT_EQ(uc.uc_mcontext.gregs[REG_RAX], getpid()); #elif defined(__aarch64__) ASSERT_EQ(uc.uc_mcontext.regs[0], (uint64_t) getpid()); +#elif defined(__riscv) && (__riscv_xlen == 64) + ASSERT_EQ(uc.uc_mcontext.__gregs[10], (uint64_t) getpid()); #endif } @@ -279,8 +323,8 @@ static void test_sigsys_runtime_install_uninstall(void) memset(&ctx, 0, sizeof(ctx)); #if defined(__x86_64__) ctx.host_nrs = &HOST_NRS_X86_64; -#elif defined(__aarch64__) - ctx.host_nrs = &HOST_NRS_AARCH64; +#elif defined(__aarch64__) || (defined(__riscv) && (__riscv_xlen == 64)) + ctx.host_nrs = &HOST_NRS_GENERIC; #endif ASSERT_EQ(kbox_syscall_trap_runtime_install(&runtime, &ctx), 0); @@ -301,11 +345,14 @@ static void test_sigsys_runtime_install_preserves_sqpoll(void) #if defined(__x86_64__) ctx.host_nrs = &HOST_NRS_X86_64; #elif defined(__aarch64__) - ctx.host_nrs = &HOST_NRS_AARCH64; + ctx.host_nrs = &HOST_NRS_GENERIC; +#elif defined(__riscv) && (__riscv_xlen == 64) + ctx.host_nrs = &HOST_NRS_GENERIC; #endif runtime.sqpoll = 1; -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__aarch64__) || \ + (defined(__riscv) && (__riscv_xlen == 64)) ASSERT_EQ(kbox_syscall_trap_runtime_install(&runtime, &ctx), 0); ASSERT_EQ(runtime.sqpoll, 1); kbox_syscall_trap_runtime_uninstall(&runtime); @@ -336,6 +383,10 @@ static void test_sigsys_trap_handle_uses_runtime_executor(void) init_sigsys(&info, 172); uc.uc_mcontext.pc = 0x7100; expected_rc = 0; +#elif defined(__riscv) && (__riscv_xlen == 64) + init_sigsys(&info, 172); + uc.uc_mcontext.__gregs[0] = 0x7100; + expected_rc = 0; #else memset(&info, 0, sizeof(info)); info.si_signo = SIGSYS; @@ -348,6 +399,8 @@ static void test_sigsys_trap_handle_uses_runtime_executor(void) ASSERT_EQ(uc.uc_mcontext.gregs[REG_RAX], info.si_syscall + 10); #elif defined(__aarch64__) ASSERT_EQ(uc.uc_mcontext.regs[0], (uint64_t) info.si_syscall + 10); +#elif defined(__riscv) && (__riscv_xlen == 64) + ASSERT_EQ(uc.uc_mcontext.__gregs[10], (uint64_t) info.si_syscall + 10); #endif ASSERT_EQ(custom_execute_calls, 1); ASSERT_EQ(custom_execute_last_nr, info.si_syscall); @@ -372,10 +425,15 @@ static void test_sigsys_dispatch_helper(void) uc.uc_mcontext.gregs[REG_RIP] = 0x7000; expected_rc = 0; #elif defined(__aarch64__) - ctx.host_nrs = &HOST_NRS_AARCH64; + ctx.host_nrs = &HOST_NRS_GENERIC; init_sigsys(&info, 172); uc.uc_mcontext.pc = 0x7000; expected_rc = 0; +#elif defined(__riscv) && (__riscv_xlen == 64) + ctx.host_nrs = &HOST_NRS_GENERIC; + init_sigsys(&info, 172); + uc.uc_mcontext.__gregs[0] = 0x7000; + expected_rc = 0; #else memset(&info, 0, sizeof(info)); info.si_signo = SIGSYS; @@ -406,10 +464,15 @@ static void test_trap_runtime_capture_and_dispatch_pending(void) uc.uc_mcontext.gregs[REG_RIP] = 0x7200; expected_rc = 0; #elif defined(__aarch64__) - ctx.host_nrs = &HOST_NRS_AARCH64; + ctx.host_nrs = &HOST_NRS_GENERIC; init_sigsys(&info, 172); uc.uc_mcontext.pc = 0x7200; expected_rc = 0; +#elif defined(__riscv) && (__riscv_xlen == 64) + ctx.host_nrs = &HOST_NRS_GENERIC; + init_sigsys(&info, 172); + uc.uc_mcontext.__gregs[0] = 0x7200; + expected_rc = 0; #else memset(&info, 0, sizeof(info)); info.si_signo = SIGSYS; @@ -466,8 +529,8 @@ static void test_trap_runtime_service_thread_dispatches(void) int i; memset(&ctx, 0, sizeof(ctx)); -#if defined(__aarch64__) - ctx.host_nrs = &HOST_NRS_AARCH64; +#if defined(__aarch64__) || (defined(__riscv) && (__riscv_xlen == 64)) + ctx.host_nrs = &HOST_NRS_GENERIC; #else ctx.host_nrs = &HOST_NRS_X86_64; #endif @@ -504,12 +567,13 @@ static void test_trap_active_dispatch_uses_service_thread(void) memset(&req, 0, sizeof(req)); #if defined(__x86_64__) ctx.host_nrs = &HOST_NRS_X86_64; -#elif defined(__aarch64__) - ctx.host_nrs = &HOST_NRS_AARCH64; +#elif defined(__aarch64__) || (defined(__riscv) && (__riscv_xlen == 64)) + ctx.host_nrs = &HOST_NRS_GENERIC; #endif req.nr = 88; -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__aarch64__) || \ + (defined(__riscv) && (__riscv_xlen == 64)) ASSERT_EQ(kbox_syscall_trap_runtime_install(&runtime, &ctx), 0); ASSERT_EQ(kbox_syscall_trap_active_pid(), runtime.pid); ASSERT_EQ(kbox_syscall_trap_active_dispatch(&req, &dispatch), 0); @@ -532,12 +596,13 @@ static void test_trap_active_dispatch_fails_cleanly_during_sqpoll_stop(void) memset(&req, 0, sizeof(req)); #if defined(__x86_64__) ctx.host_nrs = &HOST_NRS_X86_64; -#elif defined(__aarch64__) - ctx.host_nrs = &HOST_NRS_AARCH64; +#elif defined(__aarch64__) || (defined(__riscv) && (__riscv_xlen == 64)) + ctx.host_nrs = &HOST_NRS_GENERIC; #endif req.nr = 99; -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__aarch64__) || \ + (defined(__riscv) && (__riscv_xlen == 64)) ASSERT_EQ(kbox_syscall_trap_runtime_install(&runtime, &ctx), 0); runtime.sqpoll = 1; __atomic_store_n(&runtime.service_stop, 1, __ATOMIC_RELEASE); @@ -557,6 +622,8 @@ void test_syscall_trap_init(void) TEST_REGISTER(test_sigsys_decode_x86_64_registers); #elif defined(__aarch64__) TEST_REGISTER(test_sigsys_decode_aarch64_registers); +#elif defined(__riscv) && (__riscv_xlen == 64) + TEST_REGISTER(test_sigsys_decode_riscv64_registers); #endif TEST_REGISTER(test_sigsys_request_builder_uses_trap_source); TEST_REGISTER(test_sigsys_request_builder_defaults_current_guest_mem);