blob: dca79767558b812845477df0eb92b588d51a6ed5 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/service_manager/sandbox/linux/bpf_audio_policy_linux.h"
#include <sys/socket.h>
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
#include "sandbox/linux/services/syscall_wrappers.h"
#include "sandbox/linux/syscall_broker/broker_process.h"
#include "sandbox/linux/system_headers/linux_futex.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"
#include "services/service_manager/sandbox/linux/sandbox_linux.h"
using sandbox::bpf_dsl::Allow;
using sandbox::bpf_dsl::Arg;
using sandbox::bpf_dsl::Error;
using sandbox::bpf_dsl::If;
using sandbox::bpf_dsl::ResultExpr;
using sandbox::bpf_dsl::Trap;
using sandbox::syscall_broker::BrokerProcess;
namespace service_manager {
AudioProcessPolicy::AudioProcessPolicy() = default;
AudioProcessPolicy::~AudioProcessPolicy() = default;
ResultExpr AudioProcessPolicy::EvaluateSyscall(int system_call_number) const {
switch (system_call_number) {
#if defined(__NR_connect)
case __NR_connect:
#endif
#if defined(__NR_ftruncate)
case __NR_ftruncate:
#endif
#if defined(__NR_ftruncate64)
case __NR_ftruncate64:
#endif
#if defined(__NR_fallocate)
case __NR_fallocate:
#endif
#if defined(__NR_getdents)
case __NR_getdents:
#endif
#if defined(__NR_getpeername)
case __NR_getpeername:
#endif
#if defined(__NR_getsockopt)
case __NR_getsockopt:
#endif
#if defined(__NR_getsockname)
case __NR_getsockname:
#endif
#if defined(__NR_ioctl)
case __NR_ioctl:
#endif
#if defined(__NR_memfd_create)
case __NR_memfd_create:
#endif
#if defined(__NR_pwrite)
case __NR_pwrite:
#endif
#if defined(__NR_pwrite64)
case __NR_pwrite64:
#endif
#if defined(__NR_sched_setscheduler)
case __NR_sched_setscheduler:
#endif
#if defined(__NR_setsockopt)
case __NR_setsockopt:
#endif
#if defined(__NR_uname)
case __NR_uname:
#endif
return Allow();
#if defined(__NR_futex)
case __NR_futex: {
const Arg<int> op(1);
#if defined(USE_PULSEAUDIO)
return Switch(op & ~FUTEX_PRIVATE_FLAG)
.SANDBOX_BPF_DSL_CASES(
(FUTEX_CMP_REQUEUE, FUTEX_LOCK_PI, FUTEX_UNLOCK_PI, FUTEX_WAIT,
FUTEX_WAIT_BITSET, FUTEX_WAKE),
Allow())
.Default(Error(EPERM));
#else
return sandbox::RestrictFutex();
#endif
}
#endif
#if defined(__NR_kill)
case __NR_kill: {
// man kill says:
// "If sig is 0, then no signal is sent, but existence and permission
// checks are still performed; this can be used to check for the
// existence of a process ID or process group ID that the caller is
// permitted to signal."
//
// This seems to be tripping up at least ESET's NOD32 anti-virus, causing
// an unnecessary crash in the audio process. See: http://crbug.com/904787
const Arg<pid_t> pid(0);
const Arg<int> sig(1);
return If(pid == sandbox::sys_getpid(), Allow())
.ElseIf(sig == 0, Error(EPERM))
.Else(sandbox::CrashSIGSYSKill());
}
#endif
#if defined(__NR_socket)
case __NR_socket: {
const Arg<int> domain(0);
return If(domain == AF_UNIX, Allow()).Else(Error(EPERM));
}
#endif
default:
#if defined(__x86_64__)
if (sandbox::SyscallSets::IsSystemVSemaphores(system_call_number) ||
sandbox::SyscallSets::IsSystemVSharedMemory(system_call_number)) {
return Allow();
}
#elif defined(__i386__)
if (sandbox::SyscallSets::IsSystemVIpc(system_call_number))
return Allow();
#endif
auto* broker_process = SandboxLinux::GetInstance()->broker_process();
if (broker_process->IsSyscallAllowed(system_call_number))
return Trap(BrokerProcess::SIGSYS_Handler, broker_process);
return BPFBasePolicy::EvaluateSyscall(system_call_number);
}
}
} // namespace service_manager