Initial changes to support AArch64

This is a work in progress:
- Syscall tables need work
- Only tested on real hardware using one of our test hosts

As a drive-by, this change also enables the open source version to function on
POWER.

Another side-effect of this change is that the default policies no longer
check for different host architectures at runtime. On x86_64, we do not need
to check for PPC or AArch64 specifice and vice versa.

PiperOrigin-RevId: 331137472
Change-Id: Ic6d6be5cbe61d83dbe13d5a0be036871754b2eb8
This commit is contained in:
Christian Blichmann 2020-09-11 06:33:57 -07:00 committed by Copybara-Service
parent c19949eb7b
commit 21f7373e76
18 changed files with 477 additions and 58 deletions

View File

@ -84,7 +84,9 @@ void InitDefaultPolicyBuilder(sandbox2::PolicyBuilder* builder) {
__NR_kill,
__NR_tgkill,
__NR_tkill,
#ifdef __NR_readlink
__NR_readlink,
#endif
#ifdef __NR_arch_prctl // x86-64 only
__NR_arch_prctl,
#endif

View File

@ -84,11 +84,18 @@ std::unique_ptr<Policy> BufferTestcasePolicy() {
.AllowSyscall(__NR_lseek)
.AllowSyscall(__NR_close)
.BlockSyscallWithErrno(__NR_prlimit64, EPERM)
#ifdef __NR_open
.BlockSyscallWithErrno(__NR_open, ENOENT)
#endif
.BlockSyscallWithErrno(__NR_openat, ENOENT)
#ifdef __NR_access
// On Debian, even static binaries check existence of
// /etc/ld.so.nohwcap.
.BlockSyscallWithErrno(__NR_access, ENOENT)
#endif
#ifdef __NR_faccessat
.BlockSyscallWithErrno(__NR_faccessat, ENOENT)
#endif
.BuildOrDie();
return s2p;

View File

@ -61,6 +61,8 @@ constexpr cpu::Architecture Architecture() {
return cpu::kX8664;
#elif defined(SAPI_PPC64_LE)
return cpu::kPPC64LE;
#elif defined(SAPI_ARM64)
return cpu::kArm64;
#else
return cpu::kUnknown;
#endif
@ -75,8 +77,8 @@ constexpr bool IsArm64() { return Architecture() == cpu::kArm64; }
} // namespace host_cpu
static_assert(host_cpu::Architecture() != cpu::kUnknown,
"Host CPU architecture is not supported: One of x86-64 or "
"POWER64 (little endian) is required.");
"Host CPU architecture is not supported: One of x86-64, POWER64 "
"(little endian) or AArch64 is required.");
} // namespace sandbox2

View File

