Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / sandbox / linux / seccomp-bpf-helpers / baseline_policy_unittest.cc
blob614849f61c7d594efb8590c79a170f431ffa8ac9
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/baseline_policy.h"
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <sched.h>
10 #include <signal.h>
11 #include <string.h>
12 #include <sys/prctl.h>
13 #include <sys/resource.h>
14 #include <sys/socket.h>
15 #include <sys/stat.h>
16 #include <sys/syscall.h>
17 #include <sys/time.h>
18 #include <sys/types.h>
19 #include <sys/wait.h>
20 #include <time.h>
21 #include <unistd.h>
23 #include "base/files/scoped_file.h"
24 #include "base/macros.h"
25 #include "base/posix/eintr_wrapper.h"
26 #include "base/threading/thread.h"
27 #include "build/build_config.h"
28 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
29 #include "sandbox/linux/seccomp-bpf/bpf_tests.h"
30 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
31 #include "sandbox/linux/seccomp-bpf/syscall.h"
32 #include "sandbox/linux/services/syscall_wrappers.h"
33 #include "sandbox/linux/services/thread_helpers.h"
34 #include "sandbox/linux/system_headers/linux_futex.h"
35 #include "sandbox/linux/system_headers/linux_syscalls.h"
36 #include "sandbox/linux/tests/test_utils.h"
37 #include "sandbox/linux/tests/unit_tests.h"
39 namespace sandbox {
41 namespace {
43 // This also tests that read(), write() and fstat() are allowed.
44 void TestPipeOrSocketPair(base::ScopedFD read_end, base::ScopedFD write_end) {
45 BPF_ASSERT_LE(0, read_end.get());
46 BPF_ASSERT_LE(0, write_end.get());
47 struct stat stat_buf;
48 int sys_ret = fstat(read_end.get(), &stat_buf);
49 BPF_ASSERT_EQ(0, sys_ret);
50 BPF_ASSERT(S_ISFIFO(stat_buf.st_mode) || S_ISSOCK(stat_buf.st_mode));
52 const ssize_t kTestTransferSize = 4;
53 static const char kTestString[kTestTransferSize] = {'T', 'E', 'S', 'T'};
54 ssize_t transfered = 0;
56 transfered =
57 HANDLE_EINTR(write(write_end.get(), kTestString, kTestTransferSize));
58 BPF_ASSERT_EQ(kTestTransferSize, transfered);
59 char read_buf[kTestTransferSize + 1] = {0};
60 transfered = HANDLE_EINTR(read(read_end.get(), read_buf, sizeof(read_buf)));
61 BPF_ASSERT_EQ(kTestTransferSize, transfered);
62 BPF_ASSERT_EQ(0, memcmp(kTestString, read_buf, kTestTransferSize));
65 // Test that a few easy-to-test system calls are allowed.
66 BPF_TEST_C(BaselinePolicy, BaselinePolicyBasicAllowed, BaselinePolicy) {
67 BPF_ASSERT_EQ(0, sched_yield());
69 int pipefd[2];
70 int sys_ret = pipe(pipefd);
71 BPF_ASSERT_EQ(0, sys_ret);
72 TestPipeOrSocketPair(base::ScopedFD(pipefd[0]), base::ScopedFD(pipefd[1]));
74 BPF_ASSERT_LE(1, getpid());
75 BPF_ASSERT_LE(0, getuid());
78 BPF_TEST_C(BaselinePolicy, FchmodErrno, BaselinePolicy) {
79 int ret = fchmod(-1, 07777);
80 BPF_ASSERT_EQ(-1, ret);
81 // Without the sandbox, this would EBADF instead.
82 BPF_ASSERT_EQ(EPERM, errno);
85 BPF_TEST_C(BaselinePolicy, ForkErrno, BaselinePolicy) {
86 errno = 0;
87 pid_t pid = fork();
88 const int fork_errno = errno;
89 TestUtils::HandlePostForkReturn(pid);
91 BPF_ASSERT_EQ(-1, pid);
92 BPF_ASSERT_EQ(EPERM, fork_errno);
95 pid_t ForkX86Glibc() {
96 static pid_t ptid;
97 return sys_clone(CLONE_PARENT_SETTID | SIGCHLD, nullptr, &ptid, nullptr,
98 nullptr);
101 BPF_TEST_C(BaselinePolicy, ForkX86Eperm, BaselinePolicy) {
102 errno = 0;
103 pid_t pid = ForkX86Glibc();
104 const int fork_errno = errno;
105 TestUtils::HandlePostForkReturn(pid);
107 BPF_ASSERT_EQ(-1, pid);
108 BPF_ASSERT_EQ(EPERM, fork_errno);
111 pid_t ForkARMGlibc() {
112 static pid_t ctid;
113 return sys_clone(CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, nullptr,
114 nullptr, &ctid, nullptr);
117 BPF_TEST_C(BaselinePolicy, ForkArmEperm, BaselinePolicy) {
118 errno = 0;
119 pid_t pid = ForkARMGlibc();
120 const int fork_errno = errno;
121 TestUtils::HandlePostForkReturn(pid);
123 BPF_ASSERT_EQ(-1, pid);
124 BPF_ASSERT_EQ(EPERM, fork_errno);
127 BPF_TEST_C(BaselinePolicy, CreateThread, BaselinePolicy) {
128 base::Thread thread("sandbox_tests");
129 BPF_ASSERT(thread.Start());
132 BPF_DEATH_TEST_C(BaselinePolicy,
133 DisallowedCloneFlagCrashes,
134 DEATH_SEGV_MESSAGE(GetCloneErrorMessageContentForTests()),
135 BaselinePolicy) {
136 pid_t pid = sys_clone(CLONE_THREAD | SIGCHLD);
137 TestUtils::HandlePostForkReturn(pid);
140 BPF_DEATH_TEST_C(BaselinePolicy,
141 DisallowedKillCrashes,
142 DEATH_SEGV_MESSAGE(GetKillErrorMessageContentForTests()),
143 BaselinePolicy) {
144 BPF_ASSERT_NE(1, getpid());
145 kill(1, 0);
146 _exit(0);
149 BPF_TEST_C(BaselinePolicy, CanKillSelf, BaselinePolicy) {
150 int sys_ret = kill(getpid(), 0);
151 BPF_ASSERT_EQ(0, sys_ret);
154 BPF_TEST_C(BaselinePolicy, Socketpair, BaselinePolicy) {
155 int sv[2];
156 int sys_ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, sv);
157 BPF_ASSERT_EQ(0, sys_ret);
158 TestPipeOrSocketPair(base::ScopedFD(sv[0]), base::ScopedFD(sv[1]));
160 sys_ret = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sv);
161 BPF_ASSERT_EQ(0, sys_ret);
162 TestPipeOrSocketPair(base::ScopedFD(sv[0]), base::ScopedFD(sv[1]));
165 // Not all architectures can restrict the domain for socketpair().
166 #if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
167 BPF_DEATH_TEST_C(BaselinePolicy,
168 SocketpairWrongDomain,
169 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
170 BaselinePolicy) {
171 int sv[2];
172 ignore_result(socketpair(AF_INET, SOCK_STREAM, 0, sv));
173 _exit(1);
175 #endif // defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
177 BPF_TEST_C(BaselinePolicy, EPERM_open, BaselinePolicy) {
178 errno = 0;
179 int sys_ret = open("/proc/cpuinfo", O_RDONLY);
180 BPF_ASSERT_EQ(-1, sys_ret);
181 BPF_ASSERT_EQ(EPERM, errno);
184 BPF_TEST_C(BaselinePolicy, EPERM_access, BaselinePolicy) {
185 errno = 0;
186 int sys_ret = access("/proc/cpuinfo", R_OK);
187 BPF_ASSERT_EQ(-1, sys_ret);
188 BPF_ASSERT_EQ(EPERM, errno);
191 BPF_TEST_C(BaselinePolicy, EPERM_getcwd, BaselinePolicy) {
192 errno = 0;
193 char buf[1024];
194 char* cwd = getcwd(buf, sizeof(buf));
195 BPF_ASSERT_EQ(NULL, cwd);
196 BPF_ASSERT_EQ(EPERM, errno);
199 BPF_DEATH_TEST_C(BaselinePolicy,
200 SIGSYS_InvalidSyscall,
201 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
202 BaselinePolicy) {
203 Syscall::InvalidCall();
206 // A failing test using this macro could be problematic since we perform
207 // system calls by passing "0" as every argument.
208 // The kernel could SIGSEGV the process or the system call itself could reboot
209 // the machine. Some thoughts have been given when hand-picking the system
210 // calls below to limit any potential side effects outside of the current
211 // process.
212 #define TEST_BASELINE_SIGSYS(sysno) \
213 BPF_DEATH_TEST_C(BaselinePolicy, \
214 SIGSYS_##sysno, \
215 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()), \
216 BaselinePolicy) { \
217 syscall(sysno, 0, 0, 0, 0, 0, 0); \
218 _exit(1); \
221 TEST_BASELINE_SIGSYS(__NR_acct);
222 TEST_BASELINE_SIGSYS(__NR_chroot);
223 TEST_BASELINE_SIGSYS(__NR_fanotify_init);
224 TEST_BASELINE_SIGSYS(__NR_fgetxattr);
225 TEST_BASELINE_SIGSYS(__NR_getcpu);
226 TEST_BASELINE_SIGSYS(__NR_getitimer);
227 TEST_BASELINE_SIGSYS(__NR_init_module);
228 TEST_BASELINE_SIGSYS(__NR_io_cancel);
229 TEST_BASELINE_SIGSYS(__NR_keyctl);
230 TEST_BASELINE_SIGSYS(__NR_mq_open);
231 TEST_BASELINE_SIGSYS(__NR_ptrace);
232 TEST_BASELINE_SIGSYS(__NR_sched_setaffinity);
233 TEST_BASELINE_SIGSYS(__NR_setpgid);
234 TEST_BASELINE_SIGSYS(__NR_swapon);
235 TEST_BASELINE_SIGSYS(__NR_sysinfo);
236 TEST_BASELINE_SIGSYS(__NR_syslog);
237 TEST_BASELINE_SIGSYS(__NR_timer_create);
239 #if !defined(__aarch64__)
240 TEST_BASELINE_SIGSYS(__NR_eventfd);
241 TEST_BASELINE_SIGSYS(__NR_inotify_init);
242 TEST_BASELINE_SIGSYS(__NR_vserver);
243 #endif
245 BPF_DEATH_TEST_C(BaselinePolicy,
246 FutexWithRequeuePriorityInheritence,
247 DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()),
248 BaselinePolicy) {
249 syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI, 0, NULL, NULL, 0);
250 _exit(1);
253 BPF_DEATH_TEST_C(BaselinePolicy,
254 FutexWithRequeuePriorityInheritencePrivate,
255 DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()),
256 BaselinePolicy) {
257 syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI_PRIVATE, 0, NULL, NULL, 0);
258 _exit(1);
261 BPF_DEATH_TEST_C(BaselinePolicy,
262 FutexWithUnlockPIPrivate,
263 DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()),
264 BaselinePolicy) {
265 syscall(__NR_futex, NULL, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0);
266 _exit(1);
269 BPF_TEST_C(BaselinePolicy, PrctlDumpable, BaselinePolicy) {
270 const int is_dumpable = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
271 BPF_ASSERT(is_dumpable == 1 || is_dumpable == 0);
272 const int prctl_ret = prctl(PR_SET_DUMPABLE, is_dumpable, 0, 0, 0, 0);
273 BPF_ASSERT_EQ(0, prctl_ret);
276 // Workaround incomplete Android headers.
277 #if !defined(PR_CAPBSET_READ)
278 #define PR_CAPBSET_READ 23
279 #endif
281 BPF_DEATH_TEST_C(BaselinePolicy,
282 PrctlSigsys,
283 DEATH_SEGV_MESSAGE(GetPrctlErrorMessageContentForTests()),
284 BaselinePolicy) {
285 prctl(PR_CAPBSET_READ, 0, 0, 0, 0);
286 _exit(1);
289 BPF_TEST_C(BaselinePolicy, GetOrSetPriority, BaselinePolicy) {
290 errno = 0;
291 const int original_prio = getpriority(PRIO_PROCESS, 0);
292 // Check errno instead of the return value since this system call can return
293 // -1 as a valid value.
294 BPF_ASSERT_EQ(0, errno);
296 errno = 0;
297 int rc = getpriority(PRIO_PROCESS, getpid());
298 BPF_ASSERT_EQ(0, errno);
300 rc = getpriority(PRIO_PROCESS, getpid() + 1);
301 BPF_ASSERT_EQ(-1, rc);
302 BPF_ASSERT_EQ(EPERM, errno);
304 rc = setpriority(PRIO_PROCESS, 0, original_prio);
305 BPF_ASSERT_EQ(0, rc);
307 rc = setpriority(PRIO_PROCESS, getpid(), original_prio);
308 BPF_ASSERT_EQ(0, rc);
310 errno = 0;
311 rc = setpriority(PRIO_PROCESS, getpid() + 1, original_prio);
312 BPF_ASSERT_EQ(-1, rc);
313 BPF_ASSERT_EQ(EPERM, errno);
316 BPF_DEATH_TEST_C(BaselinePolicy,
317 GetPrioritySigsys,
318 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
319 BaselinePolicy) {
320 getpriority(PRIO_USER, 0);
321 _exit(1);
324 BPF_DEATH_TEST_C(BaselinePolicy,
325 ClockGettimeWithDisallowedClockCrashes,
326 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
327 BaselinePolicy) {
328 struct timespec ts;
329 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
332 } // namespace
334 } // namespace sandbox