From d0c8224e61efe31b63cdecac3dc0e1326f6b15dd Mon Sep 17 00:00:00 2001 From: "Anton D. Kachalov" Date: Wed, 16 Dec 2020 09:17:53 -0800 Subject: [PATCH] Add support for ARM32 (hard float target) This change enables support for 32-bit ARM, as used by embedded controllers and older phones. Note: This does not support 32-bit sandboxees on AArch64. Both sandboxee and host code must have the same bitness. PiperOrigin-RevId: 347835193 Change-Id: I6395882677530f9862f118d2dc10230a61049836 --- cmake/libunwind/Download.cmake | 18 + sandboxed_api/client.cc | 17 +- sandboxed_api/sandbox2/config.h | 14 +- sandboxed_api/sandbox2/mounts.cc | 1 + .../sandbox2/network_proxy/client.cc | 8 + sandboxed_api/sandbox2/policy.cc | 2 + sandboxed_api/sandbox2/policy_test.cc | 58 ++- sandboxed_api/sandbox2/policybuilder.cc | 26 +- sandboxed_api/sandbox2/policybuilder_test.cc | 8 +- sandboxed_api/sandbox2/regs.cc | 29 +- sandboxed_api/sandbox2/regs.h | 7 +- sandboxed_api/sandbox2/stack_trace.cc | 3 + sandboxed_api/sandbox2/syscall.cc | 4 + sandboxed_api/sandbox2/syscall_defs.cc | 364 ++++++++++++++++++ .../sandbox2/testcases/personality.cc | 5 +- sandboxed_api/sandbox2/util.cc | 6 +- sandboxed_api/sandbox2/util/BUILD.bazel | 1 + sandboxed_api/sandbox2/util/minielf.cc | 70 ++-- sandboxed_api/sandbox2/util/minielf.h | 4 +- sandboxed_api/sandbox2/violation.proto | 8 + 20 files changed, 576 insertions(+), 77 deletions(-) diff --git a/cmake/libunwind/Download.cmake b/cmake/libunwind/Download.cmake index cdb5f5d..88221a8 100644 --- a/cmake/libunwind/Download.cmake +++ b/cmake/libunwind/Download.cmake @@ -83,6 +83,23 @@ elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") list(APPEND _unwind_ptrace_srcs ${_unwind_src}/src/aarch64/Ginit_remote.c ) +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm") + set(_unwind_cpu "arm") + list(APPEND _unwind_platform_srcs + ${_unwind_src}/src/arm/Gcreate_addr_space.c + ${_unwind_src}/src/arm/Gex_tables.c + ${_unwind_src}/src/arm/Gglobal.c + ${_unwind_src}/src/arm/Ginit.c + ${_unwind_src}/src/arm/Gis_signal_frame.c + ${_unwind_src}/src/arm/Gregs.c + ${_unwind_src}/src/arm/Gresume.c + ${_unwind_src}/src/arm/Gstash_frame.c + ${_unwind_src}/src/arm/Gstep.c + ${_unwind_src}/src/arm/is_fpreg.c + ) + list(APPEND _unwind_ptrace_srcs + ${_unwind_src}/src/arm/Ginit_remote.c + ) endif() add_library(unwind_ptrace_wrapped STATIC @@ -165,6 +182,7 @@ add_library(unwind::unwind_ptrace_wrapped ALIAS unwind_ptrace_wrapped) target_include_directories(unwind_ptrace_wrapped PUBLIC ${_unwind_src}/include ${_unwind_src}/include/tdep + ${_unwind_src}/include/tdep-${_unwind_cpu} ${_unwind_src}/src ) target_compile_options(unwind_ptrace_wrapped PRIVATE diff --git a/sandboxed_api/client.cc b/sandboxed_api/client.cc index becdeb7..d0f3be9 100644 --- a/sandboxed_api/client.cc +++ b/sandboxed_api/client.cc @@ -55,15 +55,14 @@ ffi_type* GetFFIType(size_t size, v::Type type) { case v::Type::kFd: return &ffi_type_sint; case v::Type::kFloat: - switch (size) { - case sizeof(float): - return &ffi_type_float; - case sizeof(double): - return &ffi_type_double; - case sizeof(long double): - return &ffi_type_longdouble; - default: - LOG(FATAL) << "Unknown floating-point size: " << size; + if (size == sizeof(float)) { + return &ffi_type_float; + } else if (size == sizeof(double)) { + return &ffi_type_double; + } else if (size == sizeof(long double)) { + return &ffi_type_longdouble; + } else { + LOG(FATAL) << "Unknown floating-point size: " << size; } case v::Type::kInt: switch (size) { diff --git a/sandboxed_api/sandbox2/config.h b/sandboxed_api/sandbox2/config.h index 209cd82..76bd9a3 100644 --- a/sandboxed_api/sandbox2/config.h +++ b/sandboxed_api/sandbox2/config.h @@ -32,6 +32,11 @@ // Spellings for AArch64 #elif defined(__aarch64__) || defined(_M_ARM64) #define SAPI_ARM64 1 + +// 32-bit ARM +#elif defined(__arm__) || defined(_M_ARM) +#define SAPI_ARM 1 + #endif namespace sandbox2 { @@ -48,6 +53,7 @@ enum Architecture : uint16_t { kX86, kPPC64LE, kArm64, + kArm, }; } // namespace cpu @@ -63,6 +69,8 @@ constexpr cpu::Architecture Architecture() { return cpu::kPPC64LE; #elif defined(SAPI_ARM64) return cpu::kArm64; +#elif defined(SAPI_ARM) + return cpu::kArm; #else return cpu::kUnknown; #endif @@ -74,11 +82,15 @@ constexpr bool IsPPC64LE() { return Architecture() == cpu::kPPC64LE; } constexpr bool IsArm64() { return Architecture() == cpu::kArm64; } +constexpr bool IsArm() { return Architecture() == cpu::kArm; } + +constexpr bool Is64Bit() { return sizeof(uintptr_t) == 8; } + } // namespace host_cpu static_assert(host_cpu::Architecture() != cpu::kUnknown, "Host CPU architecture is not supported: One of x86-64, POWER64 " - "(little endian) or AArch64 is required."); + "(little endian), Arm or AArch64 is required."); } // namespace sandbox2 diff --git a/sandboxed_api/sandbox2/mounts.cc b/sandboxed_api/sandbox2/mounts.cc index 75d5f91..906d41f 100644 --- a/sandboxed_api/sandbox2/mounts.cc +++ b/sandboxed_api/sandbox2/mounts.cc @@ -115,6 +115,7 @@ absl::Status ValidateInterpreter(absl::string_view interpreter) { "/lib64/ld-linux-x86-64.so.2", "/lib64/ld64.so.2", // PPC64 "/lib/ld-linux-aarch64.so.1", // AArch64 + "/lib/ld-linux-armhf.so.3", // Arm }; if (!allowed_interpreters.contains(interpreter)) { diff --git a/sandboxed_api/sandbox2/network_proxy/client.cc b/sandboxed_api/sandbox2/network_proxy/client.cc index 3dde8c1..b470c85 100644 --- a/sandboxed_api/sandbox2/network_proxy/client.cc +++ b/sandboxed_api/sandbox2/network_proxy/client.cc @@ -55,6 +55,12 @@ constexpr int kRegSyscall = 8; constexpr int kRegArg0 = 0; constexpr int kRegArg1 = 1; constexpr int kRegArg2 = 2; +#elif defined(SAPI_ARM) +constexpr int kRegResult = 0; +constexpr int kRegSyscall = 8; +constexpr int kRegArg0 = 0; +constexpr int kRegArg1 = 1; +constexpr int kRegArg2 = 2; #endif int NetworkProxyClient::ConnectHandler(int sockfd, const struct sockaddr* addr, @@ -173,6 +179,8 @@ void NetworkProxyHandler::ProcessSeccompTrap(int nr, siginfo_t* info, auto* registers = ctx->uc_mcontext.gp_regs; #elif defined(SAPI_ARM64) auto* registers = ctx->uc_mcontext.regs; +#elif defined(SAPI_ARM) + auto* registers = &ctx->uc_mcontext.arm_r0; #endif int syscall = registers[kRegSyscall]; diff --git a/sandboxed_api/sandbox2/policy.cc b/sandboxed_api/sandbox2/policy.cc index 564307e..ceb303d 100644 --- a/sandboxed_api/sandbox2/policy.cc +++ b/sandboxed_api/sandbox2/policy.cc @@ -145,6 +145,8 @@ std::vector Policy::GetTrackingPolicy() const { JEQ32(AUDIT_ARCH_PPC64LE, TRACE(cpu::kPPC64LE)), #elif defined(SAPI_ARM64) JEQ32(AUDIT_ARCH_AARCH64, TRACE(cpu::kArm64)), +#elif defined(SAPI_ARM) + JEQ32(AUDIT_ARCH_ARM, TRACE(cpu::kArm)), #endif TRACE(cpu::kUnknown), }; diff --git a/sandboxed_api/sandbox2/policy_test.cc b/sandboxed_api/sandbox2/policy_test.cc index 54d95a2..34e4347 100644 --- a/sandboxed_api/sandbox2/policy_test.cc +++ b/sandboxed_api/sandbox2/policy_test.cc @@ -280,25 +280,53 @@ TEST(MultipleSyscalls, AddPolicyOnSyscallsWorks) { std::vector args = {path}; auto executor = absl::make_unique(path, args); - auto policy = - PolicyBuilder() + auto policy = PolicyBuilder() #ifdef __NR_open - .BlockSyscallWithErrno(__NR_open, ENOENT) + .BlockSyscallWithErrno(__NR_open, ENOENT) #endif - .BlockSyscallWithErrno(__NR_openat, ENOENT) - .AllowStaticStartup() - .AllowTcMalloc() - .AllowExit() - .AddPolicyOnSyscalls( - {__NR_getuid, __NR_getgid, __NR_geteuid, __NR_getegid}, {ALLOW}) - .AddPolicyOnSyscalls({__NR_getresuid, __NR_getresgid}, {ERRNO(42)}) - .AddPolicyOnSyscalls({__NR_read, __NR_write}, {ERRNO(43)}) - .AddPolicyOnSyscall(__NR_umask, {DENY}) - .BlockSyscallWithErrno(__NR_prlimit64, EPERM) + .BlockSyscallWithErrno(__NR_openat, ENOENT) + .AllowStaticStartup() + .AllowTcMalloc() + .AllowExit() + .AddPolicyOnSyscalls( + { + __NR_getuid, + __NR_getgid, + __NR_geteuid, + __NR_getegid, +#ifdef __NR_getuid32 + __NR_getuid32, +#endif +#ifdef __NR_getgid32 + __NR_getgid32, +#endif +#ifdef __NR_geteuid32 + __NR_geteuid32, +#endif +#ifdef __NR_getegid32 + __NR_getegid32, +#endif + }, + {ALLOW}) + .AddPolicyOnSyscalls( + { + __NR_getresuid, + __NR_getresgid, +#ifdef __NR_getresuid32 + __NR_getresuid32, +#endif +#ifdef __NR_getresgid32 + __NR_getresgid32, +#endif + }, + {ERRNO(42)}) + .AddPolicyOnSyscalls({__NR_read, __NR_write}, {ERRNO(43)}) + .AddPolicyOnSyscall(__NR_umask, {DENY}) + .BlockSyscallWithErrno(__NR_prlimit64, EPERM) #ifdef __NR_access - .BlockSyscallWithErrno(__NR_access, ENOENT) + .BlockSyscallWithErrno(__NR_access, ENOENT) #endif - .BuildOrDie(); + .BuildOrDie(); Sandbox2 s2(std::move(executor), std::move(policy)); auto result = s2.Run(); diff --git a/sandboxed_api/sandbox2/policybuilder.cc b/sandboxed_api/sandbox2/policybuilder.cc index af4f736..0bd287d 100644 --- a/sandboxed_api/sandbox2/policybuilder.cc +++ b/sandboxed_api/sandbox2/policybuilder.cc @@ -428,7 +428,9 @@ PolicyBuilder& PolicyBuilder::AllowGetPIDs() { PolicyBuilder& PolicyBuilder::AllowGetRlimit() { return AllowSyscalls({ +#ifdef __NR_getrlimit __NR_getrlimit, +#endif #ifdef __NR_ugetrlimit __NR_ugetrlimit, #endif @@ -437,7 +439,9 @@ PolicyBuilder& PolicyBuilder::AllowGetRlimit() { PolicyBuilder& PolicyBuilder::AllowSetRlimit() { return AllowSyscalls({ +#ifdef __NR_setrlimit __NR_setrlimit, +#endif #ifdef __NR_usetrlimit __NR_usetrlimit, #endif @@ -504,13 +508,16 @@ PolicyBuilder& PolicyBuilder::AllowStaticStartup() { AllowGetRlimit(); AllowSyscalls({ // These syscalls take a pointer, so no restriction. - __NR_uname, - __NR_brk, - __NR_set_tid_address, + __NR_uname, __NR_brk, __NR_set_tid_address, - // This syscall takes a pointer and a length. - // We could restrict length, but it might change, so not worth it. - __NR_set_robust_list, +#if defined(__ARM_NR_set_tls) + // libc sets the TLS during startup + __ARM_NR_set_tls, +#endif + + // This syscall takes a pointer and a length. + // We could restrict length, but it might change, so not worth it. + __NR_set_robust_list, }); AllowFutexOp(FUTEX_WAIT_BITSET); @@ -543,6 +550,13 @@ PolicyBuilder& PolicyBuilder::AllowStaticStartup() { BlockSyscallWithErrno(__NR_readlink, ENOENT); #endif + if constexpr (host_cpu::IsArm()) { + AddPolicyOnSyscall(__NR_mprotect, { + ARG_32(2), + JEQ32(PROT_READ, ALLOW), + }); + } + return *this; } diff --git a/sandboxed_api/sandbox2/policybuilder_test.cc b/sandboxed_api/sandbox2/policybuilder_test.cc index 652a827..ceab9eb 100644 --- a/sandboxed_api/sandbox2/policybuilder_test.cc +++ b/sandboxed_api/sandbox2/policybuilder_test.cc @@ -93,8 +93,8 @@ TEST_F(PolicyBuilderTest, Testpolicy_size) { builder.AllowSyscall(__NR_chroot); assert_increased(); builder.AllowSyscall(__NR_chroot); assert_same(); - builder.AllowSyscall(__NR_mmap); assert_increased(); - builder.AllowSyscall(__NR_mmap); assert_same(); + builder.AllowSyscall(__NR_umask); assert_increased(); + builder.AllowSyscall(__NR_umask); assert_same(); builder.AllowSyscall(__NR_chroot); assert_same(); builder.AllowSyscall(__NR_chroot); assert_same(); @@ -120,8 +120,8 @@ TEST_F(PolicyBuilderTest, Testpolicy_size) { builder.AddPolicyOnSyscalls({ }, { ALLOW }); assert_increased(); // This might change in the future if we implement an optimization. - builder.AddPolicyOnSyscall(__NR_mmap, { ALLOW }); assert_increased(); - builder.AddPolicyOnSyscall(__NR_mmap, { ALLOW }); assert_increased(); + builder.AddPolicyOnSyscall(__NR_umask, { ALLOW }); assert_increased(); + builder.AddPolicyOnSyscall(__NR_umask, { ALLOW }); assert_increased(); // None of the namespace functions should alter the seccomp policy. builder.AddFile("/usr/bin/find"); assert_same(); diff --git a/sandboxed_api/sandbox2/regs.cc b/sandboxed_api/sandbox2/regs.cc index 7a4c214..4fdf8a1 100644 --- a/sandboxed_api/sandbox2/regs.cc +++ b/sandboxed_api/sandbox2/regs.cc @@ -42,7 +42,8 @@ absl::Status Regs::Fetch() { ") failed: ", StrError(errno))); } #endif - if constexpr (host_cpu::IsPPC64LE() || host_cpu::IsArm64()) { + if constexpr (host_cpu::IsPPC64LE() || host_cpu::IsArm64() || + host_cpu::IsArm()) { iovec pt_iov = {&user_regs_, sizeof(user_regs_)}; if (ptrace(PTRACE_GETREGSET, pid_, NT_PRSTATUS, &pt_iov) == -1L) { @@ -85,7 +86,8 @@ absl::Status Regs::Store() { ") failed: ", StrError(errno))); } #endif - if constexpr (host_cpu::IsPPC64LE() || host_cpu::IsArm64()) { + if constexpr (host_cpu::IsPPC64LE() || host_cpu::IsArm64() || + host_cpu::IsArm()) { iovec pt_iov = {&user_regs_, sizeof(user_regs_)}; if (ptrace(PTRACE_SETREGSET, pid_, NT_PRSTATUS, &pt_iov) == -1L) { @@ -108,7 +110,7 @@ absl::Status Regs::Store() { return absl::OkStatus(); } -absl::Status Regs::SkipSyscallReturnValue(uint64_t value) { +absl::Status Regs::SkipSyscallReturnValue(uintptr_t value) { #if defined(SAPI_X86_64) user_regs_.orig_rax = -1; user_regs_.rax = value; @@ -118,6 +120,9 @@ absl::Status Regs::SkipSyscallReturnValue(uint64_t value) { #elif defined(SAPI_ARM64) user_regs_.regs[0] = -1; syscall_number_ = value; +#elif defined(SAPI_ARM) + user_regs_.orig_x0 = -1; + user_regs_.regs[7] = value; #endif return Store(); } @@ -168,6 +173,16 @@ Syscall Regs::ToSyscall(cpu::Architecture syscall_arch) const { auto ip = user_regs_.pc; return Syscall(syscall_arch, syscall_number_, args, pid_, sp, ip); } +#elif defined(SAPI_ARM) + if (ABSL_PREDICT_TRUE(syscall_arch == cpu::kArm)) { + Syscall::Args args = { + user_regs_.orig_x0, user_regs_.regs[1], user_regs_.regs[2], + user_regs_.regs[3], user_regs_.regs[4], user_regs_.regs[5], + }; + auto sp = user_regs_.regs[13]; + auto ip = user_regs_.pc; + return Syscall(syscall_arch, user_regs_.regs[7], args, pid_, sp, ip); + } #endif return Syscall(pid_); } @@ -231,6 +246,14 @@ void Regs::StoreRegisterValuesInProtobuf(RegisterValues* values) const { regs->set_sp(user_regs_.sp); regs->set_pc(user_regs_.pc); regs->set_pstate(user_regs_.pstate); +#elif defined(SAPI_ARM) + RegisterArm* regs = values->mutable_register_arm(); + for (int i = 0; i < ABSL_ARRAYSIZE(user_regs_.regs); ++i) { + regs->add_regs(user_regs_.regs[i]); + } + regs->set_pc(user_regs_.pc); + regs->set_cpsr(user_regs_.cpsr); + regs->set_orig_x0(user_regs_.orig_x0); #endif } diff --git a/sandboxed_api/sandbox2/regs.h b/sandboxed_api/sandbox2/regs.h index cce7022..62cd5b1 100644 --- a/sandboxed_api/sandbox2/regs.h +++ b/sandboxed_api/sandbox2/regs.h @@ -43,7 +43,7 @@ class Regs { absl::Status Store(); // Causes the process to skip current syscall and return given value instead - absl::Status SkipSyscallReturnValue(uint64_t value); + absl::Status SkipSyscallReturnValue(uintptr_t value); // Converts raw register values obtained on syscall entry to syscall info Syscall ToSyscall(cpu::Architecture syscall_arch) const; @@ -110,6 +110,11 @@ class Regs { uint64_t sp; uint64_t pc; uint64_t pstate; +#elif defined(SAPI_ARM) + uint32_t regs[15]; + uint32_t pc; + uint32_t cpsr; + uint32_t orig_x0; #else static_assert(false, "Host CPU architecture not supported, see config.h"); #endif diff --git a/sandboxed_api/sandbox2/stack_trace.cc b/sandboxed_api/sandbox2/stack_trace.cc index ef494b1..80cb673 100644 --- a/sandboxed_api/sandbox2/stack_trace.cc +++ b/sandboxed_api/sandbox2/stack_trace.cc @@ -85,6 +85,9 @@ std::unique_ptr StackTracePeer::GetPolicy(pid_t target_pid, // libunwind .AllowSyscall(__NR_fstat) +#ifdef __NR_fstat64 + .AllowSyscall(__NR_fstat64) +#endif .AllowSyscall(__NR_lseek) #ifdef __NR__llseek .AllowSyscall(__NR__llseek) // Newer glibc on PPC diff --git a/sandboxed_api/sandbox2/syscall.cc b/sandboxed_api/sandbox2/syscall.cc index 980320a..4fb2505 100644 --- a/sandboxed_api/sandbox2/syscall.cc +++ b/sandboxed_api/sandbox2/syscall.cc @@ -44,6 +44,8 @@ std::string Syscall::GetArchDescription(cpu::Architecture arch) { return "[PPC-64]"; case cpu::kArm64: return "[Arm-64]"; + case cpu::kArm: + return "[Arm-32]"; default: LOG(ERROR) << "Unknown CPU architecture: " << arch; return absl::StrFormat("[UNKNOWN_ARCH:%d]", arch); @@ -58,6 +60,8 @@ uint32_t Syscall::GetHostAuditArch() { return AUDIT_ARCH_PPC64LE; case cpu::kArm64: return AUDIT_ARCH_AARCH64; + case cpu::kArm: + return AUDIT_ARCH_ARM; default: // The static_assert() in config.h should prevent us from ever getting // here. diff --git a/sandboxed_api/sandbox2/syscall_defs.cc b/sandboxed_api/sandbox2/syscall_defs.cc index cf7c137..aff3ea1 100644 --- a/sandboxed_api/sandbox2/syscall_defs.cc +++ b/sandboxed_api/sandbox2/syscall_defs.cc @@ -1524,6 +1524,368 @@ constexpr std::array kSyscallDataArm64 = { static_assert(IsSorted(kSyscallDataArm64, SyscallTable::Entry::BySyscallNr), "Syscalls should be sorted"); +constexpr std::array kSyscallDataArm32 = { + // clang-format off + MakeEntry(0, "restart_syscall", kGen, kGen, kGen, kGen), + MakeEntry(1, "exit", kHex, kHex, kHex, kHex), + MakeEntry(2, "fork", kGen, kGen, kGen, kGen), + MakeEntry(3, "read", kInt, kHex, kInt), + MakeEntry(4, "write", kHex, kHex, kHex, kHex), + MakeEntry(5, "open", kPath, kHex, kOct), + MakeEntry(6, "close", kHex, kHex, kHex, kHex), + MakeEntry(8, "creat", kPath, kHex, kHex, kHex), + MakeEntry(9, "link", kPath, kPath), + MakeEntry(10, "unlink", kPath), + MakeEntry(11, "execve", kPath, kHex, kHex), + MakeEntry(12, "chdir", kPath), + MakeEntry(14, "mknod", kPath, kOct, kHex), + MakeEntry(15, "chmod", kPath, kOct), + MakeEntry(16, "lchown", kPath, kInt, kInt), + MakeEntry(19, "lseek", kGen, kGen, kGen, kGen), + MakeEntry(20, "getpid", kGen, kGen, kGen, kGen), + MakeEntry(21, "mount", kHex, kHex, kHex, kHex), + MakeEntry(23, "setuid", kGen, kGen, kGen, kGen), + MakeEntry(24, "getuid", kGen, kGen, kGen, kGen), + MakeEntry(26, "ptrace", kGen, kGen, kGen), + MakeEntry(29, "pause", kGen, kGen, kGen, kGen), + MakeEntry(33, "access", kPath, kHex), + MakeEntry(34, "nice", kHex, kHex, kHex, kHex), + MakeEntry(36, "sync", kGen, kGen, kGen, kGen), + MakeEntry(37, "kill", kHex, kHex, kHex, kHex), + MakeEntry(38, "rename", kPath, kPath), + MakeEntry(39, "mkdir", kPath, kHex, kHex, kHex), + MakeEntry(40, "rmdir", kHex, kHex, kHex, kHex), + MakeEntry(41, "dup", kGen, kGen, kGen, kGen), + MakeEntry(42, "pipe", kGen, kGen, kGen, kGen), + MakeEntry(43, "times", kGen, kGen, kGen, kGen), + MakeEntry(45, "brk", kHex), + MakeEntry(46, "setgid", kGen, kGen, kGen, kGen), + MakeEntry(47, "getgid", kGen, kGen, kGen, kGen), + MakeEntry(49, "geteuid", kGen, kGen, kGen, kGen), + MakeEntry(50, "getegid", kGen, kGen, kGen, kGen), + MakeEntry(51, "acct", kHex, kHex, kHex, kHex), + MakeEntry(52, "umount2", kHex, kHex, kHex, kHex), + MakeEntry(54, "ioctl", kGen, kGen, kGen, kGen), + MakeEntry(55, "fcntl", kGen, kGen, kGen, kGen), + MakeEntry(57, "setpgid", kGen, kGen, kGen, kGen), + MakeEntry(60, "umask", kHex), + MakeEntry(61, "chroot", kHex, kHex, kHex, kHex), + MakeEntry(62, "ustat", kGen, kGen, kGen, kGen), + MakeEntry(63, "dup2", kGen, kGen), + MakeEntry(64, "getppid", kGen, kGen, kGen, kGen), + MakeEntry(65, "getpgrp", kGen, kGen, kGen, kGen), + MakeEntry(66, "setsid", kGen, kGen, kGen, kGen), + MakeEntry(67, "sigaction", kHex, kHex, kHex, kHex), + MakeEntry(70, "setreuid", kGen, kGen, kGen, kGen), + MakeEntry(71, "setregid", kGen, kGen, kGen, kGen), + MakeEntry(72, "sigsuspend", kHex, kHex, kHex, kHex), + MakeEntry(73, "sigpending", kHex, kHex, kHex, kHex), + MakeEntry(74, "sethostname", kGen, kGen, kGen, kGen), + MakeEntry(75, "setrlimit", kGen, kGen, kGen, kGen), + MakeEntry(77, "getrusage", kGen, kGen, kGen, kGen), + MakeEntry(78, "gettimeofday", kHex, kHex), + MakeEntry(79, "settimeofday", kHex, kHex), + MakeEntry(80, "getgroups", kGen, kGen, kGen, kGen), + MakeEntry(81, "setgroups", kGen, kGen, kGen, kGen), + MakeEntry(83, "symlink", kPath, kPath), + MakeEntry(85, "readlink", kPath, kGen, kInt), + MakeEntry(86, "uselib", kPath), + MakeEntry(87, "swapon", kHex, kHex, kHex, kHex), + MakeEntry(88, "reboot", kGen, kGen, kGen, kGen), + MakeEntry(91, "munmap", kHex, kHex), + MakeEntry(92, "truncate", kPath, kHex, kHex, kHex), + MakeEntry(93, "ftruncate", kGen, kGen, kGen, kGen), + MakeEntry(94, "fchmod", kGen, kGen, kGen, kGen), + MakeEntry(95, "fchown", kGen, kGen, kGen, kGen), + MakeEntry(96, "getpriority", kGen, kGen, kGen, kGen), + MakeEntry(97, "setpriority", kGen, kGen, kGen, kGen), + MakeEntry(99, "statfs", kPath, kGen, kGen, kGen), + MakeEntry(100, "fstatfs", kGen, kGen, kGen, kGen), + MakeEntry(103, "syslog", kGen, kGen, kGen, kGen), + MakeEntry(104, "setitimer", kGen, kGen, kGen, kGen), + MakeEntry(105, "getitimer", kGen, kGen, kGen, kGen), + MakeEntry(106, "stat", kPath, kGen), + MakeEntry(107, "lstat", kPath, kGen), + MakeEntry(108, "fstat", kHex, kHex, kHex, kHex), + MakeEntry(111, "vhangup", kGen, kGen, kGen, kGen), + MakeEntry(114, "wait4", kHex, kHex, kHex, kHex), + MakeEntry(115, "swapoff", kHex, kHex, kHex, kHex), + MakeEntry(116, "sysinfo", kGen, kGen, kGen, kGen), + MakeEntry(118, "fsync", kGen, kGen, kGen, kGen), + MakeEntry(119, "sigreturn", kHex, kHex, kHex, kHex), + MakeEntry(120, "clone", kCloneFlag, kHex, kHex, kHex), + MakeEntry(121, "setdomainname", kGen, kGen, kGen, kGen), + MakeEntry(122, "uname", kGen, kGen, kGen, kGen), + MakeEntry(124, "adjtimex", kGen, kGen, kGen, kGen), + MakeEntry(125, "mprotect", kHex, kHex, kHex), + MakeEntry(126, "sigprocmask", kHex, kHex, kHex, kHex), + MakeEntry(128, "init_module", kGen, kGen, kGen, kGen), + MakeEntry(129, "delete_module", kGen, kGen, kGen, kGen), + MakeEntry(131, "quotactl", kHex, kHex, kHex, kHex), + MakeEntry(132, "getpgid", kGen, kGen, kGen, kGen), + MakeEntry(133, "fchdir", kGen, kGen, kGen, kGen), + MakeEntry(134, "bdflush", kHex, kHex, kHex, kHex), + MakeEntry(135, "sysfs", kGen, kGen, kGen, kGen), + MakeEntry(136, "personality", kGen, kGen, kGen, kGen), + MakeEntry(138, "setfsuid", kGen, kGen, kGen, kGen), + MakeEntry(139, "setfsgid", kGen, kGen, kGen, kGen), + MakeEntry(140, "_llseek", kHex, kHex, kHex, kHex), + MakeEntry(141, "getdents", kGen, kGen, kGen, kGen), + MakeEntry(142, "_newselect", kHex, kHex, kHex, kHex), + MakeEntry(143, "flock", kGen, kGen, kGen, kGen), + MakeEntry(144, "msync", kGen, kGen, kGen, kGen), + MakeEntry(145, "readv", kGen, kGen, kGen, kGen), + MakeEntry(146, "writev", kGen, kGen, kGen, kGen), + MakeEntry(147, "getsid", kGen, kGen, kGen, kGen), + MakeEntry(148, "fdatasync", kGen, kGen, kGen, kGen), + MakeEntry(149, "_sysctl", kGen, kGen, kGen, kGen), + MakeEntry(150, "mlock", kGen, kGen, kGen, kGen), + MakeEntry(151, "munlock", kGen, kGen, kGen, kGen), + MakeEntry(152, "mlockall", kGen, kGen, kGen, kGen), + MakeEntry(153, "munlockall", kGen, kGen, kGen, kGen), + MakeEntry(154, "sched_setparam", kGen, kGen, kGen, kGen), + MakeEntry(155, "sched_getparam", kGen, kGen, kGen, kGen), + MakeEntry(156, "sched_setscheduler", kGen, kGen, kGen, kGen), + MakeEntry(157, "sched_getscheduler", kGen, kGen, kGen, kGen), + MakeEntry(158, "sched_yield", kGen, kGen, kGen, kGen), + MakeEntry(159, "sched_get_priority_max", kGen, kGen, kGen, kGen), + MakeEntry(160, "sched_get_priority_min", kGen, kGen, kGen, kGen), + MakeEntry(161, "sched_rr_get_interval", kGen, kGen, kGen, kGen), + MakeEntry(162, "nanosleep", kHex, kHex), + MakeEntry(163, "mremap", kGen, kGen, kGen, kGen), + MakeEntry(164, "setresuid", kGen, kGen, kGen, kGen), + MakeEntry(165, "getresuid", kGen, kGen, kGen, kGen), + MakeEntry(168, "poll", kGen, kGen, kGen, kGen), + MakeEntry(169, "nfsservctl", kGen, kGen, kGen, kGen), + MakeEntry(170, "setresgid", kGen, kGen, kGen, kGen), + MakeEntry(171, "getresgid", kGen, kGen, kGen, kGen), + MakeEntry(172, "prctl", kHex, kHex, kHex, kHex), + MakeEntry(173, "rt_sigreturn", kGen, kGen, kGen, kGen), + MakeEntry(174, "rt_sigaction", kHex, kHex, kHex, kHex), + MakeEntry(175, "rt_sigprocmask", kGen, kGen, kGen, kGen), + MakeEntry(176, "rt_sigpending", kGen, kGen, kGen, kGen), + MakeEntry(177, "rt_sigtimedwait", kGen, kGen, kGen, kGen), + MakeEntry(178, "rt_sigqueueinfo", kGen, kGen, kGen, kGen), + MakeEntry(179, "rt_sigsuspend", kGen, kGen, kGen, kGen), + MakeEntry(180, "pread64", kGen, kGen, kGen, kGen), + MakeEntry(181, "pwrite64", kGen, kGen, kGen, kGen), + MakeEntry(182, "chown", kHex, kHex, kHex, kHex), + MakeEntry(183, "getcwd", kGen, kGen, kGen, kGen), + MakeEntry(184, "capget", kGen, kGen, kGen, kGen), + MakeEntry(185, "capset", kGen, kGen, kGen, kGen), + MakeEntry(186, "sigaltstack", kGen, kGen, kGen, kGen), + MakeEntry(187, "sendfile", kGen, kGen, kGen, kGen), + MakeEntry(190, "vfork", kGen, kGen, kGen, kGen), + MakeEntry(191, "ugetrlimit", kHex, kHex, kHex, kHex), + MakeEntry(192, "mmap2", kHex, kHex, kHex, kHex), + MakeEntry(193, "truncate64", kHex, kHex, kHex, kHex), + MakeEntry(194, "ftruncate64", kHex, kHex, kHex, kHex), + MakeEntry(195, "stat64", kHex, kHex, kHex, kHex), + MakeEntry(196, "lstat64", kHex, kHex, kHex, kHex), + MakeEntry(197, "fstat64", kHex, kHex, kHex, kHex), + MakeEntry(198, "lchown32", kHex, kHex, kHex, kHex), + MakeEntry(199, "getuid32", kHex, kHex, kHex, kHex), + MakeEntry(200, "getgid32", kHex, kHex, kHex, kHex), + MakeEntry(201, "geteuid32", kHex, kHex, kHex, kHex), + MakeEntry(202, "getegid32", kHex, kHex, kHex, kHex), + MakeEntry(203, "setreuid32", kHex, kHex, kHex, kHex), + MakeEntry(204, "setregid32", kHex, kHex, kHex, kHex), + MakeEntry(205, "getgroups32", kHex, kHex, kHex, kHex), + MakeEntry(206, "setgroups32", kHex, kHex, kHex, kHex), + MakeEntry(207, "fchown32", kHex, kHex, kHex, kHex), + MakeEntry(208, "setresuid32", kHex, kHex, kHex, kHex), + MakeEntry(209, "getresuid32", kHex, kHex, kHex, kHex), + MakeEntry(210, "setresgid32", kHex, kHex, kHex, kHex), + MakeEntry(211, "getresgid32", kHex, kHex, kHex, kHex), + MakeEntry(212, "chown32", kHex, kHex, kHex, kHex), + MakeEntry(213, "setuid32", kHex, kHex, kHex, kHex), + MakeEntry(214, "setgid32", kHex, kHex, kHex, kHex), + MakeEntry(215, "setfsuid32", kHex, kHex, kHex, kHex), + MakeEntry(216, "setfsgid32", kHex, kHex, kHex, kHex), + MakeEntry(217, "getdents64", kGen, kGen, kGen, kGen), + MakeEntry(218, "pivot_root", kHex, kHex, kHex, kHex), + MakeEntry(219, "mincore", kGen, kGen, kGen, kGen), + MakeEntry(220, "madvise", kGen, kGen, kGen, kGen), + MakeEntry(221, "fcntl64", kHex, kHex, kHex, kHex), + MakeEntry(224, "gettid", kGen, kGen, kGen, kGen), + MakeEntry(225, "readahead", kGen, kGen, kGen, kGen), + MakeEntry(226, "setxattr", kHex, kHex, kHex, kHex), + MakeEntry(227, "lsetxattr", kHex, kHex, kHex, kHex), + MakeEntry(228, "fsetxattr", kGen, kGen, kGen, kGen), + MakeEntry(229, "getxattr", kHex, kHex, kHex, kHex), + MakeEntry(230, "lgetxattr", kHex, kHex, kHex, kHex), + MakeEntry(231, "fgetxattr", kGen, kGen, kGen, kGen), + MakeEntry(232, "listxattr", kHex, kHex, kHex, kHex), + MakeEntry(233, "llistxattr", kHex, kHex, kHex, kHex), + MakeEntry(234, "flistxattr", kGen, kGen, kGen, kGen), + MakeEntry(235, "removexattr", kHex, kHex, kHex, kHex), + MakeEntry(236, "lremovexattr", kGen, kGen, kGen, kGen), + MakeEntry(237, "fremovexattr", kGen, kGen, kGen, kGen), + MakeEntry(238, "tkill", kHex, kHex, kHex, kHex), + MakeEntry(239, "sendfile64", kHex, kHex, kHex, kHex), + MakeEntry(240, "futex", kGen, kGen, kGen, kGen), + MakeEntry(241, "sched_setaffinity", kGen, kGen, kGen, kGen), + MakeEntry(242, "sched_getaffinity", kGen, kGen, kGen, kGen), + MakeEntry(243, "io_setup", kGen, kGen, kGen, kGen), + MakeEntry(244, "io_destroy", kGen, kGen, kGen, kGen), + MakeEntry(245, "io_getevents", kGen, kGen, kGen, kGen), + MakeEntry(246, "io_submit", kGen, kGen, kGen, kGen), + MakeEntry(247, "io_cancel", kGen, kGen, kGen, kGen), + MakeEntry(248, "exit_group", kHex, kHex, kHex, kHex), + MakeEntry(249, "lookup_dcookie", kGen, kGen, kGen, kGen), + MakeEntry(250, "epoll_create", kGen, kGen, kGen, kGen), + MakeEntry(251, "epoll_ctl", kGen, kGen, kGen, kGen), + MakeEntry(252, "epoll_wait", kGen, kGen, kGen, kGen), + MakeEntry(253, "remap_file_pages", kGen, kGen, kGen, kGen), + MakeEntry(256, "set_tid_address", kHex), + MakeEntry(257, "timer_create", kGen, kGen, kGen, kGen), + MakeEntry(258, "timer_settime", kGen, kGen, kGen, kGen), + MakeEntry(259, "timer_gettime", kGen, kGen, kGen, kGen), + MakeEntry(260, "timer_getoverrun", kGen, kGen, kGen, kGen), + MakeEntry(261, "timer_delete", kGen, kGen, kGen, kGen), + MakeEntry(262, "clock_settime", kGen, kGen, kGen, kGen), + MakeEntry(263, "clock_gettime", kGen, kGen, kGen, kGen), + MakeEntry(264, "clock_getres", kGen, kGen, kGen, kGen), + MakeEntry(265, "clock_nanosleep", kGen, kGen, kGen, kGen), + MakeEntry(266, "statfs64", kHex, kHex, kHex, kHex), + MakeEntry(267, "fstatfs64", kHex, kHex, kHex, kHex), + MakeEntry(268, "tgkill", kHex, kHex, kHex, kHex), + MakeEntry(269, "utimes", kGen, kGen, kGen, kGen), + MakeEntry(271, "pciconfig_iobase", kHex, kHex, kHex, kHex), + MakeEntry(272, "pciconfig_read", kHex, kHex, kHex, kHex), + MakeEntry(273, "pciconfig_write", kHex, kHex, kHex, kHex), + MakeEntry(274, "mq_open", kGen, kGen, kGen, kGen), + MakeEntry(275, "mq_unlink", kGen, kGen, kGen, kGen), + MakeEntry(276, "mq_timedsend", kGen, kGen, kGen, kGen), + MakeEntry(277, "mq_timedreceive", kGen, kGen, kGen, kGen), + MakeEntry(278, "mq_notify", kGen, kGen, kGen, kGen), + MakeEntry(279, "mq_getsetattr", kGen, kGen, kGen, kGen), + MakeEntry(280, "waitid", kGen, kGen, kGen, kGen), + MakeEntry(281, "socket", kAddressFamily, kInt, kInt), + MakeEntry(282, "bind", kGen, kGen, kGen, kGen), + MakeEntry(283, "connect", kInt, kSockaddr, kInt), + MakeEntry(284, "listen", kGen, kGen, kGen, kGen), + MakeEntry(285, "accept", kGen, kGen, kGen, kGen), + MakeEntry(286, "getsockname", kGen, kGen, kGen, kGen), + MakeEntry(287, "getpeername", kGen, kGen, kGen, kGen), + MakeEntry(288, "socketpair", kGen, kGen, kGen, kGen), + MakeEntry(289, "send", kHex, kHex, kHex, kHex), + MakeEntry(290, "sendto", kInt, kGen, kInt, kHex), + MakeEntry(291, "recv", kHex, kHex, kHex, kHex), + MakeEntry(292, "recvfrom", kGen, kGen, kGen, kGen), + MakeEntry(293, "shutdown", kGen, kGen, kGen, kGen), + MakeEntry(294, "setsockopt", kGen, kGen, kGen, kGen), + MakeEntry(295, "getsockopt", kGen, kGen, kGen, kGen), + MakeEntry(296, "sendmsg", kInt, kSockmsghdr, kHex), + MakeEntry(297, "recvmsg", kGen, kGen, kGen, kGen), + MakeEntry(298, "semop", UnknownArguments()), + MakeEntry(299, "semget", UnknownArguments()), + MakeEntry(300, "semctl", UnknownArguments()), + MakeEntry(301, "msgsnd", UnknownArguments()), + MakeEntry(302, "msgrcv", UnknownArguments()), + MakeEntry(303, "msgget", UnknownArguments()), + MakeEntry(304, "msgctl", UnknownArguments()), + MakeEntry(305, "shmat", UnknownArguments()), + MakeEntry(306, "shmdt", UnknownArguments()), + MakeEntry(307, "shmget", UnknownArguments()), + MakeEntry(308, "shmctl", UnknownArguments()), + MakeEntry(309, "add_key", kGen, kGen, kGen, kGen), + MakeEntry(310, "request_key", kGen, kGen, kGen, kGen), + MakeEntry(311, "keyctl", kGen, kGen, kGen, kGen), + MakeEntry(312, "semtimedop", UnknownArguments()), + MakeEntry(313, "vserver", kHex, kHex, kHex, kHex), + MakeEntry(314, "ioprio_set", kGen, kGen, kGen, kGen), + MakeEntry(315, "ioprio_get", kGen, kGen, kGen, kGen), + MakeEntry(316, "inotify_init", kGen, kGen, kGen, kGen), + MakeEntry(317, "inotify_add_watch", kGen, kGen, kGen, kGen), + MakeEntry(318, "inotify_rm_watch", kGen, kGen, kGen, kGen), + MakeEntry(319, "mbind", kGen, kGen, kGen, kGen), + MakeEntry(320, "get_mempolicy", kGen, kGen, kGen, kGen), + MakeEntry(321, "set_mempolicy", kGen, kGen, kGen, kGen), + MakeEntry(322, "openat", kGen, kPath, kOct, kHex), + MakeEntry(323, "mkdirat", kGen, kPath), + MakeEntry(324, "mknodat", kGen, kPath), + MakeEntry(325, "fchownat", kGen, kPath), + MakeEntry(326, "futimesat", kGen, kPath), + MakeEntry(327, "fstatat64", kHex, kHex, kHex, kHex), + MakeEntry(328, "unlinkat", kGen, kPath), + MakeEntry(329, "renameat", kGen, kPath, kGen, kPath), + MakeEntry(330, "linkat", kGen, kPath, kGen, kPath), + MakeEntry(331, "symlinkat", kPath, kGen, kPath), + MakeEntry(332, "readlinkat", kGen, kPath), + MakeEntry(333, "fchmodat", kGen, kPath), + MakeEntry(334, "faccessat", kGen, kPath), + MakeEntry(335, "pselect6", kGen, kGen, kGen, kGen), + MakeEntry(336, "ppoll", kGen, kGen, kGen, kGen), + MakeEntry(337, "unshare", kGen, kGen, kGen, kGen), + MakeEntry(338, "set_robust_list", kGen, kGen), + MakeEntry(339, "get_robust_list", kGen, kGen, kGen, kGen), + MakeEntry(340, "splice", kGen, kGen, kGen, kGen), + MakeEntry(342, "tee", kGen, kGen, kGen, kGen), + MakeEntry(343, "vmsplice", kGen, kGen, kGen, kGen), + MakeEntry(344, "move_pages", kGen, kGen, kGen, kGen), + MakeEntry(345, "getcpu", kHex, kHex, kHex), + MakeEntry(346, "epoll_pwait", kGen, kGen, kGen, kGen), + MakeEntry(347, "kexec_load", kGen, kGen, kGen, kGen), + MakeEntry(348, "utimensat", kGen, kGen, kGen, kGen), + MakeEntry(349, "signalfd", kGen, kGen, kGen, kGen), + MakeEntry(350, "timerfd_create", kGen, kGen, kGen, kGen), + MakeEntry(351, "eventfd", kGen, kGen, kGen, kGen), + MakeEntry(352, "fallocate", kGen, kGen, kGen, kGen), + MakeEntry(353, "timerfd_settime", kGen, kGen, kGen, kGen), + MakeEntry(354, "timerfd_gettime", kGen, kGen, kGen, kGen), + MakeEntry(355, "signalfd4", kGen, kGen, kGen, kGen), + MakeEntry(356, "eventfd2", kGen, kGen, kGen, kGen), + MakeEntry(357, "epoll_create1", kGen, kGen, kGen, kGen), + MakeEntry(358, "dup3", kGen, kGen, kGen), + MakeEntry(359, "pipe2", kGen, kGen, kGen, kGen), + MakeEntry(360, "inotify_init1", kGen, kGen, kGen, kGen), + MakeEntry(361, "preadv", kGen, kGen, kGen, kGen), + MakeEntry(362, "pwritev", kGen, kGen, kGen, kGen), + MakeEntry(363, "rt_tgsigqueueinfo", kGen, kGen, kGen, kGen), + MakeEntry(364, "perf_event_open", kGen, kGen, kGen, kGen), + MakeEntry(365, "recvmmsg", kHex, kHex, kHex, kHex), + MakeEntry(366, "accept4", kGen, kGen, kGen, kGen), + MakeEntry(367, "fanotify_init", kHex, kHex, kHex, kHex), + MakeEntry(368, "fanotify_mark", kHex, kHex, kHex, kHex), + MakeEntry(369, "prlimit64", kHex, kHex, kHex, kHex), + MakeEntry(370, "name_to_handle_at", kHex, kHex, kHex, kHex), + MakeEntry(371, "open_by_handle_at", kHex, kHex, kHex, kHex), + MakeEntry(372, "clock_adjtime", kHex, kHex, kHex, kHex), + MakeEntry(373, "syncfs", kHex, kHex, kHex, kHex), + MakeEntry(374, "sendmmsg", kHex, kHex, kHex, kHex), + MakeEntry(375, "setns", kHex, kHex, kHex, kHex), + MakeEntry(376, "process_vm_readv", kHex, kHex, kHex, kHex), + MakeEntry(377, "process_vm_writev", kHex, kHex, kHex, kHex), + MakeEntry(378, "kcmp", kHex, kHex, kHex, kHex), + MakeEntry(379, "finit_module", kHex, kHex, kHex, kHex), + MakeEntry(380, "sched_setattr", kGen, kGen, kGen, kGen), + MakeEntry(381, "sched_getattr", kGen, kGen, kGen, kGen), + MakeEntry(382, "renameat2", kGen, kPath, kGen, kPath), + MakeEntry(383, "seccomp", kGen, kGen, kGen, kGen), + MakeEntry(384, "getrandom", kGen, kGen, kGen, kGen), + MakeEntry(385, "memfd_create", kGen, kGen, kGen, kGen), + MakeEntry(386, "bpf", kHex, kHex, kHex, kHex), + MakeEntry(387, "execveat", kHex, kHex, kHex, kHex), + MakeEntry(388, "userfaultfd", kHex), + MakeEntry(389, "membarrier", kHex, kHex), + MakeEntry(390, "mlock2", kHex, kHex, kHex, kHex), + MakeEntry(391, "copy_file_range", kHex, kHex, kHex, kHex), + MakeEntry(392, "preadv2", kHex, kHex, kHex, kHex), + MakeEntry(393, "pwritev2", kHex, kHex, kHex, kHex), + MakeEntry(400, "migrate_pages", kGen, kGen, kGen, kGen), + MakeEntry(401, "kexec_file_load", kGen, kGen, kGen, kGen), + MakeEntry(0xf0001, "ARM_breakpoint", kHex, kHex, kHex, kHex), + MakeEntry(0xf0002, "ARM_cacheflush", kHex, kHex, kHex, kHex), + MakeEntry(0xf0003, "ARM_usr26", kHex, kHex, kHex, kHex), + MakeEntry(0xf0004, "ARM_usr32", kHex, kHex, kHex, kHex), + MakeEntry(0xf0005, "ARM_set_tls", kHex, kHex, kHex, kHex), + // clang-format on +}; + +static_assert(IsSorted(kSyscallDataArm32, SyscallTable::Entry::BySyscallNr), + "Syscalls should be sorted"); + } // namespace SyscallTable SyscallTable::get(cpu::Architecture arch) { @@ -1536,6 +1898,8 @@ SyscallTable SyscallTable::get(cpu::Architecture arch) { return SyscallTable(kSyscallDataPPC64LE); case cpu::kArm64: return SyscallTable(kSyscallDataArm64); + case cpu::kArm: + return SyscallTable(kSyscallDataArm32); default: return SyscallTable(); } diff --git a/sandboxed_api/sandbox2/testcases/personality.cc b/sandboxed_api/sandbox2/testcases/personality.cc index ecca2f0..36e9d7c 100644 --- a/sandboxed_api/sandbox2/testcases/personality.cc +++ b/sandboxed_api/sandbox2/testcases/personality.cc @@ -18,7 +18,10 @@ #include #include +#include + int main(int argc, char** argv) { - syscall(__NR_personality, 1ULL, 2ULL, 3ULL, 4ULL, 5ULL, 6ULL); + syscall(__NR_personality, uintptr_t{1}, uintptr_t{2}, uintptr_t{3}, + uintptr_t{4}, uintptr_t{5}, uintptr_t{6}); return 22; } diff --git a/sandboxed_api/sandbox2/util.cc b/sandboxed_api/sandbox2/util.cc index 9521d92..5226166 100644 --- a/sandboxed_api/sandbox2/util.cc +++ b/sandboxed_api/sandbox2/util.cc @@ -127,9 +127,9 @@ ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS ABSL_ATTRIBUTE_NOINLINE pid_t CloneAndJump(int flags, jmp_buf* env_ptr) { uint8_t stack_buf[PTHREAD_STACK_MIN] ABSL_CACHELINE_ALIGNED; - static_assert( - host_cpu::IsX8664() || host_cpu::IsPPC64LE() || host_cpu::IsArm64(), - "Host CPU architecture not supported, see config.h"); + static_assert(host_cpu::IsX8664() || host_cpu::IsPPC64LE() || + host_cpu::IsArm64() || host_cpu::IsArm(), + "Host CPU architecture not supported, see config.h"); // Stack grows down. void* stack = stack_buf + sizeof(stack_buf); int r; diff --git a/sandboxed_api/sandbox2/util/BUILD.bazel b/sandboxed_api/sandbox2/util/BUILD.bazel index 72cbad0..ada671f 100644 --- a/sandboxed_api/sandbox2/util/BUILD.bazel +++ b/sandboxed_api/sandbox2/util/BUILD.bazel @@ -137,6 +137,7 @@ cc_library( copts = sapi_platform_copts(), deps = [ ":strerror", + "//sandboxed_api/sandbox2:config", "//sandboxed_api/sandbox2:util", "//sandboxed_api/util:raw_logging", "//sandboxed_api/util:status", diff --git a/sandboxed_api/sandbox2/util/minielf.cc b/sandboxed_api/sandbox2/util/minielf.cc index 06ad483..68a8fa5 100644 --- a/sandboxed_api/sandbox2/util/minielf.cc +++ b/sandboxed_api/sandbox2/util/minielf.cc @@ -24,6 +24,7 @@ #include "absl/status/statusor.h" #include "absl/strings/match.h" #include "absl/strings/str_cat.h" +#include "sandboxed_api/sandbox2/config.h" #include "sandboxed_api/sandbox2/util.h" #include "sandboxed_api/sandbox2/util/strerror.h" #include "sandboxed_api/util/raw_logging.h" @@ -31,15 +32,20 @@ namespace sandbox2 { -constexpr int kElfHeaderSize = - sizeof(Elf64_Ehdr); // Maximum size for 64-bit binaries +using ElfEhdr = std::conditional_t; +using ElfShdr = std::conditional_t; +using ElfPhdr = std::conditional_t; +using ElfDyn = std::conditional_t; +using ElfSym = std::conditional_t; + +constexpr int kElfHeaderSize = sizeof(ElfEhdr); // Maximum size for binaries constexpr char kElfMagic[] = "\x7F" "ELF"; constexpr int kEiClassOffset = 0x04; -constexpr int kEiClass64 = 2; // 64-bit binary +constexpr int kEiClass = host_cpu::Is64Bit() ? ELFCLASS64 : ELFCLASS32; constexpr int kEiDataOffset = 0x05; constexpr int kEiDataLittle = 1; // Little Endian @@ -134,29 +140,29 @@ class ElfParser { // Reads elf header. absl::Status ReadFileHeader(); // Reads a single elf program header. - absl::StatusOr ReadProgramHeader(absl::string_view src); + absl::StatusOr ReadProgramHeader(absl::string_view src); // Reads all elf program headers. absl::Status ReadProgramHeaders(); // Reads a single elf section header. - absl::StatusOr ReadSectionHeader(absl::string_view src); + absl::StatusOr ReadSectionHeader(absl::string_view src); // Reads all elf section headers. absl::Status ReadSectionHeaders(); // Reads contents of an elf section. absl::StatusOr ReadSectionContents(int idx); absl::StatusOr ReadSectionContents( - const Elf64_Shdr& section_header); + const ElfShdr& section_header); // Reads all symbols from symtab section. - absl::Status ReadSymbolsFromSymtab(const Elf64_Shdr& symtab); + absl::Status ReadSymbolsFromSymtab(const ElfShdr& symtab); // Reads all imported libraries from dynamic section. - absl::Status ReadImportedLibrariesFromDynamic(const Elf64_Shdr& dynamic); + absl::Status ReadImportedLibrariesFromDynamic(const ElfShdr& dynamic); ElfFile result_; FILE* elf_ = nullptr; size_t file_size_ = 0; bool elf_little_ = false; - Elf64_Ehdr file_header_; - std::vector program_headers_; - std::vector section_headers_; + ElfEhdr file_header_; + std::vector program_headers_; + std::vector section_headers_; int symbol_entries_read = 0; int dynamic_entries_read = 0; @@ -191,7 +197,7 @@ absl::Status ElfParser::ReadFileHeader() { return absl::FailedPreconditionError("magic not found, not an ELF"); } - if (header[kEiClassOffset] != kEiClass64) { + if (header[kEiClassOffset] != kEiClass) { return absl::FailedPreconditionError("invalid ELF class"); } const auto elf_data = header[kEiDataOffset]; @@ -220,13 +226,13 @@ absl::Status ElfParser::ReadFileHeader() { return absl::OkStatus(); } -absl::StatusOr ElfParser::ReadSectionHeader(absl::string_view src) { - if (src.size() < sizeof(Elf64_Shdr)) { +absl::StatusOr ElfParser::ReadSectionHeader(absl::string_view src) { + if (src.size() < sizeof(ElfShdr)) { return absl::FailedPreconditionError( absl::StrCat("invalid section header data: got ", src.size(), - " bytes, ", sizeof(Elf64_Shdr), " bytes expected.")); + " bytes, ", sizeof(ElfShdr), " bytes expected.")); } - Elf64_Shdr rv; + ElfShdr rv; LOAD_MEMBER(rv, sh_name, src.data()); LOAD_MEMBER(rv, sh_type, src.data()); LOAD_MEMBER(rv, sh_flags, src.data()); @@ -245,10 +251,10 @@ absl::Status ElfParser::ReadSectionHeaders() { return absl::FailedPreconditionError( absl::StrCat("invalid section header offset: ", file_header_.e_shoff)); } - if (file_header_.e_shentsize != sizeof(Elf64_Shdr)) { + if (file_header_.e_shentsize != sizeof(ElfShdr)) { return absl::FailedPreconditionError(absl::StrCat( "section header entry size incorrect: ", file_header_.e_shentsize, - " bytes, ", sizeof(Elf64_Shdr), " expected.")); + " bytes, ", sizeof(ElfShdr), " expected.")); } if (file_header_.e_shnum > kMaxSectionHeaderEntries) { return absl::FailedPreconditionError( @@ -276,7 +282,7 @@ absl::StatusOr ElfParser::ReadSectionContents(int idx) { } absl::StatusOr ElfParser::ReadSectionContents( - const Elf64_Shdr& section_header) { + const ElfShdr& section_header) { auto offset = section_header.sh_offset; if (offset > file_size_) { return absl::FailedPreconditionError( @@ -293,13 +299,13 @@ absl::StatusOr ElfParser::ReadSectionContents( return rv; } -absl::StatusOr ElfParser::ReadProgramHeader(absl::string_view src) { - if (src.size() < sizeof(Elf64_Phdr)) { +absl::StatusOr ElfParser::ReadProgramHeader(absl::string_view src) { + if (src.size() < sizeof(ElfPhdr)) { return absl::FailedPreconditionError( absl::StrCat("invalid program header data: got ", src.size(), - " bytes, ", sizeof(Elf64_Phdr), " bytes expected.")); + " bytes, ", sizeof(ElfPhdr), " bytes expected.")); } - Elf64_Phdr rv; + ElfPhdr rv; LOAD_MEMBER(rv, p_type, src.data()); LOAD_MEMBER(rv, p_flags, src.data()); LOAD_MEMBER(rv, p_offset, src.data()); @@ -316,10 +322,10 @@ absl::Status ElfParser::ReadProgramHeaders() { return absl::FailedPreconditionError( absl::StrCat("invalid program header offset: ", file_header_.e_phoff)); } - if (file_header_.e_phentsize != sizeof(Elf64_Phdr)) { + if (file_header_.e_phentsize != sizeof(ElfPhdr)) { return absl::FailedPreconditionError(absl::StrCat( "section header entry size incorrect: ", file_header_.e_phentsize, - " bytes, ", sizeof(Elf64_Phdr), " expected.")); + " bytes, ", sizeof(ElfPhdr), " expected.")); } if (file_header_.e_phnum > kMaxProgramHeaderEntries) { return absl::FailedPreconditionError( @@ -338,11 +344,11 @@ absl::Status ElfParser::ReadProgramHeaders() { return absl::OkStatus(); } -absl::Status ElfParser::ReadSymbolsFromSymtab(const Elf64_Shdr& symtab) { +absl::Status ElfParser::ReadSymbolsFromSymtab(const ElfShdr& symtab) { if (symtab.sh_type != SHT_SYMTAB) { return absl::FailedPreconditionError("invalid symtab type"); } - if (symtab.sh_entsize != sizeof(Elf64_Sym)) { + if (symtab.sh_entsize != sizeof(ElfSym)) { return absl::InternalError( absl::StrCat("invalid symbol entry size: ", symtab.sh_entsize)); } @@ -366,7 +372,7 @@ absl::Status ElfParser::ReadSymbolsFromSymtab(const Elf64_Shdr& symtab) { result_.symbols_.reserve(result_.symbols_.size() + symbol_entries); for (absl::string_view src = symbols; !src.empty(); src = src.substr(symtab.sh_entsize)) { - Elf64_Sym symbol; + ElfSym symbol; LOAD_MEMBER(symbol, st_name, src.data()); LOAD_MEMBER(symbol, st_info, src.data()); LOAD_MEMBER(symbol, st_other, src.data()); @@ -396,11 +402,11 @@ absl::Status ElfParser::ReadSymbolsFromSymtab(const Elf64_Shdr& symtab) { } absl::Status ElfParser::ReadImportedLibrariesFromDynamic( - const Elf64_Shdr& dynamic) { + const ElfShdr& dynamic) { if (dynamic.sh_type != SHT_DYNAMIC) { return absl::FailedPreconditionError("invalid dynamic type"); } - if (dynamic.sh_entsize != sizeof(Elf64_Dyn)) { + if (dynamic.sh_entsize != sizeof(ElfDyn)) { return absl::InternalError( absl::StrCat("invalid dynamic entry size: ", dynamic.sh_entsize)); } @@ -435,7 +441,7 @@ absl::Status ElfParser::ReadImportedLibrariesFromDynamic( SAPI_ASSIGN_OR_RETURN(std::string dynamic_entries, ReadSectionContents(dynamic)); for (absl::string_view src = dynamic_entries; !src.empty(); src = src.substr(dynamic.sh_entsize)) { - Elf64_Dyn dyn; + ElfDyn dyn; LOAD_MEMBER(dyn, d_tag, src.data()); LOAD_MEMBER(dyn, d_un.d_val, src.data()); if (dyn.d_tag != DT_NEEDED) { @@ -478,7 +484,7 @@ absl::StatusOr ElfParser::Parse(FILE* elf, uint32_t features) { std::string interpreter; auto it = std::find_if( program_headers_.begin(), program_headers_.end(), - [](const Elf64_Phdr& hdr) { return hdr.p_type == PT_INTERP; }); + [](const ElfPhdr& hdr) { return hdr.p_type == PT_INTERP; }); // No interpreter usually means that the executable was statically linked. if (it != program_headers_.end()) { if (it->p_filesz > kMaxInterpreterSize) { diff --git a/sandboxed_api/sandbox2/util/minielf.h b/sandboxed_api/sandbox2/util/minielf.h index 637adc3..2b6397a 100644 --- a/sandboxed_api/sandbox2/util/minielf.h +++ b/sandboxed_api/sandbox2/util/minielf.h @@ -15,6 +15,7 @@ #ifndef SANDBOXED_API_SANDBOX2_UTIL_MINIELF_H_ #define SANDBOXED_API_SANDBOX2_UTIL_MINIELF_H_ +#include #include #include #include @@ -25,11 +26,10 @@ namespace sandbox2 { // Minimal implementation of an ELF file parser to read the program interpreter. -// Only understands 64-bit ELFs. class ElfFile { public: struct Symbol { - uint64_t address; + uintptr_t address; std::string name; }; diff --git a/sandboxed_api/sandbox2/violation.proto b/sandboxed_api/sandbox2/violation.proto index 0425db7..f017aee 100644 --- a/sandboxed_api/sandbox2/violation.proto +++ b/sandboxed_api/sandbox2/violation.proto @@ -83,12 +83,20 @@ message RegisterAarch64 { uint64 pstate = 4; } +message RegisterArm { + repeated uint32 regs = 1; + uint32 pc = 2; + uint32 cpsr = 3; + uint32 orig_x0 = 4; +} + message RegisterValues { // Architecture architecture = 1; oneof register_values { RegisterX8664 register_x86_64 = 2; RegisterPowerpc64 register_powerpc64 = 3; RegisterAarch64 register_aarch64 = 4; + RegisterArm register_arm = 5; } }