@ -52,8 +52,10 @@ std::unique_ptr<sandbox2::Policy> GetPolicy() {
// Allow the getpid() syscall.
.AllowSyscall(__NR_getpid)
#ifdef __NR_access
// On Debian, even static binaries check existence of /etc/ld.so.nohwcap.
.BlockSyscallWithErrno(__NR_access, ENOENT)
#endif
// Examples for AddPolicyOnSyscall:
.AddPolicyOnSyscall(__NR_write,

View File

@ -113,6 +113,8 @@ absl::StatusOr<std::string> ExistingPathInsideDir(
absl::Status ValidateInterpreter(absl::string_view interpreter) {
const absl::flat_hash_set<std::string> allowed_interpreters = {
"/lib64/ld-linux-x86-64.so.2",
"/lib64/ld64.so.2", // PPC64
"/lib/ld-linux-aarch64.so.1", // AArch64
};
if (!allowed_interpreters.contains(interpreter)) {
@ -139,6 +141,8 @@ constexpr absl::string_view GetPlatformCPUName() {
return "x86_64";
case cpu::kPPC64LE:
return "ppc64";
case cpu::kArm64:
return "aarch64";
default:
return "unknown";
}

View File

@ -49,10 +49,14 @@ constexpr int kRegSyscall = 0;
constexpr int kRegArg0 = 3;
constexpr int kRegArg1 = 4;
constexpr int kRegArg2 = 5;
#elif defined(SAPI_ARM64)
constexpr int kRegResult = 0;
constexpr int kRegSyscall = 8;
constexpr int kRegArg0 = 0;
constexpr int kRegArg1 = 1;
constexpr int kRegArg2 = 2;
#endif
constexpr char NetworkProxyClient::kFDName[];
int NetworkProxyClient::ConnectHandler(int sockfd, const struct sockaddr* addr,
socklen_t addrlen) {
absl::Status status = Connect(sockfd, addr, addrlen);
@ -154,20 +158,22 @@ void NetworkProxyHandler::InvokeOldAct(int nr, siginfo_t* info,
void NetworkProxyHandler::ProcessSeccompTrap(int nr, siginfo_t* info,
void* void_context) {
ucontext_t* ctx = (ucontext_t*)(void_context);
if (info->si_code != SYS_SECCOMP) {
InvokeOldAct(nr, info, void_context);
return;
}
if (!ctx) return;
auto* ctx = static_cast<ucontext_t*>(void_context);
if (!ctx) {
return;
}
#if defined(SAPI_X86_64)
auto* registers = ctx->uc_mcontext.gregs;
#elif defined(SAPI_PPC64_LE)
auto* registers = ctx->uc_mcontext.gp_regs;
using ppc_gpreg_t = std::decay<decltype(registers[0])>::type;
#elif defined(SAPI_ARM64)
auto* registers = ctx->uc_mcontext.regs;
#endif
int syscall = registers[kRegSyscall];
int sockfd;
@ -181,11 +187,10 @@ void NetworkProxyHandler::ProcessSeccompTrap(int nr, siginfo_t* info,
#if defined(SAPI_PPC64_LE)
} else if (syscall == __NR_socketcall &&
static_cast<int>(registers[kRegArg0]) == SYS_CONNECT) {
ppc_gpreg_t* args = reinterpret_cast<ppc_gpreg_t*>(registers[kRegArg1]);
sockfd = static_cast<int>(args[0]);
addr = reinterpret_cast<const struct sockaddr*>(args[1]);
addrlen = static_cast<socklen_t>(args[2]);
auto* connect_args = reinterpret_cast<uint64_t*>(registers[kRegArg1]);
sockfd = static_cast<int>(connect_args[0]);
addr = reinterpret_cast<const struct sockaddr*>(connect_args[1]);
addrlen = static_cast<socklen_t>(connect_args[2]);
#endif
} else {
InvokeOldAct(nr, info, void_context);

View File

@ -49,8 +49,12 @@ std::unique_ptr<Policy> NotifyTestcasePolicy() {
.AllowWrite()
.AllowSyscall(__NR_close)
.AddPolicyOnSyscall(__NR_personality, {SANDBOX2_TRACE})
#ifdef __NR_open
.BlockSyscallWithErrno(__NR_open, ENOENT)
#endif
#ifdef __NR_access
.BlockSyscallWithErrno(__NR_access, ENOENT)
#endif
.BlockSyscallWithErrno(__NR_openat, ENOENT)
.BlockSyscallWithErrno(__NR_prlimit64, EPERM)
.BuildOrDie();

View File

@ -82,41 +82,41 @@ std::vector<sock_filter> Policy::GetDefaultPolicy() const {
bpf_labels l = {0};
std::vector<sock_filter> policy = {
// If compiled arch is different than the runtime one, inform the Monitor.
LOAD_ARCH,
JEQ32(Syscall::GetHostAuditArch(), JUMP(&l, past_arch_check_l)),
JEQ32(AUDIT_ARCH_X86_64, TRACE(cpu::kX8664)),
JEQ32(AUDIT_ARCH_I386, TRACE(cpu::kX86)),
JEQ32(AUDIT_ARCH_PPC64LE, TRACE(cpu::kPPC64LE)),
TRACE(cpu::kUnknown),
LABEL(&l, past_arch_check_l),
// If compiled arch is different than the runtime one, inform the Monitor.
LOAD_ARCH,
JEQ32(Syscall::GetHostAuditArch(), JUMP(&l, past_arch_check_l)),
#if defined(SAPI_X86_64)
JEQ32(AUDIT_ARCH_I386, TRACE(cpu::kX86)), // 32-bit sandboxee
#endif
TRACE(cpu::kUnknown),
LABEL(&l, past_arch_check_l),
// After the policy is uploaded, forkserver will execve the sandboxee. We
// need to allow this execve but not others. Since BPF does not have
// state, we need to inform the Monitor to decide, and for that we use a
// magic value in syscall args 5. Note that this value is not supposed to
// be secret, but just an optimization so that the monitor is not
// triggered on every call to execveat.
LOAD_SYSCALL_NR,
JNE32(__NR_execveat, JUMP(&l, past_execveat_l)),
ARG_32(4),
JNE32(AT_EMPTY_PATH, JUMP(&l, past_execveat_l)),
ARG_32(5),
JNE32(internal::kExecveMagic, JUMP(&l, past_execveat_l)),
SANDBOX2_TRACE,
LABEL(&l, past_execveat_l),
// After the policy is uploaded, forkserver will execve the sandboxee. We
// need to allow this execve but not others. Since BPF does not have
// state, we need to inform the Monitor to decide, and for that we use a
// magic value in syscall args 5. Note that this value is not supposed to
// be secret, but just an optimization so that the monitor is not
// triggered on every call to execveat.
LOAD_SYSCALL_NR,
JNE32(__NR_execveat, JUMP(&l, past_execveat_l)),
ARG_32(4),
JNE32(AT_EMPTY_PATH, JUMP(&l, past_execveat_l)),
ARG_32(5),
JNE32(internal::kExecveMagic, JUMP(&l, past_execveat_l)),
SANDBOX2_TRACE,
LABEL(&l, past_execveat_l),
// Forbid some syscalls because unsafe or too risky.
LOAD_SYSCALL_NR,
JEQ32(__NR_ptrace, DENY),
JEQ32(__NR_bpf, DENY),
// Forbid some syscalls because unsafe or too risky.
LOAD_SYSCALL_NR,
JEQ32(__NR_ptrace, DENY),
JEQ32(__NR_bpf, DENY),
// Disallow clone with CLONE_UNTRACED flag.
JNE32(__NR_clone, JUMP(&l, past_clone_untraced_l)),
// Regardless of arch, we only care about the lower 32-bits of the flags.
ARG_32(0),
JA32(CLONE_UNTRACED, DENY),
LABEL(&l, past_clone_untraced_l),
// Disallow clone with CLONE_UNTRACED flag.
JNE32(__NR_clone, JUMP(&l, past_clone_untraced_l)),
// Regardless of arch, we only care about the lower 32-bits of the flags.
ARG_32(0),
JA32(CLONE_UNTRACED, DENY),
LABEL(&l, past_clone_untraced_l),
};
if (bpf_resolve_jumps(&l, policy.data(), policy.size()) != 0) {
@ -129,11 +129,16 @@ std::vector<sock_filter> Policy::GetDefaultPolicy() const {
std::vector<sock_filter> Policy::GetTrackingPolicy() const {
return {
LOAD_ARCH,
JEQ32(AUDIT_ARCH_X86_64, TRACE(cpu::kX8664)),
JEQ32(AUDIT_ARCH_I386, TRACE(cpu::kX86)),
JEQ32(AUDIT_ARCH_PPC64LE, TRACE(cpu::kPPC64LE)),
TRACE(cpu::kUnknown),
LOAD_ARCH,
#if defined(SAPI_X86_64)
JEQ32(AUDIT_ARCH_X86_64, TRACE(cpu::kX8664)),
JEQ32(AUDIT_ARCH_I386, TRACE(cpu::kX86)),
#elif defined(SAPI_PPC64_LE)
JEQ32(AUDIT_ARCH_PPC64LE, TRACE(cpu::kPPC64LE)),
#elif defined(SAPI_ARM64)
JEQ32(AUDIT_ARCH_AARCH64, TRACE(cpu::kArm64)),
#endif
TRACE(cpu::kUnknown),
};
}

View File

@ -50,9 +50,16 @@ std::unique_ptr<Policy> PolicyTestcasePolicy() {
.AllowSyscall(__NR_close)
.AllowSyscall(__NR_getppid)
.AllowTCGETS()
#ifdef __NR_open
.BlockSyscallWithErrno(__NR_open, ENOENT)
#endif
.BlockSyscallWithErrno(__NR_openat, ENOENT)
#ifdef __NR_access
.BlockSyscallWithErrno(__NR_access, ENOENT)
#endif
#ifdef __NR_faccessat
.BlockSyscallWithErrno(__NR_faccessat, ENOENT)
#endif
.BlockSyscallWithErrno(__NR_prlimit64, EPERM)
.BuildOrDie();
}
@ -162,7 +169,9 @@ std::unique_ptr<Policy> MinimalTestcasePolicy() {
.AllowStaticStartup()
.AllowExit()
.BlockSyscallWithErrno(__NR_prlimit64, EPERM)
#ifdef __NR_access
.BlockSyscallWithErrno(__NR_access, ENOENT)
#endif
.BuildOrDie();
}
@ -197,8 +206,10 @@ TEST(MinimalTest, MinimalSharedBinaryWorks) {
.AllowOpen()
.AllowExit()
.AllowMmap()
#ifdef __NR_access
// New glibc accesses /etc/ld.so.preload
.BlockSyscallWithErrno(__NR_access, ENOENT)
#endif
.BlockSyscallWithErrno(__NR_prlimit64, EPERM)
.AddLibrariesForBinary(path)
.BuildOrDie();
@ -223,7 +234,9 @@ TEST(MallocTest, SystemMallocWorks) {
.AllowSystemMalloc()
.AllowExit()
.BlockSyscallWithErrno(__NR_prlimit64, EPERM)
#ifdef __NR_access
.BlockSyscallWithErrno(__NR_access, ENOENT)
#endif
.BuildOrDie();
Sandbox2 s2(std::move(executor), std::move(policy));
@ -247,7 +260,9 @@ TEST(MultipleSyscalls, AddPolicyOnSyscallsWorks) {
auto policy =
PolicyBuilder()
#ifdef __NR_open
.BlockSyscallWithErrno(__NR_open, ENOENT)
#endif
.BlockSyscallWithErrno(__NR_openat, ENOENT)
.AllowStaticStartup()
.AllowTcMalloc()
@ -258,7 +273,9 @@ TEST(MultipleSyscalls, AddPolicyOnSyscallsWorks) {
.AddPolicyOnSyscalls({__NR_read, __NR_write}, {ERRNO(43)})
.AddPolicyOnSyscall(__NR_umask, {DENY})
.BlockSyscallWithErrno(__NR_prlimit64, EPERM)
#ifdef __NR_access
.BlockSyscallWithErrno(__NR_access, ENOENT)
#endif
.BuildOrDie();
Sandbox2 s2(std::move(executor), std::move(policy));

View File

@ -520,7 +520,12 @@ PolicyBuilder& PolicyBuilder::AllowStaticStartup() {
});
#endif
if constexpr (host_cpu::IsArm64()) {
BlockSyscallWithErrno(__NR_readlinkat, ENOENT);
}
#ifdef __NR_readlink
BlockSyscallWithErrno(__NR_readlink, ENOENT);
#endif
return *this;
}
@ -881,7 +886,9 @@ PolicyBuilder& PolicyBuilder::AddNetworkProxyPolicy() {
AllowFutexOp(FUTEX_WAIT);
AllowFutexOp(FUTEX_WAIT_BITSET);
AllowSyscalls({
#ifdef __NR_dup2
__NR_dup2,
#endif
__NR_recvmsg,
__NR_close,
__NR_gettid,

View File

@ -101,7 +101,7 @@ TEST_F(PolicyBuilderTest, Testpolicy_size) {
builder.AllowSystemMalloc(); assert_increased();
builder.AllowSyscall(__NR_munmap); assert_same();
builder.BlockSyscallWithErrno(__NR_munmap, 1); assert_same();
builder.BlockSyscallWithErrno(__NR_open, 1);
builder.BlockSyscallWithErrno(__NR_openat, 1);
assert_increased();
builder.AllowTCGETS(); assert_increased();

View File

@ -23,12 +23,18 @@
#include <cerrno>
#include "absl/base/macros.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/util/strerror.h"
namespace sandbox2 {
#ifndef NT_ARM_SYSTEM_CALL
#define NT_ARM_SYSTEM_CALL 0x404
#endif
absl::Status Regs::Fetch() {
#ifdef SAPI_X86_64
if (ptrace(PTRACE_GETREGS, pid_, 0, &user_regs_) == -1L) {
@ -36,7 +42,7 @@ absl::Status Regs::Fetch() {
") failed: ", StrError(errno)));
}
#endif
if constexpr (host_cpu::IsPPC64LE()) {
if constexpr (host_cpu::IsPPC64LE() || host_cpu::IsArm64()) {
iovec pt_iov = {&user_regs_, sizeof(user_regs_)};
if (ptrace(PTRACE_GETREGSET, pid_, NT_PRSTATUS, &pt_iov) == -1L) {
@ -50,6 +56,24 @@ absl::Status Regs::Fetch() {
") size returned: ", pt_iov.iov_len,
" different than sizeof(user_regs_): ", sizeof(user_regs_)));
}
// On AArch64, we are not done yet. Read the syscall number.
if constexpr (host_cpu::IsArm64()) {
iovec sys_iov = {&syscall_number_, sizeof(syscall_number_)};
if (ptrace(PTRACE_GETREGSET, pid_, NT_ARM_SYSTEM_CALL, &sys_iov) == -1L) {
return absl::InternalError(
absl::StrCat("ptrace(PTRACE_GETREGSET, pid=", pid_,
", NT_ARM_SYSTEM_CALL) failed: ", StrError(errno)));
}
if (sys_iov.iov_len != sizeof(syscall_number_)) {
return absl::InternalError(absl::StrCat(
"ptrace(PTRACE_GETREGSET, pid=", pid_,
", NT_ARM_SYSTEM_CALL) size returned: ", sys_iov.iov_len,
" different than sizeof(syscall_number_): ",
sizeof(syscall_number_)));
}
}
}
return absl::OkStatus();
}
@ -61,7 +85,7 @@ absl::Status Regs::Store() {
") failed: ", StrError(errno)));
}
#endif
if constexpr (host_cpu::IsPPC64LE()) {
if constexpr (host_cpu::IsPPC64LE() || host_cpu::IsArm64()) {
iovec pt_iov = {&user_regs_, sizeof(user_regs_)};
if (ptrace(PTRACE_SETREGSET, pid_, NT_PRSTATUS, &pt_iov) == -1L) {
@ -69,6 +93,17 @@ absl::Status Regs::Store() {
absl::StrCat("ptrace(PTRACE_SETREGSET, pid=", pid_,
") failed: ", StrError(errno)));
}
// Store syscall number on AArch64.
if constexpr (host_cpu::IsArm64()) {
iovec sys_iov = {&syscall_number_, sizeof(syscall_number_)};
if (ptrace(PTRACE_SETREGSET, pid_, NT_ARM_SYSTEM_CALL, &sys_iov) == -1L) {
return absl::InternalError(
absl::StrCat("ptrace(PTRACE_SETREGSET, pid=", pid_,
", NT_ARM_SYSTEM_CALL) failed: ", StrError(errno)));
}
}
}
return absl::OkStatus();
}
@ -80,6 +115,9 @@ absl::Status Regs::SkipSyscallReturnValue(uint64_t value) {
#elif defined(SAPI_PPC64_LE)
user_regs_.gpr[0] = -1;
user_regs_.gpr[3] = value;
#elif defined(SAPI_ARM64)
user_regs_.regs[0] = -1;
syscall_number_ = value;
#endif
return Store();
}
@ -114,6 +152,22 @@ Syscall Regs::ToSyscall(cpu::Architecture syscall_arch) const {
auto ip = user_regs_.nip;
return Syscall(syscall_arch, syscall, args, pid_, sp, ip);
}
#elif defined(SAPI_ARM64)
if (ABSL_PREDICT_TRUE(syscall_arch == cpu::kArm64)) {
Syscall::Args args = {
// First argument should be orig_x0, which is not available to ptrace on
// AArch64 (see
// https://undo.io/resources/arm64-vs-arm32-whats-different-linux-programmers/),
// as it will have been overwritten. For our use case, though, using
// regs[0] is fine, as we are always called on syscall entry and never
// on exit.
user_regs_.regs[0], user_regs_.regs[1], user_regs_.regs[2],
user_regs_.regs[3], user_regs_.regs[4], user_regs_.regs[5],
};
auto sp = user_regs_.sp;
auto ip = user_regs_.pc;
return Syscall(syscall_arch, syscall_number_, args, pid_, sp, ip);
}
#endif
return Syscall(pid_);
}
@ -169,6 +223,14 @@ void Regs::StoreRegisterValuesInProtobuf(RegisterValues* values) const {
regs->set_zero1(user_regs_.zero1);
regs->set_zero2(user_regs_.zero2);
regs->set_zero3(user_regs_.zero3);
#elif defined(SAPI_ARM64)
RegisterAarch64* regs = values->mutable_register_aarch64();
for (int i = 0; i < ABSL_ARRAYSIZE(user_regs_.regs); ++i) {
regs->add_regs(user_regs_.regs[i]);
}
regs->set_sp(user_regs_.sp);
regs->set_pc(user_regs_.pc);
regs->set_pstate(user_regs_.pstate);
#endif
}

View File

@ -105,6 +105,11 @@ class Regs {
uint64_t zero1;
uint64_t zero2;
uint64_t zero3;
#elif defined(SAPI_ARM64)
uint64_t regs[31];
uint64_t sp;
uint64_t pc;
uint64_t pstate;
#else
static_assert(false, "Host CPU architecture not supported, see config.h");
#endif
@ -115,6 +120,9 @@ class Regs {
// Registers fetched with ptrace(PR_GETREGS/GETREGSET, pid).
PtraceRegisters user_regs_ = {};
// On AArch64, obtaining the syscall number needs a specific call to ptrace()
int syscall_number_ = 0;
};
} // namespace sandbox2

View File

@ -31,6 +31,7 @@
#include "absl/strings/strip.h"
#include "libcap/include/sys/capability.h"
#include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/ipc.h"
#include "sandboxed_api/sandbox2/limits.h"
@ -270,6 +271,9 @@ bool StackTracePeer::LaunchLibunwindSandbox(const Regs* regs,
}
std::vector<std::string> GetStackTrace(const Regs* regs, const Mounts& mounts) {
if constexpr (host_cpu::IsArm64()) {
return {"[Stack traces unavailable]"};
}
if (absl::GetFlag(FLAGS_sandbox_disable_all_stack_traces)) {
return {"[Stacktraces disabled]"};
}

View File

@ -42,6 +42,8 @@ std::string Syscall::GetArchDescription(cpu::Architecture arch) {
return "[X86-32]";
case cpu::kPPC64LE:
return "[PPC-64]";
case cpu::kArm64:
return "[Arm-64]";
default:
LOG(ERROR) << "Unknown CPU architecture: " << arch;
return absl::StrFormat("[UNKNOWN_ARCH:%d]", arch);
@ -54,6 +56,8 @@ uint32_t Syscall::GetHostAuditArch() {
return AUDIT_ARCH_X86_64;
case cpu::kPPC64LE:
return AUDIT_ARCH_PPC64LE;
case cpu::kArm64:
return AUDIT_ARCH_AARCH64;
default:
// The static_assert() in config.h should prevent us from ever getting
// here.

View File

@ -1216,6 +1216,291 @@ constexpr SyscallTable::Entry kSyscallDataPPC64LE[] = {
MakeEntry("pwritev2", kHex, kHex, kHex, kHex, kHex, kHex), // 381
};
// TODO(cblichmann): Confirm the entries in this list.
// https://github.com/torvalds/linux/blob/v5.8/include/uapi/asm-generic/unistd.h
constexpr SyscallTable::Entry kSyscallDataArm64[] = {
MakeEntry("io_setup", UnknownArguments()), // 0
MakeEntry("io_destroy", UnknownArguments()), // 1
MakeEntry("io_submit", UnknownArguments()), // 2
MakeEntry("io_cancel", UnknownArguments()), // 3
MakeEntry("io_getevents", UnknownArguments()), // 4
MakeEntry("setxattr", kPath, kString, kGen, kInt, kHex, kGen), // 5
MakeEntry("lsetxattr", kPath, kString, kGen, kInt, kHex, kGen), // 6
MakeEntry("fsetxattr", UnknownArguments()), // 7
MakeEntry("getxattr", kPath, kString, kGen, kInt, kGen, kGen), // 8
MakeEntry("lgetxattr", kPath, kString, kGen, kInt, kGen, kGen), // 9
MakeEntry("fgetxattr", UnknownArguments()), // 10
MakeEntry("listxattr", kPath, kGen, kInt, kGen, kGen, kGen), // 11
MakeEntry("llistxattr", kPath, kGen, kInt, kGen, kGen, kGen), // 12
MakeEntry("flistxattr", UnknownArguments()), // 13
MakeEntry("removexattr", kPath, kString, kGen, kGen, kGen, kGen), // 14
MakeEntry("lremovexattr", UnknownArguments()), // 15
MakeEntry("fremovexattr", UnknownArguments()), // 16
MakeEntry("getcwd", UnknownArguments()), // 17
MakeEntry("lookup_dcookie", UnknownArguments()), // 18
MakeEntry("eventfd2", UnknownArguments()), // 19
MakeEntry("epoll_create1", UnknownArguments()), // 20
MakeEntry("epoll_ctl", UnknownArguments()), // 21
MakeEntry("epoll_pwait", UnknownArguments()), // 22
MakeEntry("dup", UnknownArguments()), // 23
MakeEntry("dup3", UnknownArguments()), // 24
MakeEntry("fcntl", UnknownArguments()), // 25
MakeEntry("inotify_init1", UnknownArguments()), // 26
MakeEntry("inotify_add_watch", UnknownArguments()), // 27
MakeEntry("inotify_rm_watch", UnknownArguments()), // 28
MakeEntry("ioctl", UnknownArguments()), // 29
MakeEntry("ioprio_set", UnknownArguments()), // 30
MakeEntry("ioprio_get", UnknownArguments()), // 31
MakeEntry("flock", UnknownArguments()), // 32
MakeEntry("mknodat", kGen, kPath, kGen, kGen, kGen, kGen), // 33
MakeEntry("mkdirat", kGen, kPath, kGen, kGen, kGen, kGen), // 34
MakeEntry("unlinkat", kGen, kPath, kGen, kGen, kGen, kGen), // 35
MakeEntry("symlinkat", kPath, kGen, kPath, kGen, kGen, kGen), // 36
MakeEntry("linkat", kGen, kPath, kGen, kPath, kGen, kGen), // 37
MakeEntry("renameat", kGen, kPath, kGen, kPath, kGen, kGen), // 38
MakeEntry("umount2", kPath, kHex, kGen, kGen, kGen, kGen), // 39
MakeEntry("mount", kPath, kPath, kString, kHex, kGen, kGen), // 40
MakeEntry("pivot_root", kPath, kPath, kGen, kGen, kGen, kGen), // 41
MakeEntry("nfsservctl", UnknownArguments()), // 42
MakeEntry("statfs", kPath, kGen, kGen, kGen, kGen, kGen), // 43
MakeEntry("fstatfs", UnknownArguments()), // 44
MakeEntry("truncate", kPath, kInt, kGen, kGen, kGen, kGen), // 45
MakeEntry("ftruncate", UnknownArguments()), // 46
MakeEntry("fallocate", UnknownArguments()), // 47
MakeEntry("faccessat", kGen, kPath, kGen, kGen, kGen, kGen), // 48
MakeEntry("chdir", kPath, kGen, kGen, kGen, kGen, kGen), // 49
MakeEntry("fchdir", UnknownArguments()), // 50
MakeEntry("chroot", kPath, kGen, kGen, kGen, kGen, kGen), // 51
MakeEntry("fchmod", UnknownArguments()), // 52
MakeEntry("fchmodat", kGen, kPath, kGen, kGen, kGen, kGen), // 53
MakeEntry("fchownat", kGen, kPath, kGen, kGen, kGen, kGen), // 54
MakeEntry("fchown", UnknownArguments()), // 55
MakeEntry("openat", kGen, kPath, kOct, kHex, kGen, kGen), // 56
MakeEntry("close", kInt, kGen, kGen, kGen, kGen, kGen), // 57
MakeEntry("vhangup", UnknownArguments()), // 58
MakeEntry("pipe2", UnknownArguments()), // 59
MakeEntry("quotactl", kInt, kPath, kInt, kGen, kGen, kGen), // 60
MakeEntry("getdents64", UnknownArguments()), // 61
MakeEntry("lseek", UnknownArguments()), // 62
MakeEntry("read", kInt, kHex, kInt, kGen, kGen, kGen), // 63
MakeEntry("write", kInt, kHex, kInt, kGen, kGen, kGen), // 64
MakeEntry("readv", UnknownArguments()), // 65
MakeEntry("writev", UnknownArguments()), // 66
MakeEntry("pread64", UnknownArguments()), // 67
MakeEntry("pwrite64", UnknownArguments()), // 68
MakeEntry("preadv", UnknownArguments()), // 69
MakeEntry("pwritev", UnknownArguments()), // 70
MakeEntry("sendfile", UnknownArguments()), // 71
MakeEntry("pselect6", UnknownArguments()), // 72
MakeEntry("ppoll", UnknownArguments()), // 73
MakeEntry("signalfd4", UnknownArguments()), // 74
MakeEntry("vmsplice", UnknownArguments()), // 75
MakeEntry("splice", UnknownArguments()), // 76
MakeEntry("tee", UnknownArguments()), // 77
MakeEntry("readlinkat", kGen, kPath, kGen, kGen, kGen, kGen), // 78
MakeEntry("newfstatat", kGen, kPath, kGen, kGen, kGen, kGen), // 79
MakeEntry("fstat", kInt, kHex, kGen, kGen, kGen, kGen), // 80
MakeEntry("sync", UnknownArguments()), // 81
MakeEntry("fsync", UnknownArguments()), // 82
MakeEntry("fdatasync", UnknownArguments()), // 83
MakeEntry("sync_file_range", UnknownArguments()), // 84
MakeEntry("timerfd_create", UnknownArguments()), // 85
MakeEntry("timerfd_settime", UnknownArguments()), // 86
MakeEntry("timerfd_gettime", UnknownArguments()), // 87
MakeEntry("utimensat", UnknownArguments()), // 88
MakeEntry("acct", kPath, kGen, kGen, kGen, kGen, kGen), // 89
MakeEntry("capget", UnknownArguments()), // 90
MakeEntry("capset", UnknownArguments()), // 91
MakeEntry("personality", UnknownArguments()), // 92
MakeEntry("exit", kInt, kGen, kGen, kGen, kGen, kGen), // 93
MakeEntry("exit_group", kInt, kGen, kGen, kGen, kGen, kGen), // 94
MakeEntry("waitid", UnknownArguments()), // 95
MakeEntry("set_tid_address", kHex, kGen, kGen, kGen, kGen, kGen), // 96
MakeEntry("unshare", UnknownArguments()), // 97
MakeEntry("futex", UnknownArguments()), // 98
MakeEntry("set_robust_list", UnknownArguments()), // 99
MakeEntry("get_robust_list", UnknownArguments()), // 100
MakeEntry("nanosleep", kHex, kHex, kGen, kGen, kGen, kGen), // 101
MakeEntry("getitimer", UnknownArguments()), // 102
MakeEntry("setitimer", UnknownArguments()), // 103
MakeEntry("kexec_load", UnknownArguments()), // 104
MakeEntry("init_module", UnknownArguments()), // 105
MakeEntry("delete_module", UnknownArguments()), // 106
MakeEntry("timer_create", UnknownArguments()), // 107
MakeEntry("timer_gettime", UnknownArguments()), // 108
MakeEntry("timer_getoverrun", UnknownArguments()), // 109
MakeEntry("timer_settime", UnknownArguments()), // 110
MakeEntry("timer_delete", UnknownArguments()), // 111
MakeEntry("clock_settime", UnknownArguments()), // 112
MakeEntry("clock_gettime", UnknownArguments()), // 113
MakeEntry("clock_getres", UnknownArguments()), // 114
MakeEntry("clock_nanosleep", UnknownArguments()), // 115
MakeEntry("syslog", UnknownArguments()), // 116
MakeEntry("ptrace", UnknownArguments()), // 117
MakeEntry("sched_setparam", UnknownArguments()), // 118
MakeEntry("sched_setscheduler", UnknownArguments()), // 119
MakeEntry("sched_getscheduler", UnknownArguments()), // 120
MakeEntry("sched_getparam", UnknownArguments()), // 121
MakeEntry("sched_setaffinity", UnknownArguments()), // 122
MakeEntry("sched_getaffinity", UnknownArguments()), // 123
MakeEntry("sched_yield", UnknownArguments()), // 124
MakeEntry("sched_get_priority_max", UnknownArguments()), // 125
MakeEntry("sched_get_priority_min", UnknownArguments()), // 126
MakeEntry("sched_rr_get_interval", UnknownArguments()), // 127
MakeEntry("restart_syscall", UnknownArguments()), // 128
MakeEntry("kill", kInt, kSignal, kGen, kGen, kGen, kGen), // 129
MakeEntry("tkill", kInt, kSignal, kGen, kGen, kGen, kGen), // 130
MakeEntry("tgkill", kInt, kInt, kSignal, kGen, kGen, kGen), // 131
MakeEntry("sigaltstack", UnknownArguments()), // 132
MakeEntry("rt_sigsuspend", UnknownArguments()), // 133
MakeEntry("rt_sigaction", kSignal, kHex, kHex, kInt, kGen, kGen), // 134
MakeEntry("rt_sigprocmask", UnknownArguments()), // 135
MakeEntry("rt_sigpending", UnknownArguments()), // 136
MakeEntry("rt_sigtimedwait", UnknownArguments()), // 137
MakeEntry("rt_sigqueueinfo", UnknownArguments()), // 138
MakeEntry("rt_sigreturn", UnknownArguments()), // 139
MakeEntry("setpriority", UnknownArguments()), // 140
MakeEntry("getpriority", UnknownArguments()), // 141
MakeEntry("reboot", UnknownArguments()), // 142
MakeEntry("setregid", UnknownArguments()), // 143
MakeEntry("setgid", UnknownArguments()), // 144
MakeEntry("setreuid", UnknownArguments()), // 145
MakeEntry("setuid", UnknownArguments()), // 146
MakeEntry("setresuid", UnknownArguments()), // 147
MakeEntry("getresuid", UnknownArguments()), // 148
MakeEntry("setresgid", UnknownArguments()), // 149
MakeEntry("getresgid", UnknownArguments()), // 150
MakeEntry("setfsuid", UnknownArguments()), // 151
MakeEntry("setfsgid", UnknownArguments()), // 152
MakeEntry("times", UnknownArguments()), // 153
MakeEntry("setpgid", UnknownArguments()), // 154
MakeEntry("getpgid", UnknownArguments()), // 155
MakeEntry("getsid", UnknownArguments()), // 156
MakeEntry("setsid", UnknownArguments()), // 157
MakeEntry("getgroups", UnknownArguments()), // 158
MakeEntry("setgroups", UnknownArguments()), // 159
MakeEntry("uname", UnknownArguments()), // 160
MakeEntry("sethostname", UnknownArguments()), // 161
MakeEntry("setdomainname", UnknownArguments()), // 162
MakeEntry("getrlimit", UnknownArguments()), // 163
MakeEntry("setrlimit", UnknownArguments()), // 164
MakeEntry("getrusage", UnknownArguments()), // 165
MakeEntry("umask", kHex, kGen, kGen, kGen, kGen, kGen), // 166
MakeEntry("prctl", kInt, kHex, kHex, kHex, kHex, kGen), // 167
MakeEntry("getcpu", kHex, kHex, kHex, kGen, kGen, kGen), // 168
MakeEntry("gettimeofday", kHex, kHex, kGen, kGen, kGen, kGen), // 169
MakeEntry("settimeofday", kHex, kHex, kGen, kGen, kGen, kGen), // 170
MakeEntry("adjtimex", UnknownArguments()), // 171
MakeEntry("getpid", UnknownArguments()), // 172
MakeEntry("getppid", UnknownArguments()), // 173
MakeEntry("getuid", UnknownArguments()), // 174
MakeEntry("geteuid", UnknownArguments()), // 175
MakeEntry("getgid", UnknownArguments()), // 176
MakeEntry("getegid", UnknownArguments()), // 177
MakeEntry("gettid", UnknownArguments()), // 178
MakeEntry("sysinfo", UnknownArguments()), // 179
MakeEntry("mq_open", UnknownArguments()), // 180
MakeEntry("mq_unlink", UnknownArguments()), // 181
MakeEntry("mq_timedsend", UnknownArguments()), // 182
MakeEntry("mq_timedreceive", UnknownArguments()), // 183
MakeEntry("mq_notify", UnknownArguments()), // 184
MakeEntry("mq_getsetattr", UnknownArguments()), // 185
MakeEntry("msgget", UnknownArguments()), // 186
MakeEntry("msgctl", UnknownArguments()), // 187
MakeEntry("msgrcv", UnknownArguments()), // 188
MakeEntry("msgsnd", UnknownArguments()), // 189
MakeEntry("semget", UnknownArguments()), // 190
MakeEntry("semctl", UnknownArguments()), // 191
MakeEntry("semtimedop", UnknownArguments()), // 192
MakeEntry("semop", UnknownArguments()), // 193
MakeEntry("shmget", UnknownArguments()), // 194
MakeEntry("shmctl", UnknownArguments()), // 195
MakeEntry("shmat", UnknownArguments()), // 196
MakeEntry("shmdt", UnknownArguments()), // 197
MakeEntry("socket", kAddressFamily, kInt, kInt, kGen, kGen, kGen), // 198
MakeEntry("socketpair", UnknownArguments()), // 199
MakeEntry("bind", UnknownArguments()), // 200
MakeEntry("listen", UnknownArguments()), // 201
MakeEntry("accept", UnknownArguments()), // 202
MakeEntry("connect", kInt, kSockaddr, kInt, kGen, kGen, kGen), // 203
MakeEntry("getsockname", UnknownArguments()), // 204
MakeEntry("getpeername", UnknownArguments()), // 205
MakeEntry("sendto", kInt, kGen, kInt, kHex, kSockaddr, kInt), // 206
MakeEntry("recvfrom", UnknownArguments()), // 207
MakeEntry("setsockopt", UnknownArguments()), // 208
MakeEntry("getsockopt", UnknownArguments()), // 209
MakeEntry("shutdown", UnknownArguments()), // 210
MakeEntry("sendmsg", kInt, kSockmsghdr, kHex, kGen, kGen, kGen), // 211
MakeEntry("recvmsg", UnknownArguments()), // 212
MakeEntry("readahead", UnknownArguments()), // 213
MakeEntry("brk", kHex, kGen, kGen, kGen, kGen, kGen), // 214
MakeEntry("munmap", kHex, kHex, kGen, kGen, kGen, kGen), // 215
MakeEntry("mremap", UnknownArguments()), // 216
MakeEntry("add_key", UnknownArguments()), // 217
MakeEntry("request_key", UnknownArguments()), // 218
MakeEntry("keyctl", UnknownArguments()), // 219
MakeEntry("clone", kCloneFlag, kHex, kHex, kHex, kHex, kGen), // 220
MakeEntry("execve", kPath, kHex, kHex, kGen, kGen, kGen), // 221
MakeEntry("mmap", kHex, kInt, kHex, kHex, kInt, kInt), // 222
MakeEntry("fadvise64", UnknownArguments()), // 223
MakeEntry("swapon", kPath, kHex, kGen, kGen, kGen, kGen), // 224
MakeEntry("swapoff", kPath, kGen, kGen, kGen, kGen, kGen), // 225
MakeEntry("mprotect", kHex, kHex, kHex, kGen, kGen, kGen), // 226
MakeEntry("msync", UnknownArguments()), // 227
MakeEntry("mlock", UnknownArguments()), // 228
MakeEntry("munlock", UnknownArguments()), // 229
MakeEntry("mlockall", UnknownArguments()), // 230
MakeEntry("munlockall", UnknownArguments()), // 231
MakeEntry("mincore", UnknownArguments()), // 232
MakeEntry("madvise", UnknownArguments()), // 233
MakeEntry("remap_file_pages", UnknownArguments()), // 234
MakeEntry("mbind", UnknownArguments()), // 235
MakeEntry("get_mempolicy", UnknownArguments()), // 236
MakeEntry("set_mempolicy", UnknownArguments()), // 237
MakeEntry("migrate_pages", UnknownArguments()), // 238
MakeEntry("move_pages", UnknownArguments()), // 239
MakeEntry("rt_tgsigqueueinfo", UnknownArguments()), // 240
MakeEntry("perf_event_open", UnknownArguments()), // 241
MakeEntry("accept4", UnknownArguments()), // 242
MakeEntry("recvmmsg", kInt, kHex, kHex, kHex, kGen, kGen), // 243
SYSCALLS_UNUSED("UNUSED244"), // 244
SYSCALLS_UNUSED("UNUSED245"), // 245
SYSCALLS_UNUSED("UNUSED246"), // 246
SYSCALLS_UNUSED("UNUSED247"), // 247
SYSCALLS_UNUSED("UNUSED248"), // 248
SYSCALLS_UNUSED("UNUSED249"), // 249
SYSCALLS_UNUSED("UNUSED250"), // 250
SYSCALLS_UNUSED("UNUSED251"), // 251
SYSCALLS_UNUSED("UNUSED252"), // 252
SYSCALLS_UNUSED("UNUSED253"), // 253
SYSCALLS_UNUSED("UNUSED254"), // 254
SYSCALLS_UNUSED("UNUSED255"), // 255
SYSCALLS_UNUSED("UNUSED256"), // 256
SYSCALLS_UNUSED("UNUSED257"), // 257
SYSCALLS_UNUSED("UNUSED258"), // 258
SYSCALLS_UNUSED("UNUSED259"), // 259
MakeEntry("wait4", kInt, kHex, kHex, kHex, kGen, kGen), // 260
MakeEntry("prlimit64", kInt, kInt, kHex, kHex, kGen, kGen), // 261
MakeEntry("fanotify_init", kHex, kHex, kInt, kGen, kGen, kGen), // 262
MakeEntry("fanotify_mark", kInt, kHex, kInt, kPath, kGen, kGen), // 263
MakeEntry("name_to_handle_at", kInt, kGen, kHex, kHex, kHex, kGen), // 264
MakeEntry("open_by_handle_at", kInt, kHex, kHex, kGen, kGen, kGen), // 265
MakeEntry("clock_adjtime", kInt, kHex, kGen, kGen, kGen, kGen), // 266
MakeEntry("syncfs", kInt, kGen, kGen, kGen, kGen, kGen), // 267
MakeEntry("setns", kInt, kHex, kGen, kGen, kGen, kGen), // 268
MakeEntry("sendmmsg", kInt, kHex, kInt, kHex, kGen, kGen), // 269
MakeEntry("process_vm_readv", kInt, kHex, kInt, kHex, kInt, kInt), // 270
MakeEntry("process_vm_writev", kInt, kHex, kInt, kHex, kInt, kInt), // 271
MakeEntry("kcmp", kInt, kInt, kInt, kHex, kHex, kGen), // 272
MakeEntry("finit_module", kInt, kPath, kHex, kGen, kGen, kGen), // 273
MakeEntry("sched_setattr", UnknownArguments()), // 274
MakeEntry("sched_getattr", UnknownArguments()), // 275
MakeEntry("renameat2", kGen, kPath, kGen, kPath, kGen, kGen), // 276
MakeEntry("seccomp", UnknownArguments()), // 277
MakeEntry("getrandom", UnknownArguments()), // 278
MakeEntry("memfd_create", UnknownArguments()), // 279
};
#undef SYSCALLS_UNUSED00_99
#undef SYSCALLS_UNUSED50_99
#undef SYSCALLS_UNUSED00_49
@ -1230,6 +1515,8 @@ SyscallTable SyscallTable::get(cpu::Architecture arch) {
return SyscallTable(kSyscallDataX8632);
case cpu::kPPC64LE:
return SyscallTable(kSyscallDataPPC64LE);
case cpu::kArm64:
return SyscallTable(kSyscallDataArm64);
default:
return SyscallTable();
}

View File

@ -126,8 +126,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 architecture not supported, see config.h");
static_assert(
host_cpu::IsX8664() || host_cpu::IsPPC64LE() || host_cpu::IsArm64(),
"Host CPU architecture not supported, see config.h");
// Stack grows down.
void* stack = stack_buf + sizeof(stack_buf);
int r;

View File

@ -25,7 +25,6 @@ enum PBViolationType {
SYSCALL_ARCHITECTURE_MISMATCH = 3;
}
// X86_64 not allowed (naming convention...)
message RegisterX8664 {
uint64 r15 = 1;
uint64 r14 = 2;
@ -77,7 +76,6 @@ message RegisterPowerpc64 {
uint64 zero3 = 17;
}
// Deprecated.
message RegisterAarch64 {
repeated uint64 regs = 1;
uint64 sp = 2;
@ -90,7 +88,7 @@ message RegisterValues {
oneof register_values {
RegisterX8664 register_x86_64 = 2;
RegisterPowerpc64 register_powerpc64 = 3;
RegisterAarch64 register_aarch64 = 4; // Deprecated.
RegisterAarch64 register_aarch64 = 4;
}
}