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 <linux/futex.h> 10 #include <sched.h> 11 #include <signal.h> 12 #include <string.h> 13 #include <sys/prctl.h> 14 #include <sys/resource.h> 15 #include <sys/socket.h> 16 #include <sys/stat.h> 17 #include <sys/syscall.h> 18 #include <sys/time.h> 19 #include <sys/types.h> 20 #include <sys/wait.h> 21 #include <time.h> 22 #include <unistd.h> 23 24 #include "base/files/scoped_file.h" 25 #include "base/macros.h" 26 #include "base/posix/eintr_wrapper.h" 27 #include "base/threading/thread.h" 28 #include "build/build_config.h" 29 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" 30 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" 31 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" 32 #include "sandbox/linux/seccomp-bpf/syscall.h" 33 #include "sandbox/linux/services/android_futex.h" 34 #include "sandbox/linux/services/linux_syscalls.h" 35 #include "sandbox/linux/services/thread_helpers.h" 36 #include "sandbox/linux/tests/unit_tests.h" 37 38 namespace sandbox { 39 40 namespace { 41 42 // |pid| is the return value of a fork()-like call. This 43 // makes sure that if fork() succeeded the child exits 44 // and the parent waits for it. 45 void HandlePostForkReturn(pid_t pid) { 46 const int kChildExitCode = 1; 47 if (pid > 0) { 48 int status = 0; 49 PCHECK(pid == HANDLE_EINTR(waitpid(pid, &status, 0))); 50 CHECK(WIFEXITED(status)); 51 CHECK_EQ(kChildExitCode, WEXITSTATUS(status)); 52 } else if (pid == 0) { 53 _exit(kChildExitCode); 54 } 55 } 56 57 // Check that HandlePostForkReturn works. 58 TEST(BaselinePolicy, HandlePostForkReturn) { 59 pid_t pid = fork(); 60 HandlePostForkReturn(pid); 61 } 62 63 // This also tests that read(), write() and fstat() are allowed. 64 void TestPipeOrSocketPair(base::ScopedFD read_end, base::ScopedFD write_end) { 65 BPF_ASSERT_LE(0, read_end.get()); 66 BPF_ASSERT_LE(0, write_end.get()); 67 struct stat stat_buf; 68 int sys_ret = fstat(read_end.get(), &stat_buf); 69 BPF_ASSERT_EQ(0, sys_ret); 70 BPF_ASSERT(S_ISFIFO(stat_buf.st_mode) || S_ISSOCK(stat_buf.st_mode)); 71 72 const ssize_t kTestTransferSize = 4; 73 static const char kTestString[kTestTransferSize] = {'T', 'E', 'S', 'T'}; 74 ssize_t transfered = 0; 75 76 transfered = 77 HANDLE_EINTR(write(write_end.get(), kTestString, kTestTransferSize)); 78 BPF_ASSERT_EQ(kTestTransferSize, transfered); 79 char read_buf[kTestTransferSize + 1] = {0}; 80 transfered = HANDLE_EINTR(read(read_end.get(), read_buf, sizeof(read_buf))); 81 BPF_ASSERT_EQ(kTestTransferSize, transfered); 82 BPF_ASSERT_EQ(0, memcmp(kTestString, read_buf, kTestTransferSize)); 83 } 84 85 // Test that a few easy-to-test system calls are allowed. 86 BPF_TEST_C(BaselinePolicy, BaselinePolicyBasicAllowed, BaselinePolicy) { 87 BPF_ASSERT_EQ(0, sched_yield()); 88 89 int pipefd[2]; 90 int sys_ret = pipe(pipefd); 91 BPF_ASSERT_EQ(0, sys_ret); 92 TestPipeOrSocketPair(base::ScopedFD(pipefd[0]), base::ScopedFD(pipefd[1])); 93 94 BPF_ASSERT_LE(1, getpid()); 95 BPF_ASSERT_LE(0, getuid()); 96 } 97 98 BPF_TEST_C(BaselinePolicy, FchmodErrno, BaselinePolicy) { 99 int ret = fchmod(-1, 07777); 100 BPF_ASSERT_EQ(-1, ret); 101 // Without the sandbox, this would EBADF instead. 102 BPF_ASSERT_EQ(EPERM, errno); 103 } 104 105 BPF_TEST_C(BaselinePolicy, ForkErrno, BaselinePolicy) { 106 errno = 0; 107 pid_t pid = fork(); 108 const int fork_errno = errno; 109 HandlePostForkReturn(pid); 110 111 BPF_ASSERT_EQ(-1, pid); 112 BPF_ASSERT_EQ(EPERM, fork_errno); 113 } 114 115 pid_t ForkX86Glibc() { 116 return syscall(__NR_clone, CLONE_PARENT_SETTID | SIGCHLD); 117 } 118 119 BPF_TEST_C(BaselinePolicy, ForkX86Eperm, BaselinePolicy) { 120 errno = 0; 121 pid_t pid = ForkX86Glibc(); 122 const int fork_errno = errno; 123 HandlePostForkReturn(pid); 124 125 BPF_ASSERT_EQ(-1, pid); 126 BPF_ASSERT_EQ(EPERM, fork_errno); 127 } 128 129 pid_t ForkARMGlibc() { 130 return syscall(__NR_clone, 131 CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD); 132 } 133 134 BPF_TEST_C(BaselinePolicy, ForkArmEperm, BaselinePolicy) { 135 errno = 0; 136 pid_t pid = ForkARMGlibc(); 137 const int fork_errno = errno; 138 HandlePostForkReturn(pid); 139 140 BPF_ASSERT_EQ(-1, pid); 141 BPF_ASSERT_EQ(EPERM, fork_errno); 142 } 143 144 BPF_TEST_C(BaselinePolicy, CreateThread, BaselinePolicy) { 145 base::Thread thread("sandbox_tests"); 146 BPF_ASSERT(thread.Start()); 147 } 148 149 BPF_DEATH_TEST_C(BaselinePolicy, 150 DisallowedCloneFlagCrashes, 151 DEATH_SEGV_MESSAGE(GetCloneErrorMessageContentForTests()), 152 BaselinePolicy) { 153 pid_t pid = syscall(__NR_clone, CLONE_THREAD | SIGCHLD); 154 HandlePostForkReturn(pid); 155 } 156 157 BPF_DEATH_TEST_C(BaselinePolicy, 158 DisallowedKillCrashes, 159 DEATH_SEGV_MESSAGE(GetKillErrorMessageContentForTests()), 160 BaselinePolicy) { 161 BPF_ASSERT_NE(1, getpid()); 162 kill(1, 0); 163 _exit(0); 164 } 165 166 BPF_TEST_C(BaselinePolicy, CanKillSelf, BaselinePolicy) { 167 int sys_ret = kill(getpid(), 0); 168 BPF_ASSERT_EQ(0, sys_ret); 169 } 170 171 BPF_TEST_C(BaselinePolicy, Socketpair, BaselinePolicy) { 172 int sv[2]; 173 int sys_ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, sv); 174 BPF_ASSERT_EQ(0, sys_ret); 175 TestPipeOrSocketPair(base::ScopedFD(sv[0]), base::ScopedFD(sv[1])); 176 177 sys_ret = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sv); 178 BPF_ASSERT_EQ(0, sys_ret); 179 TestPipeOrSocketPair(base::ScopedFD(sv[0]), base::ScopedFD(sv[1])); 180 } 181 182 // Not all architectures can restrict the domain for socketpair(). 183 #if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) 184 BPF_DEATH_TEST_C(BaselinePolicy, 185 SocketpairWrongDomain, 186 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()), 187 BaselinePolicy) { 188 int sv[2]; 189 ignore_result(socketpair(AF_INET, SOCK_STREAM, 0, sv)); 190 _exit(1); 191 } 192 #endif // defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) 193 194 BPF_TEST_C(BaselinePolicy, EPERM_open, BaselinePolicy) { 195 errno = 0; 196 int sys_ret = open("/proc/cpuinfo", O_RDONLY); 197 BPF_ASSERT_EQ(-1, sys_ret); 198 BPF_ASSERT_EQ(EPERM, errno); 199 } 200 201 BPF_TEST_C(BaselinePolicy, EPERM_access, BaselinePolicy) { 202 errno = 0; 203 int sys_ret = access("/proc/cpuinfo", R_OK); 204 BPF_ASSERT_EQ(-1, sys_ret); 205 BPF_ASSERT_EQ(EPERM, errno); 206 } 207 208 BPF_TEST_C(BaselinePolicy, EPERM_getcwd, BaselinePolicy) { 209 errno = 0; 210 char buf[1024]; 211 char* cwd = getcwd(buf, sizeof(buf)); 212 BPF_ASSERT_EQ(NULL, cwd); 213 BPF_ASSERT_EQ(EPERM, errno); 214 } 215 216 BPF_DEATH_TEST_C(BaselinePolicy, 217 SIGSYS_InvalidSyscall, 218 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()), 219 BaselinePolicy) { 220 Syscall::InvalidCall(); 221 } 222 223 // A failing test using this macro could be problematic since we perform 224 // system calls by passing "0" as every argument. 225 // The kernel could SIGSEGV the process or the system call itself could reboot 226 // the machine. Some thoughts have been given when hand-picking the system 227 // calls below to limit any potential side effects outside of the current 228 // process. 229 #define TEST_BASELINE_SIGSYS(sysno) \ 230 BPF_DEATH_TEST_C(BaselinePolicy, \ 231 SIGSYS_##sysno, \ 232 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()), \ 233 BaselinePolicy) { \ 234 syscall(sysno, 0, 0, 0, 0, 0, 0); \ 235 _exit(1); \ 236 } 237 238 TEST_BASELINE_SIGSYS(__NR_acct); 239 TEST_BASELINE_SIGSYS(__NR_chroot); 240 TEST_BASELINE_SIGSYS(__NR_fanotify_init); 241 TEST_BASELINE_SIGSYS(__NR_fgetxattr); 242 TEST_BASELINE_SIGSYS(__NR_getcpu); 243 TEST_BASELINE_SIGSYS(__NR_getitimer); 244 TEST_BASELINE_SIGSYS(__NR_init_module); 245 TEST_BASELINE_SIGSYS(__NR_io_cancel); 246 TEST_BASELINE_SIGSYS(__NR_keyctl); 247 TEST_BASELINE_SIGSYS(__NR_mq_open); 248 TEST_BASELINE_SIGSYS(__NR_ptrace); 249 TEST_BASELINE_SIGSYS(__NR_sched_setaffinity); 250 TEST_BASELINE_SIGSYS(__NR_setpgid); 251 TEST_BASELINE_SIGSYS(__NR_swapon); 252 TEST_BASELINE_SIGSYS(__NR_sysinfo); 253 TEST_BASELINE_SIGSYS(__NR_syslog); 254 TEST_BASELINE_SIGSYS(__NR_timer_create); 255 256 #if !defined(__aarch64__) 257 TEST_BASELINE_SIGSYS(__NR_eventfd); 258 TEST_BASELINE_SIGSYS(__NR_inotify_init); 259 TEST_BASELINE_SIGSYS(__NR_vserver); 260 #endif 261 262 BPF_DEATH_TEST_C(BaselinePolicy, 263 FutexWithRequeuePriorityInheritence, 264 DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()), 265 BaselinePolicy) { 266 syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI, 0, NULL, NULL, 0); 267 _exit(1); 268 } 269 270 BPF_DEATH_TEST_C(BaselinePolicy, 271 FutexWithRequeuePriorityInheritencePrivate, 272 DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()), 273 BaselinePolicy) { 274 syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI_PRIVATE, 0, NULL, NULL, 0); 275 _exit(1); 276 } 277 278 BPF_DEATH_TEST_C(BaselinePolicy, 279 FutexWithUnlockPIPrivate, 280 DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()), 281 BaselinePolicy) { 282 syscall(__NR_futex, NULL, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0); 283 _exit(1); 284 } 285 286 BPF_TEST_C(BaselinePolicy, PrctlDumpable, BaselinePolicy) { 287 const int is_dumpable = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0); 288 BPF_ASSERT(is_dumpable == 1 || is_dumpable == 0); 289 const int prctl_ret = prctl(PR_SET_DUMPABLE, is_dumpable, 0, 0, 0, 0); 290 BPF_ASSERT_EQ(0, prctl_ret); 291 } 292 293 // Workaround incomplete Android headers. 294 #if !defined(PR_CAPBSET_READ) 295 #define PR_CAPBSET_READ 23 296 #endif 297 298 BPF_DEATH_TEST_C(BaselinePolicy, 299 PrctlSigsys, 300 DEATH_SEGV_MESSAGE(GetPrctlErrorMessageContentForTests()), 301 BaselinePolicy) { 302 prctl(PR_CAPBSET_READ, 0, 0, 0, 0); 303 _exit(1); 304 } 305 306 BPF_TEST_C(BaselinePolicy, GetOrSetPriority, BaselinePolicy) { 307 errno = 0; 308 const int original_prio = getpriority(PRIO_PROCESS, 0); 309 // Check errno instead of the return value since this system call can return 310 // -1 as a valid value. 311 BPF_ASSERT_EQ(0, errno); 312 313 errno = 0; 314 int rc = getpriority(PRIO_PROCESS, getpid()); 315 BPF_ASSERT_EQ(0, errno); 316 317 rc = getpriority(PRIO_PROCESS, getpid() + 1); 318 BPF_ASSERT_EQ(-1, rc); 319 BPF_ASSERT_EQ(EPERM, errno); 320 321 rc = setpriority(PRIO_PROCESS, 0, original_prio); 322 BPF_ASSERT_EQ(0, rc); 323 324 rc = setpriority(PRIO_PROCESS, getpid(), original_prio); 325 BPF_ASSERT_EQ(0, rc); 326 327 errno = 0; 328 rc = setpriority(PRIO_PROCESS, getpid() + 1, original_prio); 329 BPF_ASSERT_EQ(-1, rc); 330 BPF_ASSERT_EQ(EPERM, errno); 331 } 332 333 BPF_DEATH_TEST_C(BaselinePolicy, 334 GetPrioritySigsys, 335 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()), 336 BaselinePolicy) { 337 getpriority(PRIO_USER, 0); 338 _exit(1); 339 } 340 341 BPF_DEATH_TEST_C(BaselinePolicy, 342 ClockGettimeWithDisallowedClockCrashes, 343 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()), 344 BaselinePolicy) { 345 struct timespec ts; 346 clock_gettime(CLOCK_MONOTONIC_RAW, &ts); 347 } 348 349 } // namespace 350 351 } // namespace sandbox 352