#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include <fcntl.h>
#include <linux/net.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <sys/syscall.h>
#include <unistd.h>
#include "base/check.h"
#include "base/debug/crash_logging.h"
#include "base/posix/eintr_wrapper.h"
#include "base/strings/safe_sprintf.h"
#include "build/build_config.h"
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
#include "sandbox/linux/seccomp-bpf/syscall.h"
#include "sandbox/linux/services/syscall_wrappers.h"
#include "sandbox/linux/system_headers/linux_seccomp.h"
#include "sandbox/linux/system_headers/linux_stat.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"
#if BUILDFLAG(IS_ANDROID)
#include <android/log.h>
#endif
#if defined(__mips__)
#include <asm/unistd.h>
#endif
#define SECCOMP_MESSAGE_COMMON_CONTENT …
#define SECCOMP_MESSAGE_CLONE_CONTENT …
#define SECCOMP_MESSAGE_PRCTL_CONTENT …
#define SECCOMP_MESSAGE_IOCTL_CONTENT …
#define SECCOMP_MESSAGE_KILL_CONTENT …
#define SECCOMP_MESSAGE_FUTEX_CONTENT …
#define SECCOMP_MESSAGE_PTRACE_CONTENT …
#define SECCOMP_MESSAGE_SOCKET_CONTENT …
#define SECCOMP_MESSAGE_SOCKOPT_CONTENT …
namespace {
#if BUILDFLAG(IS_ANDROID)
constexpr char kLogTag[] = "cr_seccomp";
#endif
base::debug::CrashKeyString* seccomp_crash_key = …;
inline bool IsArchitectureX86_64() { … }
void WriteToStdErr(const char* error_message, size_t size) { … }
uint32_t SyscallNumberToOffsetFromBase(uint32_t sysno) { … }
void PrintAndSetSeccompCrashKey(const struct arch_seccomp_data& args) { … }
}
namespace sandbox {
intptr_t CrashSIGSYS_Handler(const struct arch_seccomp_data& args, void* aux) { … }
intptr_t SIGSYSCloneFailure(const struct arch_seccomp_data& args, void* aux) { … }
intptr_t SIGSYSPrctlFailure(const struct arch_seccomp_data& args,
void* ) { … }
intptr_t SIGSYSIoctlFailure(const struct arch_seccomp_data& args,
void* ) { … }
intptr_t SIGSYSKillFailure(const struct arch_seccomp_data& args,
void* ) { … }
intptr_t SIGSYSFutexFailure(const struct arch_seccomp_data& args,
void* ) { … }
intptr_t SIGSYSPtraceFailure(const struct arch_seccomp_data& args,
void* ) { … }
intptr_t SIGSYSSocketFailure(const struct arch_seccomp_data& args, void* aux) { … }
intptr_t SIGSYSSockoptFailure(const struct arch_seccomp_data& args, void* aux) { … }
intptr_t SIGSYSSchedHandler(const struct arch_seccomp_data& args,
void* aux) { … }
intptr_t SIGSYSFstatatHandler(const struct arch_seccomp_data& args,
void* fs_denied_errno) { … }
bpf_dsl::ResultExpr CrashSIGSYS() { … }
bpf_dsl::ResultExpr CrashSIGSYSClone() { … }
bpf_dsl::ResultExpr CrashSIGSYSPrctl() { … }
bpf_dsl::ResultExpr CrashSIGSYSIoctl() { … }
bpf_dsl::ResultExpr CrashSIGSYSKill() { … }
bpf_dsl::ResultExpr CrashSIGSYSFutex() { … }
bpf_dsl::ResultExpr CrashSIGSYSPtrace() { … }
bpf_dsl::ResultExpr CrashSIGSYSSocket() { … }
bpf_dsl::ResultExpr CrashSIGSYSSockopt() { … }
bpf_dsl::ResultExpr RewriteSchedSIGSYS() { … }
bpf_dsl::ResultExpr RewriteFstatatSIGSYS(int fs_denied_errno) { … }
#if defined(__NR_socketcall)
bool CanRewriteSocketcall() {
static bool can_rewrite_socketcall = []() {
base::ScopedFD socket_fd(
syscall(__NR_socket, 0xffffff, 0xffffff, 0xffffff));
if (!socket_fd.is_valid() && errno == ENOSYS) {
return false;
}
return true;
}();
return can_rewrite_socketcall;
}
intptr_t SIGSYSSocketcallHandler(const struct arch_seccomp_data& args,
void* aux) {
const long kLastSocketcall = SYS_SENDMMSG;
static const struct {
long sysno;
size_t num_args;
size_t num_zeroes = 0;
} socketcall_args[kLastSocketcall + 1] = {
{.sysno = -1, .num_args = 0},
{.sysno = __NR_socket, .num_args = 3},
{.sysno = __NR_bind, .num_args = 3},
{.sysno = __NR_connect, .num_args = 3},
{.sysno = __NR_listen, .num_args = 2},
{.sysno = __NR_accept4, .num_args = 3, .num_zeroes = 1},
{.sysno = __NR_getsockname, .num_args = 3},
{.sysno = __NR_getpeername, .num_args = 3},
{.sysno = __NR_socketpair, .num_args = 4},
{.sysno = __NR_sendto, .num_args = 4, .num_zeroes = 2},
{.sysno = __NR_recvfrom, .num_args = 4, .num_zeroes = 2},
{.sysno = __NR_sendto, .num_args = 6},
{.sysno = __NR_recvfrom, .num_args = 6},
{.sysno = __NR_shutdown, .num_args = 2},
{.sysno = __NR_setsockopt, .num_args = 5},
{.sysno = __NR_getsockopt, .num_args = 5},
{.sysno = __NR_sendmsg, .num_args = 3},
{.sysno = __NR_recvmsg, .num_args = 3},
{.sysno = __NR_accept4, .num_args = 4},
{.sysno = __NR_recvmmsg, .num_args = 5},
{.sysno = __NR_sendmmsg, .num_args = 4}};
uint64_t call = args.args[0];
if (args.nr == __NR_socketcall && 0 < call && call <= kLastSocketcall) {
const size_t real_args_arr_len =
socketcall_args[call].num_args + socketcall_args[call].num_zeroes;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wvla-extension"
unsigned long real_args_arr[real_args_arr_len];
#pragma clang diagnostic pop
memcpy(real_args_arr, reinterpret_cast<unsigned long*>(args.args[1]),
real_args_arr_len * sizeof(unsigned long));
memset(real_args_arr + socketcall_args[call].num_args, 0,
socketcall_args[call].num_zeroes * sizeof(unsigned long));
switch (real_args_arr_len) {
case 2:
return syscall(socketcall_args[call].sysno, real_args_arr[0],
real_args_arr[1]);
case 3:
return syscall(socketcall_args[call].sysno, real_args_arr[0],
real_args_arr[1], real_args_arr[2]);
case 4:
return syscall(socketcall_args[call].sysno, real_args_arr[0],
real_args_arr[1], real_args_arr[2], real_args_arr[3]);
case 5:
return syscall(socketcall_args[call].sysno, real_args_arr[0],
real_args_arr[1], real_args_arr[2], real_args_arr[3],
real_args_arr[4]);
case 6:
return syscall(socketcall_args[call].sysno, real_args_arr[0],
real_args_arr[1], real_args_arr[2], real_args_arr[3],
real_args_arr[4], real_args_arr[5]);
default:
break;
}
}
CrashSIGSYS_Handler(args, aux);
RAW_CHECK(false);
return -ENOSYS;
}
bpf_dsl::ResultExpr RewriteSocketcallSIGSYS() {
return bpf_dsl::Trap(SIGSYSSocketcallHandler, nullptr);
}
#endif
void AllocateCrashKeys() { … }
const char* GetErrorMessageContentForTests() { … }
const char* GetCloneErrorMessageContentForTests() { … }
const char* GetPrctlErrorMessageContentForTests() { … }
const char* GetIoctlErrorMessageContentForTests() { … }
const char* GetKillErrorMessageContentForTests() { … }
const char* GetFutexErrorMessageContentForTests() { … }
const char* GetPtraceErrorMessageContentForTests() { … }
const char* GetSocketErrorMessageContentForTests() { … }
const char* GetSockoptErrorMessageContentForTests() { … }
}