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 |