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
BPF_DEATH_TEST_C(BaselinePolicy,FutexWithRequeuePriorityInheritence,DEATH_SEGV_MESSAGE (GetFutexErrorMessageContentForTests ()),BaselinePolicy)251 BPF_DEATH_TEST_C(BaselinePolicy,
252 FutexWithRequeuePriorityInheritence,
253 DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()),
254 BaselinePolicy) {
255 syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI, 0, NULL, NULL, 0);
256 _exit(1);
257 }
258
BPF_DEATH_TEST_C(BaselinePolicy,FutexWithRequeuePriorityInheritencePrivate,DEATH_SEGV_MESSAGE (GetFutexErrorMessageContentForTests ()),BaselinePolicy)259 BPF_DEATH_TEST_C(BaselinePolicy,
260 FutexWithRequeuePriorityInheritencePrivate,
261 DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()),
262 BaselinePolicy) {
263 syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI_PRIVATE, 0, NULL, NULL, 0);
264 _exit(1);
265 }
266
BPF_DEATH_TEST_C(BaselinePolicy,FutexWithUnlockPIPrivate,DEATH_SEGV_MESSAGE (GetFutexErrorMessageContentForTests ()),BaselinePolicy)267 BPF_DEATH_TEST_C(BaselinePolicy,
268 FutexWithUnlockPIPrivate,
269 DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()),
270 BaselinePolicy) {
271 syscall(__NR_futex, NULL, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0);
272 _exit(1);
273 }
274
BPF_TEST_C(BaselinePolicy,PrctlDumpable,BaselinePolicy)275 BPF_TEST_C(BaselinePolicy, PrctlDumpable, BaselinePolicy) {
276 const int is_dumpable = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
277 BPF_ASSERT(is_dumpable == 1 || is_dumpable == 0);
278 const int prctl_ret = prctl(PR_SET_DUMPABLE, is_dumpable, 0, 0, 0, 0);
279 BPF_ASSERT_EQ(0, prctl_ret);
280 }
281
282 // Workaround incomplete Android headers.
283 #if !defined(PR_CAPBSET_READ)
284 #define PR_CAPBSET_READ 23
285 #endif
286
BPF_DEATH_TEST_C(BaselinePolicy,PrctlSigsys,DEATH_SEGV_MESSAGE (GetPrctlErrorMessageContentForTests ()),BaselinePolicy)287 BPF_DEATH_TEST_C(BaselinePolicy,
288 PrctlSigsys,
289 DEATH_SEGV_MESSAGE(GetPrctlErrorMessageContentForTests()),
290 BaselinePolicy) {
291 prctl(PR_CAPBSET_READ, 0, 0, 0, 0);
292 _exit(1);
293 }
294
BPF_TEST_C(BaselinePolicy,GetOrSetPriority,BaselinePolicy)295 BPF_TEST_C(BaselinePolicy, GetOrSetPriority, BaselinePolicy) {
296 errno = 0;
297 const int original_prio = getpriority(PRIO_PROCESS, 0);
298 // Check errno instead of the return value since this system call can return
299 // -1 as a valid value.
300 BPF_ASSERT_EQ(0, errno);
301
302 errno = 0;
303 int rc = getpriority(PRIO_PROCESS, getpid());
304 BPF_ASSERT_EQ(0, errno);
305
306 rc = getpriority(PRIO_PROCESS, getpid() + 1);
307 BPF_ASSERT_EQ(-1, rc);
308 BPF_ASSERT_EQ(EPERM, errno);
309
310 rc = setpriority(PRIO_PROCESS, 0, original_prio);
311 BPF_ASSERT_EQ(0, rc);
312
313 rc = setpriority(PRIO_PROCESS, getpid(), original_prio);
314 BPF_ASSERT_EQ(0, rc);
315
316 errno = 0;
317 rc = setpriority(PRIO_PROCESS, getpid() + 1, original_prio);
318 BPF_ASSERT_EQ(-1, rc);
319 BPF_ASSERT_EQ(EPERM, errno);
320 }
321
BPF_DEATH_TEST_C(BaselinePolicy,GetPrioritySigsys,DEATH_SEGV_MESSAGE (GetErrorMessageContentForTests ()),BaselinePolicy)322 BPF_DEATH_TEST_C(BaselinePolicy,
323 GetPrioritySigsys,
324 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
325 BaselinePolicy) {
326 getpriority(PRIO_USER, 0);
327 _exit(1);
328 }
329
BPF_DEATH_TEST_C(BaselinePolicy,ClockGettimeWithDisallowedClockCrashes,DEATH_SEGV_MESSAGE (sandbox::GetErrorMessageContentForTests ()),BaselinePolicy)330 BPF_DEATH_TEST_C(BaselinePolicy,
331 ClockGettimeWithDisallowedClockCrashes,
332 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
333 BaselinePolicy) {
334 struct timespec ts;
335 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
336 }
337
338 #if !defined(__i386__)
BPF_DEATH_TEST_C(BaselinePolicy,GetSockOptWrongLevelSigsys,DEATH_SEGV_MESSAGE (sandbox::GetErrorMessageContentForTests ()),BaselinePolicy)339 BPF_DEATH_TEST_C(BaselinePolicy,
340 GetSockOptWrongLevelSigsys,
341 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
342 BaselinePolicy) {
343 int fds[2];
344 PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
345 int id;
346 socklen_t peek_off_size = sizeof(id);
347 getsockopt(fds[0], IPPROTO_TCP, SO_PEEK_OFF, &id, &peek_off_size);
348 }
349
BPF_DEATH_TEST_C(BaselinePolicy,GetSockOptWrongOptionSigsys,DEATH_SEGV_MESSAGE (sandbox::GetErrorMessageContentForTests ()),BaselinePolicy)350 BPF_DEATH_TEST_C(BaselinePolicy,
351 GetSockOptWrongOptionSigsys,
352 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
353 BaselinePolicy) {
354 int fds[2];
355 PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
356 int id;
357 socklen_t peek_off_size = sizeof(id);
358 getsockopt(fds[0], SOL_SOCKET, SO_DEBUG, &id, &peek_off_size);
359 }
360
BPF_DEATH_TEST_C(BaselinePolicy,SetSockOptWrongLevelSigsys,DEATH_SEGV_MESSAGE (sandbox::GetErrorMessageContentForTests ()),BaselinePolicy)361 BPF_DEATH_TEST_C(BaselinePolicy,
362 SetSockOptWrongLevelSigsys,
363 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
364 BaselinePolicy) {
365 int fds[2];
366 PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
367 int id;
368 setsockopt(fds[0], IPPROTO_TCP, SO_PEEK_OFF, &id, sizeof(id));
369 }
370
371
BPF_DEATH_TEST_C(BaselinePolicy,SetSockOptWrongOptionSigsys,DEATH_SEGV_MESSAGE (sandbox::GetErrorMessageContentForTests ()),BaselinePolicy)372 BPF_DEATH_TEST_C(BaselinePolicy,
373 SetSockOptWrongOptionSigsys,
374 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
375 BaselinePolicy) {
376 int fds[2];
377 PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
378 int id;
379 setsockopt(fds[0], SOL_SOCKET, SO_DEBUG, &id, sizeof(id));
380 }
381 #endif
382
383 } // namespace
384
385 } // namespace sandbox
386