Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(821)

Side by Side Diff: sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc

Issue 11096012: Add a platform-specific syscall number iterator. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Fixed upload. Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698