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> |
| 10 #include <string.h> |
| 11 #include <sys/socket.h> |
8 #include <sys/stat.h> | 12 #include <sys/stat.h> |
9 #include <sys/syscall.h> | 13 #include <sys/syscall.h> |
10 #include <sys/types.h> | 14 #include <sys/types.h> |
11 #include <sys/wait.h> | 15 #include <sys/wait.h> |
12 #include <unistd.h> | 16 #include <unistd.h> |
13 | 17 |
| 18 #include "base/files/scoped_file.h" |
| 19 #include "base/macros.h" |
14 #include "base/posix/eintr_wrapper.h" | 20 #include "base/posix/eintr_wrapper.h" |
15 #include "base/threading/thread.h" | 21 #include "base/threading/thread.h" |
16 #include "build/build_config.h" | 22 #include "build/build_config.h" |
17 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" | 23 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" |
18 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" | 24 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" |
19 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" | 25 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
20 #include "sandbox/linux/services/linux_syscalls.h" | 26 #include "sandbox/linux/services/linux_syscalls.h" |
21 #include "sandbox/linux/services/thread_helpers.h" | 27 #include "sandbox/linux/services/thread_helpers.h" |
22 #include "sandbox/linux/tests/unit_tests.h" | 28 #include "sandbox/linux/tests/unit_tests.h" |
23 | 29 |
(...skipping 15 matching lines...) Expand all Loading... |
39 _exit(kChildExitCode); | 45 _exit(kChildExitCode); |
40 } | 46 } |
41 } | 47 } |
42 | 48 |
43 // Check that HandlePostForkReturn works. | 49 // Check that HandlePostForkReturn works. |
44 TEST(BaselinePolicy, HandlePostForkReturn) { | 50 TEST(BaselinePolicy, HandlePostForkReturn) { |
45 pid_t pid = fork(); | 51 pid_t pid = fork(); |
46 HandlePostForkReturn(pid); | 52 HandlePostForkReturn(pid); |
47 } | 53 } |
48 | 54 |
| 55 // This also tests that read(), write() and fstat() are allowed. |
| 56 void TestPipeOrSocketPair(base::ScopedFD read_end, base::ScopedFD write_end) { |
| 57 BPF_ASSERT_LE(0, read_end.get()); |
| 58 BPF_ASSERT_LE(0, write_end.get()); |
| 59 struct stat stat_buf; |
| 60 int sys_ret = fstat(read_end.get(), &stat_buf); |
| 61 BPF_ASSERT_EQ(0, sys_ret); |
| 62 BPF_ASSERT(S_ISFIFO(stat_buf.st_mode) || S_ISSOCK(stat_buf.st_mode)); |
| 63 |
| 64 const ssize_t kTestTransferSize = 4; |
| 65 static const char kTestString[kTestTransferSize] = {'T', 'E', 'S', 'T'}; |
| 66 ssize_t transfered = 0; |
| 67 |
| 68 transfered = |
| 69 HANDLE_EINTR(write(write_end.get(), kTestString, kTestTransferSize)); |
| 70 BPF_ASSERT_EQ(kTestTransferSize, transfered); |
| 71 char read_buf[kTestTransferSize + 1] = {0}; |
| 72 transfered = HANDLE_EINTR(read(read_end.get(), read_buf, sizeof(read_buf))); |
| 73 BPF_ASSERT_EQ(kTestTransferSize, transfered); |
| 74 BPF_ASSERT_EQ(0, memcmp(kTestString, read_buf, kTestTransferSize)); |
| 75 } |
| 76 |
| 77 // Test that a few easy-to-test system calls are allowed. |
| 78 BPF_TEST_C(BaselinePolicy, BaselinePolicyBasicAllowed, BaselinePolicy) { |
| 79 BPF_ASSERT_EQ(0, sched_yield()); |
| 80 |
| 81 int pipefd[2]; |
| 82 int sys_ret = pipe(pipefd); |
| 83 BPF_ASSERT_EQ(0, sys_ret); |
| 84 TestPipeOrSocketPair(base::ScopedFD(pipefd[0]), base::ScopedFD(pipefd[1])); |
| 85 |
| 86 BPF_ASSERT_LE(1, getpid()); |
| 87 BPF_ASSERT_LE(0, getuid()); |
| 88 } |
| 89 |
49 BPF_TEST_C(BaselinePolicy, FchmodErrno, BaselinePolicy) { | 90 BPF_TEST_C(BaselinePolicy, FchmodErrno, BaselinePolicy) { |
50 int ret = fchmod(-1, 07777); | 91 int ret = fchmod(-1, 07777); |
51 BPF_ASSERT_EQ(-1, ret); | 92 BPF_ASSERT_EQ(-1, ret); |
52 // Without the sandbox, this would EBADF instead. | 93 // Without the sandbox, this would EBADF instead. |
53 BPF_ASSERT_EQ(EPERM, errno); | 94 BPF_ASSERT_EQ(EPERM, errno); |
54 } | 95 } |
55 | 96 |
56 // TODO(jln): make this work with the sanitizers. | 97 // TODO(jln): make this work with the sanitizers. |
57 #if !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER) && \ | 98 #if !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER) && \ |
58 !defined(MEMORY_SANITIZER) | 99 !defined(MEMORY_SANITIZER) |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 } | 143 } |
103 | 144 |
104 BPF_DEATH_TEST_C(BaselinePolicy, | 145 BPF_DEATH_TEST_C(BaselinePolicy, |
105 DisallowedCloneFlagCrashes, | 146 DisallowedCloneFlagCrashes, |
106 DEATH_MESSAGE(GetCloneErrorMessageContentForTests()), | 147 DEATH_MESSAGE(GetCloneErrorMessageContentForTests()), |
107 BaselinePolicy) { | 148 BaselinePolicy) { |
108 pid_t pid = syscall(__NR_clone, CLONE_THREAD | SIGCHLD); | 149 pid_t pid = syscall(__NR_clone, CLONE_THREAD | SIGCHLD); |
109 HandlePostForkReturn(pid); | 150 HandlePostForkReturn(pid); |
110 } | 151 } |
111 | 152 |
| 153 BPF_DEATH_TEST_C(BaselinePolicy, |
| 154 DisallowedKillCrashes, |
| 155 DEATH_MESSAGE(GetKillErrorMessageContentForTests()), |
| 156 BaselinePolicy) { |
| 157 BPF_ASSERT_NE(1, getpid()); |
| 158 kill(1, 0); |
| 159 _exit(1); |
| 160 } |
| 161 |
| 162 BPF_TEST_C(BaselinePolicy, CanKillSelf, BaselinePolicy) { |
| 163 int sys_ret = kill(getpid(), 0); |
| 164 BPF_ASSERT_EQ(0, sys_ret); |
| 165 } |
| 166 |
| 167 BPF_TEST_C(BaselinePolicy, Socketpair, BaselinePolicy) { |
| 168 int sv[2]; |
| 169 int sys_ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, sv); |
| 170 BPF_ASSERT_EQ(0, sys_ret); |
| 171 TestPipeOrSocketPair(base::ScopedFD(sv[0]), base::ScopedFD(sv[1])); |
| 172 |
| 173 sys_ret = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sv); |
| 174 BPF_ASSERT_EQ(0, sys_ret); |
| 175 TestPipeOrSocketPair(base::ScopedFD(sv[0]), base::ScopedFD(sv[1])); |
| 176 } |
| 177 |
| 178 // Not all architectures can restrict the domain for socketpair(). |
| 179 #if defined(__x86_64__) || defined(__arm__) |
| 180 BPF_DEATH_TEST_C(BaselinePolicy, |
| 181 SocketpairWrongDomain, |
| 182 DEATH_MESSAGE(GetErrorMessageContentForTests()), |
| 183 BaselinePolicy) { |
| 184 int sv[2]; |
| 185 ignore_result(socketpair(AF_INET, SOCK_STREAM, 0, sv)); |
| 186 _exit(1); |
| 187 } |
| 188 #endif // defined(__x86_64__) || defined(__arm__) |
| 189 |
| 190 BPF_TEST_C(BaselinePolicy, EPERM_open, BaselinePolicy) { |
| 191 errno = 0; |
| 192 int sys_ret = open("/proc/cpuinfo", O_RDONLY); |
| 193 BPF_ASSERT_EQ(-1, sys_ret); |
| 194 BPF_ASSERT_EQ(EPERM, errno); |
| 195 } |
| 196 |
| 197 BPF_TEST_C(BaselinePolicy, EPERM_access, BaselinePolicy) { |
| 198 errno = 0; |
| 199 int sys_ret = access("/proc/cpuinfo", R_OK); |
| 200 BPF_ASSERT_EQ(-1, sys_ret); |
| 201 BPF_ASSERT_EQ(EPERM, errno); |
| 202 } |
| 203 |
| 204 BPF_TEST_C(BaselinePolicy, EPERM_getcwd, BaselinePolicy) { |
| 205 errno = 0; |
| 206 char buf[1024]; |
| 207 char* cwd = getcwd(buf, sizeof(buf)); |
| 208 BPF_ASSERT_EQ(NULL, cwd); |
| 209 BPF_ASSERT_EQ(EPERM, errno); |
| 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_MESSAGE(GetErrorMessageContentForTests()), \ |
| 222 BaselinePolicy) { \ |
| 223 syscall(sysno, 0, 0, 0, 0, 0, 0); \ |
| 224 _exit(1); \ |
| 225 } |
| 226 |
| 227 TEST_BASELINE_SIGSYS(__NR_syslog); |
| 228 TEST_BASELINE_SIGSYS(__NR_sched_setaffinity); |
| 229 TEST_BASELINE_SIGSYS(__NR_timer_create); |
| 230 TEST_BASELINE_SIGSYS(__NR_io_cancel); |
| 231 TEST_BASELINE_SIGSYS(__NR_ptrace); |
| 232 TEST_BASELINE_SIGSYS(__NR_eventfd); |
| 233 TEST_BASELINE_SIGSYS(__NR_fgetxattr); |
| 234 TEST_BASELINE_SIGSYS(__NR_fanotify_init); |
| 235 TEST_BASELINE_SIGSYS(__NR_swapon); |
| 236 TEST_BASELINE_SIGSYS(__NR_chroot); |
| 237 TEST_BASELINE_SIGSYS(__NR_acct); |
| 238 TEST_BASELINE_SIGSYS(__NR_sysinfo); |
| 239 TEST_BASELINE_SIGSYS(__NR_inotify_init); |
| 240 TEST_BASELINE_SIGSYS(__NR_init_module); |
| 241 TEST_BASELINE_SIGSYS(__NR_keyctl); |
| 242 TEST_BASELINE_SIGSYS(__NR_mq_open); |
| 243 TEST_BASELINE_SIGSYS(__NR_vserver); |
| 244 TEST_BASELINE_SIGSYS(__NR_getcpu); |
| 245 TEST_BASELINE_SIGSYS(__NR_setpgid); |
| 246 TEST_BASELINE_SIGSYS(__NR_getitimer); |
| 247 |
112 #endif // !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER) && | 248 #endif // !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER) && |
113 // !defined(MEMORY_SANITIZER) | 249 // !defined(MEMORY_SANITIZER) |
114 | 250 |
115 } // namespace | 251 } // namespace |
116 | 252 |
117 } // namespace sandbox | 253 } // namespace sandbox |
OLD | NEW |