Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc

Issue 670183003: Update from chromium 62675d9fb31fb8cedc40f68e78e8445a74f362e7 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h"
6
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <linux/futex.h>
10 #include <sched.h>
11 #include <signal.h>
12 #include <string.h>
13 #include <sys/prctl.h>
14 #include <sys/resource.h>
15 #include <sys/socket.h>
16 #include <sys/stat.h>
17 #include <sys/syscall.h>
18 #include <sys/time.h>
19 #include <sys/types.h>
20 #include <sys/wait.h>
21 #include <time.h>
22 #include <unistd.h>
23
24 #include "base/files/scoped_file.h"
25 #include "base/macros.h"
26 #include "base/posix/eintr_wrapper.h"
27 #include "base/threading/thread.h"
28 #include "build/build_config.h"
29 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
30 #include "sandbox/linux/seccomp-bpf/bpf_tests.h"
31 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
32 #include "sandbox/linux/seccomp-bpf/syscall.h"
33 #include "sandbox/linux/services/android_futex.h"
34 #include "sandbox/linux/services/linux_syscalls.h"
35 #include "sandbox/linux/services/thread_helpers.h"
36 #include "sandbox/linux/tests/unit_tests.h"
37
38 namespace sandbox {
39
40 namespace {
41
42 // |pid| is the return value of a fork()-like call. This
43 // makes sure that if fork() succeeded the child exits
44 // and the parent waits for it.
45 void HandlePostForkReturn(pid_t pid) {
46 const int kChildExitCode = 1;
47 if (pid > 0) {
48 int status = 0;
49 PCHECK(pid == HANDLE_EINTR(waitpid(pid, &status, 0)));
50 CHECK(WIFEXITED(status));
51 CHECK_EQ(kChildExitCode, WEXITSTATUS(status));
52 } else if (pid == 0) {
53 _exit(kChildExitCode);
54 }
55 }
56
57 // Check that HandlePostForkReturn works.
58 TEST(BaselinePolicy, HandlePostForkReturn) {
59 pid_t pid = fork();
60 HandlePostForkReturn(pid);
61 }
62
63 // This also tests that read(), write() and fstat() are allowed.
64 void TestPipeOrSocketPair(base::ScopedFD read_end, base::ScopedFD write_end) {
65 BPF_ASSERT_LE(0, read_end.get());
66 BPF_ASSERT_LE(0, write_end.get());
67 struct stat stat_buf;
68 int sys_ret = fstat(read_end.get(), &stat_buf);
69 BPF_ASSERT_EQ(0, sys_ret);
70 BPF_ASSERT(S_ISFIFO(stat_buf.st_mode) || S_ISSOCK(stat_buf.st_mode));
71
72 const ssize_t kTestTransferSize = 4;
73 static const char kTestString[kTestTransferSize] = {'T', 'E', 'S', 'T'};
74 ssize_t transfered = 0;
75
76 transfered =
77 HANDLE_EINTR(write(write_end.get(), kTestString, kTestTransferSize));
78 BPF_ASSERT_EQ(kTestTransferSize, transfered);
79 char read_buf[kTestTransferSize + 1] = {0};
80 transfered = HANDLE_EINTR(read(read_end.get(), read_buf, sizeof(read_buf)));
81 BPF_ASSERT_EQ(kTestTransferSize, transfered);
82 BPF_ASSERT_EQ(0, memcmp(kTestString, read_buf, kTestTransferSize));
83 }
84
85 // Test that a few easy-to-test system calls are allowed.
86 BPF_TEST_C(BaselinePolicy, BaselinePolicyBasicAllowed, BaselinePolicy) {
87 BPF_ASSERT_EQ(0, sched_yield());
88
89 int pipefd[2];
90 int sys_ret = pipe(pipefd);
91 BPF_ASSERT_EQ(0, sys_ret);
92 TestPipeOrSocketPair(base::ScopedFD(pipefd[0]), base::ScopedFD(pipefd[1]));
93
94 BPF_ASSERT_LE(1, getpid());
95 BPF_ASSERT_LE(0, getuid());
96 }
97
98 BPF_TEST_C(BaselinePolicy, FchmodErrno, BaselinePolicy) {
99 int ret = fchmod(-1, 07777);
100 BPF_ASSERT_EQ(-1, ret);
101 // Without the sandbox, this would EBADF instead.
102 BPF_ASSERT_EQ(EPERM, errno);
103 }
104
105 BPF_TEST_C(BaselinePolicy, ForkErrno, BaselinePolicy) {
106 errno = 0;
107 pid_t pid = fork();
108 const int fork_errno = errno;
109 HandlePostForkReturn(pid);
110
111 BPF_ASSERT_EQ(-1, pid);
112 BPF_ASSERT_EQ(EPERM, fork_errno);
113 }
114
115 pid_t ForkX86Glibc() {
116 return syscall(__NR_clone, CLONE_PARENT_SETTID | SIGCHLD);
117 }
118
119 BPF_TEST_C(BaselinePolicy, ForkX86Eperm, BaselinePolicy) {
120 errno = 0;
121 pid_t pid = ForkX86Glibc();
122 const int fork_errno = errno;
123 HandlePostForkReturn(pid);
124
125 BPF_ASSERT_EQ(-1, pid);
126 BPF_ASSERT_EQ(EPERM, fork_errno);
127 }
128
129 pid_t ForkARMGlibc() {
130 return syscall(__NR_clone,
131 CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD);
132 }
133
134 BPF_TEST_C(BaselinePolicy, ForkArmEperm, BaselinePolicy) {
135 errno = 0;
136 pid_t pid = ForkARMGlibc();
137 const int fork_errno = errno;
138 HandlePostForkReturn(pid);
139
140 BPF_ASSERT_EQ(-1, pid);
141 BPF_ASSERT_EQ(EPERM, fork_errno);
142 }
143
144 BPF_TEST_C(BaselinePolicy, CreateThread, BaselinePolicy) {
145 base::Thread thread("sandbox_tests");
146 BPF_ASSERT(thread.Start());
147 }
148
149 BPF_DEATH_TEST_C(BaselinePolicy,
150 DisallowedCloneFlagCrashes,
151 DEATH_SEGV_MESSAGE(GetCloneErrorMessageContentForTests()),
152 BaselinePolicy) {
153 pid_t pid = syscall(__NR_clone, CLONE_THREAD | SIGCHLD);
154 HandlePostForkReturn(pid);
155 }
156
157 BPF_DEATH_TEST_C(BaselinePolicy,
158 DisallowedKillCrashes,
159 DEATH_SEGV_MESSAGE(GetKillErrorMessageContentForTests()),
160 BaselinePolicy) {
161 BPF_ASSERT_NE(1, getpid());
162 kill(1, 0);
163 _exit(0);
164 }
165
166 BPF_TEST_C(BaselinePolicy, CanKillSelf, BaselinePolicy) {
167 int sys_ret = kill(getpid(), 0);
168 BPF_ASSERT_EQ(0, sys_ret);
169 }
170
171 BPF_TEST_C(BaselinePolicy, Socketpair, BaselinePolicy) {
172 int sv[2];
173 int sys_ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, sv);
174 BPF_ASSERT_EQ(0, sys_ret);
175 TestPipeOrSocketPair(base::ScopedFD(sv[0]), base::ScopedFD(sv[1]));
176
177 sys_ret = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sv);
178 BPF_ASSERT_EQ(0, sys_ret);
179 TestPipeOrSocketPair(base::ScopedFD(sv[0]), base::ScopedFD(sv[1]));
180 }
181
182 // Not all architectures can restrict the domain for socketpair().
183 #if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
184 BPF_DEATH_TEST_C(BaselinePolicy,
185 SocketpairWrongDomain,
186 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
187 BaselinePolicy) {
188 int sv[2];
189 ignore_result(socketpair(AF_INET, SOCK_STREAM, 0, sv));
190 _exit(1);
191 }
192 #endif // defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
193
194 BPF_TEST_C(BaselinePolicy, EPERM_open, BaselinePolicy) {
195 errno = 0;
196 int sys_ret = open("/proc/cpuinfo", O_RDONLY);
197 BPF_ASSERT_EQ(-1, sys_ret);
198 BPF_ASSERT_EQ(EPERM, errno);
199 }
200
201 BPF_TEST_C(BaselinePolicy, EPERM_access, BaselinePolicy) {
202 errno = 0;
203 int sys_ret = access("/proc/cpuinfo", R_OK);
204 BPF_ASSERT_EQ(-1, sys_ret);
205 BPF_ASSERT_EQ(EPERM, errno);
206 }
207
208 BPF_TEST_C(BaselinePolicy, EPERM_getcwd, BaselinePolicy) {
209 errno = 0;
210 char buf[1024];
211 char* cwd = getcwd(buf, sizeof(buf));
212 BPF_ASSERT_EQ(NULL, cwd);
213 BPF_ASSERT_EQ(EPERM, errno);
214 }
215
216 BPF_DEATH_TEST_C(BaselinePolicy,
217 SIGSYS_InvalidSyscall,
218 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
219 BaselinePolicy) {
220 Syscall::InvalidCall();
221 }
222
223 // A failing test using this macro could be problematic since we perform
224 // system calls by passing "0" as every argument.
225 // The kernel could SIGSEGV the process or the system call itself could reboot
226 // the machine. Some thoughts have been given when hand-picking the system
227 // calls below to limit any potential side effects outside of the current
228 // process.
229 #define TEST_BASELINE_SIGSYS(sysno) \
230 BPF_DEATH_TEST_C(BaselinePolicy, \
231 SIGSYS_##sysno, \
232 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()), \
233 BaselinePolicy) { \
234 syscall(sysno, 0, 0, 0, 0, 0, 0); \
235 _exit(1); \
236 }
237
238 TEST_BASELINE_SIGSYS(__NR_acct);
239 TEST_BASELINE_SIGSYS(__NR_chroot);
240 TEST_BASELINE_SIGSYS(__NR_fanotify_init);
241 TEST_BASELINE_SIGSYS(__NR_fgetxattr);
242 TEST_BASELINE_SIGSYS(__NR_getcpu);
243 TEST_BASELINE_SIGSYS(__NR_getitimer);
244 TEST_BASELINE_SIGSYS(__NR_init_module);
245 TEST_BASELINE_SIGSYS(__NR_io_cancel);
246 TEST_BASELINE_SIGSYS(__NR_keyctl);
247 TEST_BASELINE_SIGSYS(__NR_mq_open);
248 TEST_BASELINE_SIGSYS(__NR_ptrace);
249 TEST_BASELINE_SIGSYS(__NR_sched_setaffinity);
250 TEST_BASELINE_SIGSYS(__NR_setpgid);
251 TEST_BASELINE_SIGSYS(__NR_swapon);
252 TEST_BASELINE_SIGSYS(__NR_sysinfo);
253 TEST_BASELINE_SIGSYS(__NR_syslog);
254 TEST_BASELINE_SIGSYS(__NR_timer_create);
255
256 #if !defined(__aarch64__)
257 TEST_BASELINE_SIGSYS(__NR_eventfd);
258 TEST_BASELINE_SIGSYS(__NR_inotify_init);
259 TEST_BASELINE_SIGSYS(__NR_vserver);
260 #endif
261
262 BPF_DEATH_TEST_C(BaselinePolicy,
263 FutexWithRequeuePriorityInheritence,
264 DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()),
265 BaselinePolicy) {
266 syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI, 0, NULL, NULL, 0);
267 _exit(1);
268 }
269
270 BPF_DEATH_TEST_C(BaselinePolicy,
271 FutexWithRequeuePriorityInheritencePrivate,
272 DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()),
273 BaselinePolicy) {
274 syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI_PRIVATE, 0, NULL, NULL, 0);
275 _exit(1);
276 }
277
278 BPF_DEATH_TEST_C(BaselinePolicy,
279 FutexWithUnlockPIPrivate,
280 DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()),
281 BaselinePolicy) {
282 syscall(__NR_futex, NULL, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0);
283 _exit(1);
284 }
285
286 BPF_TEST_C(BaselinePolicy, PrctlDumpable, BaselinePolicy) {
287 const int is_dumpable = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
288 BPF_ASSERT(is_dumpable == 1 || is_dumpable == 0);
289 const int prctl_ret = prctl(PR_SET_DUMPABLE, is_dumpable, 0, 0, 0, 0);
290 BPF_ASSERT_EQ(0, prctl_ret);
291 }
292
293 // Workaround incomplete Android headers.
294 #if !defined(PR_CAPBSET_READ)
295 #define PR_CAPBSET_READ 23
296 #endif
297
298 BPF_DEATH_TEST_C(BaselinePolicy,
299 PrctlSigsys,
300 DEATH_SEGV_MESSAGE(GetPrctlErrorMessageContentForTests()),
301 BaselinePolicy) {
302 prctl(PR_CAPBSET_READ, 0, 0, 0, 0);
303 _exit(1);
304 }
305
306 BPF_TEST_C(BaselinePolicy, GetOrSetPriority, BaselinePolicy) {
307 errno = 0;
308 const int original_prio = getpriority(PRIO_PROCESS, 0);
309 // Check errno instead of the return value since this system call can return
310 // -1 as a valid value.
311 BPF_ASSERT_EQ(0, errno);
312
313 errno = 0;
314 int rc = getpriority(PRIO_PROCESS, getpid());
315 BPF_ASSERT_EQ(0, errno);
316
317 rc = getpriority(PRIO_PROCESS, getpid() + 1);
318 BPF_ASSERT_EQ(-1, rc);
319 BPF_ASSERT_EQ(EPERM, errno);
320
321 rc = setpriority(PRIO_PROCESS, 0, original_prio);
322 BPF_ASSERT_EQ(0, rc);
323
324 rc = setpriority(PRIO_PROCESS, getpid(), original_prio);
325 BPF_ASSERT_EQ(0, rc);
326
327 errno = 0;
328 rc = setpriority(PRIO_PROCESS, getpid() + 1, original_prio);
329 BPF_ASSERT_EQ(-1, rc);
330 BPF_ASSERT_EQ(EPERM, errno);
331 }
332
333 BPF_DEATH_TEST_C(BaselinePolicy,
334 GetPrioritySigsys,
335 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
336 BaselinePolicy) {
337 getpriority(PRIO_USER, 0);
338 _exit(1);
339 }
340
341 BPF_DEATH_TEST_C(BaselinePolicy,
342 ClockGettimeWithDisallowedClockCrashes,
343 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
344 BaselinePolicy) {
345 struct timespec ts;
346 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
347 }
348
349 } // namespace
350
351 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc ('k') | sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698