summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-06 18:58:33 +0000
committerjln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-06 18:58:33 +0000
commitb66edd015fcd9d0df571d3b6ea3fcba62535efe3 (patch)
tree4108cc3a9ab0bbd0dd258e907d0d39e557171ab3
parentbf69c12ea557c501b4ea4f2819e5f39171d363bd (diff)
downloadchromium_src-b66edd015fcd9d0df571d3b6ea3fcba62535efe3.zip
chromium_src-b66edd015fcd9d0df571d3b6ea3fcba62535efe3.tar.gz
chromium_src-b66edd015fcd9d0df571d3b6ea3fcba62535efe3.tar.bz2
Merge 274934 "Linux sandbox: restrict futex operations."
> Linux sandbox: restrict futex operations. > > First-pass at restricting futex operations. We ban FUTEX_CMP_REQUEUE_PI, as it is > not used throughout Chrome. > > BUG=377392 > R=mdempsky@chromium.org > > Review URL: https://codereview.chromium.org/314903002 TBR=jln@chromium.org Review URL: https://codereview.chromium.org/317373003 git-svn-id: svn://svn.chromium.org/chrome/branches/1985/src@275491 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--sandbox/linux/sandbox_linux.gypi1
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc5
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc25
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc17
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h8
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc27
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h3
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc4
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/syscall_sets.h2
-rw-r--r--sandbox/linux/services/android_futex.h28
10 files changed, 115 insertions, 5 deletions
diff --git a/sandbox/linux/sandbox_linux.gypi b/sandbox/linux/sandbox_linux.gypi
index 0fdb6ba..8f433f0 100644
--- a/sandbox/linux/sandbox_linux.gypi
+++ b/sandbox/linux/sandbox_linux.gypi
@@ -255,6 +255,7 @@
'type': 'none',
'sources': [
'services/android_arm_ucontext.h',
+ 'services/android_futex.h',
'services/android_ucontext.h',
'services/android_i386_ucontext.h',
'services/arm_linux_syscalls.h',
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
index 217bdac..5106fba 100644
--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
@@ -32,13 +32,13 @@ bool IsBaselinePolicyAllowed(int sysno) {
SyscallSets::IsAllowedBasicScheduler(sysno) ||
SyscallSets::IsAllowedEpoll(sysno) ||
SyscallSets::IsAllowedFileSystemAccessViaFd(sysno) ||
+ SyscallSets::IsAllowedFutex(sysno) ||
SyscallSets::IsAllowedGeneralIo(sysno) ||
SyscallSets::IsAllowedGetOrModifySocket(sysno) ||
SyscallSets::IsAllowedGettime(sysno) ||
SyscallSets::IsAllowedPrctl(sysno) ||
SyscallSets::IsAllowedProcessStartOrDeath(sysno) ||
SyscallSets::IsAllowedSignalHandling(sysno) ||
- SyscallSets::IsFutex(sysno) ||
SyscallSets::IsGetSimpleId(sysno) ||
SyscallSets::IsKernelInternalApi(sysno) ||
#if defined(__arm__)
@@ -111,6 +111,9 @@ ErrorCode EvaluateSyscallImpl(int fs_denied_errno,
}
#endif
+ if (sysno == __NR_futex)
+ return RestrictFutex(sandbox);
+
if (sysno == __NR_madvise) {
// Only allow MADV_DONTNEED (aka MADV_FREE).
return sandbox->Cond(2, ErrorCode::TP_32BIT,
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
index 9182e07..97cc18f 100644
--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
@@ -5,8 +5,14 @@
#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h"
#include <errno.h>
+#include <linux/futex.h>
+#include <sched.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/syscall.h>
+#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
@@ -17,6 +23,7 @@
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/services/android_futex.h"
#include "sandbox/linux/services/linux_syscalls.h"
#include "sandbox/linux/services/thread_helpers.h"
#include "sandbox/linux/tests/unit_tests.h"
@@ -110,6 +117,24 @@ BPF_DEATH_TEST_C(BaselinePolicy,
#endif // !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER)
+#if !defined(OS_ANDROID)
+BPF_DEATH_TEST_C(BaselinePolicy,
+ FutexWithRequeuePriorityInheritence,
+ DEATH_MESSAGE(GetFutexErrorMessageContentForTests()),
+ BaselinePolicy) {
+ syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI, 0, NULL, NULL, 0);
+ _exit(1);
+}
+
+BPF_DEATH_TEST_C(BaselinePolicy,
+ FutexWithRequeuePriorityInheritencePrivate,
+ DEATH_MESSAGE(GetFutexErrorMessageContentForTests()),
+ BaselinePolicy) {
+ syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI_PRIVATE, 0, NULL, NULL, 0);
+ _exit(1);
+}
+#endif // !defined(OS_ANDROID)
+
} // namespace
} // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
index c4a6f92..6639496 100644
--- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
@@ -18,6 +18,7 @@
#define SECCOMP_MESSAGE_PRCTL_CONTENT "prctl() failure"
#define SECCOMP_MESSAGE_IOCTL_CONTENT "ioctl() failure"
#define SECCOMP_MESSAGE_KILL_CONTENT "(tg)kill() failure"
+#define SECCOMP_MESSAGE_FUTEX_CONTENT "futex() failure"
namespace {
@@ -164,6 +165,18 @@ intptr_t SIGSYSKillFailure(const struct arch_seccomp_data& args,
_exit(1);
}
+intptr_t SIGSYSFutexFailure(const struct arch_seccomp_data& args,
+ void* /* aux */) {
+ static const char kSeccompFutexError[] =
+ __FILE__ ":**CRASHING**:" SECCOMP_MESSAGE_FUTEX_CONTENT "\n";
+ WriteToStdErr(kSeccompFutexError, sizeof(kSeccompFutexError) - 1);
+ volatile int futex_op = args.args[1];
+ volatile char* addr = reinterpret_cast<volatile char*>(futex_op & 0xFFF);
+ *addr = '\0';
+ for (;;)
+ _exit(1);
+}
+
const char* GetErrorMessageContentForTests() {
return SECCOMP_MESSAGE_COMMON_CONTENT;
}
@@ -180,4 +193,8 @@ const char* GetIoctlErrorMessageContentForTests() {
return SECCOMP_MESSAGE_IOCTL_CONTENT;
}
+const char* GetFutexErrorMessageContentForTests() {
+ return SECCOMP_MESSAGE_FUTEX_CONTENT;
+}
+
} // namespace sandbox.
diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h
index fdfbb66..a04a73e 100644
--- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h
+++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h
@@ -40,7 +40,12 @@ SANDBOX_EXPORT intptr_t
SIGSYSIoctlFailure(const struct arch_seccomp_data& args, void* aux);
// The crashing address will be (pid & 0xFFF), where pid is the first
// argument (and can be a tid).
-intptr_t SIGSYSKillFailure(const struct arch_seccomp_data& args, void* aux);
+SANDBOX_EXPORT intptr_t
+ SIGSYSKillFailure(const struct arch_seccomp_data& args, void* aux);
+// The crashing address will be (op & 0xFFF), where op is the second
+// argument.
+SANDBOX_EXPORT intptr_t
+ SIGSYSFutexFailure(const struct arch_seccomp_data& args, void* aux);
// Following four functions return substrings of error messages used
// in the above four functions. They are useful in death tests.
@@ -48,6 +53,7 @@ SANDBOX_EXPORT const char* GetErrorMessageContentForTests();
SANDBOX_EXPORT const char* GetCloneErrorMessageContentForTests();
SANDBOX_EXPORT const char* GetPrctlErrorMessageContentForTests();
SANDBOX_EXPORT const char* GetIoctlErrorMessageContentForTests();
+SANDBOX_EXPORT const char* GetFutexErrorMessageContentForTests();
} // namespace sandbox.
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
index 29c5910..16c37a0 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
@@ -7,6 +7,7 @@
#include <errno.h>
#include <fcntl.h>
#include <fcntl.h>
+#include <linux/futex.h>
#include <linux/net.h>
#include <sched.h>
#include <signal.h>
@@ -19,10 +20,12 @@
#include "base/basictypes.h"
#include "base/logging.h"
+#include "base/macros.h"
#include "build/build_config.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/services/android_futex.h"
#if defined(OS_ANDROID)
#if !defined(F_DUPFD_CLOEXEC)
@@ -246,4 +249,28 @@ ErrorCode RestrictKillTarget(pid_t target_pid, SandboxBPF* sandbox, int sysno) {
}
}
+ErrorCode RestrictFutex(SandboxBPF* sandbox) {
+ // In futex.c, the kernel does "int cmd = op & FUTEX_CMD_MASK;". We need to
+ // make sure that the combination below will cover every way to get
+ // FUTEX_CMP_REQUEUE_PI.
+ const int kBannedFutexBits =
+ ~(FUTEX_CMD_MASK | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME);
+ COMPILE_ASSERT(0 == kBannedFutexBits,
+ need_to_explicitly_blacklist_more_bits);
+
+ return sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ FUTEX_CMP_REQUEUE_PI,
+ sandbox->Trap(SIGSYSFutexFailure, NULL),
+ sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ FUTEX_CMP_REQUEUE_PI_PRIVATE,
+ sandbox->Trap(SIGSYSFutexFailure, NULL),
+ sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ FUTEX_CMP_REQUEUE_PI | FUTEX_CLOCK_REALTIME,
+ sandbox->Trap(SIGSYSFutexFailure, NULL),
+ sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ FUTEX_CMP_REQUEUE_PI_PRIVATE | FUTEX_CLOCK_REALTIME,
+ sandbox->Trap(SIGSYSFutexFailure, NULL),
+ ErrorCode(ErrorCode::ERR_ALLOWED)))));
+}
+
} // namespace sandbox.
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
index 5283b49..a673932 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
@@ -62,6 +62,9 @@ SANDBOX_EXPORT ErrorCode RestrictSocketcallCommand(SandboxBPF* sandbox);
// |sysno| is tkill.
ErrorCode RestrictKillTarget(pid_t target_pid, SandboxBPF* sandbox, int sysno);
+// Crash if FUTEX_CMP_REQUEUE_PI is used in the second argument of futex(2).
+ErrorCode RestrictFutex(SandboxBPF* sandbox);
+
} // namespace sandbox.
#endif // SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SYSCALL_PARAMETERS_RESTRICTIONS_H_
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
index 5f8785e..079f8c1 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
@@ -374,12 +374,12 @@ bool SyscallSets::IsAllowedProcessStartOrDeath(int sysno) {
}
// It's difficult to restrict those, but there is attack surface here.
-bool SyscallSets::IsFutex(int sysno) {
+bool SyscallSets::IsAllowedFutex(int sysno) {
switch (sysno) {
- case __NR_futex:
case __NR_get_robust_list:
case __NR_set_robust_list:
return true;
+ case __NR_futex:
default:
return false;
}
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h
index dc92681..de87573 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h
@@ -37,7 +37,7 @@ class SANDBOX_EXPORT SyscallSets {
// This should be thought through in conjunction with IsFutex().
static bool IsAllowedProcessStartOrDeath(int sysno);
// It's difficult to restrict those, but there is attack surface here.
- static bool IsFutex(int sysno);
+ static bool IsAllowedFutex(int sysno);
static bool IsAllowedEpoll(int sysno);
static bool IsAllowedGetOrModifySocket(int sysno);
static bool IsDeniedGetOrModifySocket(int sysno);
diff --git a/sandbox/linux/services/android_futex.h b/sandbox/linux/services/android_futex.h
new file mode 100644
index 0000000..032b024
--- /dev/null
+++ b/sandbox/linux/services/android_futex.h
@@ -0,0 +1,28 @@
+// Copyright 2014 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.
+
+#ifndef SANDBOX_LINUX_SERVICES_ANDROID_FUTEX_H_
+#define SANDBOX_LINUX_SERVICES_ANDROID_FUTEX_H_
+
+#if !defined(FUTEX_PRIVATE_FLAG)
+#define FUTEX_PRIVATE_FLAG 128
+#endif
+
+#if !defined(FUTEX_CLOCK_REALTIME)
+#define FUTEX_CLOCK_REALTIME 256
+#endif
+
+#if !defined(FUTEX_CMP_REQUEUE_PI)
+#define FUTEX_CMP_REQUEUE_PI 12
+#endif
+
+#if !defined(FUTEX_CMP_REQUEUE_PI_PRIVATE)
+#define FUTEX_CMP_REQUEUE_PI_PRIVATE (FUTEX_CMP_REQUEUE_PI | FUTEX_PRIVATE_FLAG)
+#endif
+
+#if !defined(FUTEX_CMD_MASK)
+#define FUTEX_CMD_MASK ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME)
+#endif
+
+#endif // SANDBOX_LINUX_SERVICES_ANDROID_FUTEX_H_