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 <netinet/in.h>
10 #include <sched.h>
11 #include <signal.h>
12 #include <stddef.h>
13 #include <string.h>
14 #include <sys/prctl.h>
15 #include <sys/resource.h>
16 #include <sys/socket.h>
17 #include <sys/stat.h>
18 #include <sys/syscall.h>
19 #include <sys/time.h>
20 #include <sys/types.h>
21 #include <sys/wait.h>
22 #include <time.h>
23 #include <unistd.h>
24
25 #include "base/files/scoped_file.h"
26 #include "base/macros.h"
27 #include "base/posix/eintr_wrapper.h"
28 #include "base/threading/thread.h"
29 #include "build/build_config.h"
30 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
31 #include "sandbox/linux/seccomp-bpf/bpf_tests.h"
32 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
33 #include "sandbox/linux/seccomp-bpf/syscall.h"
34 #include "sandbox/linux/services/syscall_wrappers.h"
35 #include "sandbox/linux/services/thread_helpers.h"
36 #include "sandbox/linux/system_headers/linux_futex.h"
37 #include "sandbox/linux/system_headers/linux_syscalls.h"
38 #include "sandbox/linux/tests/test_utils.h"
39 #include "sandbox/linux/tests/unit_tests.h"
40
41 #if !defined(SO_PEEK_OFF)
42 #define SO_PEEK_OFF 42
43 #endif
44
45 namespace sandbox {
46
47 namespace {
48
49 // This also tests that read(), write() and fstat() are allowed.
TestPipeOrSocketPair(base::ScopedFD read_end,base::ScopedFD write_end)50 void TestPipeOrSocketPair(base::ScopedFD read_end, base::ScopedFD write_end) {
51 BPF_ASSERT_LE(0, read_end.get());
52 BPF_ASSERT_LE(0, write_end.get());
53 struct stat stat_buf;
54 int sys_ret = fstat(read_end.get(), &stat_buf);
55 BPF_ASSERT_EQ(0, sys_ret);
56 BPF_ASSERT(S_ISFIFO(stat_buf.st_mode) || S_ISSOCK(stat_buf.st_mode));
57
58 const ssize_t kTestTransferSize = 4;
59 static const char kTestString[kTestTransferSize] = {'T', 'E', 'S', 'T'};
60 ssize_t transfered = 0;
61
62 transfered =
63 HANDLE_EINTR(write(write_end.get(), kTestString, kTestTransferSize));
64 BPF_ASSERT_EQ(kTestTransferSize, transfered);
65 char read_buf[kTestTransferSize + 1] = {0};
66 transfered = HANDLE_EINTR(read(read_end.get(), read_buf, sizeof(read_buf)));
67 BPF_ASSERT_EQ(kTestTransferSize, transfered);
68 BPF_ASSERT_EQ(0, memcmp(kTestString, read_buf, kTestTransferSize));
69 }
70
71 // Test that a few easy-to-test system calls are allowed.
BPF_TEST_C(BaselinePolicy,BaselinePolicyBasicAllowed,BaselinePolicy)72 BPF_TEST_C(BaselinePolicy, BaselinePolicyBasicAllowed, BaselinePolicy) {
73 BPF_ASSERT_EQ(0, sched_yield());
74
75 int pipefd[2];
76 int sys_ret = pipe(pipefd);
77 BPF_ASSERT_EQ(0, sys_ret);
78 TestPipeOrSocketPair(base::ScopedFD(pipefd[0]), base::ScopedFD(pipefd[1]));
79
80 BPF_ASSERT_LE(1, getpid());
81 BPF_ASSERT_LE(0, getuid());
82 }
83
BPF_TEST_C(BaselinePolicy,FchmodErrno,BaselinePolicy)84 BPF_TEST_C(BaselinePolicy, FchmodErrno, BaselinePolicy) {
85 int ret = fchmod(-1, 07777);
86 BPF_ASSERT_EQ(-1, ret);
87 // Without the sandbox, this would EBADF instead.
88 BPF_ASSERT_EQ(EPERM, errno);
89 }
90
BPF_TEST_C(BaselinePolicy,ForkErrno,BaselinePolicy)91 BPF_TEST_C(BaselinePolicy, ForkErrno, BaselinePolicy) {
92 errno = 0;
93 pid_t pid = fork();
94 const int fork_errno = errno;
95 TestUtils::HandlePostForkReturn(pid);
96
97 BPF_ASSERT_EQ(-1, pid);
98 BPF_ASSERT_EQ(EPERM, fork_errno);
99 }
100
ForkX86Glibc()101 pid_t ForkX86Glibc() {
102 static pid_t ptid;
103 return sys_clone(CLONE_PARENT_SETTID | SIGCHLD, nullptr, &ptid, nullptr,
104 nullptr);
105 }
106
BPF_TEST_C(BaselinePolicy,ForkX86Eperm,BaselinePolicy)107 BPF_TEST_C(BaselinePolicy, ForkX86Eperm, BaselinePolicy) {
108 errno = 0;
109 pid_t pid = ForkX86Glibc();
110 const int fork_errno = errno;
111 TestUtils::HandlePostForkReturn(pid);
112
113 BPF_ASSERT_EQ(-1, pid);
114 BPF_ASSERT_EQ(EPERM, fork_errno);
115 }
116
ForkARMGlibc()117 pid_t ForkARMGlibc() {
118 static pid_t ctid;
119 return sys_clone(CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, nullptr,
120 nullptr, &ctid, nullptr);
121 }
122
BPF_TEST_C(BaselinePolicy,ForkArmEperm,BaselinePolicy)123 BPF_TEST_C(BaselinePolicy, ForkArmEperm, BaselinePolicy) {
124 errno = 0;
125 pid_t pid = ForkARMGlibc();
126 const int fork_errno = errno;
127 TestUtils::HandlePostForkReturn(pid);
128
129 BPF_ASSERT_EQ(-1, pid);
130 BPF_ASSERT_EQ(EPERM, fork_errno);
131 }
132
BPF_TEST_C(BaselinePolicy,CreateThread,BaselinePolicy)133 BPF_TEST_C(BaselinePolicy, CreateThread, BaselinePolicy) {
134 base::Thread thread("sandbox_tests");
135 BPF_ASSERT(thread.Start());
136 }
137
BPF_DEATH_TEST_C(BaselinePolicy,DisallowedCloneFlagCrashes,DEATH_SEGV_MESSAGE (GetCloneErrorMessageContentForTests ()),BaselinePolicy)138 BPF_DEATH_TEST_C(BaselinePolicy,
139 DisallowedCloneFlagCrashes,
140 DEATH_SEGV_MESSAGE(GetCloneErrorMessageContentForTests()),
141 BaselinePolicy) {
142 pid_t pid = sys_clone(CLONE_THREAD | SIGCHLD);
143 TestUtils::HandlePostForkReturn(pid);
144 }
145
BPF_DEATH_TEST_C(BaselinePolicy,DisallowedKillCrashes,DEATH_SEGV_MESSAGE (GetKillErrorMessageContentForTests ()),BaselinePolicy)146 BPF_DEATH_TEST_C(BaselinePolicy,
147 DisallowedKillCrashes,
148 DEATH_SEGV_MESSAGE(GetKillErrorMessageContentForTests()),
149 BaselinePolicy) {
150 BPF_ASSERT_NE(1, getpid());
151 kill(1, 0);
152 _exit(0);
153 }
154
BPF_TEST_C(BaselinePolicy,CanKillSelf,BaselinePolicy)155 BPF_TEST_C(BaselinePolicy, CanKillSelf, BaselinePolicy) {
156 int sys_ret = kill(getpid(), 0);
157 BPF_ASSERT_EQ(0, sys_ret);
158 }
159
BPF_TEST_C(BaselinePolicy,Socketpair,BaselinePolicy)160 BPF_TEST_C(BaselinePolicy, Socketpair, BaselinePolicy) {
161 int sv[2];
162 int sys_ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, sv);
163 BPF_ASSERT_EQ(0, sys_ret);
164 TestPipeOrSocketPair(base::ScopedFD(sv[0]), base::ScopedFD(sv[1]));
165
166 sys_ret = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sv);
167 BPF_ASSERT_EQ(0, sys_ret);
168 TestPipeOrSocketPair(base::ScopedFD(sv[0]), base::ScopedFD(sv[1]));
169 }
170
171 // Not all architectures can restrict the domain for socketpair().
172 #if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
BPF_DEATH_TEST_C(BaselinePolicy,SocketpairWrongDomain,DEATH_SEGV_MESSAGE (GetErrorMessageContentForTests ()),BaselinePolicy)173 BPF_DEATH_TEST_C(BaselinePolicy,
174 SocketpairWrongDomain,
175 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
176 BaselinePolicy) {
177 int sv[2];
178 ignore_result(socketpair(AF_INET, SOCK_STREAM, 0, sv));
179 _exit(1);
180 }
181 #endif // defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
182
BPF_TEST_C(BaselinePolicy,EPERM_open,BaselinePolicy)183 BPF_TEST_C(BaselinePolicy, EPERM_open, BaselinePolicy) {
184 errno = 0;
185 int sys_ret = open("/proc/cpuinfo", O_RDONLY);
186 BPF_ASSERT_EQ(-1, sys_ret);
187 BPF_ASSERT_EQ(EPERM, errno);
188 }
189
BPF_TEST_C(BaselinePolicy,EPERM_access,BaselinePolicy)190 BPF_TEST_C(BaselinePolicy, EPERM_access, BaselinePolicy) {
191 errno = 0;
192 int sys_ret = access("/proc/cpuinfo", R_OK);
193 BPF_ASSERT_EQ(-1, sys_ret);
194 BPF_ASSERT_EQ(EPERM, errno);
195 }
196
BPF_TEST_C(BaselinePolicy,EPERM_getcwd,BaselinePolicy)197 BPF_TEST_C(BaselinePolicy, EPERM_getcwd, BaselinePolicy) {
198 errno = 0;
199 char buf[1024];
200 char* cwd = getcwd(buf, sizeof(buf));
201 BPF_ASSERT_EQ(NULL, cwd);
202 BPF_ASSERT_EQ(EPERM, errno);
203 }
204
BPF_DEATH_TEST_C(BaselinePolicy,SIGSYS_InvalidSyscall,DEATH_SEGV_MESSAGE (GetErrorMessageContentForTests ()),BaselinePolicy)205 BPF_DEATH_TEST_C(BaselinePolicy,
206 SIGSYS_InvalidSyscall,
207 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
208 BaselinePolicy) {
209 Syscall::InvalidCall();
210 }
211
212 // A failing test using this macro could be problematic since we perform
213 // system calls by passing "0" as every argument.
214 // The kernel could SIGSEGV the process or the system call itself could reboot
215 // the machine. Some thoughts have been given when hand-picking the system
216 // calls below to limit any potential side effects outside of the current
217 // process.
218 #define TEST_BASELINE_SIGSYS(sysno) \
219 BPF_DEATH_TEST_C(BaselinePolicy, \
220 SIGSYS_##sysno, \
221 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()), \
222 BaselinePolicy) { \
223 syscall(sysno, 0, 0, 0, 0, 0, 0); \
224 _exit(1); \
225 }
226
227 TEST_BASELINE_SIGSYS(__NR_acct);
228 TEST_BASELINE_SIGSYS(__NR_chroot);
229 TEST_BASELINE_SIGSYS(__NR_fanotify_init);
230 TEST_BASELINE_SIGSYS(__NR_fgetxattr);
231 TEST_BASELINE_SIGSYS(__NR_getcpu);
232 TEST_BASELINE_SIGSYS(__NR_getitimer);
233 TEST_BASELINE_SIGSYS(__NR_init_module);
234 TEST_BASELINE_SIGSYS(__NR_io_cancel);
235 TEST_BASELINE_SIGSYS(__NR_keyctl);
236 TEST_BASELINE_SIGSYS(__NR_mq_open);
237 TEST_BASELINE_SIGSYS(__NR_ptrace);
238 TEST_BASELINE_SIGSYS(__NR_sched_setaffinity);
239 TEST_BASELINE_SIGSYS(__NR_setpgid);
240 TEST_BASELINE_SIGSYS(__NR_swapon);
241 TEST_BASELINE_SIGSYS(__NR_sysinfo);
242 TEST_BASELINE_SIGSYS(__NR_syslog);
243 TEST_BASELINE_SIGSYS(__NR_timer_create);
244
245 #if !defined(__aarch64__)
246 TEST_BASELINE_SIGSYS(__NR_eventfd);
247 TEST_BASELINE_SIGSYS(__NR_inotify_init);
248 TEST_BASELINE_SIGSYS(__NR_vserver);
249 #endif
250
251 #if defined(LIBC_GLIBC) && !defined(OS_CHROMEOS)
BPF_TEST_C(BaselinePolicy,FutexEINVAL,BaselinePolicy)252 BPF_TEST_C(BaselinePolicy, FutexEINVAL, BaselinePolicy) {
253 int ops[] = {
254 FUTEX_CMP_REQUEUE_PI, FUTEX_CMP_REQUEUE_PI_PRIVATE,
255 FUTEX_UNLOCK_PI_PRIVATE,
256 };
257
258 for (int op : ops) {
259 BPF_ASSERT_EQ(-1, syscall(__NR_futex, NULL, op, 0, NULL, NULL, 0));
260 BPF_ASSERT_EQ(EINVAL, errno);
261 }
262 }
263 #else
BPF_DEATH_TEST_C(BaselinePolicy,FutexWithRequeuePriorityInheritence,DEATH_SEGV_MESSAGE (GetFutexErrorMessageContentForTests ()),BaselinePolicy)264 BPF_DEATH_TEST_C(BaselinePolicy,
265 FutexWithRequeuePriorityInheritence,
266 DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()),
267 BaselinePolicy) {
268 syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI, 0, NULL, NULL, 0);
269 _exit(1);
270 }
271
BPF_DEATH_TEST_C(BaselinePolicy,FutexWithRequeuePriorityInheritencePrivate,DEATH_SEGV_MESSAGE (GetFutexErrorMessageContentForTests ()),BaselinePolicy)272 BPF_DEATH_TEST_C(BaselinePolicy,
273 FutexWithRequeuePriorityInheritencePrivate,
274 DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()),
275 BaselinePolicy) {
276 syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI_PRIVATE, 0, NULL, NULL, 0);
277 _exit(1);
278 }
279
BPF_DEATH_TEST_C(BaselinePolicy,FutexWithUnlockPIPrivate,DEATH_SEGV_MESSAGE (GetFutexErrorMessageContentForTests ()),BaselinePolicy)280 BPF_DEATH_TEST_C(BaselinePolicy,
281 FutexWithUnlockPIPrivate,
282 DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()),
283 BaselinePolicy) {
284 syscall(__NR_futex, NULL, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0);
285 _exit(1);
286 }
287 #endif // defined(LIBC_GLIBC) && !defined(OS_CHROMEOS)
288
BPF_TEST_C(BaselinePolicy,PrctlDumpable,BaselinePolicy)289 BPF_TEST_C(BaselinePolicy, PrctlDumpable, BaselinePolicy) {
290 const int is_dumpable = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
291 BPF_ASSERT(is_dumpable == 1 || is_dumpable == 0);
292 const int prctl_ret = prctl(PR_SET_DUMPABLE, is_dumpable, 0, 0, 0, 0);
293 BPF_ASSERT_EQ(0, prctl_ret);
294 }
295
296 // Workaround incomplete Android headers.
297 #if !defined(PR_CAPBSET_READ)
298 #define PR_CAPBSET_READ 23
299 #endif
300
BPF_DEATH_TEST_C(BaselinePolicy,PrctlSigsys,DEATH_SEGV_MESSAGE (GetPrctlErrorMessageContentForTests ()),BaselinePolicy)301 BPF_DEATH_TEST_C(BaselinePolicy,
302 PrctlSigsys,
303 DEATH_SEGV_MESSAGE(GetPrctlErrorMessageContentForTests()),
304 BaselinePolicy) {
305 prctl(PR_CAPBSET_READ, 0, 0, 0, 0);
306 _exit(1);
307 }
308
BPF_TEST_C(BaselinePolicy,GetOrSetPriority,BaselinePolicy)309 BPF_TEST_C(BaselinePolicy, GetOrSetPriority, BaselinePolicy) {
310 errno = 0;
311 const int original_prio = getpriority(PRIO_PROCESS, 0);
312 // Check errno instead of the return value since this system call can return
313 // -1 as a valid value.
314 BPF_ASSERT_EQ(0, errno);
315
316 errno = 0;
317 int rc = getpriority(PRIO_PROCESS, getpid());
318 BPF_ASSERT_EQ(0, errno);
319
320 rc = getpriority(PRIO_PROCESS, getpid() + 1);
321 BPF_ASSERT_EQ(-1, rc);
322 BPF_ASSERT_EQ(EPERM, errno);
323
324 rc = setpriority(PRIO_PROCESS, 0, original_prio);
325 BPF_ASSERT_EQ(0, rc);
326
327 rc = setpriority(PRIO_PROCESS, getpid(), original_prio);
328 BPF_ASSERT_EQ(0, rc);
329
330 errno = 0;
331 rc = setpriority(PRIO_PROCESS, getpid() + 1, original_prio);
332 BPF_ASSERT_EQ(-1, rc);
333 BPF_ASSERT_EQ(EPERM, errno);
334 }
335
BPF_DEATH_TEST_C(BaselinePolicy,GetPrioritySigsys,DEATH_SEGV_MESSAGE (GetErrorMessageContentForTests ()),BaselinePolicy)336 BPF_DEATH_TEST_C(BaselinePolicy,
337 GetPrioritySigsys,
338 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
339 BaselinePolicy) {
340 getpriority(PRIO_USER, 0);
341 _exit(1);
342 }
343
BPF_DEATH_TEST_C(BaselinePolicy,ClockGettimeWithDisallowedClockCrashes,DEATH_SEGV_MESSAGE (sandbox::GetErrorMessageContentForTests ()),BaselinePolicy)344 BPF_DEATH_TEST_C(BaselinePolicy,
345 ClockGettimeWithDisallowedClockCrashes,
346 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
347 BaselinePolicy) {
348 struct timespec ts;
349 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
350 }
351
352 #if !defined(__i386__)
BPF_DEATH_TEST_C(BaselinePolicy,GetSockOptWrongLevelSigsys,DEATH_SEGV_MESSAGE (sandbox::GetErrorMessageContentForTests ()),BaselinePolicy)353 BPF_DEATH_TEST_C(BaselinePolicy,
354 GetSockOptWrongLevelSigsys,
355 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
356 BaselinePolicy) {
357 int fds[2];
358 PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
359 int id;
360 socklen_t peek_off_size = sizeof(id);
361 getsockopt(fds[0], IPPROTO_TCP, SO_PEEK_OFF, &id, &peek_off_size);
362 }
363
BPF_DEATH_TEST_C(BaselinePolicy,GetSockOptWrongOptionSigsys,DEATH_SEGV_MESSAGE (sandbox::GetErrorMessageContentForTests ()),BaselinePolicy)364 BPF_DEATH_TEST_C(BaselinePolicy,
365 GetSockOptWrongOptionSigsys,
366 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
367 BaselinePolicy) {
368 int fds[2];
369 PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
370 int id;
371 socklen_t peek_off_size = sizeof(id);
372 getsockopt(fds[0], SOL_SOCKET, SO_DEBUG, &id, &peek_off_size);
373 }
374
BPF_DEATH_TEST_C(BaselinePolicy,SetSockOptWrongLevelSigsys,DEATH_SEGV_MESSAGE (sandbox::GetErrorMessageContentForTests ()),BaselinePolicy)375 BPF_DEATH_TEST_C(BaselinePolicy,
376 SetSockOptWrongLevelSigsys,
377 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
378 BaselinePolicy) {
379 int fds[2];
380 PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
381 int id;
382 setsockopt(fds[0], IPPROTO_TCP, SO_PEEK_OFF, &id, sizeof(id));
383 }
384
385
BPF_DEATH_TEST_C(BaselinePolicy,SetSockOptWrongOptionSigsys,DEATH_SEGV_MESSAGE (sandbox::GetErrorMessageContentForTests ()),BaselinePolicy)386 BPF_DEATH_TEST_C(BaselinePolicy,
387 SetSockOptWrongOptionSigsys,
388 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
389 BaselinePolicy) {
390 int fds[2];
391 PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
392 int id;
393 setsockopt(fds[0], SOL_SOCKET, SO_DEBUG, &id, sizeof(id));
394 }
395 #endif
396
397 } // namespace
398
399 } // namespace sandbox
400