Updating XTBs based on .GRDs from branch master
[chromium-blink-merge.git] / sandbox / linux / seccomp-bpf-helpers / syscall_parameters_restrictions_unittests.cc
blobaaed480d6996389bad8d91514861d177f37be1c2
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
7 #include <errno.h>
8 #include <sched.h>
9 #include <sys/resource.h>
10 #include <sys/syscall.h>
11 #include <sys/types.h>
12 #include <time.h>
13 #include <unistd.h>
15 #include "base/bind.h"
16 #include "base/synchronization/waitable_event.h"
17 #include "base/sys_info.h"
18 #include "base/threading/thread.h"
19 #include "base/time/time.h"
20 #include "build/build_config.h"
21 #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
22 #include "sandbox/linux/bpf_dsl/policy.h"
23 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
24 #include "sandbox/linux/seccomp-bpf/bpf_tests.h"
25 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
26 #include "sandbox/linux/seccomp-bpf/syscall.h"
27 #include "sandbox/linux/services/syscall_wrappers.h"
28 #include "sandbox/linux/system_headers/linux_syscalls.h"
29 #include "sandbox/linux/system_headers/linux_time.h"
30 #include "sandbox/linux/tests/unit_tests.h"
32 #if !defined(OS_ANDROID)
33 #include "third_party/lss/linux_syscall_support.h" // for MAKE_PROCESS_CPUCLOCK
34 #endif
36 namespace sandbox {
38 namespace {
40 // NOTE: most of the parameter restrictions are tested in
41 // baseline_policy_unittest.cc as a more end-to-end test.
43 using sandbox::bpf_dsl::Allow;
44 using sandbox::bpf_dsl::ResultExpr;
46 class RestrictClockIdPolicy : public bpf_dsl::Policy {
47 public:
48 RestrictClockIdPolicy() {}
49 ~RestrictClockIdPolicy() override {}
51 ResultExpr EvaluateSyscall(int sysno) const override {
52 switch (sysno) {
53 case __NR_clock_gettime:
54 case __NR_clock_getres:
55 return RestrictClockID();
56 default:
57 return Allow();
62 void CheckClock(clockid_t clockid) {
63 struct timespec ts;
64 ts.tv_sec = -1;
65 ts.tv_nsec = -1;
66 BPF_ASSERT_EQ(0, clock_getres(clockid, &ts));
67 BPF_ASSERT_EQ(0, ts.tv_sec);
68 BPF_ASSERT_LE(0, ts.tv_nsec);
69 ts.tv_sec = -1;
70 ts.tv_nsec = -1;
71 BPF_ASSERT_EQ(0, clock_gettime(clockid, &ts));
72 BPF_ASSERT_LE(0, ts.tv_sec);
73 BPF_ASSERT_LE(0, ts.tv_nsec);
76 BPF_TEST_C(ParameterRestrictions,
77 clock_gettime_allowed,
78 RestrictClockIdPolicy) {
79 CheckClock(CLOCK_MONOTONIC);
80 CheckClock(CLOCK_MONOTONIC_COARSE);
81 CheckClock(CLOCK_PROCESS_CPUTIME_ID);
82 CheckClock(CLOCK_REALTIME);
83 CheckClock(CLOCK_REALTIME_COARSE);
84 CheckClock(CLOCK_THREAD_CPUTIME_ID);
87 BPF_DEATH_TEST_C(ParameterRestrictions,
88 clock_gettime_crash_monotonic_raw,
89 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
90 RestrictClockIdPolicy) {
91 struct timespec ts;
92 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
95 #if defined(OS_CHROMEOS)
97 // A custom BPF tester delegate to run IsRunningOnChromeOS() before
98 // the sandbox is enabled because we cannot run it with non-SFI BPF
99 // sandbox enabled.
100 class ClockSystemTesterDelegate : public sandbox::BPFTesterDelegate {
101 public:
102 ClockSystemTesterDelegate()
103 : is_running_on_chromeos_(base::SysInfo::IsRunningOnChromeOS()) {}
104 ~ClockSystemTesterDelegate() override {}
106 scoped_ptr<sandbox::bpf_dsl::Policy> GetSandboxBPFPolicy() override {
107 return scoped_ptr<sandbox::bpf_dsl::Policy>(new RestrictClockIdPolicy());
109 void RunTestFunction() override {
110 if (is_running_on_chromeos_) {
111 CheckClock(base::TraceTicks::kClockSystemTrace);
112 } else {
113 struct timespec ts;
114 // kClockSystemTrace is 11, which is CLOCK_THREAD_CPUTIME_ID of
115 // the init process (pid=1). If kernel supports this feature,
116 // this may succeed even if this is not running on Chrome OS. We
117 // just check this clock_gettime call does not crash.
118 clock_gettime(base::TraceTicks::kClockSystemTrace, &ts);
122 private:
123 const bool is_running_on_chromeos_;
124 DISALLOW_COPY_AND_ASSIGN(ClockSystemTesterDelegate);
127 BPF_TEST_D(BPFTest, BPFTestWithDelegateClass, ClockSystemTesterDelegate);
129 #elif defined(OS_LINUX)
131 BPF_DEATH_TEST_C(ParameterRestrictions,
132 clock_gettime_crash_system_trace,
133 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
134 RestrictClockIdPolicy) {
135 struct timespec ts;
136 clock_gettime(base::TraceTicks::kClockSystemTrace, &ts);
139 #endif // defined(OS_CHROMEOS)
141 #if !defined(OS_ANDROID)
142 BPF_DEATH_TEST_C(ParameterRestrictions,
143 clock_gettime_crash_cpu_clock,
144 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
145 RestrictClockIdPolicy) {
146 // We can't use clock_getcpuclockid() because it's not implemented in newlib,
147 // and it might not work inside the sandbox anyway.
148 const pid_t kInitPID = 1;
149 const clockid_t kInitCPUClockID =
150 MAKE_PROCESS_CPUCLOCK(kInitPID, CPUCLOCK_SCHED);
152 struct timespec ts;
153 clock_gettime(kInitCPUClockID, &ts);
155 #endif // !defined(OS_ANDROID)
157 class RestrictSchedPolicy : public bpf_dsl::Policy {
158 public:
159 RestrictSchedPolicy() {}
160 ~RestrictSchedPolicy() override {}
162 ResultExpr EvaluateSyscall(int sysno) const override {
163 switch (sysno) {
164 case __NR_sched_getparam:
165 return RestrictSchedTarget(getpid(), sysno);
166 default:
167 return Allow();
172 void CheckSchedGetParam(pid_t pid, struct sched_param* param) {
173 BPF_ASSERT_EQ(0, sched_getparam(pid, param));
176 void SchedGetParamThread(base::WaitableEvent* thread_run) {
177 const pid_t pid = getpid();
178 const pid_t tid = sys_gettid();
179 BPF_ASSERT_NE(pid, tid);
181 struct sched_param current_pid_param;
182 CheckSchedGetParam(pid, &current_pid_param);
184 struct sched_param zero_param;
185 CheckSchedGetParam(0, &zero_param);
187 struct sched_param tid_param;
188 CheckSchedGetParam(tid, &tid_param);
190 BPF_ASSERT_EQ(zero_param.sched_priority, tid_param.sched_priority);
192 // Verify that the SIGSYS handler sets errno properly.
193 errno = 0;
194 BPF_ASSERT_EQ(-1, sched_getparam(tid, NULL));
195 BPF_ASSERT_EQ(EINVAL, errno);
197 thread_run->Signal();
200 BPF_TEST_C(ParameterRestrictions,
201 sched_getparam_allowed,
202 RestrictSchedPolicy) {
203 base::WaitableEvent thread_run(true, false);
204 // Run the actual test in a new thread so that the current pid and tid are
205 // different.
206 base::Thread getparam_thread("sched_getparam_thread");
207 BPF_ASSERT(getparam_thread.Start());
208 getparam_thread.message_loop()->PostTask(
209 FROM_HERE, base::Bind(&SchedGetParamThread, &thread_run));
210 BPF_ASSERT(thread_run.TimedWait(base::TimeDelta::FromMilliseconds(5000)));
211 getparam_thread.Stop();
214 BPF_DEATH_TEST_C(ParameterRestrictions,
215 sched_getparam_crash_non_zero,
216 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
217 RestrictSchedPolicy) {
218 const pid_t kInitPID = 1;
219 struct sched_param param;
220 sched_getparam(kInitPID, &param);
223 class RestrictPrlimit64Policy : public bpf_dsl::Policy {
224 public:
225 RestrictPrlimit64Policy() {}
226 ~RestrictPrlimit64Policy() override {}
228 ResultExpr EvaluateSyscall(int sysno) const override {
229 switch (sysno) {
230 case __NR_prlimit64:
231 return RestrictPrlimit64(getpid());
232 default:
233 return Allow();
238 BPF_TEST_C(ParameterRestrictions, prlimit64_allowed, RestrictPrlimit64Policy) {
239 BPF_ASSERT_EQ(0, sys_prlimit64(0, RLIMIT_AS, NULL, NULL));
240 BPF_ASSERT_EQ(0, sys_prlimit64(getpid(), RLIMIT_AS, NULL, NULL));
243 BPF_DEATH_TEST_C(ParameterRestrictions,
244 prlimit64_crash_not_self,
245 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
246 RestrictPrlimit64Policy) {
247 const pid_t kInitPID = 1;
248 BPF_ASSERT_NE(kInitPID, getpid());
249 sys_prlimit64(kInitPID, RLIMIT_AS, NULL, NULL);
252 class RestrictGetrusagePolicy : public bpf_dsl::Policy {
253 public:
254 RestrictGetrusagePolicy() {}
255 ~RestrictGetrusagePolicy() override {}
257 ResultExpr EvaluateSyscall(int sysno) const override {
258 switch (sysno) {
259 case __NR_getrusage:
260 return RestrictGetrusage();
261 default:
262 return Allow();
267 BPF_TEST_C(ParameterRestrictions, getrusage_allowed, RestrictGetrusagePolicy) {
268 struct rusage usage;
269 BPF_ASSERT_EQ(0, getrusage(RUSAGE_SELF, &usage));
272 BPF_DEATH_TEST_C(ParameterRestrictions,
273 getrusage_crash_not_self,
274 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
275 RestrictGetrusagePolicy) {
276 struct rusage usage;
277 getrusage(RUSAGE_CHILDREN, &usage);
280 } // namespace
282 } // namespace sandbox