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 <ostream> | 5 #include <ostream> |
6 | 6 |
7 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" | 7 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" |
8 #include "sandbox/linux/seccomp-bpf/verifier.h" | 8 #include "sandbox/linux/seccomp-bpf/verifier.h" |
9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
10 | 10 |
11 using namespace playground2; | 11 using namespace playground2; |
12 | 12 |
13 namespace { | 13 namespace { |
14 | 14 |
15 const int kExpectedReturnValue = 42; | 15 const int kExpectedReturnValue = 42; |
16 #if defined(__arm__) | 16 #if defined(__arm__) |
17 const int kArmPublicSysnoCeiling = __NR_SYSCALL_BASE + 1024; | 17 const int kArmPublicSysnoCeiling = __NR_SYSCALL_BASE + 1024; |
jln (very slow on Chromium)
2012/10/12 20:26:52
I believe this can now be removed?
Jorge Lucangeli Obes
2012/10/13 01:39:30
Done.
| |
18 #endif | 18 #endif |
19 | 19 |
20 // This test should execute no matter whether we have kernel support. So, | 20 // This test should execute no matter whether we have kernel support. So, |
21 // we make it a TEST() instead of a BPF_TEST(). | 21 // we make it a TEST() instead of a BPF_TEST(). |
22 TEST(SandboxBpf, CallSupports) { | 22 TEST(SandboxBpf, CallSupports) { |
23 // We check that we don't crash, but it's ok if the kernel doesn't | 23 // We check that we don't crash, but it's ok if the kernel doesn't |
24 // support it. | 24 // support it. |
25 bool seccomp_bpf_supported = | 25 bool seccomp_bpf_supported = |
26 Sandbox::supportsSeccompSandbox(-1) == Sandbox::STATUS_AVAILABLE; | 26 Sandbox::supportsSeccompSandbox(-1) == Sandbox::STATUS_AVAILABLE; |
27 // We want to log whether or not seccomp BPF is actually supported | 27 // We want to log whether or not seccomp BPF is actually supported |
28 // since actual test coverage depends on it. | 28 // since actual test coverage depends on it. |
29 RecordProperty("SeccompBPFSupported", | 29 RecordProperty("SeccompBPFSupported", |
30 seccomp_bpf_supported ? "true." : "false."); | 30 seccomp_bpf_supported ? "true." : "false."); |
31 std::cout << "Seccomp BPF supported: " | 31 std::cout << "Seccomp BPF supported: " |
32 << (seccomp_bpf_supported ? "true." : "false.") | 32 << (seccomp_bpf_supported ? "true." : "false.") |
33 << "\n"; | 33 << "\n"; |
34 } | 34 } |
35 | 35 |
36 SANDBOX_TEST(SandboxBpf, CallSupportsTwice) { | 36 SANDBOX_TEST(SandboxBpf, CallSupportsTwice) { |
37 Sandbox::supportsSeccompSandbox(-1); | 37 Sandbox::supportsSeccompSandbox(-1); |
38 Sandbox::supportsSeccompSandbox(-1); | 38 Sandbox::supportsSeccompSandbox(-1); |
39 } | 39 } |
40 | 40 |
41 // A simple blacklist test | 41 // A simple blacklist test |
42 | 42 |
43 ErrorCode BlacklistNanosleepPolicy(int sysno) { | 43 ErrorCode BlacklistNanosleepPolicy(int sysno) { |
44 if (sysno < static_cast<int>(MIN_SYSCALL) || | 44 if (!Sandbox::isValidSyscallNumber(sysno)) { |
45 sysno > static_cast<int>(MAX_SYSCALL)) { | |
46 // FIXME: we should really not have to do that in a trivial policy | 45 // FIXME: we should really not have to do that in a trivial policy |
47 return ErrorCode(ENOSYS); | 46 return ErrorCode(ENOSYS); |
48 } | 47 } |
48 | |
49 switch (sysno) { | 49 switch (sysno) { |
50 case __NR_nanosleep: | 50 case __NR_nanosleep: |
51 return ErrorCode(EACCES); | 51 return ErrorCode(EACCES); |
52 default: | 52 default: |
53 return ErrorCode(ErrorCode::ERR_ALLOWED); | 53 return ErrorCode(ErrorCode::ERR_ALLOWED); |
54 } | 54 } |
55 } | 55 } |
56 | 56 |
57 BPF_TEST(SandboxBpf, ApplyBasicBlacklistPolicy, BlacklistNanosleepPolicy) { | 57 BPF_TEST(SandboxBpf, ApplyBasicBlacklistPolicy, BlacklistNanosleepPolicy) { |
58 // nanosleep() should be denied | 58 // nanosleep() should be denied |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
93 static int BlacklistNanosleepPolicySigsysAuxData; | 93 static int BlacklistNanosleepPolicySigsysAuxData; |
94 | 94 |
95 intptr_t EnomemHandler(const struct arch_seccomp_data& args, void *aux) { | 95 intptr_t EnomemHandler(const struct arch_seccomp_data& args, void *aux) { |
96 // We also check that the auxiliary data is correct | 96 // We also check that the auxiliary data is correct |
97 SANDBOX_ASSERT(aux); | 97 SANDBOX_ASSERT(aux); |
98 *(static_cast<int*>(aux)) = kExpectedReturnValue; | 98 *(static_cast<int*>(aux)) = kExpectedReturnValue; |
99 return -ENOMEM; | 99 return -ENOMEM; |
100 } | 100 } |
101 | 101 |
102 ErrorCode BlacklistNanosleepPolicySigsys(int sysno) { | 102 ErrorCode BlacklistNanosleepPolicySigsys(int sysno) { |
103 if (sysno < static_cast<int>(MIN_SYSCALL) || | 103 if (!Sandbox::isValidSyscallNumber(sysno)) { |
104 sysno > static_cast<int>(MAX_SYSCALL)) { | |
105 // FIXME: we should really not have to do that in a trivial policy | 104 // FIXME: we should really not have to do that in a trivial policy |
106 return ErrorCode(ENOSYS); | 105 return ErrorCode(ENOSYS); |
107 } | 106 } |
107 | |
108 switch (sysno) { | 108 switch (sysno) { |
109 case __NR_nanosleep: | 109 case __NR_nanosleep: |
110 return Sandbox::Trap(EnomemHandler, | 110 return Sandbox::Trap(EnomemHandler, |
111 static_cast<void *>(&BlacklistNanosleepPolicySigsysAuxData)); | 111 static_cast<void *>(&BlacklistNanosleepPolicySigsysAuxData)); |
112 default: | 112 default: |
113 return ErrorCode(ErrorCode::ERR_ALLOWED); | 113 return ErrorCode(ErrorCode::ERR_ALLOWED); |
114 } | 114 } |
115 } | 115 } |
116 | 116 |
117 BPF_TEST(SandboxBpf, BasicBlacklistWithSigsys, | 117 BPF_TEST(SandboxBpf, BasicBlacklistWithSigsys, |
(...skipping 23 matching lines...) Expand all Loading... | |
141 // sure that the compiler can have an opportunity to coalesce syscalls with | 141 // sure that the compiler can have an opportunity to coalesce syscalls with |
142 // contiguous numbers and we also make sure that disjoint sets can return the | 142 // contiguous numbers and we also make sure that disjoint sets can return the |
143 // same errno. | 143 // same errno. |
144 int SysnoToRandomErrno(int sysno) { | 144 int SysnoToRandomErrno(int sysno) { |
145 // Small contiguous sets of 3 system calls return an errno equal to the | 145 // Small contiguous sets of 3 system calls return an errno equal to the |
146 // index of that set + 1 (so that we never return a NUL errno). | 146 // index of that set + 1 (so that we never return a NUL errno). |
147 return ((sysno & ~3) >> 2) % 29 + 1; | 147 return ((sysno & ~3) >> 2) % 29 + 1; |
148 } | 148 } |
149 | 149 |
150 ErrorCode SyntheticPolicy(int sysno) { | 150 ErrorCode SyntheticPolicy(int sysno) { |
151 if (sysno < static_cast<int>(MIN_SYSCALL) || | 151 if (!Sandbox::isValidSyscallNumber(sysno)) { |
152 sysno > static_cast<int>(MAX_SYSCALL)) { | 152 // FIXME: we should really not have to do that in a trivial policy |
153 // FIXME: we should really not have to do that in a trivial policy. | |
154 return ErrorCode(ENOSYS); | 153 return ErrorCode(ENOSYS); |
155 } | 154 } |
156 | 155 |
157 // TODO(jorgelo): remove this restriction once crbug.com/141694 is fixed. | 156 // TODO(jorgelo): remove this once the new code generator lands. |
158 #if defined(__arm__) | 157 #if defined(__arm__) |
159 if (sysno > kArmPublicSysnoCeiling) | 158 if (sysno > static_cast<int>(MAX_PUBLIC_SYSCALL)) { |
160 return ErrorCode(ENOSYS); | 159 return ErrorCode(ENOSYS); |
160 } | |
161 #endif | 161 #endif |
162 | 162 |
163 // TODO(markus): allow calls to write(). This should start working as soon | 163 // TODO(markus): allow calls to write(). This should start working as soon |
164 // as we switch to the new code generator. Currently we are blowing up, | 164 // as we switch to the new code generator. Currently we are blowing up, |
165 // because our jumptable is getting too big. | 165 // because our jumptable is getting too big. |
166 if (sysno == __NR_exit_group /* || sysno == __NR_write */) { | 166 if (sysno == __NR_exit_group /* || sysno == __NR_write */) { |
167 // exit_group() is special, we really need it to work. | 167 // exit_group() is special, we really need it to work. |
168 // write() is needed for BPF_ASSERT() to report a useful error message. | 168 // write() is needed for BPF_ASSERT() to report a useful error message. |
169 return ErrorCode(ErrorCode::ERR_ALLOWED); | 169 return ErrorCode(ErrorCode::ERR_ALLOWED); |
170 } else { | 170 } else { |
171 return ErrorCode(SysnoToRandomErrno(sysno)); | 171 return ErrorCode(SysnoToRandomErrno(sysno)); |
172 } | 172 } |
173 } | 173 } |
174 | 174 |
175 BPF_TEST(SandboxBpf, SyntheticPolicy, SyntheticPolicy) { | 175 BPF_TEST(SandboxBpf, SyntheticPolicy, SyntheticPolicy) { |
176 // Ensure that that kExpectedReturnValue + syscallnumber + 1 does not int | 176 // Ensure that that kExpectedReturnValue + syscallnumber + 1 does not int |
177 // overflow. | 177 // overflow. |
178 BPF_ASSERT( | 178 BPF_ASSERT( |
179 std::numeric_limits<int>::max() - kExpectedReturnValue - 1 >= | 179 std::numeric_limits<int>::max() - kExpectedReturnValue - 1 >= |
180 static_cast<int>(MAX_SYSCALL)); | 180 static_cast<int>(MAX_PUBLIC_SYSCALL)); |
181 | |
182 // TODO(jorgelo): remove this limit once crbug.com/141694 is fixed. | |
183 #if defined(__arm__) | |
184 const int sysno_ceiling = kArmPublicSysnoCeiling; | |
185 #else | |
186 const int sysno_ceiling = static_cast<int>(MAX_SYSCALL); | |
187 #endif | |
188 | 181 |
189 for (int syscall_number = static_cast<int>(MIN_SYSCALL); | 182 for (int syscall_number = static_cast<int>(MIN_SYSCALL); |
190 syscall_number <= sysno_ceiling; | 183 syscall_number <= static_cast<int>(MAX_PUBLIC_SYSCALL); |
191 ++syscall_number) { | 184 ++syscall_number) { |
192 if (syscall_number == __NR_exit_group || | 185 if (syscall_number == __NR_exit_group || |
193 syscall_number == __NR_write) { | 186 syscall_number == __NR_write) { |
194 // exit_group() is special | 187 // exit_group() is special |
195 continue; | 188 continue; |
196 } | 189 } |
197 errno = 0; | 190 errno = 0; |
198 BPF_ASSERT(syscall(syscall_number) == -1); | 191 BPF_ASSERT(syscall(syscall_number) == -1); |
199 BPF_ASSERT(errno == SysnoToRandomErrno(syscall_number)); | 192 BPF_ASSERT(errno == SysnoToRandomErrno(syscall_number)); |
200 } | 193 } |
201 } | 194 } |
202 | 195 |
196 #if defined(__arm__) | |
197 // A simple policy that tests whether ARM private system calls are supported | |
198 // by our BPF compiler and by the BPF interpreter in the kernel. | |
199 | |
200 // For ARM private system calls, return an errno equal to their offset from | |
201 // __ARM_NR_BASE plus 1 (to avoid NUL errno). | |
jln (very slow on Chromium)
2012/10/12 20:26:52
You mean offset from MIN_PRIVATE_SYSCALL, no ?
Jorge Lucangeli Obes
2012/10/13 01:39:30
It's the same thing:
#define MIN_PRIVATE_SYSCALL (
| |
202 int ArmPrivateSysnoToErrno(int sysno) { | |
203 if (sysno >= static_cast<int>(MIN_PRIVATE_SYSCALL) && | |
204 sysno <= static_cast<int>(MAX_PRIVATE_SYSCALL)) { | |
205 return (sysno - MIN_PRIVATE_SYSCALL) + 1; | |
206 } else { | |
207 return ENOSYS; | |
208 } | |
209 } | |
210 | |
211 ErrorCode ArmPrivatePolicy(int sysno) { | |
jln (very slow on Chromium)
2012/10/12 20:26:52
I'm a bit worried that this wouldn't be a viable p
Jorge Lucangeli Obes
2012/10/13 01:39:30
Done.
| |
212 if (!Sandbox::isValidSyscallNumber(sysno)) { | |
213 // FIXME: we should really not have to do that in a trivial policy. | |
214 return ErrorCode(ENOSYS); | |
215 } | |
216 | |
217 if (sysno >= static_cast<int>(MIN_PRIVATE_SYSCALL) && | |
218 sysno <= static_cast<int>(MAX_PRIVATE_SYSCALL)) { | |
219 return ErrorCode(ArmPrivateSysnoToErrno(sysno)); | |
220 } else { | |
221 return ErrorCode(ErrorCode::ERR_ALLOWED); | |
222 } | |
223 } | |
224 | |
225 BPF_TEST(SandboxBpf, ArmPrivatePolicy, ArmPrivatePolicy) { | |
226 for (int syscall_number = static_cast<int>(MIN_PRIVATE_SYSCALL); | |
227 syscall_number <= static_cast<int>(MAX_PRIVATE_SYSCALL); | |
228 ++syscall_number) { | |
229 errno = 0; | |
230 BPF_ASSERT(syscall(syscall_number) == -1); | |
231 BPF_ASSERT(errno == ArmPrivateSysnoToErrno(syscall_number)); | |
232 } | |
233 } | |
234 #endif // defined(__arm__) | |
235 | |
203 } // namespace | 236 } // namespace |
OLD | NEW |