• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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