#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/prctl.h>
#include <sys/ptrace.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <memory>
#include <vector>
#include "base/containers/adapters.h"
#include "base/containers/contains.h"
#if defined(ANDROID)
#define __user
#endif
#include <linux/futex.h>
#include "base/check.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/posix/eintr_wrapper.h"
#include "base/synchronization/waitable_event.h"
#include "base/system/sys_info.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/bpf_dsl/errorcode.h"
#include "sandbox/linux/bpf_dsl/linux_syscall_ranges.h"
#include "sandbox/linux/bpf_dsl/policy.h"
#include "sandbox/linux/bpf_dsl/seccomp_macros.h"
#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
#include "sandbox/linux/seccomp-bpf/die.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
#include "sandbox/linux/seccomp-bpf/syscall.h"
#include "sandbox/linux/seccomp-bpf/trap.h"
#include "sandbox/linux/services/syscall_wrappers.h"
#include "sandbox/linux/services/thread_helpers.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"
#include "sandbox/linux/tests/scoped_temporary_file.h"
#include "sandbox/linux/tests/unit_tests.h"
#include "testing/gtest/include/gtest/gtest.h"
#ifndef PR_GET_ENDIAN
#define PR_GET_ENDIAN …
#endif
#ifndef PR_CAPBSET_READ
#define PR_CAPBSET_READ …
#define PR_CAPBSET_DROP …
#endif
namespace sandbox {
namespace bpf_dsl {
namespace {
const int kExpectedReturnValue = …;
const char kSandboxDebuggingEnv[] = …;
void EnableUnsafeTraps() { … }
intptr_t IncreaseCounter(const struct arch_seccomp_data& args, void* aux) { … }
class VerboseAPITestingPolicy : public Policy { … };
SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(VerboseAPITesting)) { … }
class DenylistNanosleepPolicy : public Policy { … };
BPF_TEST_C(SandboxBPF, ApplyBasicDenylistPolicy, DenylistNanosleepPolicy) { …
BPF_TEST_C(SandboxBPF, UseVsyscall, DenylistNanosleepPolicy) { … }
bool IsSyscallForTestHarness(int sysno) { … }
class AllowlistGetpidPolicy : public Policy { … };
BPF_TEST_C(SandboxBPF, ApplyBasicAllowlistPolicy, AllowlistGetpidPolicy) { …
intptr_t EnomemHandler(const struct arch_seccomp_data& args, void* aux) { … }
class DenylistNanosleepTrapPolicy : public Policy { … };
BPF_TEST(SandboxBPF,
BasicDenylistWithSigsys,
DenylistNanosleepTrapPolicy,
int ) { … }
class ErrnoTestPolicy : public Policy { … };
ResultExpr ErrnoTestPolicy::EvaluateSyscall(int sysno) const { … }
BPF_TEST_C(SandboxBPF, ErrnoTest, ErrnoTestPolicy) { … }
class StackingPolicyPartOne : public Policy { … };
class StackingPolicyPartTwo : public Policy { … };
BPF_DEATH_TEST_C(SandboxBPF,
StackingPolicy,
DEATH_SUCCESS_ALLOW_NOISE(),
StackingPolicyPartOne) { … }
int SysnoToRandomErrno(int sysno) { … }
class SyntheticPolicy : public Policy { … };
BPF_TEST_C(SandboxBPF, SyntheticPolicy, SyntheticPolicy) { … }
#if defined(__arm__)
int ArmPrivateSysnoToErrno(int sysno) {
if (sysno >= static_cast<int>(MIN_PRIVATE_SYSCALL) &&
sysno <= static_cast<int>(MAX_PRIVATE_SYSCALL)) {
return (sysno - MIN_PRIVATE_SYSCALL) + 1;
}
return ENOSYS;
}
class ArmPrivatePolicy : public Policy {
public:
ArmPrivatePolicy() = default;
ArmPrivatePolicy(const ArmPrivatePolicy&) = delete;
ArmPrivatePolicy& operator=(const ArmPrivatePolicy&) = delete;
~ArmPrivatePolicy() override = default;
ResultExpr EvaluateSyscall(int sysno) const override {
DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
if (sysno >= static_cast<int>(__ARM_NR_set_tls + 1) &&
sysno <= static_cast<int>(MAX_PRIVATE_SYSCALL)) {
return Error(ArmPrivateSysnoToErrno(sysno));
}
return Allow();
}
};
BPF_TEST_C(SandboxBPF, ArmPrivatePolicy, ArmPrivatePolicy) {
for (int syscall_number = static_cast<int>(__ARM_NR_set_tls + 1);
syscall_number <= static_cast<int>(MAX_PRIVATE_SYSCALL);
++syscall_number) {
errno = 0;
BPF_ASSERT(syscall(syscall_number) == -1);
BPF_ASSERT(errno == ArmPrivateSysnoToErrno(syscall_number));
}
}
#endif
intptr_t CountSyscalls(const struct arch_seccomp_data& args, void* aux) { … }
class GreyListedPolicy : public Policy { … };
BPF_TEST(SandboxBPF, GreyListedPolicy, GreyListedPolicy, int ) { … }
SANDBOX_TEST(SandboxBPF, EnableUnsafeTrapsInSigSysHandler) { …
intptr_t PrctlHandler(const struct arch_seccomp_data& args, void*) { … }
class PrctlPolicy : public Policy { … };
BPF_TEST_C(SandboxBPF, ForwardSyscall, PrctlPolicy) { … }
intptr_t AllowRedirectedSyscall(const struct arch_seccomp_data& args, void*) { … }
class RedirectAllSyscallsPolicy : public Policy { … };
ResultExpr RedirectAllSyscallsPolicy::EvaluateSyscall(int sysno) const { … }
#if !defined(ADDRESS_SANITIZER)
int bus_handler_fd_ = …;
void SigBusHandler(int, siginfo_t* info, void* void_context) { … }
BPF_TEST_C(SandboxBPF, SigBus, RedirectAllSyscallsPolicy) { … }
#endif
BPF_TEST_C(SandboxBPF, SigMask, RedirectAllSyscallsPolicy) { … }
BPF_TEST_C(SandboxBPF, UnsafeTrapWithErrno, RedirectAllSyscallsPolicy) { … }
class SimpleCondTestPolicy : public Policy { … };
ResultExpr SimpleCondTestPolicy::EvaluateSyscall(int sysno) const { … }
BPF_TEST_C(SandboxBPF, SimpleCondTest, SimpleCondTestPolicy) { … }
class EqualityStressTest { … };
class EqualityStressTestPolicy : public Policy { … };
BPF_TEST(SandboxBPF,
EqualityTests,
EqualityStressTestPolicy,
EqualityStressTest ) { …
class EqualityArgumentWidthPolicy : public Policy { … };
ResultExpr EqualityArgumentWidthPolicy::EvaluateSyscall(int sysno) const { … }
BPF_TEST_C(SandboxBPF, EqualityArgumentWidth, EqualityArgumentWidthPolicy) { …
#if __SIZEOF_POINTER__ > 4
BPF_DEATH_TEST_C(SandboxBPF,
EqualityArgumentUnallowed64bit,
DEATH_MESSAGE("Unexpected 64bit argument detected"),
EqualityArgumentWidthPolicy) { … }
#endif
class EqualityWithNegativeArgumentsPolicy : public Policy { … };
BPF_TEST_C(SandboxBPF,
EqualityWithNegativeArguments,
EqualityWithNegativeArgumentsPolicy) { …
#if __SIZEOF_POINTER__ > 4
BPF_DEATH_TEST_C(SandboxBPF,
EqualityWithNegative64bitArguments,
DEATH_MESSAGE("Unexpected 64bit argument detected"),
EqualityWithNegativeArgumentsPolicy) { … }
#endif
class AllBitTestPolicy : public Policy { … };
ResultExpr AllBitTestPolicy::HasAllBits32(uint32_t bits) { … }
ResultExpr AllBitTestPolicy::HasAllBits64(uint64_t bits) { … }
ResultExpr AllBitTestPolicy::EvaluateSyscall(int sysno) const { … }
#define BITMASK_TEST(testcase, arg, op, mask, expected_value) …
#define EXPECT_FAILURE …
#define EXPECT_SUCCESS …
#define EXPT64_SUCCESS …
BPF_TEST_C(SandboxBPF, AllBitTests, AllBitTestPolicy) { …
class AnyBitTestPolicy : public Policy { … };
ResultExpr AnyBitTestPolicy::HasAnyBits32(uint32_t bits) { … }
ResultExpr AnyBitTestPolicy::HasAnyBits64(uint64_t bits) { … }
ResultExpr AnyBitTestPolicy::EvaluateSyscall(int sysno) const { … }
BPF_TEST_C(SandboxBPF, AnyBitTests, AnyBitTestPolicy) { …
class MaskedEqualTestPolicy : public Policy { … };
ResultExpr MaskedEqualTestPolicy::MaskedEqual32(uint32_t mask, uint32_t value) { … }
ResultExpr MaskedEqualTestPolicy::MaskedEqual64(uint64_t mask, uint64_t value) { … }
ResultExpr MaskedEqualTestPolicy::EvaluateSyscall(int sysno) const { … }
#define MASKEQ_TEST(rulenum, arg, expected_result) …
BPF_TEST_C(SandboxBPF, MaskedEqualTests, MaskedEqualTestPolicy) { …
intptr_t PthreadTrapHandler(const struct arch_seccomp_data& args, void* aux) { … }
class PthreadPolicyEquality : public Policy { … };
ResultExpr PthreadPolicyEquality::EvaluateSyscall(int sysno) const { … }
class PthreadPolicyBitMask : public Policy { … };
BoolExpr PthreadPolicyBitMask::HasAnyBits(const Arg<unsigned long>& arg,
unsigned long bits) { … }
BoolExpr PthreadPolicyBitMask::HasAllBits(const Arg<unsigned long>& arg,
unsigned long bits) { … }
ResultExpr PthreadPolicyBitMask::EvaluateSyscall(int sysno) const { … }
static void* ThreadFnc(void* arg) { … }
static void PthreadTest() { … }
BPF_TEST_C(SandboxBPF, PthreadEquality, PthreadPolicyEquality) { …
BPF_TEST_C(SandboxBPF, PthreadBitMask, PthreadPolicyBitMask) { …
#ifndef PTRACE_O_TRACESECCOMP
#define PTRACE_O_TRACESECCOMP …
#endif
#ifdef PTRACE_EVENT_SECCOMP
#define IS_SECCOMP_EVENT …
#else
#define IS_SECCOMP_EVENT(status) …
#endif
#if defined(__arm__)
#ifndef PTRACE_SET_SYSCALL
#define PTRACE_SET_SYSCALL …
#endif
#endif
#if defined(__aarch64__)
#ifndef PTRACE_GETREGS
#if defined(__GLIBC__)
#define PTRACE_GETREGS …
#else
#define PTRACE_GETREGS …
#endif
#endif
#endif
#if defined(__aarch64__)
#ifndef PTRACE_SETREGS
#if defined(__GLIBC__)
#define PTRACE_SETREGS …
#else
#define PTRACE_SETREGS …
#endif
#endif
#endif
#if !defined(__arm__) && !defined(__aarch64__) && !defined(__mips__)
long SetSyscall(pid_t pid, regs_struct* regs, int syscall_number) { … }
#endif
const uint16_t kTraceData = …;
class TraceAllPolicy : public Policy { … };
SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(SeccompRetTrace)) { … }
#if !BUILDFLAG(IS_ANDROID)
bool FullPwrite64(int fd, const char* buffer, size_t count, off64_t offset) { … }
bool FullPread64(int fd, char* buffer, size_t count, off64_t offset) { … }
bool pread_64_was_forwarded = …;
class TrapPread64Policy : public Policy { … };
BPF_TEST_C(SandboxBPF, Pread64, TrapPread64Policy) { … }
#endif
void* TsyncApplyToTwoThreadsFunc(void* cond_ptr) { … }
SANDBOX_TEST(SandboxBPF, Tsync) { … }
class AllowAllPolicy : public Policy { … };
SANDBOX_DEATH_TEST(
SandboxBPF,
StartMultiThreadedAsSingleThreaded,
DEATH_MESSAGE(
ThreadHelpers::GetAssertSingleThreadedErrorMessageForTests())) { … }
intptr_t NoOpHandler(const struct arch_seccomp_data& args, void*) { … }
class UnsafeTrapWithCondPolicy : public Policy { … };
BPF_TEST_C(SandboxBPF, UnsafeTrapWithCond, UnsafeTrapWithCondPolicy) { …
}
}
}