Commit f5afc495 authored by jln's avatar jln Committed by Commit bot

NonSFI sandbox: restrict futex(2) operations.

We restrict futex operations to everything but "priority inheritance".

BUG=408847
CQ_EXTRA_TRYBOTS=tryserver.chromium.linux:linux_rel_precise32

Review URL: https://codereview.chromium.org/549653002

Cr-Commit-Position: refs/heads/master@{#293776}
parent de3a5e8b
......@@ -6,12 +6,14 @@
#include <errno.h>
#include <fcntl.h>
#include <linux/futex.h>
#include <linux/net.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/ptrace.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include "base/basictypes.h"
#include "base/logging.h"
......@@ -28,11 +30,15 @@
#define MAP_STACK 0x20000
#endif
#define CASES SANDBOX_BPF_DSL_CASES
using sandbox::CrashSIGSYS;
using sandbox::CrashSIGSYSClone;
using sandbox::CrashSIGSYSFutex;
using sandbox::CrashSIGSYSPrctl;
using sandbox::bpf_dsl::Allow;
using sandbox::bpf_dsl::Arg;
using sandbox::bpf_dsl::BoolExpr;
using sandbox::bpf_dsl::Error;
using sandbox::bpf_dsl::If;
using sandbox::bpf_dsl::ResultExpr;
......@@ -95,6 +101,23 @@ ResultExpr RestrictClone() {
Allow()).Else(CrashSIGSYSClone());
}
ResultExpr RestrictFutexOperation() {
// TODO(hamaji): Allow only FUTEX_PRIVATE_FLAG futexes.
const int kAllowedFutexFlags = FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME;
const int kOperationMask = ~kAllowedFutexFlags;
const Arg<int> op(1);
return Switch(op & kOperationMask)
.CASES((FUTEX_WAIT,
FUTEX_WAKE,
FUTEX_REQUEUE,
FUTEX_CMP_REQUEUE,
FUTEX_WAKE_OP,
FUTEX_WAIT_BITSET,
FUTEX_WAKE_BITSET),
Allow())
.Default(CrashSIGSYSFutex());
}
ResultExpr RestrictPrctl() {
// base::PlatformThread::SetName() uses PR_SET_NAME so we return
// EPERM for it. Otherwise, we will raise SIGSYS.
......@@ -214,8 +237,6 @@ ResultExpr NaClNonSfiBPFSandboxPolicy::EvaluateSyscall(int sysno) const {
#elif defined(__x86_64__)
case __NR_fstat:
#endif
// TODO(hamaji): Allow only FUTEX_PRIVATE_FLAG.
case __NR_futex:
// TODO(hamaji): Remove the need of gettid. Currently, this is
// called from PlatformThread::CurrentId().
case __NR_gettid:
......@@ -256,6 +277,9 @@ ResultExpr NaClNonSfiBPFSandboxPolicy::EvaluateSyscall(int sysno) const {
#endif
return RestrictFcntlCommands();
case __NR_futex:
return RestrictFutexOperation();
#if defined(__x86_64__)
case __NR_mmap:
#endif
......
......@@ -10,6 +10,7 @@
#include <errno.h>
#include <fcntl.h>
#include <linux/futex.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
......@@ -32,6 +33,7 @@
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "base/sys_info.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
......@@ -306,6 +308,38 @@ BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
fcntl(0, F_DUPFD_CLOEXEC);
}
BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
FutexWithRequeuePriorityInheritence,
DEATH_MESSAGE(sandbox::GetFutexErrorMessageContentForTests()),
nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI, 0, NULL, NULL, 0);
_exit(1);
}
BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
FutexWithRequeuePriorityInheritencePrivate,
DEATH_MESSAGE(sandbox::GetFutexErrorMessageContentForTests()),
nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI_PRIVATE, 0, NULL, NULL, 0);
_exit(1);
}
BPF_TEST_C(NaClNonSfiSandboxTest,
StartingAndJoiningThreadWorks,
nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
base::Thread thread("sandbox_tests");
BPF_ASSERT(thread.Start());
// |thread|'s destructor will join the thread.
}
BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
FutexWithUnlockPIPrivate,
DEATH_MESSAGE(sandbox::GetFutexErrorMessageContentForTests()),
nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
syscall(__NR_futex, NULL, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0);
_exit(1);
}
void* DoAllowedAnonymousMmap() {
return mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_SHARED, -1, 0);
......
......@@ -229,12 +229,10 @@ ResultExpr RestrictKillTarget(pid_t target_pid, int sysno) {
ResultExpr RestrictFutex() {
const int kAllowedFutexFlags = FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME;
const int kOperationMask = ~kAllowedFutexFlags;
const Arg<int> op(1);
return Switch(op & kOperationMask)
.CASES((FUTEX_WAIT,
FUTEX_WAKE,
FUTEX_FD,
FUTEX_REQUEUE,
FUTEX_CMP_REQUEUE,
FUTEX_WAKE_OP,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment