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

Linux sandbox: move RestrictClockID() to sandbox/

We move RestrictClockID() from the NaCl NonSFI sandbox to the
main helpers in sandbox/.

BUG=413469
TBR=brettw

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

Cr-Commit-Position: refs/heads/master@{#294533}
parent c6d19cf9
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "content/public/common/sandbox_init.h" #include "content/public/common/sandbox_init.h"
#include "sandbox/linux/bpf_dsl/bpf_dsl.h" #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.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/sandbox_bpf_policy.h" #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
#include "sandbox/linux/services/linux_syscalls.h" #include "sandbox/linux/services/linux_syscalls.h"
...@@ -67,26 +68,6 @@ ResultExpr RestrictFcntlCommands() { ...@@ -67,26 +68,6 @@ ResultExpr RestrictFcntlCommands() {
Allow()).Else(CrashSIGSYS()); Allow()).Else(CrashSIGSYS());
} }
ResultExpr RestrictClockID() {
// We allow accessing only CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID,
// CLOCK_REALTIME, and CLOCK_THREAD_CPUTIME_ID. In particular, this disallows
// access to arbitrary per-{process,thread} CPU-time clock IDs (such as those
// returned by {clock,pthread}_getcpuclockid), which can leak information
// about the state of the host OS.
COMPILE_ASSERT(4 == sizeof(clockid_t), clockid_is_not_32bit);
const Arg<clockid_t> clockid(0);
return If(
#if defined(OS_CHROMEOS)
// Allow the special clock for Chrome OS used by Chrome tracing.
clockid == base::TimeTicks::kClockSystemTrace ||
#endif
clockid == CLOCK_MONOTONIC ||
clockid == CLOCK_PROCESS_CPUTIME_ID ||
clockid == CLOCK_REALTIME ||
clockid == CLOCK_THREAD_CPUTIME_ID,
Allow()).Else(CrashSIGSYS());
}
ResultExpr RestrictClone() { ResultExpr RestrictClone() {
// We allow clone only for new thread creation. // We allow clone only for new thread creation.
const Arg<int> flags(0); const Arg<int> flags(0);
...@@ -259,7 +240,7 @@ ResultExpr NaClNonSfiBPFSandboxPolicy::EvaluateSyscall(int sysno) const { ...@@ -259,7 +240,7 @@ ResultExpr NaClNonSfiBPFSandboxPolicy::EvaluateSyscall(int sysno) const {
case __NR_clock_getres: case __NR_clock_getres:
case __NR_clock_gettime: case __NR_clock_gettime:
return RestrictClockID(); return sandbox::RestrictClockID();
case __NR_clone: case __NR_clone:
return RestrictClone(); return RestrictClone();
......
...@@ -431,6 +431,10 @@ BPF_TEST_C(NaClNonSfiSandboxTest, ...@@ -431,6 +431,10 @@ BPF_TEST_C(NaClNonSfiSandboxTest,
BPF_ASSERT_EQ(ENOMEM, errno); BPF_ASSERT_EQ(ENOMEM, errno);
} }
// clockid restrictions are mostly tested in sandbox/ with the
// RestrictClockID() unittests. Some basic tests are duplicated here as
// a precaution.
void CheckClock(clockid_t clockid) { void CheckClock(clockid_t clockid) {
struct timespec ts; struct timespec ts;
ts.tv_sec = ts.tv_nsec = -1; ts.tv_sec = ts.tv_nsec = -1;
...@@ -456,67 +460,6 @@ BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, ...@@ -456,67 +460,6 @@ BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
clock_gettime(CLOCK_MONOTONIC_RAW, &ts); clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
} }
#if defined(OS_CHROMEOS)
// A custom BPF tester delegate to run IsRunningOnChromeOS() before
// the sandbox is enabled because we cannot run it with non-SFI BPF
// sandbox enabled.
class ClockSystemTesterDelegate : public sandbox::BPFTesterDelegate {
public:
ClockSystemTesterDelegate()
: is_running_on_chromeos_(base::SysInfo::IsRunningOnChromeOS()) {}
virtual ~ClockSystemTesterDelegate() {}
virtual scoped_ptr<sandbox::SandboxBPFPolicy> GetSandboxBPFPolicy() OVERRIDE {
return scoped_ptr<sandbox::SandboxBPFPolicy>(
new nacl::nonsfi::NaClNonSfiBPFSandboxPolicy());
}
virtual void RunTestFunction() OVERRIDE {
if (is_running_on_chromeos_) {
CheckClock(base::TimeTicks::kClockSystemTrace);
} else {
struct timespec ts;
// kClockSystemTrace is 11, which is CLOCK_THREAD_CPUTIME_ID of
// the init process (pid=1). If kernel supports this feature,
// this may succeed even if this is not running on Chrome OS. We
// just check this clock_gettime call does not crash.
clock_gettime(base::TimeTicks::kClockSystemTrace, &ts);
}
}
private:
const bool is_running_on_chromeos_;
DISALLOW_COPY_AND_ASSIGN(ClockSystemTesterDelegate);
};
BPF_TEST_D(BPFTest, BPFTestWithDelegateClass, ClockSystemTesterDelegate);
#else
BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
clock_gettime_crash_system_trace,
DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
struct timespec ts;
clock_gettime(base::TimeTicks::kClockSystemTrace, &ts);
}
#endif // defined(OS_CHROMEOS)
BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
clock_gettime_crash_cpu_clock,
DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
// We can't use clock_getcpuclockid() because it's not implemented in newlib,
// and it might not work inside the sandbox anyway.
const pid_t kInitPID = 1;
const clockid_t kInitCPUClockID =
MAKE_PROCESS_CPUCLOCK(kInitPID, CPUCLOCK_SCHED);
struct timespec ts;
clock_gettime(kInitCPUClockID, &ts);
}
BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
invalid_syscall_crash, invalid_syscall_crash,
DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()), DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
......
...@@ -96,6 +96,7 @@ test("sandbox_linux_unittests") { ...@@ -96,6 +96,7 @@ test("sandbox_linux_unittests") {
"bpf_dsl/bpf_dsl_unittest.cc", "bpf_dsl/bpf_dsl_unittest.cc",
"bpf_dsl/cons_unittest.cc", "bpf_dsl/cons_unittest.cc",
"seccomp-bpf-helpers/baseline_policy_unittest.cc", "seccomp-bpf-helpers/baseline_policy_unittest.cc",
"seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc",
"seccomp-bpf/bpf_tests_unittest.cc", "seccomp-bpf/bpf_tests_unittest.cc",
"seccomp-bpf/codegen_unittest.cc", "seccomp-bpf/codegen_unittest.cc",
"seccomp-bpf/errorcode_unittest.cc", "seccomp-bpf/errorcode_unittest.cc",
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
'bpf_dsl/bpf_dsl_unittest.cc', 'bpf_dsl/bpf_dsl_unittest.cc',
'bpf_dsl/cons_unittest.cc', 'bpf_dsl/cons_unittest.cc',
'seccomp-bpf-helpers/baseline_policy_unittest.cc', 'seccomp-bpf-helpers/baseline_policy_unittest.cc',
'seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc',
'seccomp-bpf/bpf_tests_unittest.cc', 'seccomp-bpf/bpf_tests_unittest.cc',
'seccomp-bpf/codegen_unittest.cc', 'seccomp-bpf/codegen_unittest.cc',
'seccomp-bpf/errorcode_unittest.cc', 'seccomp-bpf/errorcode_unittest.cc',
......
...@@ -2,4 +2,5 @@ include_rules = [ ...@@ -2,4 +2,5 @@ include_rules = [
"+sandbox/linux/bpf_dsl", "+sandbox/linux/bpf_dsl",
"+sandbox/linux/services", "+sandbox/linux/services",
"+sandbox/linux/seccomp-bpf", "+sandbox/linux/seccomp-bpf",
"+third_party/lss/linux_syscall_support.h",
] ]
...@@ -18,11 +18,13 @@ ...@@ -18,11 +18,13 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
#include <time.h>
#include <unistd.h> #include <unistd.h>
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/time/time.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include "sandbox/linux/seccomp-bpf/linux_seccomp.h" #include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
...@@ -247,4 +249,19 @@ ResultExpr RestrictGetSetpriority(pid_t target_pid) { ...@@ -247,4 +249,19 @@ ResultExpr RestrictGetSetpriority(pid_t target_pid) {
.Else(CrashSIGSYS()); .Else(CrashSIGSYS());
} }
ResultExpr RestrictClockID() {
COMPILE_ASSERT(4 == sizeof(clockid_t), clockid_is_not_32bit);
const Arg<clockid_t> clockid(0);
return If(
#if defined(OS_CHROMEOS)
// Allow the special clock for Chrome OS used by Chrome tracing.
clockid == base::TimeTicks::kClockSystemTrace ||
#endif
clockid == CLOCK_MONOTONIC ||
clockid == CLOCK_PROCESS_CPUTIME_ID ||
clockid == CLOCK_REALTIME ||
clockid == CLOCK_THREAD_CPUTIME_ID,
Allow()).Else(CrashSIGSYS());
}
} // namespace sandbox. } // namespace sandbox.
...@@ -66,6 +66,15 @@ bpf_dsl::ResultExpr RestrictFutex(); ...@@ -66,6 +66,15 @@ bpf_dsl::ResultExpr RestrictFutex();
// |target_pid| while calling setpriority(2) / getpriority(2). // |target_pid| while calling setpriority(2) / getpriority(2).
bpf_dsl::ResultExpr RestrictGetSetpriority(pid_t target_pid); bpf_dsl::ResultExpr RestrictGetSetpriority(pid_t target_pid);
// Restrict |clk_id| for clock_getres(), clock_gettime() and clock_settime().
// We allow accessing only CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID,
// CLOCK_REALTIME, and CLOCK_THREAD_CPUTIME_ID. In particular, this disallows
// access to arbitrary per-{process,thread} CPU-time clock IDs (such as those
// returned by {clock,pthread}_getcpuclockid), which can leak information
// about the state of the host OS.
// On Chrome OS, base::TimeTicks::kClockSystemTrace is also allowed.
SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictClockID();
} // namespace sandbox. } // namespace sandbox.
#endif // SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SYSCALL_PARAMETERS_RESTRICTIONS_H_ #endif // SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SYSCALL_PARAMETERS_RESTRICTIONS_H_
// 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.
#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
#include <time.h>
#include "base/sys_info.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#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/seccomp-bpf/syscall.h"
#include "sandbox/linux/services/linux_syscalls.h"
#include "sandbox/linux/tests/unit_tests.h"
#include "third_party/lss/linux_syscall_support.h" // for MAKE_PROCESS_CPUCLOCK
namespace sandbox {
namespace {
// NOTE: most of the parameter restrictions are tested in
// baseline_policy_unittest.cc as a more end-to-end test.
using sandbox::bpf_dsl::Allow;
using sandbox::bpf_dsl::ResultExpr;
using sandbox::bpf_dsl::SandboxBPFDSLPolicy;
class RestrictClockIdPolicy : public SandboxBPFDSLPolicy {
public:
RestrictClockIdPolicy() {}
virtual ~RestrictClockIdPolicy() {}
virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE {
switch (sysno) {
case __NR_clock_gettime:
case __NR_clock_getres:
return RestrictClockID();
default:
return Allow();
}
}
};
void CheckClock(clockid_t clockid) {
struct timespec ts;
ts.tv_sec = ts.tv_nsec = -1;
BPF_ASSERT_EQ(0, clock_gettime(clockid, &ts));
BPF_ASSERT_LE(0, ts.tv_sec);
BPF_ASSERT_LE(0, ts.tv_nsec);
}
BPF_TEST_C(ParameterRestrictions,
clock_gettime_allowed,
RestrictClockIdPolicy) {
CheckClock(CLOCK_MONOTONIC);
CheckClock(CLOCK_PROCESS_CPUTIME_ID);
CheckClock(CLOCK_REALTIME);
CheckClock(CLOCK_THREAD_CPUTIME_ID);
}
BPF_DEATH_TEST_C(ParameterRestrictions,
clock_gettime_crash_monotonic_raw,
DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
RestrictClockIdPolicy) {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
}
#if defined(OS_CHROMEOS)
// A custom BPF tester delegate to run IsRunningOnChromeOS() before
// the sandbox is enabled because we cannot run it with non-SFI BPF
// sandbox enabled.
class ClockSystemTesterDelegate : public sandbox::BPFTesterDelegate {
public:
ClockSystemTesterDelegate()
: is_running_on_chromeos_(base::SysInfo::IsRunningOnChromeOS()) {}
virtual ~ClockSystemTesterDelegate() {}
virtual scoped_ptr<sandbox::SandboxBPFPolicy> GetSandboxBPFPolicy() OVERRIDE {
return scoped_ptr<sandbox::SandboxBPFPolicy>(
new RestrictClockIdPolicy());
}
virtual void RunTestFunction() OVERRIDE {
if (is_running_on_chromeos_) {
CheckClock(base::TimeTicks::kClockSystemTrace);
} else {
struct timespec ts;
// kClockSystemTrace is 11, which is CLOCK_THREAD_CPUTIME_ID of
// the init process (pid=1). If kernel supports this feature,
// this may succeed even if this is not running on Chrome OS. We
// just check this clock_gettime call does not crash.
clock_gettime(base::TimeTicks::kClockSystemTrace, &ts);
}
}
private:
const bool is_running_on_chromeos_;
DISALLOW_COPY_AND_ASSIGN(ClockSystemTesterDelegate);
};
BPF_TEST_D(BPFTest, BPFTestWithDelegateClass, ClockSystemTesterDelegate);
#elif defined(OS_LINUX)
BPF_DEATH_TEST_C(ParameterRestrictions,
clock_gettime_crash_system_trace,
DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
RestrictClockIdPolicy) {
struct timespec ts;
clock_gettime(base::TimeTicks::kClockSystemTrace, &ts);
}
#endif // defined(OS_CHROMEOS)
BPF_DEATH_TEST_C(ParameterRestrictions,
clock_gettime_crash_cpu_clock,
DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
RestrictClockIdPolicy) {
// We can't use clock_getcpuclockid() because it's not implemented in newlib,
// and it might not work inside the sandbox anyway.
const pid_t kInitPID = 1;
const clockid_t kInitCPUClockID =
MAKE_PROCESS_CPUCLOCK(kInitPID, CPUCLOCK_SCHED);
struct timespec ts;
clock_gettime(kInitCPUClockID, &ts);
}
} // namespace
} // namespace sandbox
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