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 #ifndef SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ | 5 #ifndef SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ |
6 #define SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ | 6 #define SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ |
7 | 7 |
8 #include <endian.h> | 8 #include <endian.h> |
9 #include <errno.h> | 9 #include <errno.h> |
10 #include <fcntl.h> | 10 #include <fcntl.h> |
(...skipping 19 matching lines...) Expand all Loading... | |
30 #include <sys/stat.h> | 30 #include <sys/stat.h> |
31 #include <sys/types.h> | 31 #include <sys/types.h> |
32 #include <sys/uio.h> | 32 #include <sys/uio.h> |
33 #include <sys/wait.h> | 33 #include <sys/wait.h> |
34 #include <time.h> | 34 #include <time.h> |
35 #include <unistd.h> | 35 #include <unistd.h> |
36 | 36 |
37 #include <algorithm> | 37 #include <algorithm> |
38 #include <limits> | 38 #include <limits> |
39 #include <map> | 39 #include <map> |
40 #include <set> | |
40 #include <utility> | 41 #include <utility> |
41 #include <vector> | 42 #include <vector> |
42 | 43 |
43 #ifndef SECCOMP_BPF_STANDALONE | 44 #if !defined(SECCOMP_BPF_STANDALONE) |
44 #include "base/basictypes.h" | 45 #include "base/basictypes.h" |
45 #include "base/logging.h" | 46 #include "base/logging.h" |
46 #include "base/posix/eintr_wrapper.h" | 47 #include "base/posix/eintr_wrapper.h" |
47 #endif | 48 #endif |
48 | 49 |
49 #if defined(SECCOMP_BPF_VALGRIND_HACKS) | 50 #if defined(SECCOMP_BPF_VALGRIND_HACKS) |
50 #ifndef SECCOMP_BPF_STANDALONE | 51 #if !defined(SECCOMP_BPF_STANDALONE) |
51 #include "base/third_party/valgrind/valgrind.h" | 52 #include "base/third_party/valgrind/valgrind.h" |
52 #endif | 53 #endif |
53 #endif | 54 #endif |
54 | 55 |
55 | 56 |
56 // The Seccomp2 kernel ABI is not part of older versions of glibc. | 57 // The Seccomp2 kernel ABI is not part of older versions of glibc. |
57 // As we can't break compilation with these versions of the library, | 58 // As we can't break compilation with these versions of the library, |
58 // we explicitly define all missing symbols. | 59 // we explicitly define all missing symbols. |
59 | 60 |
60 #ifndef PR_SET_NO_NEW_PRIVS | 61 #ifndef PR_SET_NO_NEW_PRIVS |
61 #define PR_SET_NO_NEW_PRIVS 38 | 62 #define PR_SET_NO_NEW_PRIVS 38 |
62 #define PR_GET_NO_NEW_PRIVS 39 | 63 #define PR_GET_NO_NEW_PRIVS 39 |
63 #endif | 64 #endif |
64 #ifndef IPC_64 | 65 #ifndef IPC_64 |
65 #define IPC_64 0x0100 | 66 #define IPC_64 0x0100 |
66 #endif | 67 #endif |
68 | |
69 // In order to build will older tool chains, we currently have to avoid | |
70 // including <linux/seccomp.h>. Until that can be fixed (if ever). Rely on | |
71 // our own definitions of the seccomp kernel ABI. | |
67 #ifndef SECCOMP_MODE_FILTER | 72 #ifndef SECCOMP_MODE_FILTER |
68 #define SECCOMP_MODE_DISABLED 0 | 73 #define SECCOMP_MODE_DISABLED 0 |
69 #define SECCOMP_MODE_STRICT 1 | 74 #define SECCOMP_MODE_STRICT 1 |
70 #define SECCOMP_MODE_FILTER 2 // User user-supplied filter | 75 #define SECCOMP_MODE_FILTER 2 // User user-supplied filter |
76 #endif | |
77 | |
78 #ifndef SECCOMP_RET_KILL | |
79 // Return values supported for BPF filter programs. Please note that the | |
80 // "illegal" SECCOMP_RET_INVALID is not supported by the kernel, should only | |
81 // ever be used internally, and would result in the kernel killing our process. | |
71 #define SECCOMP_RET_KILL 0x00000000U // Kill the task immediately | 82 #define SECCOMP_RET_KILL 0x00000000U // Kill the task immediately |
83 #define SECCOMP_RET_INVALID 0x00010000U // Illegal return value | |
72 #define SECCOMP_RET_TRAP 0x00030000U // Disallow and force a SIGSYS | 84 #define SECCOMP_RET_TRAP 0x00030000U // Disallow and force a SIGSYS |
73 #define SECCOMP_RET_ERRNO 0x00050000U // Returns an errno | 85 #define SECCOMP_RET_ERRNO 0x00050000U // Returns an errno |
74 #define SECCOMP_RET_TRACE 0x7ff00000U // Pass to a tracer or disallow | 86 #define SECCOMP_RET_TRACE 0x7ff00000U // Pass to a tracer or disallow |
75 #define SECCOMP_RET_ALLOW 0x7fff0000U // Allow | 87 #define SECCOMP_RET_ALLOW 0x7fff0000U // Allow |
76 #define SECCOMP_RET_INVALID 0x8f8f8f8fU // Illegal return value | |
77 #define SECCOMP_RET_ACTION 0xffff0000U // Masks for the return value | 88 #define SECCOMP_RET_ACTION 0xffff0000U // Masks for the return value |
78 #define SECCOMP_RET_DATA 0x0000ffffU // sections | 89 #define SECCOMP_RET_DATA 0x0000ffffU // sections |
90 #else | |
91 #define SECCOMP_RET_INVALID 0x00010000U // Illegal return value | |
79 #endif | 92 #endif |
80 #define SECCOMP_DENY_ERRNO EPERM | 93 |
81 #ifndef SYS_SECCOMP | 94 #ifndef SYS_SECCOMP |
82 #define SYS_SECCOMP 1 | 95 #define SYS_SECCOMP 1 |
83 #endif | 96 #endif |
84 | 97 |
85 // Impose some reasonable maximum BPF program size. Realistically, the | 98 // Impose some reasonable maximum BPF program size. Realistically, the |
86 // kernel probably has much lower limits. But by limiting to less than | 99 // kernel probably has much lower limits. But by limiting to less than |
87 // 30 bits, we can ease requirements on some of our data types. | 100 // 30 bits, we can ease requirements on some of our data types. |
88 #define SECCOMP_MAX_PROGRAM_SIZE (1<<30) | 101 #define SECCOMP_MAX_PROGRAM_SIZE (1<<30) |
89 | 102 |
90 #if defined(__i386__) | 103 #if defined(__i386__) |
91 #define MIN_SYSCALL 0u | 104 #define MIN_SYSCALL 0u |
92 #define MAX_PUBLIC_SYSCALL 1024u | 105 #define MAX_PUBLIC_SYSCALL 1024u |
93 #define MAX_SYSCALL MAX_PUBLIC_SYSCALL | 106 #define MAX_SYSCALL MAX_PUBLIC_SYSCALL |
94 #define SECCOMP_ARCH AUDIT_ARCH_I386 | 107 #define SECCOMP_ARCH AUDIT_ARCH_I386 |
95 | 108 |
96 #define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.gregs[(_reg)]) | 109 #define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.gregs[(_reg)]) |
97 #define SECCOMP_RESULT(_ctx) SECCOMP_REG(_ctx, REG_EAX) | 110 #define SECCOMP_RESULT(_ctx) SECCOMP_REG(_ctx, REG_EAX) |
98 #define SECCOMP_SYSCALL(_ctx) SECCOMP_REG(_ctx, REG_EAX) | 111 #define SECCOMP_SYSCALL(_ctx) SECCOMP_REG(_ctx, REG_EAX) |
99 #define SECCOMP_IP(_ctx) SECCOMP_REG(_ctx, REG_EIP) | 112 #define SECCOMP_IP(_ctx) SECCOMP_REG(_ctx, REG_EIP) |
100 #define SECCOMP_PARM1(_ctx) SECCOMP_REG(_ctx, REG_EBX) | 113 #define SECCOMP_PARM1(_ctx) SECCOMP_REG(_ctx, REG_EBX) |
101 #define SECCOMP_PARM2(_ctx) SECCOMP_REG(_ctx, REG_ECX) | 114 #define SECCOMP_PARM2(_ctx) SECCOMP_REG(_ctx, REG_ECX) |
102 #define SECCOMP_PARM3(_ctx) SECCOMP_REG(_ctx, REG_EDX) | 115 #define SECCOMP_PARM3(_ctx) SECCOMP_REG(_ctx, REG_EDX) |
103 #define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, REG_ESI) | 116 #define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, REG_ESI) |
104 #define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, REG_EDI) | 117 #define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, REG_EDI) |
105 #define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, REG_EBP) | 118 #define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, REG_EBP) |
119 #define SECCOMP_NR_IDX (offsetof(struct arch_seccomp_data, nr)) | |
120 #define SECCOMP_ARCH_IDX (offsetof(struct arch_seccomp_data, arch)) | |
121 #define SECCOMP_IP_MSB_IDX (offsetof(struct arch_seccomp_data, \ | |
122 instruction_pointer) + 4) | |
123 #define SECCOMP_IP_LSB_IDX (offsetof(struct arch_seccomp_data, \ | |
124 instruction_pointer) + 0) | |
125 #define SECCOMP_ARG_MSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ | |
126 8*(nr) + 4) | |
127 #define SECCOMP_ARG_LSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ | |
128 8*(nr) + 0) | |
106 | 129 |
107 #elif defined(__x86_64__) | 130 #elif defined(__x86_64__) |
108 #define MIN_SYSCALL 0u | 131 #define MIN_SYSCALL 0u |
109 #define MAX_PUBLIC_SYSCALL 1024u | 132 #define MAX_PUBLIC_SYSCALL 1024u |
110 #define MAX_SYSCALL MAX_PUBLIC_SYSCALL | 133 #define MAX_SYSCALL MAX_PUBLIC_SYSCALL |
111 #define SECCOMP_ARCH AUDIT_ARCH_X86_64 | 134 #define SECCOMP_ARCH AUDIT_ARCH_X86_64 |
112 | 135 |
113 #define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.gregs[(_reg)]) | 136 #define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.gregs[(_reg)]) |
114 #define SECCOMP_RESULT(_ctx) SECCOMP_REG(_ctx, REG_RAX) | 137 #define SECCOMP_RESULT(_ctx) SECCOMP_REG(_ctx, REG_RAX) |
115 #define SECCOMP_SYSCALL(_ctx) SECCOMP_REG(_ctx, REG_RAX) | 138 #define SECCOMP_SYSCALL(_ctx) SECCOMP_REG(_ctx, REG_RAX) |
116 #define SECCOMP_IP(_ctx) SECCOMP_REG(_ctx, REG_RIP) | 139 #define SECCOMP_IP(_ctx) SECCOMP_REG(_ctx, REG_RIP) |
117 #define SECCOMP_PARM1(_ctx) SECCOMP_REG(_ctx, REG_RDI) | 140 #define SECCOMP_PARM1(_ctx) SECCOMP_REG(_ctx, REG_RDI) |
118 #define SECCOMP_PARM2(_ctx) SECCOMP_REG(_ctx, REG_RSI) | 141 #define SECCOMP_PARM2(_ctx) SECCOMP_REG(_ctx, REG_RSI) |
119 #define SECCOMP_PARM3(_ctx) SECCOMP_REG(_ctx, REG_RDX) | 142 #define SECCOMP_PARM3(_ctx) SECCOMP_REG(_ctx, REG_RDX) |
120 #define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, REG_R10) | 143 #define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, REG_R10) |
121 #define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, REG_R8) | 144 #define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, REG_R8) |
122 #define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, REG_R9) | 145 #define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, REG_R9) |
146 #define SECCOMP_NR_IDX (offsetof(struct arch_seccomp_data, nr)) | |
147 #define SECCOMP_ARCH_IDX (offsetof(struct arch_seccomp_data, arch)) | |
148 #define SECCOMP_IP_MSB_IDX (offsetof(struct arch_seccomp_data, \ | |
149 instruction_pointer) + 4) | |
150 #define SECCOMP_IP_LSB_IDX (offsetof(struct arch_seccomp_data, \ | |
151 instruction_pointer) + 0) | |
152 #define SECCOMP_ARG_MSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ | |
153 8*(nr) + 4) | |
154 #define SECCOMP_ARG_LSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ | |
155 8*(nr) + 0) | |
123 | 156 |
124 #elif defined(__arm__) && (defined(__thumb__) || defined(__ARM_EABI__)) | 157 #elif defined(__arm__) && (defined(__thumb__) || defined(__ARM_EABI__)) |
125 // ARM EABI includes "ARM private" system calls starting at |__ARM_NR_BASE|, | 158 // ARM EABI includes "ARM private" system calls starting at |__ARM_NR_BASE|, |
126 // and a "ghost syscall private to the kernel", cmpxchg, | 159 // and a "ghost syscall private to the kernel", cmpxchg, |
127 // at |__ARM_NR_BASE+0x00fff0|. | 160 // at |__ARM_NR_BASE+0x00fff0|. |
128 // See </arch/arm/include/asm/unistd.h> in the Linux kernel. | 161 // See </arch/arm/include/asm/unistd.h> in the Linux kernel. |
129 #define MIN_SYSCALL ((unsigned int)__NR_SYSCALL_BASE) | 162 #define MIN_SYSCALL ((unsigned int)__NR_SYSCALL_BASE) |
130 #define MAX_PUBLIC_SYSCALL (MIN_SYSCALL + 1024u) | 163 #define MAX_PUBLIC_SYSCALL (MIN_SYSCALL + 1024u) |
131 #define MIN_PRIVATE_SYSCALL ((unsigned int)__ARM_NR_BASE) | 164 #define MIN_PRIVATE_SYSCALL ((unsigned int)__ARM_NR_BASE) |
132 #define MAX_PRIVATE_SYSCALL (MIN_PRIVATE_SYSCALL + 16u) | 165 #define MAX_PRIVATE_SYSCALL (MIN_PRIVATE_SYSCALL + 16u) |
133 #define MIN_GHOST_SYSCALL ((unsigned int)__ARM_NR_BASE + 0xfff0u) | 166 #define MIN_GHOST_SYSCALL ((unsigned int)__ARM_NR_BASE + 0xfff0u) |
134 #define MAX_SYSCALL (MIN_GHOST_SYSCALL + 4u) | 167 #define MAX_SYSCALL (MIN_GHOST_SYSCALL + 4u) |
135 // <linux/audit.h> includes <linux/elf-em.h>, which does not define EM_ARM. | 168 // <linux/audit.h> includes <linux/elf-em.h>, which does not define EM_ARM. |
136 // <linux/elf.h> only includes <asm/elf.h> if we're in the kernel. | 169 // <linux/elf.h> only includes <asm/elf.h> if we're in the kernel. |
137 # if !defined(EM_ARM) | 170 # if !defined(EM_ARM) |
138 # define EM_ARM 40 | 171 # define EM_ARM 40 |
139 # endif | 172 # endif |
140 #define SECCOMP_ARCH AUDIT_ARCH_ARM | 173 #define SECCOMP_ARCH AUDIT_ARCH_ARM |
141 | 174 |
142 // ARM sigcontext_t is different from i386/x86_64. | 175 // ARM sigcontext_t is different from i386/x86_64. |
143 // See </arch/arm/include/asm/sigcontext.h> in the Linux kernel. | 176 // See </arch/arm/include/asm/sigcontext.h> in the Linux kernel. |
144 #define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.arm_##_reg) | 177 #define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.arm_##_reg) |
145 // ARM EABI syscall convention. | 178 // ARM EABI syscall convention. |
146 #define SECCOMP_RESULT(_ctx) SECCOMP_REG(_ctx, r0) | 179 #define SECCOMP_RESULT(_ctx) SECCOMP_REG(_ctx, r0) |
147 #define SECCOMP_SYSCALL(_ctx) SECCOMP_REG(_ctx, r7) | 180 #define SECCOMP_SYSCALL(_ctx) SECCOMP_REG(_ctx, r7) |
148 #define SECCOMP_IP(_ctx) SECCOMP_REG(_ctx, pc) | 181 #define SECCOMP_IP(_ctx) SECCOMP_REG(_ctx, pc) |
149 #define SECCOMP_PARM1(_ctx) SECCOMP_REG(_ctx, r0) | 182 #define SECCOMP_PARM1(_ctx) SECCOMP_REG(_ctx, r0) |
150 #define SECCOMP_PARM2(_ctx) SECCOMP_REG(_ctx, r1) | 183 #define SECCOMP_PARM2(_ctx) SECCOMP_REG(_ctx, r1) |
151 #define SECCOMP_PARM3(_ctx) SECCOMP_REG(_ctx, r2) | 184 #define SECCOMP_PARM3(_ctx) SECCOMP_REG(_ctx, r2) |
152 #define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, r3) | 185 #define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, r3) |
153 #define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, r4) | 186 #define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, r4) |
154 #define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, r5) | 187 #define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, r5) |
188 #define SECCOMP_NR_IDX (offsetof(struct arch_seccomp_data, nr)) | |
189 #define SECCOMP_ARCH_IDX (offsetof(struct arch_seccomp_data, arch)) | |
190 #define SECCOMP_IP_MSB_IDX (offsetof(struct arch_seccomp_data, \ | |
191 instruction_pointer) + 4) | |
192 #define SECCOMP_IP_LSB_IDX (offsetof(struct arch_seccomp_data, \ | |
193 instruction_pointer) + 0) | |
194 #define SECCOMP_ARG_MSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ | |
195 8*(nr) + 4) | |
196 #define SECCOMP_ARG_LSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ | |
197 8*(nr) + 0) | |
155 | 198 |
156 #else | 199 #else |
157 #error Unsupported target platform | 200 #error Unsupported target platform |
158 | 201 |
159 #endif | 202 #endif |
160 | 203 |
161 #if defined(SECCOMP_BPF_STANDALONE) | 204 #if defined(SECCOMP_BPF_STANDALONE) |
162 #define arraysize(x) (sizeof(x)/sizeof(*(x))) | 205 #define arraysize(x) (sizeof(x)/sizeof(*(x))) |
163 #define HANDLE_EINTR TEMP_FAILURE_RETRY | 206 #define HANDLE_EINTR TEMP_FAILURE_RETRY |
164 #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ | 207 #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
213 // Please note that TrapFnc is executed from signal context and must be | 256 // Please note that TrapFnc is executed from signal context and must be |
214 // async-signal safe: | 257 // async-signal safe: |
215 // http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html | 258 // http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html |
216 // Also note that it follows the calling convention of native system calls. | 259 // Also note that it follows the calling convention of native system calls. |
217 // In other words, it reports an error by returning an exit code in the | 260 // In other words, it reports an error by returning an exit code in the |
218 // range -1..-4096. It should not set errno when reporting errors; on the | 261 // range -1..-4096. It should not set errno when reporting errors; on the |
219 // other hand, accidentally modifying errno is harmless and the changes will | 262 // other hand, accidentally modifying errno is harmless and the changes will |
220 // be undone afterwards. | 263 // be undone afterwards. |
221 typedef intptr_t (*TrapFnc)(const struct arch_seccomp_data& args, void *aux); | 264 typedef intptr_t (*TrapFnc)(const struct arch_seccomp_data& args, void *aux); |
222 | 265 |
223 enum Operation { | |
224 OP_NOP, OP_EQUAL, OP_NOTEQUAL, OP_LESS, | |
225 OP_LESS_EQUAL, OP_GREATER, OP_GREATER_EQUAL, | |
226 OP_HAS_BITS, OP_DOES_NOT_HAVE_BITS | |
227 }; | |
228 | |
229 struct Constraint { | |
230 bool is32bit; | |
231 Operation op; | |
232 uint32_t value; | |
233 ErrorCode passed; | |
234 ErrorCode failed; | |
235 }; | |
236 | |
237 // When calling setSandboxPolicy(), the caller can provide an arbitrary | 266 // When calling setSandboxPolicy(), the caller can provide an arbitrary |
238 // pointer. This pointer will then be forwarded to the sandbox policy | 267 // pointer. This pointer will then be forwarded to the sandbox policy |
239 // each time a call is made through an EvaluateSyscall function pointer. | 268 // each time a call is made through an EvaluateSyscall function pointer. |
240 // One common use case would be to pass the "aux" pointer as an argument | 269 // One common use case would be to pass the "aux" pointer as an argument |
241 // to Trap() functions. | 270 // to Trap() functions. |
242 typedef ErrorCode (*EvaluateSyscall)(int sysnum, void *aux); | 271 typedef ErrorCode (*EvaluateSyscall)(int sysnum, void *aux); |
243 typedef std::vector<std::pair<EvaluateSyscall, void *> >Evaluators; | 272 typedef std::vector<std::pair<EvaluateSyscall, void *> >Evaluators; |
244 | 273 |
245 // Checks whether a particular system call number is valid on the current | 274 // Checks whether a particular system call number is valid on the current |
246 // architecture. E.g. on ARM there's a non-contiguous range of private | 275 // architecture. E.g. on ARM there's a non-contiguous range of private |
247 // system calls. | 276 // system calls. |
248 static bool isValidSyscallNumber(int sysnum); | 277 static bool IsValidSyscallNumber(int sysnum); |
249 | 278 |
250 // There are a lot of reasons why the Seccomp sandbox might not be available. | 279 // There are a lot of reasons why the Seccomp sandbox might not be available. |
251 // This could be because the kernel does not support Seccomp mode, or it | 280 // This could be because the kernel does not support Seccomp mode, or it |
252 // could be because another sandbox is already active. | 281 // could be because another sandbox is already active. |
253 // "proc_fd" should be a file descriptor for "/proc", or -1 if not | 282 // "proc_fd" should be a file descriptor for "/proc", or -1 if not |
254 // provided by the caller. | 283 // provided by the caller. |
255 static SandboxStatus supportsSeccompSandbox(int proc_fd); | 284 static SandboxStatus SupportsSeccompSandbox(int proc_fd); |
256 | 285 |
257 // The sandbox needs to be able to access files in "/proc/self". If this | 286 // The sandbox needs to be able to access files in "/proc/self". If this |
258 // directory is not accessible when "startSandbox()" gets called, the caller | 287 // directory is not accessible when "startSandbox()" gets called, the caller |
259 // can provide an already opened file descriptor by calling "setProcFd()". | 288 // can provide an already opened file descriptor by calling "setProcFd()". |
260 // The sandbox becomes the new owner of this file descriptor and will | 289 // The sandbox becomes the new owner of this file descriptor and will |
261 // eventually close it when "startSandbox()" executes. | 290 // eventually close it when "startSandbox()" executes. |
262 static void setProcFd(int proc_fd); | 291 static void SetProcFd(int proc_fd); |
263 | 292 |
264 // The system call evaluator function is called with the system | 293 // The system call evaluator function is called with the system |
265 // call number. It can decide to allow the system call unconditionally | 294 // call number. It can decide to allow the system call unconditionally |
266 // by returning ERR_ALLOWED; it can deny the system call unconditionally by | 295 // by returning ERR_ALLOWED; it can deny the system call unconditionally by |
267 // returning an appropriate "errno" value; or it can request inspection | 296 // returning an appropriate "errno" value; or it can request inspection |
268 // of system call argument(s) by returning a suitable ErrorCode. | 297 // of system call argument(s) by returning a suitable ErrorCode. |
269 // The "aux" parameter can be used to pass optional data to the system call | 298 // The "aux" parameter can be used to pass optional data to the system call |
270 // evaluator. There are different possible uses for this data, but one of the | 299 // evaluator. There are different possible uses for this data, but one of the |
271 // use cases would be for the policy to then forward this pointer to a Trap() | 300 // use cases would be for the policy to then forward this pointer to a Trap() |
272 // handler. In this case, of course, the data that is pointed to must remain | 301 // handler. In this case, of course, the data that is pointed to must remain |
273 // valid for the entire time that Trap() handlers can be called; typically, | 302 // valid for the entire time that Trap() handlers can be called; typically, |
274 // this would be the lifetime of the program. | 303 // this would be the lifetime of the program. |
275 static void setSandboxPolicy(EvaluateSyscall syscallEvaluator, void *aux); | 304 static void SetSandboxPolicy(EvaluateSyscall syscallEvaluator, void *aux); |
276 | 305 |
277 // We can use ErrorCode to request calling of a trap handler. This method | 306 // We can use ErrorCode to request calling of a trap handler. This method |
278 // performs the required wrapping of the callback function into an | 307 // performs the required wrapping of the callback function into an |
279 // ErrorCode object. | 308 // ErrorCode object. |
280 // The "aux" field can carry a pointer to arbitrary data. See EvaluateSyscall | 309 // The "aux" field can carry a pointer to arbitrary data. See EvaluateSyscall |
281 // for a description of how to pass data from setSandboxPolicy() to a Trap() | 310 // for a description of how to pass data from setSandboxPolicy() to a Trap() |
282 // handler. | 311 // handler. |
283 static ErrorCode Trap(ErrorCode::TrapFnc fnc, const void *aux); | 312 static ErrorCode Trap(ErrorCode::TrapFnc fnc, const void *aux); |
284 | 313 |
285 // Calls a user-space trap handler and disables all sandboxing for system | 314 // Calls a user-space trap handler and disables all sandboxing for system |
286 // calls made from this trap handler. | 315 // calls made from this trap handler. |
287 // NOTE: This feature, by definition, disables all security features of | 316 // NOTE: This feature, by definition, disables all security features of |
288 // the sandbox. It should never be used in production, but it can be | 317 // the sandbox. It should never be used in production, but it can be |
289 // very useful to diagnose code that is incompatible with the sandbox. | 318 // very useful to diagnose code that is incompatible with the sandbox. |
290 // If even a single system call returns "UnsafeTrap", the security of | 319 // If even a single system call returns "UnsafeTrap", the security of |
291 // entire sandbox should be considered compromised. | 320 // entire sandbox should be considered compromised. |
292 static ErrorCode UnsafeTrap(ErrorCode::TrapFnc fnc, const void *aux); | 321 static ErrorCode UnsafeTrap(ErrorCode::TrapFnc fnc, const void *aux); |
293 | 322 |
294 // From within an UnsafeTrap() it is often useful to be able to execute | 323 // From within an UnsafeTrap() it is often useful to be able to execute |
295 // the system call that triggered the trap. The ForwardSyscall() method | 324 // the system call that triggered the trap. The ForwardSyscall() method |
296 // makes this easy. It is more efficient than calling glibc's syscall() | 325 // makes this easy. It is more efficient than calling glibc's syscall() |
297 // function, as it avoid the extra round-trip to the signal handler. And | 326 // function, as it avoid the extra round-trip to the signal handler. And |
298 // it automatically does the correct thing to report kernel-style error | 327 // it automatically does the correct thing to report kernel-style error |
299 // conditions, rather than setting errno. See the comments for TrapFnc for | 328 // conditions, rather than setting errno. See the comments for TrapFnc for |
300 // details. In other words, the return value from ForwardSyscall() is | 329 // details. In other words, the return value from ForwardSyscall() is |
301 // directly suitable as a return value for a trap handler. | 330 // directly suitable as a return value for a trap handler. |
302 static intptr_t ForwardSyscall(const struct arch_seccomp_data& args); | 331 static intptr_t ForwardSyscall(const struct arch_seccomp_data& args); |
303 | 332 |
333 // We can also use ErrorCode to request evaluation of a conditional | |
334 // statement based on inspection of system call parameters. | |
335 // This method wrap an ErrorCode object around the conditional statement. | |
336 // Argument "argno" (1..6) will be compared to "value" using comparator | |
337 // "op". If the condition is true "passed" will be returned, otherwise | |
338 // "failed". | |
339 // If "is32bit" is set, the argument must in the range of 0x0..(1u << 32 - 1) | |
340 // If it is outside this range, the sandbox treats the system call just | |
341 // the same as any other ABI violation (i.e. it aborts with an error | |
342 // message). | |
343 static ErrorCode Cond(int argno, ErrorCode::ArgType is_32bit, | |
344 ErrorCode::Operation op, | |
345 uint64_t value, const ErrorCode& passed, | |
346 const ErrorCode& failed); | |
347 | |
304 // Kill the program and print an error message. | 348 // Kill the program and print an error message. |
305 static ErrorCode Kill(const char *msg); | 349 static ErrorCode Kill(const char *msg); |
306 | 350 |
307 // This is the main public entry point. It finds all system calls that | 351 // This is the main public entry point. It finds all system calls that |
308 // need rewriting, sets up the resources needed by the sandbox, and | 352 // need rewriting, sets up the resources needed by the sandbox, and |
309 // enters Seccomp mode. | 353 // enters Seccomp mode. |
310 static void startSandbox() { startSandboxInternal(false); } | 354 static void StartSandbox() { StartSandboxInternal(false); } |
311 | 355 |
312 private: | 356 private: |
313 friend class ErrorCode; | |
314 friend class CodeGen; | 357 friend class CodeGen; |
315 friend class SandboxUnittestHelper; | 358 friend class SandboxUnittestHelper; |
359 friend class ErrorCode; | |
316 friend class Util; | 360 friend class Util; |
317 friend class Verifier; | 361 friend class Verifier; |
318 | 362 |
319 typedef std::vector<struct sock_filter> Program; | 363 typedef std::vector<struct sock_filter> Program; |
320 | 364 |
321 struct Range { | 365 struct Range { |
322 Range(uint32_t f, uint32_t t, const ErrorCode& e) | 366 Range(uint32_t f, uint32_t t, const ErrorCode& e) |
323 : from(f), | 367 : from(f), |
324 to(t), | 368 to(t), |
325 err(e) { | 369 err(e) { |
326 } | 370 } |
327 uint32_t from, to; | 371 uint32_t from, to; |
328 ErrorCode err; | 372 ErrorCode err; |
329 }; | 373 }; |
330 struct TrapKey { | 374 struct TrapKey { |
331 TrapKey(TrapFnc f, const void *a, bool s) | 375 TrapKey(TrapFnc f, const void *a, bool s) |
332 : fnc(f), | 376 : fnc(f), |
333 aux(a), | 377 aux(a), |
334 safe(s) { | 378 safe(s) { |
335 } | 379 } |
336 TrapFnc fnc; | 380 TrapFnc fnc; |
337 const void *aux; | 381 const void *aux; |
338 bool safe; | 382 bool safe; |
339 bool operator<(const TrapKey&) const; | 383 bool operator<(const TrapKey&) const; |
340 }; | 384 }; |
341 typedef std::vector<Range> Ranges; | 385 typedef std::vector<Range> Ranges; |
342 typedef std::map<uint32_t, ErrorCode> ErrMap; | 386 typedef std::map<uint32_t, ErrorCode> ErrMap; |
343 typedef std::vector<ErrorCode> Traps; | 387 typedef std::vector<ErrorCode> Traps; |
344 typedef std::map<TrapKey, uint16_t> TrapIds; | 388 typedef std::map<TrapKey, uint16_t> TrapIds; |
389 typedef std::set<ErrorCode, struct ErrorCode::LessThan> Conds; | |
345 | 390 |
346 // Get a file descriptor pointing to "/proc", if currently available. | 391 // Get a file descriptor pointing to "/proc", if currently available. |
347 static int proc_fd() { return proc_fd_; } | 392 static int ProcFd() { return proc_fd_; } |
jln (very slow on Chromium)
2012/12/14 02:28:02
Nit: for accessors, the correct is indeed proc_fd(
| |
348 | 393 |
349 static ErrorCode probeEvaluator(int sysnum, void *) __attribute__((const)); | 394 static ErrorCode ProbeEvaluator(int sysnum, void *) __attribute__((const)); |
350 static void probeProcess(void); | 395 static void ProbeProcess(void); |
351 static ErrorCode allowAllEvaluator(int sysnum, void *aux); | 396 static ErrorCode AllowAllEvaluator(int sysnum, void *aux); |
352 static void tryVsyscallProcess(void); | 397 static void TryVsyscallProcess(void); |
353 static bool kernelSupportSeccompBPF(int proc_fd); | 398 static bool KernelSupportSeccompBPF(int proc_fd); |
354 static bool RunFunctionInPolicy(void (*function)(), | 399 static bool RunFunctionInPolicy(void (*function)(), |
355 EvaluateSyscall syscallEvaluator, | 400 EvaluateSyscall syscall_evaluator, |
356 void *aux, | 401 void *aux, |
357 int proc_fd); | 402 int proc_fd); |
358 static void startSandboxInternal(bool quiet); | 403 static void StartSandboxInternal(bool quiet); |
359 static bool isSingleThreaded(int proc_fd); | 404 static bool IsSingleThreaded(int proc_fd); |
360 static bool isDenied(const ErrorCode& code); | 405 static bool IsDenied(const ErrorCode& code); |
361 static bool disableFilesystem(); | 406 static bool DisableFilesystem(); |
362 static void policySanityChecks(EvaluateSyscall syscallEvaluator, | 407 static void PolicySanityChecks(EvaluateSyscall syscall_evaluator, |
363 void *aux); | 408 void *aux); |
364 | 409 |
365 // Function that can be passed as a callback function to CodeGen::Traverse(). | 410 // Function that can be passed as a callback function to CodeGen::Traverse(). |
366 // Checks whether the "insn" returns an UnsafeTrap() ErrorCode. If so, it | 411 // Checks whether the "insn" returns an UnsafeTrap() ErrorCode. If so, it |
367 // sets the "bool" variable pointed to by "aux". | 412 // sets the "bool" variable pointed to by "aux". |
368 static void CheckForUnsafeErrorCodes(Instruction *insn, void *aux); | 413 static void CheckForUnsafeErrorCodes(Instruction *insn, void *aux); |
369 | 414 |
370 // Function that can be passed as a callback function to CodeGen::Traverse(). | 415 // Function that can be passed as a callback function to CodeGen::Traverse(). |
371 // Checks whether the "insn" returns an errno value from a BPF filter. If so, | 416 // Checks whether the "insn" returns an errno value from a BPF filter. If so, |
372 // it rewrites the instruction to instead call a Trap() handler that does | 417 // it rewrites the instruction to instead call a Trap() handler that does |
373 // the same thing. "aux" is ignored. | 418 // the same thing. "aux" is ignored. |
374 static void RedirectToUserspace(Instruction *insn, void *aux); | 419 static void RedirectToUserspace(Instruction *insn, void *aux); |
375 | 420 |
376 // Stackable wrapper around an Evaluators handler. Changes ErrorCodes | 421 // Stackable wrapper around an Evaluators handler. Changes ErrorCodes |
377 // returned by a system call evaluator to match the changes made by | 422 // returned by a system call evaluator to match the changes made by |
378 // RedirectToUserspace(). "aux" should be pointer to wrapped system call | 423 // RedirectToUserspace(). "aux" should be pointer to wrapped system call |
379 // evaluator. | 424 // evaluator. |
380 static ErrorCode RedirectToUserspaceEvalWrapper(int sysnum, void *aux); | 425 static ErrorCode RedirectToUserspaceEvalWrapper(int sysnum, void *aux); |
381 | 426 |
382 static void installFilter(bool quiet); | 427 static void InstallFilter(bool quiet); |
383 static void findRanges(Ranges *ranges); | 428 static void FindRanges(Ranges *ranges); |
384 static Instruction *assembleJumpTable(CodeGen *gen, | 429 static Instruction *AssembleJumpTable(CodeGen *gen, |
385 Ranges::const_iterator start, | 430 Ranges::const_iterator start, |
386 Ranges::const_iterator stop); | 431 Ranges::const_iterator stop); |
387 static void sigSys(int nr, siginfo_t *info, void *void_context); | 432 static Instruction *RetExpression(CodeGen *gen, const ErrorCode& cond); |
433 static Instruction *CondExpression(CodeGen *gen, const ErrorCode& cond); | |
434 | |
435 // Returns the fatal ErrorCode that is used to indicate that somebody | |
436 // attempted to pass a 64bit value in a 32bit system call argument. | |
437 static ErrorCode Unexpected64bitArgument(); | |
438 | |
439 static void SigSys(int nr, siginfo_t *info, void *void_context); | |
388 static ErrorCode MakeTrap(ErrorCode::TrapFnc fn, const void *aux, bool safe); | 440 static ErrorCode MakeTrap(ErrorCode::TrapFnc fn, const void *aux, bool safe); |
389 | 441 |
390 // A Trap() handler that returns an "errno" value. The value is encoded | 442 // A Trap() handler that returns an "errno" value. The value is encoded |
391 // in the "aux" parameter. | 443 // in the "aux" parameter. |
392 static intptr_t ReturnErrno(const struct arch_seccomp_data&, void *aux); | 444 static intptr_t ReturnErrno(const struct arch_seccomp_data&, void *aux); |
393 | 445 |
394 static intptr_t bpfFailure(const struct arch_seccomp_data& data, void *aux); | 446 static intptr_t BpfFailure(const struct arch_seccomp_data& data, void *aux); |
395 static int getTrapId(TrapFnc fnc, const void *aux); | |
396 | 447 |
397 static SandboxStatus status_; | 448 static SandboxStatus status_; |
398 static int proc_fd_; | 449 static int proc_fd_; |
399 static Evaluators evaluators_; | 450 static Evaluators evaluators_; |
400 static Traps *traps_; | 451 static Traps *traps_; |
401 static TrapIds trapIds_; | 452 static TrapIds trap_ids_; |
402 static ErrorCode *trapArray_; | 453 static ErrorCode *trap_array_; |
403 static size_t trapArraySize_; | 454 static size_t trap_array_size_; |
404 static bool has_unsafe_traps_; | 455 static bool has_unsafe_traps_; |
456 static Conds conds_; | |
457 | |
405 DISALLOW_IMPLICIT_CONSTRUCTORS(Sandbox); | 458 DISALLOW_IMPLICIT_CONSTRUCTORS(Sandbox); |
406 }; | 459 }; |
407 | 460 |
408 } // namespace | 461 } // namespace |
409 | 462 |
410 #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ | 463 #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ |
OLD | NEW |