Home | History | Annotate | Download | only in seccomp-bpf-helpers
      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.
     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.
     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 
     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 
     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 
    101 pid_t ForkX86Glibc() {
    102   static pid_t ptid;
    103   return sys_clone(CLONE_PARENT_SETTID | SIGCHLD, nullptr, &ptid, nullptr,
    104                    nullptr);
    105 }
    106 
    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 
    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 
    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 
    133 BPF_TEST_C(BaselinePolicy, CreateThread, BaselinePolicy) {
    134   base::Thread thread("sandbox_tests");
    135   BPF_ASSERT(thread.Start());
    136 }
    137 
    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 
    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 
    155 BPF_TEST_C(BaselinePolicy, CanKillSelf, BaselinePolicy) {
    156   int sys_ret = kill(getpid(), 0);
    157   BPF_ASSERT_EQ(0, sys_ret);
    158 }
    159 
    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__)
    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 
    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 
    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 
    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 
    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 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 
    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 
    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 
    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 
    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 
    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 
    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 
    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__)
    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 
    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 
    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 
    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