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

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

Issue 299683004: Rewrite all BPF policies to use DSL API Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Overhaul of DSL and implementation Created 6 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h ('k') | no next file » | 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) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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 "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h" 5 #include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <fcntl.h> 9 #include <fcntl.h>
10 #include <linux/net.h> 10 #include <linux/net.h>
11 #include <sched.h> 11 #include <sched.h>
12 #include <signal.h> 12 #include <signal.h>
13 #include <sys/ioctl.h> 13 #include <sys/ioctl.h>
14 #include <sys/mman.h> 14 #include <sys/mman.h>
15 #include <sys/prctl.h> 15 #include <sys/prctl.h>
16 #include <sys/stat.h> 16 #include <sys/stat.h>
17 #include <sys/types.h> 17 #include <sys/types.h>
18 #include <unistd.h> 18 #include <unistd.h>
19 19
20 #include "base/basictypes.h" 20 #include "base/basictypes.h"
21 #include "base/logging.h" 21 #include "base/logging.h"
22 #include "build/build_config.h" 22 #include "build/build_config.h"
23 #include "sandbox/linux/seccomp-bpf-helpers/bpf_dsl.h"
23 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" 24 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
24 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h" 25 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
25 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" 26 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
26 27
27 #if defined(OS_ANDROID) 28 #if defined(OS_ANDROID)
28 #if !defined(F_DUPFD_CLOEXEC) 29 #if !defined(F_DUPFD_CLOEXEC)
29 #define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6) 30 #define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
30 #endif 31 #endif
31 #endif 32 #endif
32 33
33 #if defined(__arm__) && !defined(MAP_STACK) 34 #if defined(__arm__) && !defined(MAP_STACK)
34 #define MAP_STACK 0x20000 // Daisy build environment has old headers. 35 #define MAP_STACK 0x20000 // Daisy build environment has old headers.
35 #endif 36 #endif
36 37
38 using namespace sandbox::bpf_dsl;
39
37 namespace { 40 namespace {
38 41
39 inline bool IsArchitectureX86_64() { 42 inline bool IsArchitectureX86_64() {
40 #if defined(__x86_64__) 43 #if defined(__x86_64__)
41 return true; 44 return true;
42 #else 45 #else
43 return false; 46 return false;
44 #endif 47 #endif
45 } 48 }
46 49
(...skipping 13 matching lines...) Expand all
60 #endif 63 #endif
61 } 64 }
62 65
63 } // namespace. 66 } // namespace.
64 67
65 namespace sandbox { 68 namespace sandbox {
66 69
67 // Allow Glibc's and Android pthread creation flags, crash on any other 70 // Allow Glibc's and Android pthread creation flags, crash on any other
68 // thread creation attempts and EPERM attempts to use neither 71 // thread creation attempts and EPERM attempts to use neither
69 // CLONE_VM, nor CLONE_THREAD, which includes all fork() implementations. 72 // CLONE_VM, nor CLONE_THREAD, which includes all fork() implementations.
70 ErrorCode RestrictCloneToThreadsAndEPERMFork(SandboxBPF* sandbox) { 73 ResultExpr RestrictCloneToThreadsAndEPERMFork() {
74 const Arg<int> flags_arg(0);
71 if (!IsAndroid()) { 75 if (!IsAndroid()) {
72 const uint64_t kGlibcPthreadFlags = 76 const uint64_t kGlibcPthreadFlags =
73 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | 77 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD |
74 CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID | 78 CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID |
75 CLONE_CHILD_CLEARTID; 79 CLONE_CHILD_CLEARTID;
76 80
77 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 81 return If(flags_arg == kGlibcPthreadFlags).Then(
78 kGlibcPthreadFlags, 82 Allow()
79 ErrorCode(ErrorCode::ERR_ALLOWED), 83 ).ElseIf((flags_arg & (CLONE_VM | CLONE_THREAD)) == 0).Then(
80 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, 84 Error(EPERM)
81 CLONE_VM | CLONE_THREAD, 85 ).Else(
82 sandbox->Trap(SIGSYSCloneFailure, NULL), 86 bpf_dsl::Trap(SIGSYSCloneFailure, NULL)
83 ErrorCode(EPERM))); 87 );
84 } else { 88 } else {
85 const uint64_t kAndroidCloneMask = CLONE_VM | CLONE_FS | CLONE_FILES | 89 const uint64_t kAndroidCloneMask = CLONE_VM | CLONE_FS | CLONE_FILES |
86 CLONE_SIGHAND | CLONE_THREAD | 90 CLONE_SIGHAND | CLONE_THREAD |
87 CLONE_SYSVSEM; 91 CLONE_SYSVSEM;
88 const uint64_t kObsoleteAndroidCloneMask = 92 const uint64_t kObsoleteAndroidCloneMask =
89 kAndroidCloneMask | CLONE_DETACHED; 93 kAndroidCloneMask | CLONE_DETACHED;
90 94
91 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 95 return If(flags_arg == kAndroidCloneMask ||
92 kAndroidCloneMask, 96 flags_arg == kObsoleteAndroidCloneMask).Then(
93 ErrorCode(ErrorCode::ERR_ALLOWED), 97 Allow()
94 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 98 ).ElseIf((flags_arg & (CLONE_VM | CLONE_THREAD)) == 0).Then(
95 kObsoleteAndroidCloneMask, 99 Error(EPERM)
96 ErrorCode(ErrorCode::ERR_ALLOWED), 100 ).Else(
97 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, 101 bpf_dsl::Trap(SIGSYSCloneFailure, NULL)
98 CLONE_VM | CLONE_THREAD, 102 );
99 sandbox->Trap(SIGSYSCloneFailure, NULL),
100 ErrorCode(EPERM))));
101 } 103 }
102 } 104 }
103 105
104 ErrorCode RestrictPrctl(SandboxBPF* sandbox) { 106 ResultExpr RestrictPrctl() {
105 // Will need to add seccomp compositing in the future. PR_SET_PTRACER is 107 // Will need to add seccomp compositing in the future. PR_SET_PTRACER is
106 // used by breakpad but not needed anymore. 108 // used by breakpad but not needed anymore.
107 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 109 const Arg<int> option_arg(0);
108 PR_SET_NAME, ErrorCode(ErrorCode::ERR_ALLOWED), 110 return If(option_arg == PR_SET_NAME ||
109 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 111 option_arg == PR_SET_DUMPABLE ||
110 PR_SET_DUMPABLE, ErrorCode(ErrorCode::ERR_ALLOWED), 112 option_arg == PR_GET_DUMPABLE).Then(
111 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 113 Allow()
112 PR_GET_DUMPABLE, ErrorCode(ErrorCode::ERR_ALLOWED), 114 ).Else(
113 sandbox->Trap(SIGSYSPrctlFailure, NULL)))); 115 bpf_dsl::Trap(SIGSYSPrctlFailure, NULL)
116 );
114 } 117 }
115 118
116 ErrorCode RestrictIoctl(SandboxBPF* sandbox) { 119 ResultExpr RestrictIoctl() {
117 return sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, TCGETS, 120 const Arg<int> request_arg(1);
118 ErrorCode(ErrorCode::ERR_ALLOWED), 121 return If(request_arg == TCGETS || request_arg == FIONREAD).Then(
119 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, FIONREAD, 122 Allow()
120 ErrorCode(ErrorCode::ERR_ALLOWED), 123 ).Else(
121 sandbox->Trap(SIGSYSIoctlFailure, NULL))); 124 bpf_dsl::Trap(SIGSYSIoctlFailure, NULL)
125 );
122 } 126 }
123 127
124 ErrorCode RestrictMmapFlags(SandboxBPF* sandbox) { 128 ResultExpr RestrictMmapFlags() {
125 // The flags you see are actually the allowed ones, and the variable is a 129 // The flags you see are actually the allowed ones, and the variable is a
126 // "denied" mask because of the negation operator. 130 // "denied" mask because of the negation operator.
127 // Significantly, we don't permit MAP_HUGETLB, or the newer flags such as 131 // Significantly, we don't permit MAP_HUGETLB, or the newer flags such as
128 // MAP_POPULATE. 132 // MAP_POPULATE.
129 // TODO(davidung), remove MAP_DENYWRITE with updated Tegra libraries. 133 // TODO(davidung), remove MAP_DENYWRITE with updated Tegra libraries.
130 uint32_t denied_mask = ~(MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS | 134 uint32_t denied_mask = ~(MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS |
131 MAP_STACK | MAP_NORESERVE | MAP_FIXED | 135 MAP_STACK | MAP_NORESERVE | MAP_FIXED |
132 MAP_DENYWRITE); 136 MAP_DENYWRITE);
133 return sandbox->Cond(3, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, 137 const Arg<int> flags_arg(3);
134 denied_mask, 138 return If((flags_arg & denied_mask) == 0).Then(
135 sandbox->Trap(CrashSIGSYS_Handler, NULL), 139 Allow()
136 ErrorCode(ErrorCode::ERR_ALLOWED)); 140 ).Else(
141 bpf_dsl::Trap(CrashSIGSYS_Handler, NULL)
142 );
137 } 143 }
138 144
139 ErrorCode RestrictMprotectFlags(SandboxBPF* sandbox) { 145 ResultExpr RestrictMprotectFlags() {
140 // The flags you see are actually the allowed ones, and the variable is a 146 // The flags you see are actually the allowed ones, and the variable is a
141 // "denied" mask because of the negation operator. 147 // "denied" mask because of the negation operator.
142 // Significantly, we don't permit weird undocumented flags such as 148 // Significantly, we don't permit weird undocumented flags such as
143 // PROT_GROWSDOWN. 149 // PROT_GROWSDOWN.
144 uint32_t denied_mask = ~(PROT_READ | PROT_WRITE | PROT_EXEC); 150 uint32_t denied_mask = ~(PROT_READ | PROT_WRITE | PROT_EXEC);
145 return sandbox->Cond(2, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, 151 const Arg<int> prot_arg(2);
146 denied_mask, 152 return If((prot_arg & denied_mask) == 0).Then(
147 sandbox->Trap(CrashSIGSYS_Handler, NULL), 153 Allow()
148 ErrorCode(ErrorCode::ERR_ALLOWED)); 154 ).Else(
155 bpf_dsl::Trap(CrashSIGSYS_Handler, NULL)
156 );
149 } 157 }
150 158
151 ErrorCode RestrictFcntlCommands(SandboxBPF* sandbox) { 159 ResultExpr RestrictFcntlCommands() {
152 // We also restrict the flags in F_SETFL. We don't want to permit flags with 160 // We also restrict the flags in F_SETFL. We don't want to permit flags with
153 // a history of trouble such as O_DIRECT. The flags you see are actually the 161 // a history of trouble such as O_DIRECT. The flags you see are actually the
154 // allowed ones, and the variable is a "denied" mask because of the negation 162 // allowed ones, and the variable is a "denied" mask because of the negation
155 // operator. 163 // operator.
156 // Glibc overrides the kernel's O_LARGEFILE value. Account for this. 164 // Glibc overrides the kernel's O_LARGEFILE value. Account for this.
157 int kOLargeFileFlag = O_LARGEFILE; 165 int kOLargeFileFlag = O_LARGEFILE;
158 if (IsArchitectureX86_64() || IsArchitectureI386()) 166 if (IsArchitectureX86_64() || IsArchitectureI386())
159 kOLargeFileFlag = 0100000; 167 kOLargeFileFlag = 0100000;
160 168
161 // TODO(jln): add TP_LONG/TP_SIZET types.
162 ErrorCode::ArgType mask_long_type;
163 if (sizeof(long) == 8)
164 mask_long_type = ErrorCode::TP_64BIT;
165 else if (sizeof(long) == 4)
166 mask_long_type = ErrorCode::TP_32BIT;
167 else
168 NOTREACHED();
169
170 unsigned long denied_mask = ~(O_ACCMODE | O_APPEND | O_NONBLOCK | O_SYNC | 169 unsigned long denied_mask = ~(O_ACCMODE | O_APPEND | O_NONBLOCK | O_SYNC |
171 kOLargeFileFlag | O_CLOEXEC | O_NOATIME); 170 kOLargeFileFlag | O_CLOEXEC | O_NOATIME);
172 return sandbox->Cond(1, ErrorCode::TP_32BIT, 171 const Arg<int> cmd_arg(1);
173 ErrorCode::OP_EQUAL, F_GETFL, 172 const Arg<unsigned long> flags_arg(2);
174 ErrorCode(ErrorCode::ERR_ALLOWED), 173
175 sandbox->Cond(1, ErrorCode::TP_32BIT, 174 return If(cmd_arg == F_GETFL ||
176 ErrorCode::OP_EQUAL, F_SETFL, 175 (cmd_arg == F_SETFL && (flags_arg & denied_mask) == 0) ||
177 sandbox->Cond(2, mask_long_type, 176 cmd_arg == F_GETFD ||
178 ErrorCode::OP_HAS_ANY_BITS, denied_mask, 177 cmd_arg == F_SETFD ||
179 sandbox->Trap(CrashSIGSYS_Handler, NULL), 178 cmd_arg == F_DUPFD ||
180 ErrorCode(ErrorCode::ERR_ALLOWED)), 179 cmd_arg == F_SETLK ||
181 sandbox->Cond(1, ErrorCode::TP_32BIT, 180 cmd_arg == F_SETLKW ||
182 ErrorCode::OP_EQUAL, F_GETFD, 181 cmd_arg == F_GETLK ||
183 ErrorCode(ErrorCode::ERR_ALLOWED), 182 cmd_arg == F_DUPFD_CLOEXEC).Then(
184 sandbox->Cond(1, ErrorCode::TP_32BIT, 183 Allow()
185 ErrorCode::OP_EQUAL, F_SETFD, 184 ).Else(
186 ErrorCode(ErrorCode::ERR_ALLOWED), 185 bpf_dsl::Trap(CrashSIGSYS_Handler, NULL)
187 sandbox->Cond(1, ErrorCode::TP_32BIT, 186 );
188 ErrorCode::OP_EQUAL, F_DUPFD,
189 ErrorCode(ErrorCode::ERR_ALLOWED),
190 sandbox->Cond(1, ErrorCode::TP_32BIT,
191 ErrorCode::OP_EQUAL, F_SETLK,
192 ErrorCode(ErrorCode::ERR_ALLOWED),
193 sandbox->Cond(1, ErrorCode::TP_32BIT,
194 ErrorCode::OP_EQUAL, F_SETLKW,
195 ErrorCode(ErrorCode::ERR_ALLOWED),
196 sandbox->Cond(1, ErrorCode::TP_32BIT,
197 ErrorCode::OP_EQUAL, F_GETLK,
198 ErrorCode(ErrorCode::ERR_ALLOWED),
199 sandbox->Cond(1, ErrorCode::TP_32BIT,
200 ErrorCode::OP_EQUAL, F_DUPFD_CLOEXEC,
201 ErrorCode(ErrorCode::ERR_ALLOWED),
202 sandbox->Trap(CrashSIGSYS_Handler, NULL))))))))));
203 } 187 }
204 188
205 #if defined(__i386__) 189 #if defined(__i386__)
206 ErrorCode RestrictSocketcallCommand(SandboxBPF* sandbox) { 190 ResultExpr RestrictSocketcallCommand() {
207 // Unfortunately, we are unable to restrict the first parameter to 191 // Unfortunately, we are unable to restrict the first parameter to
208 // socketpair(2). Whilst initially sounding bad, it's noteworthy that very 192 // socketpair(2). Whilst initially sounding bad, it's noteworthy that very
209 // few protocols actually support socketpair(2). The scary call that we're 193 // few protocols actually support socketpair(2). The scary call that we're
210 // worried about, socket(2), remains blocked. 194 // worried about, socket(2), remains blocked.
211 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 195 const Arg<int> call_arg(0);
212 SYS_SOCKETPAIR, ErrorCode(ErrorCode::ERR_ALLOWED), 196 return If(call_arg == SYS_SOCKETPAIR ||
213 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 197 call_arg == SYS_SEND ||
214 SYS_SEND, ErrorCode(ErrorCode::ERR_ALLOWED), 198 call_arg == SYS_RECV ||
215 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 199 call_arg == SYS_SENDTO ||
216 SYS_RECV, ErrorCode(ErrorCode::ERR_ALLOWED), 200 call_arg == SYS_RECVFROM ||
217 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 201 call_arg == SYS_SHUTDOWN ||
218 SYS_SENDTO, ErrorCode(ErrorCode::ERR_ALLOWED), 202 call_arg == SYS_SENDMSG ||
219 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 203 call_arg == SYS_RECVMSG).Then(
220 SYS_RECVFROM, ErrorCode(ErrorCode::ERR_ALLOWED), 204 Allow()
221 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 205 ).Else(
222 SYS_SHUTDOWN, ErrorCode(ErrorCode::ERR_ALLOWED), 206 Error(EPERM)
223 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 207 );
224 SYS_SENDMSG, ErrorCode(ErrorCode::ERR_ALLOWED),
225 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
226 SYS_RECVMSG, ErrorCode(ErrorCode::ERR_ALLOWED),
227 ErrorCode(EPERM)))))))));
228 } 208 }
229 #endif 209 #endif
230 210
231 ErrorCode RestrictKillTarget(pid_t target_pid, SandboxBPF* sandbox, int sysno) { 211 ResultExpr RestrictKillTarget(pid_t target_pid, int sysno) {
232 switch (sysno) { 212 switch (sysno) {
233 case __NR_kill: 213 case __NR_kill:
234 case __NR_tgkill: 214 case __NR_tgkill: {
235 return sandbox->Cond(0, 215 const Arg<pid_t> target_arg(0);
236 ErrorCode::TP_32BIT, 216 return If(target_arg == target_pid).Then(
237 ErrorCode::OP_EQUAL, 217 Allow()
238 target_pid, 218 ).Else(
239 ErrorCode(ErrorCode::ERR_ALLOWED), 219 bpf_dsl::Trap(SIGSYSKillFailure, NULL)
240 sandbox->Trap(SIGSYSKillFailure, NULL)); 220 );
221 }
241 case __NR_tkill: 222 case __NR_tkill:
242 return sandbox->Trap(SIGSYSKillFailure, NULL); 223 return bpf_dsl::Trap(SIGSYSKillFailure, NULL);
243 default: 224 default:
244 NOTREACHED(); 225 NOTREACHED();
245 return sandbox->Trap(CrashSIGSYS_Handler, NULL); 226 return bpf_dsl::Trap(CrashSIGSYS_Handler, NULL);
246 } 227 }
247 } 228 }
248 229
249 } // namespace sandbox. 230 } // namespace sandbox.
OLDNEW
« no previous file with comments | « sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698