|
OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef SANDBOX_BPF_H__ | |
6 #define SANDBOX_BPF_H__ | |
7 | |
8 #include <endian.h> | |
9 #include <errno.h> | |
10 #include <fcntl.h> | |
11 #include <linux/audit.h> | |
12 #include <linux/filter.h> | |
13 // #include <linux/seccomp.h> | |
Chris Evans
2012/06/01 20:07:55
Remove if it's dead code.
Markus (顧孟勤)
2012/06/01 21:38:52
It's not dead code. It just doesn't work correctly
| |
14 #include <linux/unistd.h> | |
15 #include <netinet/in.h> | |
16 #include <netinet/tcp.h> | |
17 #include <netinet/udp.h> | |
18 #include <sched.h> | |
19 #include <stddef.h> | |
20 #include <stdint.h> | |
21 #include <stdio.h> | |
22 #include <stdlib.h> | |
23 #include <string.h> | |
24 #include <sys/ioctl.h> | |
25 #include <sys/ipc.h> | |
26 #include <sys/mman.h> | |
27 #include <sys/prctl.h> | |
28 #include <sys/shm.h> | |
29 #include <sys/stat.h> | |
30 #include <sys/types.h> | |
31 #include <sys/uio.h> | |
32 #include <sys/wait.h> | |
33 #include <unistd.h> | |
34 | |
35 #include <algorithm> | |
36 #include <utility> | |
37 #include <vector> | |
38 | |
39 #ifndef SECCOMP_BPF_STANDALONE | |
40 #include "base/basictypes.h" | |
41 #include "base/eintr_wrapper.h" | |
42 #include "base/logging.h" | |
43 #endif | |
44 | |
45 // The Seccomp2 kernel ABI is not part of older versions of glibc. | |
46 // As we can't break compilation with these versions of the library, | |
47 // we explicitly define all missing symbols. | |
48 | |
49 #ifndef PR_SET_NO_NEW_PRIVS | |
50 #define PR_SET_NO_NEW_PRIVS 38 | |
51 #define PR_GET_NO_NEW_PRIVS 39 | |
52 #endif | |
53 #ifndef IPC_64 | |
54 #define IPC_64 0x0100 | |
55 #endif | |
56 #ifndef SECCOMP_MODE_FILTER | |
57 #define SECCOMP_MODE_DISABLED 0 | |
58 #define SECCOMP_MODE_STRICT 1 | |
59 #define SECCOMP_MODE_FILTER 2 // User user-supplied filter | |
60 #define SECCOMP_RET_KILL 0x00000000U // Kill the task immediately | |
61 #define SECCOMP_RET_TRAP 0x00030000U // Disallow and force a SIGSYS | |
62 #define SECCOMP_RET_ERRNO 0x00050000U // Returns an errno | |
63 #define SECCOMP_RET_TRACE 0x7ff00000U // Pass to a tracer or disallow | |
64 #define SECCOMP_RET_ALLOW 0x7fff0000U // Allow | |
65 #define SECCOMP_RET_ACTION 0xffff0000U // Masks for the return value | |
66 #define SECCOMP_RET_DATA 0x0000ffffU // sections | |
67 #endif | |
68 #define SECCOMP_RET_DENY (SECCOMP_RET_ERRNO|EPERM) | |
69 #ifndef SYS_SECCOMP | |
70 #define SYS_SECCOMP 1 | |
71 #endif | |
72 | |
73 #if defined(__i386__) | |
74 #define MIN_SYSCALL 0 | |
75 #define MAX_SYSCALL 512 | |
76 #define SECCOMP_ARCH AUDIT_ARCH_I386 | |
77 #define REG_RESULT REG_EAX | |
78 #define REG_SYSCALL REG_EAX | |
79 #define REG_PARM1 REG_EBX | |
80 #define REG_PARM2 REG_ECX | |
81 #define REG_PARM3 REG_EDX | |
82 #define REG_PARM4 REG_ESI | |
83 #define REG_PARM5 REG_EDI | |
84 #define REG_PARM6 REG_EBP | |
85 #elif defined(__x86_64__) | |
86 #define MIN_SYSCALL 0 | |
87 #define MAX_SYSCALL 512 | |
88 #define SECCOMP_ARCH AUDIT_ARCH_X86_64 | |
89 #define REG_RESULT REG_RAX | |
90 #define REG_SYSCALL REG_RAX | |
91 #define REG_PARM1 REG_RDI | |
92 #define REG_PARM2 REG_RSI | |
93 #define REG_PARM3 REG_RDX | |
94 #define REG_PARM4 REG_R10 | |
95 #define REG_PARM5 REG_R8 | |
96 #define REG_PARM6 REG_R9 | |
97 #else | |
98 #define Unsupported target platform | |
Chris Evans
2012/06/01 20:07:55
Did you mean #error ?
Markus (顧孟勤)
2012/06/01 21:38:52
Doh
| |
99 #endif | |
100 | |
101 struct arch_seccomp_data { | |
102 int nr; | |
103 uint32_t arch; | |
104 uint64_t instruction_pointer; | |
105 uint64_t args[6]; | |
106 }; | |
107 | |
108 #ifdef SECCOMP_BPF_STANDALONE | |
109 #define arraysize(x) \ | |
110 (static_cast<int>(sizeof(x)/sizeof(*(x)))) | |
Chris Evans
2012/06/01 20:07:55
A size macro might want to return size_t ?
Markus (顧孟勤)
2012/06/01 21:38:52
Really. Do I have to? It means a million ugly cast
| |
111 #define HANDLE_EINTR TEMP_FAILURE_RETRY | |
112 #endif | |
113 | |
114 | |
115 namespace playground2 { | |
116 | |
117 class Sandbox { | |
118 friend class Util; | |
119 | |
120 public: | |
121 enum ErrorCode { | |
122 SB_TRAP = -1, | |
123 SB_ALLOWED = 0x0000, | |
124 SB_INSPECT_ARG_1 = 0x8001, | |
125 SB_INSPECT_ARG_2 = 0x8002, | |
126 SB_INSPECT_ARG_3 = 0x8004, | |
127 SB_INSPECT_ARG_4 = 0x8008, | |
128 SB_INSPECT_ARG_5 = 0x8010, | |
129 SB_INSPECT_ARG_6 = 0x8020 | |
130 }; | |
131 | |
132 enum Operation { | |
133 OP_NOP, OP_EQUAL, OP_NOTEQUAL, OP_LESS, | |
134 OP_LESS_EQUAL, OP_GREATER, OP_GREATER_EQUAL, | |
135 OP_HAS_BITS, OP_DOES_NOT_HAVE_BITS | |
136 }; | |
137 | |
138 struct Constraint { | |
139 bool is32bit; | |
140 Operation op; | |
141 uint32_t value; | |
142 ErrorCode passed; | |
143 ErrorCode failed; | |
144 }; | |
145 | |
146 typedef ErrorCode (*EvaluateSyscall)(int sysno); | |
147 typedef int (*EvaluateArguments)(int sysno, int arg, | |
148 Constraint *constraint); | |
Chris Evans
2012/06/01 20:07:55
Style: I think Chromium style is to position the p
Chris Evans
2012/06/01 20:07:55
Style: I think Chromium style is to position the p
Markus (顧孟勤)
2012/06/01 21:38:52
This is so broken. And it tends to get painful whe
| |
149 | |
150 // There are a lot of reasons why the Seccomp sandbox might not be available. | |
151 // This could be because the kernel does not support Seccomp mode, or it | |
152 // could be because another sandbox is already active. | |
153 // "proc_fd" should be a file descriptor for "/proc", or -1 if not | |
154 // provided by the caller. | |
155 static bool supportsSeccompSandbox(int proc_fd); | |
156 | |
157 // The sandbox needs to be able to access files in "/proc/self". If this | |
158 // directory is not accessible when "startSandbox()" gets called, the caller | |
159 // can provide an already opened file descriptor by calling "setProcFd()". | |
160 // The sandbox becomes the newer owner of this file descriptor and will | |
Chris Evans
2012/06/01 20:07:55
Typo: newer -> new ?
Markus (顧孟勤)
2012/06/01 21:38:52
Done.
| |
161 // eventually close it when "startSandbox()" executes. | |
162 static void setProcFd(int proc_fd); | |
163 | |
164 // The system call evaluator function is called with the system | |
165 // call number. It can decide to allow the system call unconditionally | |
166 // by returning "0"; it can deny the system call unconditionally by | |
167 // returning an appropriate "errno" value; or it can request inspection | |
168 // of system call argument(s) by returning a suitable combination of | |
169 // SB_INSPECT_ARG_x bits. | |
170 // The system argument evaluator is called (if needed) to query additional | |
171 // constraints for the system call arguments. In the vast majority of | |
172 // cases, it will set a "Constraint" that forces a new "errno" value. | |
173 // But for more complex filters, it is possible to return another mask | |
174 // of SB_INSPECT_ARG_x bits. | |
175 static void setSandboxPolicy(EvaluateSyscall syscallEvaluator, | |
176 EvaluateArguments argumentEvaluator); | |
177 | |
178 // This is the main public entry point. It finds all system calls that | |
179 // need rewriting, sets up the resources needed by the sandbox, and | |
180 // enters Seccomp mode. | |
181 static void startSandbox(); | |
182 | |
183 protected: | |
184 // Print an error message and terminate the program. Used for fatal errors. | |
185 #ifdef SECCOMP_BPF_STANDALONE | |
186 static void die(const char *msg) __attribute__((noreturn)) { | |
187 if (msg) { | |
188 HANDLE_EINTR(write(2, msg, strlen(msg))); | |
189 HANDLE_EINTR(write(2, "\n", 1)); | |
190 } | |
191 for (;;) { | |
Chris Evans
2012/06/01 20:07:55
Why loop infinitely? At least a comment why we're
| |
192 syscall(__NR_exit_group, 1); | |
193 _exit(1); | |
194 } | |
195 } | |
196 #else | |
197 #define die(msg) LOG(FATAL) << (msg) | |
198 #endif | |
199 | |
200 // Get a file descriptor pointing to "/proc", if currently available. | |
201 static int getProcFd() { return proc_fd_; } | |
202 | |
203 private: | |
204 enum SandboxStatus { | |
205 STATUS_UNKNOWN, STATUS_UNSUPPORTED, STATUS_AVAILABLE, STATUS_ENABLED | |
206 }; | |
207 | |
208 static bool isSingleThreaded(int proc_fd); | |
209 static bool disableFilesystem(); | |
210 static void installFilter(); | |
211 static void sigSys(int nr, siginfo_t *info, void *void_context); | |
212 | |
213 static SandboxStatus status_; | |
214 static int proc_fd_; | |
215 static std::vector<std::pair<EvaluateSyscall, | |
216 EvaluateArguments> > evaluators_; | |
217 }; | |
218 | |
219 } // namespace | |
220 | |
221 #endif // SANDBOX_BPF_H__ | |
OLD | NEW |