• 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 
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