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
45namespace sandbox {
46
47namespace {
48
49// This also tests that read(), write() and fstat() are allowed.
50void 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.
72BPF_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
84BPF_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
91BPF_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
101pid_t ForkX86Glibc() {
102  static pid_t ptid;
103  return sys_clone(CLONE_PARENT_SETTID | SIGCHLD, nullptr, &ptid, nullptr,
104                   nullptr);
105}
106
107BPF_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
117pid_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
123BPF_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
133BPF_TEST_C(BaselinePolicy, CreateThread, BaselinePolicy) {
134  base::Thread thread("sandbox_tests");
135  BPF_ASSERT(thread.Start());
136}
137
138BPF_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
146BPF_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
155BPF_TEST_C(BaselinePolicy, CanKillSelf, BaselinePolicy) {
156  int sys_ret = kill(getpid(), 0);
157  BPF_ASSERT_EQ(0, sys_ret);
158}
159
160BPF_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__)
173BPF_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
183BPF_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
190BPF_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
197BPF_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
205BPF_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
227TEST_BASELINE_SIGSYS(__NR_acct);
228TEST_BASELINE_SIGSYS(__NR_chroot);
229TEST_BASELINE_SIGSYS(__NR_fanotify_init);
230TEST_BASELINE_SIGSYS(__NR_fgetxattr);
231TEST_BASELINE_SIGSYS(__NR_getcpu);
232TEST_BASELINE_SIGSYS(__NR_getitimer);
233TEST_BASELINE_SIGSYS(__NR_init_module);
234TEST_BASELINE_SIGSYS(__NR_io_cancel);
235TEST_BASELINE_SIGSYS(__NR_keyctl);
236TEST_BASELINE_SIGSYS(__NR_mq_open);
237TEST_BASELINE_SIGSYS(__NR_ptrace);
238TEST_BASELINE_SIGSYS(__NR_sched_setaffinity);
239TEST_BASELINE_SIGSYS(__NR_setpgid);
240TEST_BASELINE_SIGSYS(__NR_swapon);
241TEST_BASELINE_SIGSYS(__NR_sysinfo);
242TEST_BASELINE_SIGSYS(__NR_syslog);
243TEST_BASELINE_SIGSYS(__NR_timer_create);
244
245#if !defined(__aarch64__)
246TEST_BASELINE_SIGSYS(__NR_eventfd);
247TEST_BASELINE_SIGSYS(__NR_inotify_init);
248TEST_BASELINE_SIGSYS(__NR_vserver);
249#endif
250
251BPF_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
259BPF_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
267BPF_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
275BPF_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
287BPF_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
295BPF_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
322BPF_DEATH_TEST_C(BaselinePolicy,
323                 GetPrioritySigsys,
324                 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
325                 BaselinePolicy) {
326  getpriority(PRIO_USER, 0);
327  _exit(1);
328}
329
330BPF_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__)
339BPF_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
350BPF_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
361BPF_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
372BPF_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