diff options
author | jln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-06 18:58:33 +0000 |
---|---|---|
committer | jln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-06 18:58:33 +0000 |
commit | b66edd015fcd9d0df571d3b6ea3fcba62535efe3 (patch) | |
tree | 4108cc3a9ab0bbd0dd258e907d0d39e557171ab3 | |
parent | bf69c12ea557c501b4ea4f2819e5f39171d363bd (diff) | |
download | chromium_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
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_ |