diff options
author | jln <jln@chromium.org> | 2014-09-11 19:47:44 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-09-12 02:53:00 +0000 |
commit | fcdfb1094c7db30011101c0442957b8e1b5252d1 (patch) | |
tree | 23ec244b8f3bfe7b009020ed67834c51b780d632 /sandbox | |
parent | c6d19cf91bc709f1fa52b4e9e4a44dc4eb5562be (diff) | |
download | chromium_src-fcdfb1094c7db30011101c0442957b8e1b5252d1.zip chromium_src-fcdfb1094c7db30011101c0442957b8e1b5252d1.tar.gz chromium_src-fcdfb1094c7db30011101c0442957b8e1b5252d1.tar.bz2 |
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}
Diffstat (limited to 'sandbox')
6 files changed, 165 insertions, 0 deletions
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn index 708543f..b2521af 100644 --- a/sandbox/linux/BUILD.gn +++ b/sandbox/linux/BUILD.gn @@ -96,6 +96,7 @@ test("sandbox_linux_unittests") { "bpf_dsl/bpf_dsl_unittest.cc", "bpf_dsl/cons_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/codegen_unittest.cc", "seccomp-bpf/errorcode_unittest.cc", diff --git a/sandbox/linux/sandbox_linux_test_sources.gypi b/sandbox/linux/sandbox_linux_test_sources.gypi index c2f365b..75717ea 100644 --- a/sandbox/linux/sandbox_linux_test_sources.gypi +++ b/sandbox/linux/sandbox_linux_test_sources.gypi @@ -37,6 +37,7 @@ 'bpf_dsl/bpf_dsl_unittest.cc', 'bpf_dsl/cons_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/codegen_unittest.cc', 'seccomp-bpf/errorcode_unittest.cc', diff --git a/sandbox/linux/seccomp-bpf-helpers/DEPS b/sandbox/linux/seccomp-bpf-helpers/DEPS index d4b2611..01e1fe2 100644 --- a/sandbox/linux/seccomp-bpf-helpers/DEPS +++ b/sandbox/linux/seccomp-bpf-helpers/DEPS @@ -2,4 +2,5 @@ include_rules = [ "+sandbox/linux/bpf_dsl", "+sandbox/linux/services", "+sandbox/linux/seccomp-bpf", + "+third_party/lss/linux_syscall_support.h", ] diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc index b61b8ea..94c2333 100644 --- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc +++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc @@ -18,11 +18,13 @@ #include <sys/stat.h> #include <sys/time.h> #include <sys/types.h> +#include <time.h> #include <unistd.h> #include "base/basictypes.h" #include "base/logging.h" #include "base/macros.h" +#include "base/time/time.h" #include "build/build_config.h" #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" #include "sandbox/linux/seccomp-bpf/linux_seccomp.h" @@ -247,4 +249,19 @@ ResultExpr RestrictGetSetpriority(pid_t target_pid) { .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. diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h index 7a0c197..6509f3f 100644 --- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h +++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h @@ -66,6 +66,15 @@ bpf_dsl::ResultExpr RestrictFutex(); // |target_pid| while calling setpriority(2) / getpriority(2). 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. #endif // SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SYSCALL_PARAMETERS_RESTRICTIONS_H_ diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc new file mode 100644 index 0000000..d631bb0 --- /dev/null +++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc @@ -0,0 +1,136 @@ +// 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 |