OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <errno.h> | 5 #include <errno.h> |
6 #include <pthread.h> | 6 #include <pthread.h> |
7 #include <sched.h> | 7 #include <sched.h> |
8 #include <sys/prctl.h> | 8 #include <sys/prctl.h> |
9 #include <sys/syscall.h> | 9 #include <sys/syscall.h> |
10 #include <sys/time.h> | 10 #include <sys/time.h> |
(...skipping 22 matching lines...) Expand all Loading... |
33 | 33 |
34 // Workaround for Android's prctl.h file. | 34 // Workaround for Android's prctl.h file. |
35 #ifndef PR_GET_ENDIAN | 35 #ifndef PR_GET_ENDIAN |
36 #define PR_GET_ENDIAN 19 | 36 #define PR_GET_ENDIAN 19 |
37 #endif | 37 #endif |
38 #ifndef PR_CAPBSET_READ | 38 #ifndef PR_CAPBSET_READ |
39 #define PR_CAPBSET_READ 23 | 39 #define PR_CAPBSET_READ 23 |
40 #define PR_CAPBSET_DROP 24 | 40 #define PR_CAPBSET_DROP 24 |
41 #endif | 41 #endif |
42 | 42 |
43 using namespace playground2; | 43 namespace sandbox { |
44 using sandbox::BrokerProcess; | |
45 | 44 |
46 namespace { | 45 namespace { |
47 | 46 |
48 const int kExpectedReturnValue = 42; | 47 const int kExpectedReturnValue = 42; |
49 const char kSandboxDebuggingEnv[] = "CHROME_SANDBOX_DEBUGGING"; | 48 const char kSandboxDebuggingEnv[] = "CHROME_SANDBOX_DEBUGGING"; |
50 | 49 |
51 // This test should execute no matter whether we have kernel support. So, | 50 // This test should execute no matter whether we have kernel support. So, |
52 // we make it a TEST() instead of a BPF_TEST(). | 51 // we make it a TEST() instead of a BPF_TEST(). |
53 TEST(SandboxBpf, CallSupports) { | 52 TEST(SandboxBPF, CallSupports) { |
54 // We check that we don't crash, but it's ok if the kernel doesn't | 53 // We check that we don't crash, but it's ok if the kernel doesn't |
55 // support it. | 54 // support it. |
56 bool seccomp_bpf_supported = | 55 bool seccomp_bpf_supported = |
57 Sandbox::SupportsSeccompSandbox(-1) == Sandbox::STATUS_AVAILABLE; | 56 SandboxBPF::SupportsSeccompSandbox(-1) == SandboxBPF::STATUS_AVAILABLE; |
58 // We want to log whether or not seccomp BPF is actually supported | 57 // We want to log whether or not seccomp BPF is actually supported |
59 // since actual test coverage depends on it. | 58 // since actual test coverage depends on it. |
60 RecordProperty("SeccompBPFSupported", | 59 RecordProperty("SeccompBPFSupported", |
61 seccomp_bpf_supported ? "true." : "false."); | 60 seccomp_bpf_supported ? "true." : "false."); |
62 std::cout << "Seccomp BPF supported: " | 61 std::cout << "Seccomp BPF supported: " |
63 << (seccomp_bpf_supported ? "true." : "false.") << "\n"; | 62 << (seccomp_bpf_supported ? "true." : "false.") << "\n"; |
64 RecordProperty("PointerSize", sizeof(void*)); | 63 RecordProperty("PointerSize", sizeof(void*)); |
65 std::cout << "Pointer size: " << sizeof(void*) << "\n"; | 64 std::cout << "Pointer size: " << sizeof(void*) << "\n"; |
66 } | 65 } |
67 | 66 |
68 SANDBOX_TEST(SandboxBpf, CallSupportsTwice) { | 67 SANDBOX_TEST(SandboxBPF, CallSupportsTwice) { |
69 Sandbox::SupportsSeccompSandbox(-1); | 68 SandboxBPF::SupportsSeccompSandbox(-1); |
70 Sandbox::SupportsSeccompSandbox(-1); | 69 SandboxBPF::SupportsSeccompSandbox(-1); |
71 } | 70 } |
72 | 71 |
73 // BPF_TEST does a lot of the boiler-plate code around setting up a | 72 // BPF_TEST does a lot of the boiler-plate code around setting up a |
74 // policy and optional passing data between the caller, the policy and | 73 // policy and optional passing data between the caller, the policy and |
75 // any Trap() handlers. This is great for writing short and concise tests, | 74 // any Trap() handlers. This is great for writing short and concise tests, |
76 // and it helps us accidentally forgetting any of the crucial steps in | 75 // and it helps us accidentally forgetting any of the crucial steps in |
77 // setting up the sandbox. But it wouldn't hurt to have at least one test | 76 // setting up the sandbox. But it wouldn't hurt to have at least one test |
78 // that explicitly walks through all these steps. | 77 // that explicitly walks through all these steps. |
79 | 78 |
80 intptr_t FakeGetPid(const struct arch_seccomp_data& args, void* aux) { | 79 intptr_t FakeGetPid(const struct arch_seccomp_data& args, void* aux) { |
81 BPF_ASSERT(aux); | 80 BPF_ASSERT(aux); |
82 pid_t* pid_ptr = static_cast<pid_t*>(aux); | 81 pid_t* pid_ptr = static_cast<pid_t*>(aux); |
83 return (*pid_ptr)++; | 82 return (*pid_ptr)++; |
84 } | 83 } |
85 | 84 |
86 ErrorCode VerboseAPITestingPolicy(Sandbox* sandbox, int sysno, void* aux) { | 85 ErrorCode VerboseAPITestingPolicy(SandboxBPF* sandbox, int sysno, void* aux) { |
87 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 86 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
88 return ErrorCode(ENOSYS); | 87 return ErrorCode(ENOSYS); |
89 } else if (sysno == __NR_getpid) { | 88 } else if (sysno == __NR_getpid) { |
90 return sandbox->Trap(FakeGetPid, aux); | 89 return sandbox->Trap(FakeGetPid, aux); |
91 } else { | 90 } else { |
92 return ErrorCode(ErrorCode::ERR_ALLOWED); | 91 return ErrorCode(ErrorCode::ERR_ALLOWED); |
93 } | 92 } |
94 } | 93 } |
95 | 94 |
96 SANDBOX_TEST(SandboxBpf, DISABLE_ON_TSAN(VerboseAPITesting)) { | 95 SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(VerboseAPITesting)) { |
97 if (Sandbox::SupportsSeccompSandbox(-1) == | 96 if (SandboxBPF::SupportsSeccompSandbox(-1) == |
98 playground2::Sandbox::STATUS_AVAILABLE) { | 97 sandbox::SandboxBPF::STATUS_AVAILABLE) { |
99 pid_t test_var = 0; | 98 pid_t test_var = 0; |
100 Sandbox sandbox; | 99 SandboxBPF sandbox; |
101 sandbox.SetSandboxPolicyDeprecated(VerboseAPITestingPolicy, &test_var); | 100 sandbox.SetSandboxPolicyDeprecated(VerboseAPITestingPolicy, &test_var); |
102 sandbox.StartSandbox(); | 101 sandbox.StartSandbox(); |
103 | 102 |
104 BPF_ASSERT(test_var == 0); | 103 BPF_ASSERT(test_var == 0); |
105 BPF_ASSERT(syscall(__NR_getpid) == 0); | 104 BPF_ASSERT(syscall(__NR_getpid) == 0); |
106 BPF_ASSERT(test_var == 1); | 105 BPF_ASSERT(test_var == 1); |
107 BPF_ASSERT(syscall(__NR_getpid) == 1); | 106 BPF_ASSERT(syscall(__NR_getpid) == 1); |
108 BPF_ASSERT(test_var == 2); | 107 BPF_ASSERT(test_var == 2); |
109 | 108 |
110 // N.B.: Any future call to getpid() would corrupt the stack. | 109 // N.B.: Any future call to getpid() would corrupt the stack. |
111 // This is OK. The SANDBOX_TEST() macro is guaranteed to | 110 // This is OK. The SANDBOX_TEST() macro is guaranteed to |
112 // only ever call _exit() after the test completes. | 111 // only ever call _exit() after the test completes. |
113 } | 112 } |
114 } | 113 } |
115 | 114 |
116 // A simple blacklist test | 115 // A simple blacklist test |
117 | 116 |
118 ErrorCode BlacklistNanosleepPolicy(Sandbox*, int sysno, void*) { | 117 ErrorCode BlacklistNanosleepPolicy(SandboxBPF*, int sysno, void*) { |
119 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 118 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
120 // FIXME: we should really not have to do that in a trivial policy | 119 // FIXME: we should really not have to do that in a trivial policy |
121 return ErrorCode(ENOSYS); | 120 return ErrorCode(ENOSYS); |
122 } | 121 } |
123 | 122 |
124 switch (sysno) { | 123 switch (sysno) { |
125 case __NR_nanosleep: | 124 case __NR_nanosleep: |
126 return ErrorCode(EACCES); | 125 return ErrorCode(EACCES); |
127 default: | 126 default: |
128 return ErrorCode(ErrorCode::ERR_ALLOWED); | 127 return ErrorCode(ErrorCode::ERR_ALLOWED); |
129 } | 128 } |
130 } | 129 } |
131 | 130 |
132 BPF_TEST(SandboxBpf, ApplyBasicBlacklistPolicy, BlacklistNanosleepPolicy) { | 131 BPF_TEST(SandboxBPF, ApplyBasicBlacklistPolicy, BlacklistNanosleepPolicy) { |
133 // nanosleep() should be denied | 132 // nanosleep() should be denied |
134 const struct timespec ts = {0, 0}; | 133 const struct timespec ts = {0, 0}; |
135 errno = 0; | 134 errno = 0; |
136 BPF_ASSERT(syscall(__NR_nanosleep, &ts, NULL) == -1); | 135 BPF_ASSERT(syscall(__NR_nanosleep, &ts, NULL) == -1); |
137 BPF_ASSERT(errno == EACCES); | 136 BPF_ASSERT(errno == EACCES); |
138 } | 137 } |
139 | 138 |
140 // Now do a simple whitelist test | 139 // Now do a simple whitelist test |
141 | 140 |
142 ErrorCode WhitelistGetpidPolicy(Sandbox*, int sysno, void*) { | 141 ErrorCode WhitelistGetpidPolicy(SandboxBPF*, int sysno, void*) { |
143 switch (sysno) { | 142 switch (sysno) { |
144 case __NR_getpid: | 143 case __NR_getpid: |
145 case __NR_exit_group: | 144 case __NR_exit_group: |
146 return ErrorCode(ErrorCode::ERR_ALLOWED); | 145 return ErrorCode(ErrorCode::ERR_ALLOWED); |
147 default: | 146 default: |
148 return ErrorCode(ENOMEM); | 147 return ErrorCode(ENOMEM); |
149 } | 148 } |
150 } | 149 } |
151 | 150 |
152 BPF_TEST(SandboxBpf, ApplyBasicWhitelistPolicy, WhitelistGetpidPolicy) { | 151 BPF_TEST(SandboxBPF, ApplyBasicWhitelistPolicy, WhitelistGetpidPolicy) { |
153 // getpid() should be allowed | 152 // getpid() should be allowed |
154 errno = 0; | 153 errno = 0; |
155 BPF_ASSERT(syscall(__NR_getpid) > 0); | 154 BPF_ASSERT(syscall(__NR_getpid) > 0); |
156 BPF_ASSERT(errno == 0); | 155 BPF_ASSERT(errno == 0); |
157 | 156 |
158 // getpgid() should be denied | 157 // getpgid() should be denied |
159 BPF_ASSERT(getpgid(0) == -1); | 158 BPF_ASSERT(getpgid(0) == -1); |
160 BPF_ASSERT(errno == ENOMEM); | 159 BPF_ASSERT(errno == ENOMEM); |
161 } | 160 } |
162 | 161 |
163 // A simple blacklist policy, with a SIGSYS handler | 162 // A simple blacklist policy, with a SIGSYS handler |
164 | 163 |
165 intptr_t EnomemHandler(const struct arch_seccomp_data& args, void* aux) { | 164 intptr_t EnomemHandler(const struct arch_seccomp_data& args, void* aux) { |
166 // We also check that the auxiliary data is correct | 165 // We also check that the auxiliary data is correct |
167 SANDBOX_ASSERT(aux); | 166 SANDBOX_ASSERT(aux); |
168 *(static_cast<int*>(aux)) = kExpectedReturnValue; | 167 *(static_cast<int*>(aux)) = kExpectedReturnValue; |
169 return -ENOMEM; | 168 return -ENOMEM; |
170 } | 169 } |
171 | 170 |
172 ErrorCode BlacklistNanosleepPolicySigsys(Sandbox* sandbox, | 171 ErrorCode BlacklistNanosleepPolicySigsys(SandboxBPF* sandbox, |
173 int sysno, | 172 int sysno, |
174 void* aux) { | 173 void* aux) { |
175 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 174 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
176 // FIXME: we should really not have to do that in a trivial policy | 175 // FIXME: we should really not have to do that in a trivial policy |
177 return ErrorCode(ENOSYS); | 176 return ErrorCode(ENOSYS); |
178 } | 177 } |
179 | 178 |
180 switch (sysno) { | 179 switch (sysno) { |
181 case __NR_nanosleep: | 180 case __NR_nanosleep: |
182 return sandbox->Trap(EnomemHandler, aux); | 181 return sandbox->Trap(EnomemHandler, aux); |
183 default: | 182 default: |
184 return ErrorCode(ErrorCode::ERR_ALLOWED); | 183 return ErrorCode(ErrorCode::ERR_ALLOWED); |
185 } | 184 } |
186 } | 185 } |
187 | 186 |
188 BPF_TEST(SandboxBpf, | 187 BPF_TEST(SandboxBPF, |
189 BasicBlacklistWithSigsys, | 188 BasicBlacklistWithSigsys, |
190 BlacklistNanosleepPolicySigsys, | 189 BlacklistNanosleepPolicySigsys, |
191 int /* BPF_AUX */) { | 190 int /* BPF_AUX */) { |
192 // getpid() should work properly | 191 // getpid() should work properly |
193 errno = 0; | 192 errno = 0; |
194 BPF_ASSERT(syscall(__NR_getpid) > 0); | 193 BPF_ASSERT(syscall(__NR_getpid) > 0); |
195 BPF_ASSERT(errno == 0); | 194 BPF_ASSERT(errno == 0); |
196 | 195 |
197 // Our Auxiliary Data, should be reset by the signal handler | 196 // Our Auxiliary Data, should be reset by the signal handler |
198 BPF_AUX = -1; | 197 BPF_AUX = -1; |
199 const struct timespec ts = {0, 0}; | 198 const struct timespec ts = {0, 0}; |
200 BPF_ASSERT(syscall(__NR_nanosleep, &ts, NULL) == -1); | 199 BPF_ASSERT(syscall(__NR_nanosleep, &ts, NULL) == -1); |
201 BPF_ASSERT(errno == ENOMEM); | 200 BPF_ASSERT(errno == ENOMEM); |
202 | 201 |
203 // We expect the signal handler to modify AuxData | 202 // We expect the signal handler to modify AuxData |
204 BPF_ASSERT(BPF_AUX == kExpectedReturnValue); | 203 BPF_ASSERT(BPF_AUX == kExpectedReturnValue); |
205 } | 204 } |
206 | 205 |
207 // A simple test that verifies we can return arbitrary errno values. | 206 // A simple test that verifies we can return arbitrary errno values. |
208 | 207 |
209 ErrorCode ErrnoTestPolicy(Sandbox*, int sysno, void*) { | 208 ErrorCode ErrnoTestPolicy(SandboxBPF*, int sysno, void*) { |
210 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 209 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
211 // FIXME: we should really not have to do that in a trivial policy | 210 // FIXME: we should really not have to do that in a trivial policy |
212 return ErrorCode(ENOSYS); | 211 return ErrorCode(ENOSYS); |
213 } | 212 } |
214 | 213 |
215 switch (sysno) { | 214 switch (sysno) { |
216 case __NR_dup2: | 215 case __NR_dup2: |
217 // Pretend that dup2() worked, but don't actually do anything. | 216 // Pretend that dup2() worked, but don't actually do anything. |
218 return ErrorCode(0); | 217 return ErrorCode(0); |
219 case __NR_setuid: | 218 case __NR_setuid: |
220 #if defined(__NR_setuid32) | 219 #if defined(__NR_setuid32) |
221 case __NR_setuid32: | 220 case __NR_setuid32: |
222 #endif | 221 #endif |
223 // Return errno = 1. | 222 // Return errno = 1. |
224 return ErrorCode(1); | 223 return ErrorCode(1); |
225 case __NR_setgid: | 224 case __NR_setgid: |
226 #if defined(__NR_setgid32) | 225 #if defined(__NR_setgid32) |
227 case __NR_setgid32: | 226 case __NR_setgid32: |
228 #endif | 227 #endif |
229 // Return maximum errno value (typically 4095). | 228 // Return maximum errno value (typically 4095). |
230 return ErrorCode(ErrorCode::ERR_MAX_ERRNO); | 229 return ErrorCode(ErrorCode::ERR_MAX_ERRNO); |
231 case __NR_uname: | 230 case __NR_uname: |
232 // Return errno = 42; | 231 // Return errno = 42; |
233 return ErrorCode(42); | 232 return ErrorCode(42); |
234 default: | 233 default: |
235 return ErrorCode(ErrorCode::ERR_ALLOWED); | 234 return ErrorCode(ErrorCode::ERR_ALLOWED); |
236 } | 235 } |
237 } | 236 } |
238 | 237 |
239 BPF_TEST(SandboxBpf, ErrnoTest, ErrnoTestPolicy) { | 238 BPF_TEST(SandboxBPF, ErrnoTest, ErrnoTestPolicy) { |
240 // Verify that dup2() returns success, but doesn't actually run. | 239 // Verify that dup2() returns success, but doesn't actually run. |
241 int fds[4]; | 240 int fds[4]; |
242 BPF_ASSERT(pipe(fds) == 0); | 241 BPF_ASSERT(pipe(fds) == 0); |
243 BPF_ASSERT(pipe(fds + 2) == 0); | 242 BPF_ASSERT(pipe(fds + 2) == 0); |
244 BPF_ASSERT(dup2(fds[2], fds[0]) == 0); | 243 BPF_ASSERT(dup2(fds[2], fds[0]) == 0); |
245 char buf[1] = {}; | 244 char buf[1] = {}; |
246 BPF_ASSERT(write(fds[1], "\x55", 1) == 1); | 245 BPF_ASSERT(write(fds[1], "\x55", 1) == 1); |
247 BPF_ASSERT(write(fds[3], "\xAA", 1) == 1); | 246 BPF_ASSERT(write(fds[3], "\xAA", 1) == 1); |
248 BPF_ASSERT(read(fds[0], buf, 1) == 1); | 247 BPF_ASSERT(read(fds[0], buf, 1) == 1); |
249 | 248 |
(...skipping 21 matching lines...) Expand all Loading... |
271 | 270 |
272 // Finally, test an errno in between the minimum and maximum. | 271 // Finally, test an errno in between the minimum and maximum. |
273 errno = 0; | 272 errno = 0; |
274 struct utsname uts_buf; | 273 struct utsname uts_buf; |
275 BPF_ASSERT(uname(&uts_buf) == -1); | 274 BPF_ASSERT(uname(&uts_buf) == -1); |
276 BPF_ASSERT(errno == 42); | 275 BPF_ASSERT(errno == 42); |
277 } | 276 } |
278 | 277 |
279 // Testing the stacking of two sandboxes | 278 // Testing the stacking of two sandboxes |
280 | 279 |
281 ErrorCode StackingPolicyPartOne(Sandbox* sandbox, int sysno, void*) { | 280 ErrorCode StackingPolicyPartOne(SandboxBPF* sandbox, int sysno, void*) { |
282 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 281 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
283 return ErrorCode(ENOSYS); | 282 return ErrorCode(ENOSYS); |
284 } | 283 } |
285 | 284 |
286 switch (sysno) { | 285 switch (sysno) { |
287 case __NR_getppid: | 286 case __NR_getppid: |
288 return sandbox->Cond(0, | 287 return sandbox->Cond(0, |
289 ErrorCode::TP_32BIT, | 288 ErrorCode::TP_32BIT, |
290 ErrorCode::OP_EQUAL, | 289 ErrorCode::OP_EQUAL, |
291 0, | 290 0, |
292 ErrorCode(ErrorCode::ERR_ALLOWED), | 291 ErrorCode(ErrorCode::ERR_ALLOWED), |
293 ErrorCode(EPERM)); | 292 ErrorCode(EPERM)); |
294 default: | 293 default: |
295 return ErrorCode(ErrorCode::ERR_ALLOWED); | 294 return ErrorCode(ErrorCode::ERR_ALLOWED); |
296 } | 295 } |
297 } | 296 } |
298 | 297 |
299 ErrorCode StackingPolicyPartTwo(Sandbox* sandbox, int sysno, void*) { | 298 ErrorCode StackingPolicyPartTwo(SandboxBPF* sandbox, int sysno, void*) { |
300 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 299 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
301 return ErrorCode(ENOSYS); | 300 return ErrorCode(ENOSYS); |
302 } | 301 } |
303 | 302 |
304 switch (sysno) { | 303 switch (sysno) { |
305 case __NR_getppid: | 304 case __NR_getppid: |
306 return sandbox->Cond(0, | 305 return sandbox->Cond(0, |
307 ErrorCode::TP_32BIT, | 306 ErrorCode::TP_32BIT, |
308 ErrorCode::OP_EQUAL, | 307 ErrorCode::OP_EQUAL, |
309 0, | 308 0, |
310 ErrorCode(EINVAL), | 309 ErrorCode(EINVAL), |
311 ErrorCode(ErrorCode::ERR_ALLOWED)); | 310 ErrorCode(ErrorCode::ERR_ALLOWED)); |
312 default: | 311 default: |
313 return ErrorCode(ErrorCode::ERR_ALLOWED); | 312 return ErrorCode(ErrorCode::ERR_ALLOWED); |
314 } | 313 } |
315 } | 314 } |
316 | 315 |
317 BPF_TEST(SandboxBpf, StackingPolicy, StackingPolicyPartOne) { | 316 BPF_TEST(SandboxBPF, StackingPolicy, StackingPolicyPartOne) { |
318 errno = 0; | 317 errno = 0; |
319 BPF_ASSERT(syscall(__NR_getppid, 0) > 0); | 318 BPF_ASSERT(syscall(__NR_getppid, 0) > 0); |
320 BPF_ASSERT(errno == 0); | 319 BPF_ASSERT(errno == 0); |
321 | 320 |
322 BPF_ASSERT(syscall(__NR_getppid, 1) == -1); | 321 BPF_ASSERT(syscall(__NR_getppid, 1) == -1); |
323 BPF_ASSERT(errno == EPERM); | 322 BPF_ASSERT(errno == EPERM); |
324 | 323 |
325 // Stack a second sandbox with its own policy. Verify that we can further | 324 // Stack a second sandbox with its own policy. Verify that we can further |
326 // restrict filters, but we cannot relax existing filters. | 325 // restrict filters, but we cannot relax existing filters. |
327 Sandbox sandbox; | 326 SandboxBPF sandbox; |
328 sandbox.SetSandboxPolicyDeprecated(StackingPolicyPartTwo, NULL); | 327 sandbox.SetSandboxPolicyDeprecated(StackingPolicyPartTwo, NULL); |
329 sandbox.StartSandbox(); | 328 sandbox.StartSandbox(); |
330 | 329 |
331 errno = 0; | 330 errno = 0; |
332 BPF_ASSERT(syscall(__NR_getppid, 0) == -1); | 331 BPF_ASSERT(syscall(__NR_getppid, 0) == -1); |
333 BPF_ASSERT(errno == EINVAL); | 332 BPF_ASSERT(errno == EINVAL); |
334 | 333 |
335 BPF_ASSERT(syscall(__NR_getppid, 1) == -1); | 334 BPF_ASSERT(syscall(__NR_getppid, 1) == -1); |
336 BPF_ASSERT(errno == EPERM); | 335 BPF_ASSERT(errno == EPERM); |
337 } | 336 } |
338 | 337 |
339 // A more complex, but synthetic policy. This tests the correctness of the BPF | 338 // A more complex, but synthetic policy. This tests the correctness of the BPF |
340 // program by iterating through all syscalls and checking for an errno that | 339 // program by iterating through all syscalls and checking for an errno that |
341 // depends on the syscall number. Unlike the Verifier, this exercises the BPF | 340 // depends on the syscall number. Unlike the Verifier, this exercises the BPF |
342 // interpreter in the kernel. | 341 // interpreter in the kernel. |
343 | 342 |
344 // We try to make sure we exercise optimizations in the BPF compiler. We make | 343 // We try to make sure we exercise optimizations in the BPF compiler. We make |
345 // sure that the compiler can have an opportunity to coalesce syscalls with | 344 // sure that the compiler can have an opportunity to coalesce syscalls with |
346 // contiguous numbers and we also make sure that disjoint sets can return the | 345 // contiguous numbers and we also make sure that disjoint sets can return the |
347 // same errno. | 346 // same errno. |
348 int SysnoToRandomErrno(int sysno) { | 347 int SysnoToRandomErrno(int sysno) { |
349 // Small contiguous sets of 3 system calls return an errno equal to the | 348 // Small contiguous sets of 3 system calls return an errno equal to the |
350 // index of that set + 1 (so that we never return a NUL errno). | 349 // index of that set + 1 (so that we never return a NUL errno). |
351 return ((sysno & ~3) >> 2) % 29 + 1; | 350 return ((sysno & ~3) >> 2) % 29 + 1; |
352 } | 351 } |
353 | 352 |
354 ErrorCode SyntheticPolicy(Sandbox*, int sysno, void*) { | 353 ErrorCode SyntheticPolicy(SandboxBPF*, int sysno, void*) { |
355 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 354 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
356 // FIXME: we should really not have to do that in a trivial policy | 355 // FIXME: we should really not have to do that in a trivial policy |
357 return ErrorCode(ENOSYS); | 356 return ErrorCode(ENOSYS); |
358 } | 357 } |
359 | 358 |
360 // TODO(jorgelo): remove this once the new code generator lands. | 359 // TODO(jorgelo): remove this once the new code generator lands. |
361 #if defined(__arm__) | 360 #if defined(__arm__) |
362 if (sysno > static_cast<int>(MAX_PUBLIC_SYSCALL)) { | 361 if (sysno > static_cast<int>(MAX_PUBLIC_SYSCALL)) { |
363 return ErrorCode(ENOSYS); | 362 return ErrorCode(ENOSYS); |
364 } | 363 } |
365 #endif | 364 #endif |
366 | 365 |
367 if (sysno == __NR_exit_group || sysno == __NR_write) { | 366 if (sysno == __NR_exit_group || sysno == __NR_write) { |
368 // exit_group() is special, we really need it to work. | 367 // exit_group() is special, we really need it to work. |
369 // write() is needed for BPF_ASSERT() to report a useful error message. | 368 // write() is needed for BPF_ASSERT() to report a useful error message. |
370 return ErrorCode(ErrorCode::ERR_ALLOWED); | 369 return ErrorCode(ErrorCode::ERR_ALLOWED); |
371 } else { | 370 } else { |
372 return ErrorCode(SysnoToRandomErrno(sysno)); | 371 return ErrorCode(SysnoToRandomErrno(sysno)); |
373 } | 372 } |
374 } | 373 } |
375 | 374 |
376 BPF_TEST(SandboxBpf, SyntheticPolicy, SyntheticPolicy) { | 375 BPF_TEST(SandboxBPF, SyntheticPolicy, SyntheticPolicy) { |
377 // Ensure that that kExpectedReturnValue + syscallnumber + 1 does not int | 376 // Ensure that that kExpectedReturnValue + syscallnumber + 1 does not int |
378 // overflow. | 377 // overflow. |
379 BPF_ASSERT(std::numeric_limits<int>::max() - kExpectedReturnValue - 1 >= | 378 BPF_ASSERT(std::numeric_limits<int>::max() - kExpectedReturnValue - 1 >= |
380 static_cast<int>(MAX_PUBLIC_SYSCALL)); | 379 static_cast<int>(MAX_PUBLIC_SYSCALL)); |
381 | 380 |
382 for (int syscall_number = static_cast<int>(MIN_SYSCALL); | 381 for (int syscall_number = static_cast<int>(MIN_SYSCALL); |
383 syscall_number <= static_cast<int>(MAX_PUBLIC_SYSCALL); | 382 syscall_number <= static_cast<int>(MAX_PUBLIC_SYSCALL); |
384 ++syscall_number) { | 383 ++syscall_number) { |
385 if (syscall_number == __NR_exit_group || syscall_number == __NR_write) { | 384 if (syscall_number == __NR_exit_group || syscall_number == __NR_write) { |
386 // exit_group() is special | 385 // exit_group() is special |
(...skipping 13 matching lines...) Expand all Loading... |
400 // MIN_PRIVATE_SYSCALL plus 1 (to avoid NUL errno). | 399 // MIN_PRIVATE_SYSCALL plus 1 (to avoid NUL errno). |
401 int ArmPrivateSysnoToErrno(int sysno) { | 400 int ArmPrivateSysnoToErrno(int sysno) { |
402 if (sysno >= static_cast<int>(MIN_PRIVATE_SYSCALL) && | 401 if (sysno >= static_cast<int>(MIN_PRIVATE_SYSCALL) && |
403 sysno <= static_cast<int>(MAX_PRIVATE_SYSCALL)) { | 402 sysno <= static_cast<int>(MAX_PRIVATE_SYSCALL)) { |
404 return (sysno - MIN_PRIVATE_SYSCALL) + 1; | 403 return (sysno - MIN_PRIVATE_SYSCALL) + 1; |
405 } else { | 404 } else { |
406 return ENOSYS; | 405 return ENOSYS; |
407 } | 406 } |
408 } | 407 } |
409 | 408 |
410 ErrorCode ArmPrivatePolicy(Sandbox*, int sysno, void*) { | 409 ErrorCode ArmPrivatePolicy(SandboxBPF*, int sysno, void*) { |
411 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 410 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
412 // FIXME: we should really not have to do that in a trivial policy. | 411 // FIXME: we should really not have to do that in a trivial policy. |
413 return ErrorCode(ENOSYS); | 412 return ErrorCode(ENOSYS); |
414 } | 413 } |
415 | 414 |
416 // Start from |__ARM_NR_set_tls + 1| so as not to mess with actual | 415 // Start from |__ARM_NR_set_tls + 1| so as not to mess with actual |
417 // ARM private system calls. | 416 // ARM private system calls. |
418 if (sysno >= static_cast<int>(__ARM_NR_set_tls + 1) && | 417 if (sysno >= static_cast<int>(__ARM_NR_set_tls + 1) && |
419 sysno <= static_cast<int>(MAX_PRIVATE_SYSCALL)) { | 418 sysno <= static_cast<int>(MAX_PRIVATE_SYSCALL)) { |
420 return ErrorCode(ArmPrivateSysnoToErrno(sysno)); | 419 return ErrorCode(ArmPrivateSysnoToErrno(sysno)); |
421 } else { | 420 } else { |
422 return ErrorCode(ErrorCode::ERR_ALLOWED); | 421 return ErrorCode(ErrorCode::ERR_ALLOWED); |
423 } | 422 } |
424 } | 423 } |
425 | 424 |
426 BPF_TEST(SandboxBpf, ArmPrivatePolicy, ArmPrivatePolicy) { | 425 BPF_TEST(SandboxBPF, ArmPrivatePolicy, ArmPrivatePolicy) { |
427 for (int syscall_number = static_cast<int>(__ARM_NR_set_tls + 1); | 426 for (int syscall_number = static_cast<int>(__ARM_NR_set_tls + 1); |
428 syscall_number <= static_cast<int>(MAX_PRIVATE_SYSCALL); | 427 syscall_number <= static_cast<int>(MAX_PRIVATE_SYSCALL); |
429 ++syscall_number) { | 428 ++syscall_number) { |
430 errno = 0; | 429 errno = 0; |
431 BPF_ASSERT(syscall(syscall_number) == -1); | 430 BPF_ASSERT(syscall(syscall_number) == -1); |
432 BPF_ASSERT(errno == ArmPrivateSysnoToErrno(syscall_number)); | 431 BPF_ASSERT(errno == ArmPrivateSysnoToErrno(syscall_number)); |
433 } | 432 } |
434 } | 433 } |
435 #endif // defined(__arm__) | 434 #endif // defined(__arm__) |
436 | 435 |
437 intptr_t CountSyscalls(const struct arch_seccomp_data& args, void* aux) { | 436 intptr_t CountSyscalls(const struct arch_seccomp_data& args, void* aux) { |
438 // Count all invocations of our callback function. | 437 // Count all invocations of our callback function. |
439 ++*reinterpret_cast<int*>(aux); | 438 ++*reinterpret_cast<int*>(aux); |
440 | 439 |
441 // Verify that within the callback function all filtering is temporarily | 440 // Verify that within the callback function all filtering is temporarily |
442 // disabled. | 441 // disabled. |
443 BPF_ASSERT(syscall(__NR_getpid) > 1); | 442 BPF_ASSERT(syscall(__NR_getpid) > 1); |
444 | 443 |
445 // Verify that we can now call the underlying system call without causing | 444 // Verify that we can now call the underlying system call without causing |
446 // infinite recursion. | 445 // infinite recursion. |
447 return Sandbox::ForwardSyscall(args); | 446 return SandboxBPF::ForwardSyscall(args); |
448 } | 447 } |
449 | 448 |
450 ErrorCode GreyListedPolicy(Sandbox* sandbox, int sysno, void* aux) { | 449 ErrorCode GreyListedPolicy(SandboxBPF* sandbox, int sysno, void* aux) { |
451 // The use of UnsafeTrap() causes us to print a warning message. This is | 450 // The use of UnsafeTrap() causes us to print a warning message. This is |
452 // generally desirable, but it results in the unittest failing, as it doesn't | 451 // generally desirable, but it results in the unittest failing, as it doesn't |
453 // expect any messages on "stderr". So, temporarily disable messages. The | 452 // expect any messages on "stderr". So, temporarily disable messages. The |
454 // BPF_TEST() is guaranteed to turn messages back on, after the policy | 453 // BPF_TEST() is guaranteed to turn messages back on, after the policy |
455 // function has completed. | 454 // function has completed. |
456 setenv(kSandboxDebuggingEnv, "t", 0); | 455 setenv(kSandboxDebuggingEnv, "t", 0); |
457 Die::SuppressInfoMessages(true); | 456 Die::SuppressInfoMessages(true); |
458 | 457 |
459 // Some system calls must always be allowed, if our policy wants to make | 458 // Some system calls must always be allowed, if our policy wants to make |
460 // use of UnsafeTrap() | 459 // use of UnsafeTrap() |
461 if (sysno == __NR_rt_sigprocmask || sysno == __NR_rt_sigreturn | 460 if (sysno == __NR_rt_sigprocmask || sysno == __NR_rt_sigreturn |
462 #if defined(__NR_sigprocmask) | 461 #if defined(__NR_sigprocmask) |
463 || | 462 || |
464 sysno == __NR_sigprocmask | 463 sysno == __NR_sigprocmask |
465 #endif | 464 #endif |
466 #if defined(__NR_sigreturn) | 465 #if defined(__NR_sigreturn) |
467 || | 466 || |
468 sysno == __NR_sigreturn | 467 sysno == __NR_sigreturn |
469 #endif | 468 #endif |
470 ) { | 469 ) { |
471 return ErrorCode(ErrorCode::ERR_ALLOWED); | 470 return ErrorCode(ErrorCode::ERR_ALLOWED); |
472 } else if (sysno == __NR_getpid) { | 471 } else if (sysno == __NR_getpid) { |
473 // Disallow getpid() | 472 // Disallow getpid() |
474 return ErrorCode(EPERM); | 473 return ErrorCode(EPERM); |
475 } else if (Sandbox::IsValidSyscallNumber(sysno)) { | 474 } else if (SandboxBPF::IsValidSyscallNumber(sysno)) { |
476 // Allow (and count) all other system calls. | 475 // Allow (and count) all other system calls. |
477 return sandbox->UnsafeTrap(CountSyscalls, aux); | 476 return sandbox->UnsafeTrap(CountSyscalls, aux); |
478 } else { | 477 } else { |
479 return ErrorCode(ENOSYS); | 478 return ErrorCode(ENOSYS); |
480 } | 479 } |
481 } | 480 } |
482 | 481 |
483 BPF_TEST(SandboxBpf, GreyListedPolicy, GreyListedPolicy, int /* BPF_AUX */) { | 482 BPF_TEST(SandboxBPF, GreyListedPolicy, GreyListedPolicy, int /* BPF_AUX */) { |
484 BPF_ASSERT(syscall(__NR_getpid) == -1); | 483 BPF_ASSERT(syscall(__NR_getpid) == -1); |
485 BPF_ASSERT(errno == EPERM); | 484 BPF_ASSERT(errno == EPERM); |
486 BPF_ASSERT(BPF_AUX == 0); | 485 BPF_ASSERT(BPF_AUX == 0); |
487 BPF_ASSERT(syscall(__NR_geteuid) == syscall(__NR_getuid)); | 486 BPF_ASSERT(syscall(__NR_geteuid) == syscall(__NR_getuid)); |
488 BPF_ASSERT(BPF_AUX == 2); | 487 BPF_ASSERT(BPF_AUX == 2); |
489 char name[17] = {}; | 488 char name[17] = {}; |
490 BPF_ASSERT(!syscall(__NR_prctl, | 489 BPF_ASSERT(!syscall(__NR_prctl, |
491 PR_GET_NAME, | 490 PR_GET_NAME, |
492 name, | 491 name, |
493 (void*)NULL, | 492 (void*)NULL, |
494 (void*)NULL, | 493 (void*)NULL, |
495 (void*)NULL)); | 494 (void*)NULL)); |
496 BPF_ASSERT(BPF_AUX == 3); | 495 BPF_ASSERT(BPF_AUX == 3); |
497 BPF_ASSERT(*name); | 496 BPF_ASSERT(*name); |
498 } | 497 } |
499 | 498 |
500 SANDBOX_TEST(SandboxBpf, EnableUnsafeTrapsInSigSysHandler) { | 499 SANDBOX_TEST(SandboxBPF, EnableUnsafeTrapsInSigSysHandler) { |
501 // Disabling warning messages that could confuse our test framework. | 500 // Disabling warning messages that could confuse our test framework. |
502 setenv(kSandboxDebuggingEnv, "t", 0); | 501 setenv(kSandboxDebuggingEnv, "t", 0); |
503 Die::SuppressInfoMessages(true); | 502 Die::SuppressInfoMessages(true); |
504 | 503 |
505 unsetenv(kSandboxDebuggingEnv); | 504 unsetenv(kSandboxDebuggingEnv); |
506 SANDBOX_ASSERT(Trap::EnableUnsafeTrapsInSigSysHandler() == false); | 505 SANDBOX_ASSERT(Trap::EnableUnsafeTrapsInSigSysHandler() == false); |
507 setenv(kSandboxDebuggingEnv, "", 1); | 506 setenv(kSandboxDebuggingEnv, "", 1); |
508 SANDBOX_ASSERT(Trap::EnableUnsafeTrapsInSigSysHandler() == false); | 507 SANDBOX_ASSERT(Trap::EnableUnsafeTrapsInSigSysHandler() == false); |
509 setenv(kSandboxDebuggingEnv, "t", 1); | 508 setenv(kSandboxDebuggingEnv, "t", 1); |
510 SANDBOX_ASSERT(Trap::EnableUnsafeTrapsInSigSysHandler() == true); | 509 SANDBOX_ASSERT(Trap::EnableUnsafeTrapsInSigSysHandler() == true); |
511 } | 510 } |
512 | 511 |
513 intptr_t PrctlHandler(const struct arch_seccomp_data& args, void*) { | 512 intptr_t PrctlHandler(const struct arch_seccomp_data& args, void*) { |
514 if (args.args[0] == PR_CAPBSET_DROP && static_cast<int>(args.args[1]) == -1) { | 513 if (args.args[0] == PR_CAPBSET_DROP && static_cast<int>(args.args[1]) == -1) { |
515 // prctl(PR_CAPBSET_DROP, -1) is never valid. The kernel will always | 514 // prctl(PR_CAPBSET_DROP, -1) is never valid. The kernel will always |
516 // return an error. But our handler allows this call. | 515 // return an error. But our handler allows this call. |
517 return 0; | 516 return 0; |
518 } else { | 517 } else { |
519 return Sandbox::ForwardSyscall(args); | 518 return SandboxBPF::ForwardSyscall(args); |
520 } | 519 } |
521 } | 520 } |
522 | 521 |
523 ErrorCode PrctlPolicy(Sandbox* sandbox, int sysno, void* aux) { | 522 ErrorCode PrctlPolicy(SandboxBPF* sandbox, int sysno, void* aux) { |
524 setenv(kSandboxDebuggingEnv, "t", 0); | 523 setenv(kSandboxDebuggingEnv, "t", 0); |
525 Die::SuppressInfoMessages(true); | 524 Die::SuppressInfoMessages(true); |
526 | 525 |
527 if (sysno == __NR_prctl) { | 526 if (sysno == __NR_prctl) { |
528 // Handle prctl() inside an UnsafeTrap() | 527 // Handle prctl() inside an UnsafeTrap() |
529 return sandbox->UnsafeTrap(PrctlHandler, NULL); | 528 return sandbox->UnsafeTrap(PrctlHandler, NULL); |
530 } else if (Sandbox::IsValidSyscallNumber(sysno)) { | 529 } else if (SandboxBPF::IsValidSyscallNumber(sysno)) { |
531 // Allow all other system calls. | 530 // Allow all other system calls. |
532 return ErrorCode(ErrorCode::ERR_ALLOWED); | 531 return ErrorCode(ErrorCode::ERR_ALLOWED); |
533 } else { | 532 } else { |
534 return ErrorCode(ENOSYS); | 533 return ErrorCode(ENOSYS); |
535 } | 534 } |
536 } | 535 } |
537 | 536 |
538 BPF_TEST(SandboxBpf, ForwardSyscall, PrctlPolicy) { | 537 BPF_TEST(SandboxBPF, ForwardSyscall, PrctlPolicy) { |
539 // This call should never be allowed. But our policy will intercept it and | 538 // This call should never be allowed. But our policy will intercept it and |
540 // let it pass successfully. | 539 // let it pass successfully. |
541 BPF_ASSERT( | 540 BPF_ASSERT( |
542 !prctl(PR_CAPBSET_DROP, -1, (void*)NULL, (void*)NULL, (void*)NULL)); | 541 !prctl(PR_CAPBSET_DROP, -1, (void*)NULL, (void*)NULL, (void*)NULL)); |
543 | 542 |
544 // Verify that the call will fail, if it makes it all the way to the kernel. | 543 // Verify that the call will fail, if it makes it all the way to the kernel. |
545 BPF_ASSERT( | 544 BPF_ASSERT( |
546 prctl(PR_CAPBSET_DROP, -2, (void*)NULL, (void*)NULL, (void*)NULL) == -1); | 545 prctl(PR_CAPBSET_DROP, -2, (void*)NULL, (void*)NULL, (void*)NULL) == -1); |
547 | 546 |
548 // And verify that other uses of prctl() work just fine. | 547 // And verify that other uses of prctl() work just fine. |
549 char name[17] = {}; | 548 char name[17] = {}; |
550 BPF_ASSERT(!syscall(__NR_prctl, | 549 BPF_ASSERT(!syscall(__NR_prctl, |
551 PR_GET_NAME, | 550 PR_GET_NAME, |
552 name, | 551 name, |
553 (void*)NULL, | 552 (void*)NULL, |
554 (void*)NULL, | 553 (void*)NULL, |
555 (void*)NULL)); | 554 (void*)NULL)); |
556 BPF_ASSERT(*name); | 555 BPF_ASSERT(*name); |
557 | 556 |
558 // Finally, verify that system calls other than prctl() are completely | 557 // Finally, verify that system calls other than prctl() are completely |
559 // unaffected by our policy. | 558 // unaffected by our policy. |
560 struct utsname uts = {}; | 559 struct utsname uts = {}; |
561 BPF_ASSERT(!uname(&uts)); | 560 BPF_ASSERT(!uname(&uts)); |
562 BPF_ASSERT(!strcmp(uts.sysname, "Linux")); | 561 BPF_ASSERT(!strcmp(uts.sysname, "Linux")); |
563 } | 562 } |
564 | 563 |
565 intptr_t AllowRedirectedSyscall(const struct arch_seccomp_data& args, void*) { | 564 intptr_t AllowRedirectedSyscall(const struct arch_seccomp_data& args, void*) { |
566 return Sandbox::ForwardSyscall(args); | 565 return SandboxBPF::ForwardSyscall(args); |
567 } | 566 } |
568 | 567 |
569 ErrorCode RedirectAllSyscallsPolicy(Sandbox* sandbox, int sysno, void* aux) { | 568 ErrorCode RedirectAllSyscallsPolicy(SandboxBPF* sandbox, int sysno, void* aux) { |
570 setenv(kSandboxDebuggingEnv, "t", 0); | 569 setenv(kSandboxDebuggingEnv, "t", 0); |
571 Die::SuppressInfoMessages(true); | 570 Die::SuppressInfoMessages(true); |
572 | 571 |
573 // Some system calls must always be allowed, if our policy wants to make | 572 // Some system calls must always be allowed, if our policy wants to make |
574 // use of UnsafeTrap() | 573 // use of UnsafeTrap() |
575 if (sysno == __NR_rt_sigprocmask || sysno == __NR_rt_sigreturn | 574 if (sysno == __NR_rt_sigprocmask || sysno == __NR_rt_sigreturn |
576 #if defined(__NR_sigprocmask) | 575 #if defined(__NR_sigprocmask) |
577 || | 576 || |
578 sysno == __NR_sigprocmask | 577 sysno == __NR_sigprocmask |
579 #endif | 578 #endif |
580 #if defined(__NR_sigreturn) | 579 #if defined(__NR_sigreturn) |
581 || | 580 || |
582 sysno == __NR_sigreturn | 581 sysno == __NR_sigreturn |
583 #endif | 582 #endif |
584 ) { | 583 ) { |
585 return ErrorCode(ErrorCode::ERR_ALLOWED); | 584 return ErrorCode(ErrorCode::ERR_ALLOWED); |
586 } else if (Sandbox::IsValidSyscallNumber(sysno)) { | 585 } else if (SandboxBPF::IsValidSyscallNumber(sysno)) { |
587 return sandbox->UnsafeTrap(AllowRedirectedSyscall, aux); | 586 return sandbox->UnsafeTrap(AllowRedirectedSyscall, aux); |
588 } else { | 587 } else { |
589 return ErrorCode(ENOSYS); | 588 return ErrorCode(ENOSYS); |
590 } | 589 } |
591 } | 590 } |
592 | 591 |
593 int bus_handler_fd_ = -1; | 592 int bus_handler_fd_ = -1; |
594 | 593 |
595 void SigBusHandler(int, siginfo_t* info, void* void_context) { | 594 void SigBusHandler(int, siginfo_t* info, void* void_context) { |
596 BPF_ASSERT(write(bus_handler_fd_, "\x55", 1) == 1); | 595 BPF_ASSERT(write(bus_handler_fd_, "\x55", 1) == 1); |
597 } | 596 } |
598 | 597 |
599 BPF_TEST(SandboxBpf, SigBus, RedirectAllSyscallsPolicy) { | 598 BPF_TEST(SandboxBPF, SigBus, RedirectAllSyscallsPolicy) { |
600 // We use the SIGBUS bit in the signal mask as a thread-local boolean | 599 // We use the SIGBUS bit in the signal mask as a thread-local boolean |
601 // value in the implementation of UnsafeTrap(). This is obviously a bit | 600 // value in the implementation of UnsafeTrap(). This is obviously a bit |
602 // of a hack that could conceivably interfere with code that uses SIGBUS | 601 // of a hack that could conceivably interfere with code that uses SIGBUS |
603 // in more traditional ways. This test verifies that basic functionality | 602 // in more traditional ways. This test verifies that basic functionality |
604 // of SIGBUS is not impacted, but it is certainly possibly to construe | 603 // of SIGBUS is not impacted, but it is certainly possibly to construe |
605 // more complex uses of signals where our use of the SIGBUS mask is not | 604 // more complex uses of signals where our use of the SIGBUS mask is not |
606 // 100% transparent. This is expected behavior. | 605 // 100% transparent. This is expected behavior. |
607 int fds[2]; | 606 int fds[2]; |
608 BPF_ASSERT(pipe(fds) == 0); | 607 BPF_ASSERT(pipe(fds) == 0); |
609 bus_handler_fd_ = fds[1]; | 608 bus_handler_fd_ = fds[1]; |
610 struct sigaction sa = {}; | 609 struct sigaction sa = {}; |
611 sa.sa_sigaction = SigBusHandler; | 610 sa.sa_sigaction = SigBusHandler; |
612 sa.sa_flags = SA_SIGINFO; | 611 sa.sa_flags = SA_SIGINFO; |
613 BPF_ASSERT(sigaction(SIGBUS, &sa, NULL) == 0); | 612 BPF_ASSERT(sigaction(SIGBUS, &sa, NULL) == 0); |
614 raise(SIGBUS); | 613 raise(SIGBUS); |
615 char c = '\000'; | 614 char c = '\000'; |
616 BPF_ASSERT(read(fds[0], &c, 1) == 1); | 615 BPF_ASSERT(read(fds[0], &c, 1) == 1); |
617 BPF_ASSERT(close(fds[0]) == 0); | 616 BPF_ASSERT(close(fds[0]) == 0); |
618 BPF_ASSERT(close(fds[1]) == 0); | 617 BPF_ASSERT(close(fds[1]) == 0); |
619 BPF_ASSERT(c == 0x55); | 618 BPF_ASSERT(c == 0x55); |
620 } | 619 } |
621 | 620 |
622 BPF_TEST(SandboxBpf, SigMask, RedirectAllSyscallsPolicy) { | 621 BPF_TEST(SandboxBPF, SigMask, RedirectAllSyscallsPolicy) { |
623 // Signal masks are potentially tricky to handle. For instance, if we | 622 // Signal masks are potentially tricky to handle. For instance, if we |
624 // ever tried to update them from inside a Trap() or UnsafeTrap() handler, | 623 // ever tried to update them from inside a Trap() or UnsafeTrap() handler, |
625 // the call to sigreturn() at the end of the signal handler would undo | 624 // the call to sigreturn() at the end of the signal handler would undo |
626 // all of our efforts. So, it makes sense to test that sigprocmask() | 625 // all of our efforts. So, it makes sense to test that sigprocmask() |
627 // works, even if we have a policy in place that makes use of UnsafeTrap(). | 626 // works, even if we have a policy in place that makes use of UnsafeTrap(). |
628 // In practice, this works because we force sigprocmask() to be handled | 627 // In practice, this works because we force sigprocmask() to be handled |
629 // entirely in the kernel. | 628 // entirely in the kernel. |
630 sigset_t mask0, mask1, mask2; | 629 sigset_t mask0, mask1, mask2; |
631 | 630 |
632 // Call sigprocmask() to verify that SIGUSR2 wasn't blocked, if we didn't | 631 // Call sigprocmask() to verify that SIGUSR2 wasn't blocked, if we didn't |
633 // change the mask (it shouldn't have been, as it isn't blocked by default | 632 // change the mask (it shouldn't have been, as it isn't blocked by default |
634 // in POSIX). | 633 // in POSIX). |
635 // | 634 // |
636 // Use SIGUSR2 because Android seems to use SIGUSR1 for some purpose. | 635 // Use SIGUSR2 because Android seems to use SIGUSR1 for some purpose. |
637 sigemptyset(&mask0); | 636 sigemptyset(&mask0); |
638 BPF_ASSERT(!sigprocmask(SIG_BLOCK, &mask0, &mask1)); | 637 BPF_ASSERT(!sigprocmask(SIG_BLOCK, &mask0, &mask1)); |
639 BPF_ASSERT(!sigismember(&mask1, SIGUSR2)); | 638 BPF_ASSERT(!sigismember(&mask1, SIGUSR2)); |
640 | 639 |
641 // Try again, and this time we verify that we can block it. This | 640 // Try again, and this time we verify that we can block it. This |
642 // requires a second call to sigprocmask(). | 641 // requires a second call to sigprocmask(). |
643 sigaddset(&mask0, SIGUSR2); | 642 sigaddset(&mask0, SIGUSR2); |
644 BPF_ASSERT(!sigprocmask(SIG_BLOCK, &mask0, NULL)); | 643 BPF_ASSERT(!sigprocmask(SIG_BLOCK, &mask0, NULL)); |
645 BPF_ASSERT(!sigprocmask(SIG_BLOCK, NULL, &mask2)); | 644 BPF_ASSERT(!sigprocmask(SIG_BLOCK, NULL, &mask2)); |
646 BPF_ASSERT(sigismember(&mask2, SIGUSR2)); | 645 BPF_ASSERT(sigismember(&mask2, SIGUSR2)); |
647 } | 646 } |
648 | 647 |
649 BPF_TEST(SandboxBpf, UnsafeTrapWithErrno, RedirectAllSyscallsPolicy) { | 648 BPF_TEST(SandboxBPF, UnsafeTrapWithErrno, RedirectAllSyscallsPolicy) { |
650 // An UnsafeTrap() (or for that matter, a Trap()) has to report error | 649 // An UnsafeTrap() (or for that matter, a Trap()) has to report error |
651 // conditions by returning an exit code in the range -1..-4096. This | 650 // conditions by returning an exit code in the range -1..-4096. This |
652 // should happen automatically if using ForwardSyscall(). If the TrapFnc() | 651 // should happen automatically if using ForwardSyscall(). If the TrapFnc() |
653 // uses some other method to make system calls, then it is responsible | 652 // uses some other method to make system calls, then it is responsible |
654 // for computing the correct return code. | 653 // for computing the correct return code. |
655 // This test verifies that ForwardSyscall() does the correct thing. | 654 // This test verifies that ForwardSyscall() does the correct thing. |
656 | 655 |
657 // The glibc system wrapper will ultimately set errno for us. So, from normal | 656 // The glibc system wrapper will ultimately set errno for us. So, from normal |
658 // userspace, all of this should be completely transparent. | 657 // userspace, all of this should be completely transparent. |
659 errno = 0; | 658 errno = 0; |
660 BPF_ASSERT(close(-1) == -1); | 659 BPF_ASSERT(close(-1) == -1); |
661 BPF_ASSERT(errno == EBADF); | 660 BPF_ASSERT(errno == EBADF); |
662 | 661 |
663 // Explicitly avoid the glibc wrapper. This is not normally the way anybody | 662 // Explicitly avoid the glibc wrapper. This is not normally the way anybody |
664 // would make system calls, but it allows us to verify that we don't | 663 // would make system calls, but it allows us to verify that we don't |
665 // accidentally mess with errno, when we shouldn't. | 664 // accidentally mess with errno, when we shouldn't. |
666 errno = 0; | 665 errno = 0; |
667 struct arch_seccomp_data args = {}; | 666 struct arch_seccomp_data args = {}; |
668 args.nr = __NR_close; | 667 args.nr = __NR_close; |
669 args.args[0] = -1; | 668 args.args[0] = -1; |
670 BPF_ASSERT(Sandbox::ForwardSyscall(args) == -EBADF); | 669 BPF_ASSERT(SandboxBPF::ForwardSyscall(args) == -EBADF); |
671 BPF_ASSERT(errno == 0); | 670 BPF_ASSERT(errno == 0); |
672 } | 671 } |
673 | 672 |
674 // Test a trap handler that makes use of a broker process to open(). | 673 // Test a trap handler that makes use of a broker process to open(). |
675 | 674 |
676 class InitializedOpenBroker { | 675 class InitializedOpenBroker { |
677 public: | 676 public: |
678 InitializedOpenBroker() : initialized_(false) { | 677 InitializedOpenBroker() : initialized_(false) { |
679 std::vector<std::string> allowed_files; | 678 std::vector<std::string> allowed_files; |
680 allowed_files.push_back("/proc/allowed"); | 679 allowed_files.push_back("/proc/allowed"); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
712 // the openat() system call. | 711 // the openat() system call. |
713 BPF_ASSERT(static_cast<int>(args.args[0]) == AT_FDCWD); | 712 BPF_ASSERT(static_cast<int>(args.args[0]) == AT_FDCWD); |
714 return broker_process->Open(reinterpret_cast<const char*>(args.args[1]), | 713 return broker_process->Open(reinterpret_cast<const char*>(args.args[1]), |
715 static_cast<int>(args.args[2])); | 714 static_cast<int>(args.args[2])); |
716 default: | 715 default: |
717 BPF_ASSERT(false); | 716 BPF_ASSERT(false); |
718 return -ENOSYS; | 717 return -ENOSYS; |
719 } | 718 } |
720 } | 719 } |
721 | 720 |
722 ErrorCode DenyOpenPolicy(Sandbox* sandbox, int sysno, void* aux) { | 721 ErrorCode DenyOpenPolicy(SandboxBPF* sandbox, int sysno, void* aux) { |
723 InitializedOpenBroker* iob = static_cast<InitializedOpenBroker*>(aux); | 722 InitializedOpenBroker* iob = static_cast<InitializedOpenBroker*>(aux); |
724 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 723 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
725 return ErrorCode(ENOSYS); | 724 return ErrorCode(ENOSYS); |
726 } | 725 } |
727 | 726 |
728 switch (sysno) { | 727 switch (sysno) { |
729 case __NR_access: | 728 case __NR_access: |
730 case __NR_open: | 729 case __NR_open: |
731 case __NR_openat: | 730 case __NR_openat: |
732 // We get a InitializedOpenBroker class, but our trap handler wants | 731 // We get a InitializedOpenBroker class, but our trap handler wants |
733 // the BrokerProcess object. | 732 // the BrokerProcess object. |
734 return ErrorCode( | 733 return ErrorCode( |
735 sandbox->Trap(BrokerOpenTrapHandler, iob->broker_process())); | 734 sandbox->Trap(BrokerOpenTrapHandler, iob->broker_process())); |
736 default: | 735 default: |
737 return ErrorCode(ErrorCode::ERR_ALLOWED); | 736 return ErrorCode(ErrorCode::ERR_ALLOWED); |
738 } | 737 } |
739 } | 738 } |
740 | 739 |
741 // We use a InitializedOpenBroker class, so that we can run unsandboxed | 740 // We use a InitializedOpenBroker class, so that we can run unsandboxed |
742 // code in its constructor, which is the only way to do so in a BPF_TEST. | 741 // code in its constructor, which is the only way to do so in a BPF_TEST. |
743 BPF_TEST(SandboxBpf, | 742 BPF_TEST(SandboxBPF, |
744 UseOpenBroker, | 743 UseOpenBroker, |
745 DenyOpenPolicy, | 744 DenyOpenPolicy, |
746 InitializedOpenBroker /* BPF_AUX */) { | 745 InitializedOpenBroker /* BPF_AUX */) { |
747 BPF_ASSERT(BPF_AUX.initialized()); | 746 BPF_ASSERT(BPF_AUX.initialized()); |
748 BrokerProcess* broker_process = BPF_AUX.broker_process(); | 747 BrokerProcess* broker_process = BPF_AUX.broker_process(); |
749 BPF_ASSERT(broker_process != NULL); | 748 BPF_ASSERT(broker_process != NULL); |
750 | 749 |
751 // First, use the broker "manually" | 750 // First, use the broker "manually" |
752 BPF_ASSERT(broker_process->Open("/proc/denied", O_RDONLY) == -EPERM); | 751 BPF_ASSERT(broker_process->Open("/proc/denied", O_RDONLY) == -EPERM); |
753 BPF_ASSERT(broker_process->Access("/proc/denied", R_OK) == -EPERM); | 752 BPF_ASSERT(broker_process->Access("/proc/denied", R_OK) == -EPERM); |
(...skipping 24 matching lines...) Expand all Loading... |
778 | 777 |
779 // This is also white listed and does exist. | 778 // This is also white listed and does exist. |
780 int cpu_info_access = access("/proc/cpuinfo", R_OK); | 779 int cpu_info_access = access("/proc/cpuinfo", R_OK); |
781 BPF_ASSERT(cpu_info_access == 0); | 780 BPF_ASSERT(cpu_info_access == 0); |
782 int cpu_info_fd = open("/proc/cpuinfo", O_RDONLY); | 781 int cpu_info_fd = open("/proc/cpuinfo", O_RDONLY); |
783 BPF_ASSERT(cpu_info_fd >= 0); | 782 BPF_ASSERT(cpu_info_fd >= 0); |
784 char buf[1024]; | 783 char buf[1024]; |
785 BPF_ASSERT(read(cpu_info_fd, buf, sizeof(buf)) > 0); | 784 BPF_ASSERT(read(cpu_info_fd, buf, sizeof(buf)) > 0); |
786 } | 785 } |
787 | 786 |
788 // Simple test demonstrating how to use Sandbox::Cond() | 787 // Simple test demonstrating how to use SandboxBPF::Cond() |
789 | 788 |
790 ErrorCode SimpleCondTestPolicy(Sandbox* sandbox, int sysno, void*) { | 789 ErrorCode SimpleCondTestPolicy(SandboxBPF* sandbox, int sysno, void*) { |
791 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 790 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
792 // FIXME: we should really not have to do that in a trivial policy | 791 // FIXME: we should really not have to do that in a trivial policy |
793 return ErrorCode(ENOSYS); | 792 return ErrorCode(ENOSYS); |
794 } | 793 } |
795 | 794 |
796 // We deliberately return unusual errno values upon failure, so that we | 795 // We deliberately return unusual errno values upon failure, so that we |
797 // can uniquely test for these values. In a "real" policy, you would want | 796 // can uniquely test for these values. In a "real" policy, you would want |
798 // to return more traditional values. | 797 // to return more traditional values. |
799 switch (sysno) { | 798 switch (sysno) { |
800 case __NR_open: | 799 case __NR_open: |
801 // Allow opening files for reading, but don't allow writing. | 800 // Allow opening files for reading, but don't allow writing. |
(...skipping 16 matching lines...) Expand all Loading... |
818 ErrorCode::TP_32BIT, | 817 ErrorCode::TP_32BIT, |
819 ErrorCode::OP_EQUAL, | 818 ErrorCode::OP_EQUAL, |
820 PR_GET_DUMPABLE, | 819 PR_GET_DUMPABLE, |
821 ErrorCode(ErrorCode::ERR_ALLOWED), | 820 ErrorCode(ErrorCode::ERR_ALLOWED), |
822 ErrorCode(ENOMEM))); | 821 ErrorCode(ENOMEM))); |
823 default: | 822 default: |
824 return ErrorCode(ErrorCode::ERR_ALLOWED); | 823 return ErrorCode(ErrorCode::ERR_ALLOWED); |
825 } | 824 } |
826 } | 825 } |
827 | 826 |
828 BPF_TEST(SandboxBpf, SimpleCondTest, SimpleCondTestPolicy) { | 827 BPF_TEST(SandboxBPF, SimpleCondTest, SimpleCondTestPolicy) { |
829 int fd; | 828 int fd; |
830 BPF_ASSERT((fd = open("/proc/self/comm", O_RDWR)) == -1); | 829 BPF_ASSERT((fd = open("/proc/self/comm", O_RDWR)) == -1); |
831 BPF_ASSERT(errno == EROFS); | 830 BPF_ASSERT(errno == EROFS); |
832 BPF_ASSERT((fd = open("/proc/self/comm", O_RDONLY)) >= 0); | 831 BPF_ASSERT((fd = open("/proc/self/comm", O_RDONLY)) >= 0); |
833 close(fd); | 832 close(fd); |
834 | 833 |
835 int ret; | 834 int ret; |
836 BPF_ASSERT((ret = prctl(PR_GET_DUMPABLE)) >= 0); | 835 BPF_ASSERT((ret = prctl(PR_GET_DUMPABLE)) >= 0); |
837 BPF_ASSERT(prctl(PR_SET_DUMPABLE, 1 - ret) == 0); | 836 BPF_ASSERT(prctl(PR_SET_DUMPABLE, 1 - ret) == 0); |
838 BPF_ASSERT(prctl(PR_GET_ENDIAN, &ret) == -1); | 837 BPF_ASSERT(prctl(PR_GET_ENDIAN, &ret) == -1); |
839 BPF_ASSERT(errno == ENOMEM); | 838 BPF_ASSERT(errno == ENOMEM); |
840 } | 839 } |
841 | 840 |
842 // This test exercises the Sandbox::Cond() method by building a complex | 841 // This test exercises the SandboxBPF::Cond() method by building a complex |
843 // tree of conditional equality operations. It then makes system calls and | 842 // tree of conditional equality operations. It then makes system calls and |
844 // verifies that they return the values that we expected from our BPF | 843 // verifies that they return the values that we expected from our BPF |
845 // program. | 844 // program. |
846 class EqualityStressTest { | 845 class EqualityStressTest { |
847 public: | 846 public: |
848 EqualityStressTest() { | 847 EqualityStressTest() { |
849 // We want a deterministic test | 848 // We want a deterministic test |
850 srand(0); | 849 srand(0); |
851 | 850 |
852 // Iterates over system call numbers and builds a random tree of | 851 // Iterates over system call numbers and builds a random tree of |
(...skipping 19 matching lines...) Expand all Loading... |
872 } | 871 } |
873 | 872 |
874 ~EqualityStressTest() { | 873 ~EqualityStressTest() { |
875 for (std::vector<ArgValue*>::iterator iter = arg_values_.begin(); | 874 for (std::vector<ArgValue*>::iterator iter = arg_values_.begin(); |
876 iter != arg_values_.end(); | 875 iter != arg_values_.end(); |
877 ++iter) { | 876 ++iter) { |
878 DeleteArgValue(*iter); | 877 DeleteArgValue(*iter); |
879 } | 878 } |
880 } | 879 } |
881 | 880 |
882 ErrorCode Policy(Sandbox* sandbox, int sysno) { | 881 ErrorCode Policy(SandboxBPF* sandbox, int sysno) { |
883 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 882 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
884 // FIXME: we should really not have to do that in a trivial policy | 883 // FIXME: we should really not have to do that in a trivial policy |
885 return ErrorCode(ENOSYS); | 884 return ErrorCode(ENOSYS); |
886 } else if (sysno < 0 || sysno >= (int)arg_values_.size() || | 885 } else if (sysno < 0 || sysno >= (int)arg_values_.size() || |
887 IsReservedSyscall(sysno)) { | 886 IsReservedSyscall(sysno)) { |
888 // We only return ErrorCode values for the system calls that | 887 // We only return ErrorCode values for the system calls that |
889 // are part of our test data. Every other system call remains | 888 // are part of our test data. Every other system call remains |
890 // allowed. | 889 // allowed. |
891 return ErrorCode(ErrorCode::ERR_ALLOWED); | 890 return ErrorCode(ErrorCode::ERR_ALLOWED); |
892 } else { | 891 } else { |
893 // ToErrorCode() turns an ArgValue object into an ErrorCode that is | 892 // ToErrorCode() turns an ArgValue object into an ErrorCode that is |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1032 } | 1031 } |
1033 delete[] arg_value->tests; | 1032 delete[] arg_value->tests; |
1034 } | 1033 } |
1035 if (!arg_value->err) { | 1034 if (!arg_value->err) { |
1036 DeleteArgValue(arg_value->arg_value); | 1035 DeleteArgValue(arg_value->arg_value); |
1037 } | 1036 } |
1038 delete arg_value; | 1037 delete arg_value; |
1039 } | 1038 } |
1040 } | 1039 } |
1041 | 1040 |
1042 ErrorCode ToErrorCode(Sandbox* sandbox, ArgValue* arg_value) { | 1041 ErrorCode ToErrorCode(SandboxBPF* sandbox, ArgValue* arg_value) { |
1043 // Compute the ErrorCode that should be returned, if none of our | 1042 // Compute the ErrorCode that should be returned, if none of our |
1044 // tests succeed (i.e. the system call parameter doesn't match any | 1043 // tests succeed (i.e. the system call parameter doesn't match any |
1045 // of the values in arg_value->tests[].k_value). | 1044 // of the values in arg_value->tests[].k_value). |
1046 ErrorCode err; | 1045 ErrorCode err; |
1047 if (arg_value->err) { | 1046 if (arg_value->err) { |
1048 // If this was a leaf node, return the errno value that we expect to | 1047 // If this was a leaf node, return the errno value that we expect to |
1049 // return from the BPF filter program. | 1048 // return from the BPF filter program. |
1050 err = ErrorCode(arg_value->err); | 1049 err = ErrorCode(arg_value->err); |
1051 } else { | 1050 } else { |
1052 // If this wasn't a leaf node yet, recursively descend into the rest | 1051 // If this wasn't a leaf node yet, recursively descend into the rest |
1053 // of the tree. This will end up adding a few more Sandbox::Cond() | 1052 // of the tree. This will end up adding a few more SandboxBPF::Cond() |
1054 // tests to our ErrorCode. | 1053 // tests to our ErrorCode. |
1055 err = ToErrorCode(sandbox, arg_value->arg_value); | 1054 err = ToErrorCode(sandbox, arg_value->arg_value); |
1056 } | 1055 } |
1057 | 1056 |
1058 // Now, iterate over all the test cases that we want to compare against. | 1057 // Now, iterate over all the test cases that we want to compare against. |
1059 // This builds a chain of Sandbox::Cond() tests | 1058 // This builds a chain of SandboxBPF::Cond() tests |
1060 // (aka "if ... elif ... elif ... elif ... fi") | 1059 // (aka "if ... elif ... elif ... elif ... fi") |
1061 for (int n = arg_value->size; n-- > 0;) { | 1060 for (int n = arg_value->size; n-- > 0;) { |
1062 ErrorCode matched; | 1061 ErrorCode matched; |
1063 // Again, we distinguish between leaf nodes and subtrees. | 1062 // Again, we distinguish between leaf nodes and subtrees. |
1064 if (arg_value->tests[n].err) { | 1063 if (arg_value->tests[n].err) { |
1065 matched = ErrorCode(arg_value->tests[n].err); | 1064 matched = ErrorCode(arg_value->tests[n].err); |
1066 } else { | 1065 } else { |
1067 matched = ToErrorCode(sandbox, arg_value->tests[n].arg_value); | 1066 matched = ToErrorCode(sandbox, arg_value->tests[n].arg_value); |
1068 } | 1067 } |
1069 // For now, all of our tests are limited to 32bit. | 1068 // For now, all of our tests are limited to 32bit. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1133 std::vector<ArgValue*> arg_values_; | 1132 std::vector<ArgValue*> arg_values_; |
1134 | 1133 |
1135 // Don't increase these values. We are pushing the limits of the maximum | 1134 // Don't increase these values. We are pushing the limits of the maximum |
1136 // BPF program that the kernel will allow us to load. If the values are | 1135 // BPF program that the kernel will allow us to load. If the values are |
1137 // increased too much, the test will start failing. | 1136 // increased too much, the test will start failing. |
1138 static const int kNumTestCases = 40; | 1137 static const int kNumTestCases = 40; |
1139 static const int kMaxFanOut = 3; | 1138 static const int kMaxFanOut = 3; |
1140 static const int kMaxArgs = 6; | 1139 static const int kMaxArgs = 6; |
1141 }; | 1140 }; |
1142 | 1141 |
1143 ErrorCode EqualityStressTestPolicy(Sandbox* sandbox, int sysno, void* aux) { | 1142 ErrorCode EqualityStressTestPolicy(SandboxBPF* sandbox, int sysno, void* aux) { |
1144 return reinterpret_cast<EqualityStressTest*>(aux)->Policy(sandbox, sysno); | 1143 return reinterpret_cast<EqualityStressTest*>(aux)->Policy(sandbox, sysno); |
1145 } | 1144 } |
1146 | 1145 |
1147 BPF_TEST(SandboxBpf, | 1146 BPF_TEST(SandboxBPF, |
1148 EqualityTests, | 1147 EqualityTests, |
1149 EqualityStressTestPolicy, | 1148 EqualityStressTestPolicy, |
1150 EqualityStressTest /* BPF_AUX */) { | 1149 EqualityStressTest /* BPF_AUX */) { |
1151 BPF_AUX.VerifyFilter(); | 1150 BPF_AUX.VerifyFilter(); |
1152 } | 1151 } |
1153 | 1152 |
1154 ErrorCode EqualityArgumentWidthPolicy(Sandbox* sandbox, int sysno, void*) { | 1153 ErrorCode EqualityArgumentWidthPolicy(SandboxBPF* sandbox, int sysno, void*) { |
1155 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 1154 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
1156 // FIXME: we should really not have to do that in a trivial policy | 1155 // FIXME: we should really not have to do that in a trivial policy |
1157 return ErrorCode(ENOSYS); | 1156 return ErrorCode(ENOSYS); |
1158 } else if (sysno == __NR_uname) { | 1157 } else if (sysno == __NR_uname) { |
1159 return sandbox->Cond( | 1158 return sandbox->Cond( |
1160 0, | 1159 0, |
1161 ErrorCode::TP_32BIT, | 1160 ErrorCode::TP_32BIT, |
1162 ErrorCode::OP_EQUAL, | 1161 ErrorCode::OP_EQUAL, |
1163 0, | 1162 0, |
1164 sandbox->Cond(1, | 1163 sandbox->Cond(1, |
1165 ErrorCode::TP_32BIT, | 1164 ErrorCode::TP_32BIT, |
(...skipping 13 matching lines...) Expand all Loading... |
1179 ErrorCode::TP_64BIT, | 1178 ErrorCode::TP_64BIT, |
1180 ErrorCode::OP_EQUAL, | 1179 ErrorCode::OP_EQUAL, |
1181 0x55555555AAAAAAAAULL, | 1180 0x55555555AAAAAAAAULL, |
1182 ErrorCode(1), | 1181 ErrorCode(1), |
1183 ErrorCode(2))); | 1182 ErrorCode(2))); |
1184 } else { | 1183 } else { |
1185 return ErrorCode(ErrorCode::ERR_ALLOWED); | 1184 return ErrorCode(ErrorCode::ERR_ALLOWED); |
1186 } | 1185 } |
1187 } | 1186 } |
1188 | 1187 |
1189 BPF_TEST(SandboxBpf, EqualityArgumentWidth, EqualityArgumentWidthPolicy) { | 1188 BPF_TEST(SandboxBPF, EqualityArgumentWidth, EqualityArgumentWidthPolicy) { |
1190 BPF_ASSERT(SandboxSyscall(__NR_uname, 0, 0x55555555) == -1); | 1189 BPF_ASSERT(SandboxSyscall(__NR_uname, 0, 0x55555555) == -1); |
1191 BPF_ASSERT(SandboxSyscall(__NR_uname, 0, 0xAAAAAAAA) == -2); | 1190 BPF_ASSERT(SandboxSyscall(__NR_uname, 0, 0xAAAAAAAA) == -2); |
1192 #if __SIZEOF_POINTER__ > 4 | 1191 #if __SIZEOF_POINTER__ > 4 |
1193 // On 32bit machines, there is no way to pass a 64bit argument through the | 1192 // On 32bit machines, there is no way to pass a 64bit argument through the |
1194 // syscall interface. So, we have to skip the part of the test that requires | 1193 // syscall interface. So, we have to skip the part of the test that requires |
1195 // 64bit arguments. | 1194 // 64bit arguments. |
1196 BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x55555555AAAAAAAAULL) == -1); | 1195 BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x55555555AAAAAAAAULL) == -1); |
1197 BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x5555555500000000ULL) == -2); | 1196 BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x5555555500000000ULL) == -2); |
1198 BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x5555555511111111ULL) == -2); | 1197 BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x5555555511111111ULL) == -2); |
1199 BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x11111111AAAAAAAAULL) == -2); | 1198 BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x11111111AAAAAAAAULL) == -2); |
1200 #else | 1199 #else |
1201 BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x55555555) == -2); | 1200 BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x55555555) == -2); |
1202 #endif | 1201 #endif |
1203 } | 1202 } |
1204 | 1203 |
1205 #if __SIZEOF_POINTER__ > 4 | 1204 #if __SIZEOF_POINTER__ > 4 |
1206 // On 32bit machines, there is no way to pass a 64bit argument through the | 1205 // On 32bit machines, there is no way to pass a 64bit argument through the |
1207 // syscall interface. So, we have to skip the part of the test that requires | 1206 // syscall interface. So, we have to skip the part of the test that requires |
1208 // 64bit arguments. | 1207 // 64bit arguments. |
1209 BPF_DEATH_TEST(SandboxBpf, | 1208 BPF_DEATH_TEST(SandboxBPF, |
1210 EqualityArgumentUnallowed64bit, | 1209 EqualityArgumentUnallowed64bit, |
1211 DEATH_MESSAGE("Unexpected 64bit argument detected"), | 1210 DEATH_MESSAGE("Unexpected 64bit argument detected"), |
1212 EqualityArgumentWidthPolicy) { | 1211 EqualityArgumentWidthPolicy) { |
1213 SandboxSyscall(__NR_uname, 0, 0x5555555555555555ULL); | 1212 SandboxSyscall(__NR_uname, 0, 0x5555555555555555ULL); |
1214 } | 1213 } |
1215 #endif | 1214 #endif |
1216 | 1215 |
1217 ErrorCode EqualityWithNegativeArgumentsPolicy(Sandbox* sandbox, | 1216 ErrorCode EqualityWithNegativeArgumentsPolicy(SandboxBPF* sandbox, |
1218 int sysno, | 1217 int sysno, |
1219 void*) { | 1218 void*) { |
1220 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 1219 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
1221 // FIXME: we should really not have to do that in a trivial policy | 1220 // FIXME: we should really not have to do that in a trivial policy |
1222 return ErrorCode(ENOSYS); | 1221 return ErrorCode(ENOSYS); |
1223 } else if (sysno == __NR_uname) { | 1222 } else if (sysno == __NR_uname) { |
1224 return sandbox->Cond(0, | 1223 return sandbox->Cond(0, |
1225 ErrorCode::TP_32BIT, | 1224 ErrorCode::TP_32BIT, |
1226 ErrorCode::OP_EQUAL, | 1225 ErrorCode::OP_EQUAL, |
1227 0xFFFFFFFF, | 1226 0xFFFFFFFF, |
1228 ErrorCode(1), | 1227 ErrorCode(1), |
1229 ErrorCode(2)); | 1228 ErrorCode(2)); |
1230 } else { | 1229 } else { |
1231 return ErrorCode(ErrorCode::ERR_ALLOWED); | 1230 return ErrorCode(ErrorCode::ERR_ALLOWED); |
1232 } | 1231 } |
1233 } | 1232 } |
1234 | 1233 |
1235 BPF_TEST(SandboxBpf, | 1234 BPF_TEST(SandboxBPF, |
1236 EqualityWithNegativeArguments, | 1235 EqualityWithNegativeArguments, |
1237 EqualityWithNegativeArgumentsPolicy) { | 1236 EqualityWithNegativeArgumentsPolicy) { |
1238 BPF_ASSERT(SandboxSyscall(__NR_uname, 0xFFFFFFFF) == -1); | 1237 BPF_ASSERT(SandboxSyscall(__NR_uname, 0xFFFFFFFF) == -1); |
1239 BPF_ASSERT(SandboxSyscall(__NR_uname, -1) == -1); | 1238 BPF_ASSERT(SandboxSyscall(__NR_uname, -1) == -1); |
1240 BPF_ASSERT(SandboxSyscall(__NR_uname, -1LL) == -1); | 1239 BPF_ASSERT(SandboxSyscall(__NR_uname, -1LL) == -1); |
1241 } | 1240 } |
1242 | 1241 |
1243 #if __SIZEOF_POINTER__ > 4 | 1242 #if __SIZEOF_POINTER__ > 4 |
1244 BPF_DEATH_TEST(SandboxBpf, | 1243 BPF_DEATH_TEST(SandboxBPF, |
1245 EqualityWithNegative64bitArguments, | 1244 EqualityWithNegative64bitArguments, |
1246 DEATH_MESSAGE("Unexpected 64bit argument detected"), | 1245 DEATH_MESSAGE("Unexpected 64bit argument detected"), |
1247 EqualityWithNegativeArgumentsPolicy) { | 1246 EqualityWithNegativeArgumentsPolicy) { |
1248 // When expecting a 32bit system call argument, we look at the MSB of the | 1247 // When expecting a 32bit system call argument, we look at the MSB of the |
1249 // 64bit value and allow both "0" and "-1". But the latter is allowed only | 1248 // 64bit value and allow both "0" and "-1". But the latter is allowed only |
1250 // iff the LSB was negative. So, this death test should error out. | 1249 // iff the LSB was negative. So, this death test should error out. |
1251 BPF_ASSERT(SandboxSyscall(__NR_uname, 0xFFFFFFFF00000000LL) == -1); | 1250 BPF_ASSERT(SandboxSyscall(__NR_uname, 0xFFFFFFFF00000000LL) == -1); |
1252 } | 1251 } |
1253 #endif | 1252 #endif |
1254 ErrorCode AllBitTestPolicy(Sandbox *sandbox, int sysno, void *) { | 1253 ErrorCode AllBitTestPolicy(SandboxBPF* sandbox, int sysno, void *) { |
1255 // Test the OP_HAS_ALL_BITS conditional test operator with a couple of | 1254 // Test the OP_HAS_ALL_BITS conditional test operator with a couple of |
1256 // different bitmasks. We try to find bitmasks that could conceivably | 1255 // different bitmasks. We try to find bitmasks that could conceivably |
1257 // touch corner cases. | 1256 // touch corner cases. |
1258 // For all of these tests, we override the uname(). We can make use with | 1257 // For all of these tests, we override the uname(). We can make use with |
1259 // a single system call number, as we use the first system call argument to | 1258 // a single system call number, as we use the first system call argument to |
1260 // select the different bit masks that we want to test against. | 1259 // select the different bit masks that we want to test against. |
1261 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 1260 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
1262 // FIXME: we should really not have to do that in a trivial policy | 1261 // FIXME: we should really not have to do that in a trivial policy |
1263 return ErrorCode(ENOSYS); | 1262 return ErrorCode(ENOSYS); |
1264 } else if (sysno == __NR_uname) { | 1263 } else if (sysno == __NR_uname) { |
1265 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 0, | 1264 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 0, |
1266 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ALL_BITS, | 1265 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ALL_BITS, |
1267 0x0, | 1266 0x0, |
1268 ErrorCode(1), ErrorCode(0)), | 1267 ErrorCode(1), ErrorCode(0)), |
1269 | 1268 |
1270 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 1, | 1269 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 1, |
1271 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ALL_BITS, | 1270 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ALL_BITS, |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1337 // exit code of -1 or 0. | 1336 // exit code of -1 or 0. |
1338 #define EXPECT_FAILURE 0 | 1337 #define EXPECT_FAILURE 0 |
1339 #define EXPECT_SUCCESS -1 | 1338 #define EXPECT_SUCCESS -1 |
1340 | 1339 |
1341 // A couple of our tests behave differently on 32bit and 64bit systems, as | 1340 // A couple of our tests behave differently on 32bit and 64bit systems, as |
1342 // there is no way for a 32bit system call to pass in a 64bit system call | 1341 // there is no way for a 32bit system call to pass in a 64bit system call |
1343 // argument "arg". | 1342 // argument "arg". |
1344 // We expect these tests to succeed on 64bit systems, but to tail on 32bit | 1343 // We expect these tests to succeed on 64bit systems, but to tail on 32bit |
1345 // systems. | 1344 // systems. |
1346 #define EXPT64_SUCCESS (sizeof(void*) > 4 ? EXPECT_SUCCESS : EXPECT_FAILURE) | 1345 #define EXPT64_SUCCESS (sizeof(void*) > 4 ? EXPECT_SUCCESS : EXPECT_FAILURE) |
1347 BPF_TEST(SandboxBpf, AllBitTests, AllBitTestPolicy) { | 1346 BPF_TEST(SandboxBPF, AllBitTests, AllBitTestPolicy) { |
1348 // 32bit test: all of 0x0 (should always be true) | 1347 // 32bit test: all of 0x0 (should always be true) |
1349 BITMASK_TEST( 0, 0, ALLBITS32, 0, EXPECT_SUCCESS); | 1348 BITMASK_TEST( 0, 0, ALLBITS32, 0, EXPECT_SUCCESS); |
1350 BITMASK_TEST( 0, 1, ALLBITS32, 0, EXPECT_SUCCESS); | 1349 BITMASK_TEST( 0, 1, ALLBITS32, 0, EXPECT_SUCCESS); |
1351 BITMASK_TEST( 0, 3, ALLBITS32, 0, EXPECT_SUCCESS); | 1350 BITMASK_TEST( 0, 3, ALLBITS32, 0, EXPECT_SUCCESS); |
1352 BITMASK_TEST( 0, 0xFFFFFFFFU, ALLBITS32, 0, EXPECT_SUCCESS); | 1351 BITMASK_TEST( 0, 0xFFFFFFFFU, ALLBITS32, 0, EXPECT_SUCCESS); |
1353 BITMASK_TEST( 0, -1LL, ALLBITS32, 0, EXPECT_SUCCESS); | 1352 BITMASK_TEST( 0, -1LL, ALLBITS32, 0, EXPECT_SUCCESS); |
1354 | 1353 |
1355 // 32bit test: all of 0x1 | 1354 // 32bit test: all of 0x1 |
1356 BITMASK_TEST( 1, 0, ALLBITS32, 0x1, EXPECT_FAILURE); | 1355 BITMASK_TEST( 1, 0, ALLBITS32, 0x1, EXPECT_FAILURE); |
1357 BITMASK_TEST( 1, 1, ALLBITS32, 0x1, EXPECT_SUCCESS); | 1356 BITMASK_TEST( 1, 1, ALLBITS32, 0x1, EXPECT_SUCCESS); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1440 | 1439 |
1441 // 64bit test: all of 0x100000001 | 1440 // 64bit test: all of 0x100000001 |
1442 BITMASK_TEST(10, 0x000000000LL, ALLBITS64,0x100000001, EXPECT_FAILURE); | 1441 BITMASK_TEST(10, 0x000000000LL, ALLBITS64,0x100000001, EXPECT_FAILURE); |
1443 BITMASK_TEST(10, 0x000000001LL, ALLBITS64,0x100000001, EXPECT_FAILURE); | 1442 BITMASK_TEST(10, 0x000000001LL, ALLBITS64,0x100000001, EXPECT_FAILURE); |
1444 BITMASK_TEST(10, 0x100000000LL, ALLBITS64,0x100000001, EXPECT_FAILURE); | 1443 BITMASK_TEST(10, 0x100000000LL, ALLBITS64,0x100000001, EXPECT_FAILURE); |
1445 BITMASK_TEST(10, 0x100000001LL, ALLBITS64,0x100000001, EXPT64_SUCCESS); | 1444 BITMASK_TEST(10, 0x100000001LL, ALLBITS64,0x100000001, EXPT64_SUCCESS); |
1446 BITMASK_TEST(10, 0xFFFFFFFFU, ALLBITS64,0x100000001, EXPECT_FAILURE); | 1445 BITMASK_TEST(10, 0xFFFFFFFFU, ALLBITS64,0x100000001, EXPECT_FAILURE); |
1447 BITMASK_TEST(10, -1L, ALLBITS64,0x100000001, EXPT64_SUCCESS); | 1446 BITMASK_TEST(10, -1L, ALLBITS64,0x100000001, EXPT64_SUCCESS); |
1448 } | 1447 } |
1449 | 1448 |
1450 ErrorCode AnyBitTestPolicy(Sandbox* sandbox, int sysno, void*) { | 1449 ErrorCode AnyBitTestPolicy(SandboxBPF* sandbox, int sysno, void*) { |
1451 // Test the OP_HAS_ANY_BITS conditional test operator with a couple of | 1450 // Test the OP_HAS_ANY_BITS conditional test operator with a couple of |
1452 // different bitmasks. We try to find bitmasks that could conceivably | 1451 // different bitmasks. We try to find bitmasks that could conceivably |
1453 // touch corner cases. | 1452 // touch corner cases. |
1454 // For all of these tests, we override the uname(). We can make use with | 1453 // For all of these tests, we override the uname(). We can make use with |
1455 // a single system call number, as we use the first system call argument to | 1454 // a single system call number, as we use the first system call argument to |
1456 // select the different bit masks that we want to test against. | 1455 // select the different bit masks that we want to test against. |
1457 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 1456 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
1458 // FIXME: we should really not have to do that in a trivial policy | 1457 // FIXME: we should really not have to do that in a trivial policy |
1459 return ErrorCode(ENOSYS); | 1458 return ErrorCode(ENOSYS); |
1460 } else if (sysno == __NR_uname) { | 1459 } else if (sysno == __NR_uname) { |
1461 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 0, | 1460 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 0, |
1462 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, | 1461 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, |
1463 0x0, | 1462 0x0, |
1464 ErrorCode(1), ErrorCode(0)), | 1463 ErrorCode(1), ErrorCode(0)), |
1465 | 1464 |
1466 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 1, | 1465 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 1, |
1467 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, | 1466 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1514 sandbox->Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ANY_BITS, | 1513 sandbox->Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ANY_BITS, |
1515 0x100000001ULL, | 1514 0x100000001ULL, |
1516 ErrorCode(1), ErrorCode(0)), | 1515 ErrorCode(1), ErrorCode(0)), |
1517 | 1516 |
1518 sandbox->Kill("Invalid test case number")))))))))))); | 1517 sandbox->Kill("Invalid test case number")))))))))))); |
1519 } else { | 1518 } else { |
1520 return ErrorCode(ErrorCode::ERR_ALLOWED); | 1519 return ErrorCode(ErrorCode::ERR_ALLOWED); |
1521 } | 1520 } |
1522 } | 1521 } |
1523 | 1522 |
1524 BPF_TEST(SandboxBpf, AnyBitTests, AnyBitTestPolicy) { | 1523 BPF_TEST(SandboxBPF, AnyBitTests, AnyBitTestPolicy) { |
1525 // 32bit test: any of 0x0 (should always be false) | 1524 // 32bit test: any of 0x0 (should always be false) |
1526 BITMASK_TEST( 0, 0, ANYBITS32, 0x0, EXPECT_FAILURE); | 1525 BITMASK_TEST( 0, 0, ANYBITS32, 0x0, EXPECT_FAILURE); |
1527 BITMASK_TEST( 0, 1, ANYBITS32, 0x0, EXPECT_FAILURE); | 1526 BITMASK_TEST( 0, 1, ANYBITS32, 0x0, EXPECT_FAILURE); |
1528 BITMASK_TEST( 0, 3, ANYBITS32, 0x0, EXPECT_FAILURE); | 1527 BITMASK_TEST( 0, 3, ANYBITS32, 0x0, EXPECT_FAILURE); |
1529 BITMASK_TEST( 0, 0xFFFFFFFFU, ANYBITS32, 0x0, EXPECT_FAILURE); | 1528 BITMASK_TEST( 0, 0xFFFFFFFFU, ANYBITS32, 0x0, EXPECT_FAILURE); |
1530 BITMASK_TEST( 0, -1LL, ANYBITS32, 0x0, EXPECT_FAILURE); | 1529 BITMASK_TEST( 0, -1LL, ANYBITS32, 0x0, EXPECT_FAILURE); |
1531 | 1530 |
1532 // 32bit test: any of 0x1 | 1531 // 32bit test: any of 0x1 |
1533 BITMASK_TEST( 1, 0, ANYBITS32, 0x1, EXPECT_FAILURE); | 1532 BITMASK_TEST( 1, 0, ANYBITS32, 0x1, EXPECT_FAILURE); |
1534 BITMASK_TEST( 1, 1, ANYBITS32, 0x1, EXPECT_SUCCESS); | 1533 BITMASK_TEST( 1, 1, ANYBITS32, 0x1, EXPECT_SUCCESS); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1644 (long long)args.args[0], | 1643 (long long)args.args[0], |
1645 (long long)args.args[1], | 1644 (long long)args.args[1], |
1646 (long long)args.args[2], | 1645 (long long)args.args[2], |
1647 (long long)args.args[3], | 1646 (long long)args.args[3], |
1648 (long long)args.args[4], | 1647 (long long)args.args[4], |
1649 (long long)args.args[5], | 1648 (long long)args.args[5], |
1650 msg); | 1649 msg); |
1651 } | 1650 } |
1652 return -EPERM; | 1651 return -EPERM; |
1653 } | 1652 } |
1654 ErrorCode PthreadPolicyEquality(Sandbox* sandbox, int sysno, void* aux) { | 1653 ErrorCode PthreadPolicyEquality(SandboxBPF* sandbox, int sysno, void* aux) { |
1655 // This policy allows creating threads with pthread_create(). But it | 1654 // This policy allows creating threads with pthread_create(). But it |
1656 // doesn't allow any other uses of clone(). Most notably, it does not | 1655 // doesn't allow any other uses of clone(). Most notably, it does not |
1657 // allow callers to implement fork() or vfork() by passing suitable flags | 1656 // allow callers to implement fork() or vfork() by passing suitable flags |
1658 // to the clone() system call. | 1657 // to the clone() system call. |
1659 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 1658 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
1660 // FIXME: we should really not have to do that in a trivial policy | 1659 // FIXME: we should really not have to do that in a trivial policy |
1661 return ErrorCode(ENOSYS); | 1660 return ErrorCode(ENOSYS); |
1662 } else if (sysno == __NR_clone) { | 1661 } else if (sysno == __NR_clone) { |
1663 // We have seen two different valid combinations of flags. Glibc | 1662 // We have seen two different valid combinations of flags. Glibc |
1664 // uses the more modern flags, sets the TLS from the call to clone(), and | 1663 // uses the more modern flags, sets the TLS from the call to clone(), and |
1665 // uses futexes to monitor threads. Android's C run-time library, doesn't | 1664 // uses futexes to monitor threads. Android's C run-time library, doesn't |
1666 // do any of this, but it sets the obsolete (and no-op) CLONE_DETACHED. | 1665 // do any of this, but it sets the obsolete (and no-op) CLONE_DETACHED. |
1667 // More recent versions of Android don't set CLONE_DETACHED anymore, so | 1666 // More recent versions of Android don't set CLONE_DETACHED anymore, so |
1668 // the last case accounts for that. | 1667 // the last case accounts for that. |
1669 // The following policy is very strict. It only allows the exact masks | 1668 // The following policy is very strict. It only allows the exact masks |
(...skipping 14 matching lines...) Expand all Loading... |
1684 ErrorCode(ErrorCode::ERR_ALLOWED), | 1683 ErrorCode(ErrorCode::ERR_ALLOWED), |
1685 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, | 1684 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
1686 kBaseAndroidCloneMask, | 1685 kBaseAndroidCloneMask, |
1687 ErrorCode(ErrorCode::ERR_ALLOWED), | 1686 ErrorCode(ErrorCode::ERR_ALLOWED), |
1688 sandbox->Trap(PthreadTrapHandler, "Unknown mask")))); | 1687 sandbox->Trap(PthreadTrapHandler, "Unknown mask")))); |
1689 } else { | 1688 } else { |
1690 return ErrorCode(ErrorCode::ERR_ALLOWED); | 1689 return ErrorCode(ErrorCode::ERR_ALLOWED); |
1691 } | 1690 } |
1692 } | 1691 } |
1693 | 1692 |
1694 ErrorCode PthreadPolicyBitMask(Sandbox* sandbox, int sysno, void* aux) { | 1693 ErrorCode PthreadPolicyBitMask(SandboxBPF* sandbox, int sysno, void* aux) { |
1695 // This policy allows creating threads with pthread_create(). But it | 1694 // This policy allows creating threads with pthread_create(). But it |
1696 // doesn't allow any other uses of clone(). Most notably, it does not | 1695 // doesn't allow any other uses of clone(). Most notably, it does not |
1697 // allow callers to implement fork() or vfork() by passing suitable flags | 1696 // allow callers to implement fork() or vfork() by passing suitable flags |
1698 // to the clone() system call. | 1697 // to the clone() system call. |
1699 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 1698 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
1700 // FIXME: we should really not have to do that in a trivial policy | 1699 // FIXME: we should really not have to do that in a trivial policy |
1701 return ErrorCode(ENOSYS); | 1700 return ErrorCode(ENOSYS); |
1702 } else if (sysno == __NR_clone) { | 1701 } else if (sysno == __NR_clone) { |
1703 // We have seen two different valid combinations of flags. Glibc | 1702 // We have seen two different valid combinations of flags. Glibc |
1704 // uses the more modern flags, sets the TLS from the call to clone(), and | 1703 // uses the more modern flags, sets the TLS from the call to clone(), and |
1705 // uses futexes to monitor threads. Android's C run-time library, doesn't | 1704 // uses futexes to monitor threads. Android's C run-time library, doesn't |
1706 // do any of this, but it sets the obsolete (and no-op) CLONE_DETACHED. | 1705 // do any of this, but it sets the obsolete (and no-op) CLONE_DETACHED. |
1707 // The following policy allows for either combination of flags, but it | 1706 // The following policy allows for either combination of flags, but it |
1708 // is generally a little more conservative than strictly necessary. We | 1707 // is generally a little more conservative than strictly necessary. We |
1709 // err on the side of rather safe than sorry. | 1708 // err on the side of rather safe than sorry. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1768 // run-time libraries other than glibc might call __NR_fork instead of | 1767 // run-time libraries other than glibc might call __NR_fork instead of |
1769 // __NR_clone, and that would introduce a bogus test failure. | 1768 // __NR_clone, and that would introduce a bogus test failure. |
1770 int pid; | 1769 int pid; |
1771 BPF_ASSERT(SandboxSyscall(__NR_clone, | 1770 BPF_ASSERT(SandboxSyscall(__NR_clone, |
1772 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD, | 1771 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD, |
1773 0, | 1772 0, |
1774 0, | 1773 0, |
1775 &pid) == -EPERM); | 1774 &pid) == -EPERM); |
1776 } | 1775 } |
1777 | 1776 |
1778 BPF_TEST(SandboxBpf, PthreadEquality, PthreadPolicyEquality) { PthreadTest(); } | 1777 BPF_TEST(SandboxBPF, PthreadEquality, PthreadPolicyEquality) { PthreadTest(); } |
1779 | 1778 |
1780 BPF_TEST(SandboxBpf, PthreadBitMask, PthreadPolicyBitMask) { PthreadTest(); } | 1779 BPF_TEST(SandboxBPF, PthreadBitMask, PthreadPolicyBitMask) { PthreadTest(); } |
1781 | 1780 |
1782 } // namespace | 1781 } // namespace |
| 1782 |
| 1783 } // namespace sandbox |
OLD | NEW |