Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h" | 5 #include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <sched.h> | |
| 9 #include <signal.h> | |
| 8 #include <sys/stat.h> | 10 #include <sys/stat.h> |
| 11 #include <sys/socket.h> | |
| 9 #include <sys/syscall.h> | 12 #include <sys/syscall.h> |
| 10 #include <sys/types.h> | 13 #include <sys/types.h> |
| 11 #include <sys/wait.h> | 14 #include <sys/wait.h> |
| 12 #include <unistd.h> | 15 #include <unistd.h> |
| 13 | 16 |
| 17 #include "base/files/scoped_file.h" | |
| 18 #include "base/macros.h" | |
| 14 #include "base/posix/eintr_wrapper.h" | 19 #include "base/posix/eintr_wrapper.h" |
| 15 #include "base/threading/thread.h" | 20 #include "base/threading/thread.h" |
| 16 #include "build/build_config.h" | 21 #include "build/build_config.h" |
| 17 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" | 22 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" |
| 18 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" | 23 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" |
| 19 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" | 24 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
| 20 #include "sandbox/linux/services/linux_syscalls.h" | 25 #include "sandbox/linux/services/linux_syscalls.h" |
| 21 #include "sandbox/linux/services/thread_helpers.h" | 26 #include "sandbox/linux/services/thread_helpers.h" |
| 22 #include "sandbox/linux/tests/unit_tests.h" | 27 #include "sandbox/linux/tests/unit_tests.h" |
| 23 | 28 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 39 _exit(kChildExitCode); | 44 _exit(kChildExitCode); |
| 40 } | 45 } |
| 41 } | 46 } |
| 42 | 47 |
| 43 // Check that HandlePostForkReturn works. | 48 // Check that HandlePostForkReturn works. |
| 44 TEST(BaselinePolicy, HandlePostForkReturn) { | 49 TEST(BaselinePolicy, HandlePostForkReturn) { |
| 45 pid_t pid = fork(); | 50 pid_t pid = fork(); |
| 46 HandlePostForkReturn(pid); | 51 HandlePostForkReturn(pid); |
| 47 } | 52 } |
| 48 | 53 |
| 54 // This also tests that read(), write() and fstat() are allowed. | |
| 55 void TestPipeOrSocketPair(base::ScopedFD read_end, base::ScopedFD write_end) { | |
| 56 BPF_ASSERT_LE(0, read_end.get()); | |
| 57 BPF_ASSERT_LE(0, write_end.get()); | |
| 58 struct stat stat_buf; | |
| 59 int sys_ret = fstat(read_end.get(), &stat_buf); | |
| 60 BPF_ASSERT_EQ(0, sys_ret); | |
| 61 BPF_ASSERT(S_ISFIFO(stat_buf.st_mode) || S_ISSOCK(stat_buf.st_mode)); | |
| 62 | |
| 63 const ssize_t kTestTransferSize = 4; | |
| 64 static const char kTestString[kTestTransferSize] = {'T', 'E', 'S', 'T'}; | |
| 65 ssize_t transfered = 0; | |
| 66 | |
| 67 transfered = | |
| 68 HANDLE_EINTR(write(write_end.get(), kTestString, kTestTransferSize)); | |
| 69 BPF_ASSERT_EQ(kTestTransferSize, transfered); | |
| 70 char read_buf[kTestTransferSize + 1] = {0}; | |
| 71 transfered = HANDLE_EINTR(read(read_end.get(), read_buf, sizeof(read_buf))); | |
| 72 BPF_ASSERT_EQ(kTestTransferSize, transfered); | |
| 73 BPF_ASSERT_EQ(0, bcmp(kTestString, read_buf, kTestTransferSize)); | |
|
mdempsky
2014/05/17 00:59:43
s/bcmp/memcmp/ and #include <string.h> (bcmp was r
jln (very slow on Chromium)
2014/05/17 01:29:47
Done.
| |
| 74 } | |
| 75 | |
| 76 // Test that a few easy-to-test system calls are allowed. | |
| 77 BPF_TEST_C(BaselinePolicy, BaselinePolicyBasicAllowed, BaselinePolicy) { | |
| 78 BPF_ASSERT_EQ(0, sched_yield()); | |
| 79 | |
| 80 int pipefd[2]; | |
| 81 int sys_ret = pipe(pipefd); | |
| 82 BPF_ASSERT_EQ(0, sys_ret); | |
| 83 TestPipeOrSocketPair(base::ScopedFD(pipefd[0]), base::ScopedFD(pipefd[1])); | |
| 84 | |
| 85 BPF_ASSERT_LE(1, getpid()); | |
| 86 BPF_ASSERT_LE(0, getuid()); | |
| 87 } | |
| 88 | |
| 49 BPF_TEST_C(BaselinePolicy, FchmodErrno, BaselinePolicy) { | 89 BPF_TEST_C(BaselinePolicy, FchmodErrno, BaselinePolicy) { |
| 50 int ret = fchmod(-1, 07777); | 90 int ret = fchmod(-1, 07777); |
| 51 BPF_ASSERT_EQ(-1, ret); | 91 BPF_ASSERT_EQ(-1, ret); |
| 52 // Without the sandbox, this would EBADF instead. | 92 // Without the sandbox, this would EBADF instead. |
| 53 BPF_ASSERT_EQ(EPERM, errno); | 93 BPF_ASSERT_EQ(EPERM, errno); |
| 54 } | 94 } |
| 55 | 95 |
| 56 // TODO(jln): make this work with the sanitizers. | 96 // TODO(jln): make this work with the sanitizers. |
| 57 #if !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER) && \ | 97 #if !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER) && \ |
| 58 !defined(MEMORY_SANITIZER) | 98 !defined(MEMORY_SANITIZER) |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 102 } | 142 } |
| 103 | 143 |
| 104 BPF_DEATH_TEST_C(BaselinePolicy, | 144 BPF_DEATH_TEST_C(BaselinePolicy, |
| 105 DisallowedCloneFlagCrashes, | 145 DisallowedCloneFlagCrashes, |
| 106 DEATH_MESSAGE(GetCloneErrorMessageContentForTests()), | 146 DEATH_MESSAGE(GetCloneErrorMessageContentForTests()), |
| 107 BaselinePolicy) { | 147 BaselinePolicy) { |
| 108 pid_t pid = syscall(__NR_clone, CLONE_THREAD | SIGCHLD); | 148 pid_t pid = syscall(__NR_clone, CLONE_THREAD | SIGCHLD); |
| 109 HandlePostForkReturn(pid); | 149 HandlePostForkReturn(pid); |
| 110 } | 150 } |
| 111 | 151 |
| 152 BPF_DEATH_TEST_C(BaselinePolicy, | |
| 153 DisallowedKillCrashes, | |
| 154 DEATH_MESSAGE(GetKillErrorMessageContentForTests()), | |
| 155 BaselinePolicy) { | |
| 156 BPF_ASSERT_NE(1, getpid()); | |
| 157 kill(1, SIGCONT); | |
|
mdempsky
2014/05/17 00:59:43
I assume you picked SIGCONT because it won't do an
jln (very slow on Chromium)
2014/05/17 01:29:47
Done.
| |
| 158 _exit(1); | |
| 159 } | |
| 160 | |
| 161 BPF_TEST_C(BaselinePolicy, CanKillSelf, BaselinePolicy) { | |
| 162 int sys_ret = kill(getpid(), SIGCONT); | |
| 163 BPF_ASSERT_EQ(0, sys_ret); | |
| 164 } | |
| 165 | |
| 166 BPF_TEST_C(BaselinePolicy, Socketpair, BaselinePolicy) { | |
| 167 int sv[2]; | |
| 168 int sys_ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, sv); | |
| 169 TestPipeOrSocketPair(base::ScopedFD(sv[0]), base::ScopedFD(sv[1])); | |
| 170 | |
| 171 sys_ret = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sv); | |
| 172 TestPipeOrSocketPair(base::ScopedFD(sv[0]), base::ScopedFD(sv[1])); | |
| 173 } | |
| 174 | |
| 175 // Not all architectures can restrict the domain for socketpair(). | |
| 176 #if defined(__x86_64__) || defined(__arm__) | |
| 177 BPF_DEATH_TEST_C(BaselinePolicy, | |
| 178 SocketpairWrongDomain, | |
| 179 DEATH_MESSAGE(GetErrorMessageContentForTests()), | |
| 180 BaselinePolicy) { | |
| 181 int sv[2]; | |
| 182 ignore_result(socketpair(AF_INET, SOCK_STREAM, 0, sv)); | |
| 183 _exit(1); | |
| 184 } | |
| 185 #endif // defined(__x86_64__) || defined(__arm__) | |
| 186 | |
| 187 BPF_TEST_C(BaselinePolicy, EPERM_open, BaselinePolicy) { | |
| 188 errno = 0; | |
| 189 int sys_ret = open("/proc/cpuinfo", O_RDONLY); | |
| 190 BPF_ASSERT_EQ(-1, sys_ret); | |
| 191 BPF_ASSERT_EQ(EPERM, errno); | |
| 192 } | |
| 193 | |
| 194 BPF_TEST_C(BaselinePolicy, EPERM_access, BaselinePolicy) { | |
| 195 errno = 0; | |
| 196 int sys_ret = access("/proc/cpuinfo", R_OK); | |
| 197 BPF_ASSERT_EQ(-1, sys_ret); | |
| 198 BPF_ASSERT_EQ(EPERM, errno); | |
| 199 } | |
| 200 | |
| 201 BPF_TEST_C(BaselinePolicy, EPERM_getcwd, BaselinePolicy) { | |
| 202 errno = 0; | |
| 203 char buf[1024]; | |
| 204 char* cwd = getcwd(buf, sizeof(buf)); | |
| 205 BPF_ASSERT_EQ(NULL, cwd); | |
| 206 BPF_ASSERT_EQ(EPERM, errno); | |
| 207 } | |
| 208 | |
| 209 // A failing test using this macro could be problematic since we perform | |
| 210 // system calls by passing "0" as every argument. | |
| 211 // The kernel could SIGSEGV the process or the system call itself could reboot | |
| 212 // the machine. Some thoughts have been given when hand-picking the system | |
| 213 // calls below to limit any potential side effects outside of the current | |
| 214 // process. | |
| 215 #define TEST_BASELINE_SIGSYS(sysno) \ | |
| 216 BPF_DEATH_TEST_C(BaselinePolicy, \ | |
| 217 SIGSYS_##sysno, \ | |
| 218 DEATH_MESSAGE(GetErrorMessageContentForTests()), \ | |
| 219 BaselinePolicy) { \ | |
| 220 syscall(sysno, 0, 0, 0, 0, 0, 0); \ | |
| 221 _exit(1); \ | |
| 222 } | |
| 223 | |
| 224 TEST_BASELINE_SIGSYS(__NR_syslog); | |
| 225 TEST_BASELINE_SIGSYS(__NR_sched_setaffinity); | |
| 226 TEST_BASELINE_SIGSYS(__NR_timer_create); | |
| 227 TEST_BASELINE_SIGSYS(__NR_io_cancel); | |
| 228 TEST_BASELINE_SIGSYS(__NR_ptrace); | |
| 229 TEST_BASELINE_SIGSYS(__NR_eventfd); | |
| 230 TEST_BASELINE_SIGSYS(__NR_fgetxattr); | |
| 231 TEST_BASELINE_SIGSYS(__NR_fanotify_init); | |
| 232 TEST_BASELINE_SIGSYS(__NR_swapon); | |
| 233 TEST_BASELINE_SIGSYS(__NR_chroot); | |
| 234 TEST_BASELINE_SIGSYS(__NR_acct); | |
| 235 TEST_BASELINE_SIGSYS(__NR_sysinfo); | |
| 236 TEST_BASELINE_SIGSYS(__NR_inotify_init); | |
| 237 TEST_BASELINE_SIGSYS(__NR_init_module); | |
| 238 TEST_BASELINE_SIGSYS(__NR_keyctl); | |
| 239 TEST_BASELINE_SIGSYS(__NR_mq_open); | |
| 240 TEST_BASELINE_SIGSYS(__NR_vserver); | |
| 241 TEST_BASELINE_SIGSYS(__NR_getcpu); | |
| 242 TEST_BASELINE_SIGSYS(__NR_setpgid); | |
| 243 TEST_BASELINE_SIGSYS(__NR_getitimer); | |
| 244 | |
| 112 #endif // !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER) && | 245 #endif // !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER) && |
| 113 // !defined(MEMORY_SANITIZER) | 246 // !defined(MEMORY_SANITIZER) |
| 114 | 247 |
| 115 } // namespace | 248 } // namespace |
| 116 | 249 |
| 117 } // namespace sandbox | 250 } // namespace sandbox |
| OLD | NEW |