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

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

Powered by Google App Engine
This is Rietveld 408576698