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
3 // found in the LICENSE file.
5 #include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
10 #include <linux/net.h>
13 #include <sys/ioctl.h>
15 #include <sys/prctl.h>
17 #include <sys/types.h>
20 #include "base/basictypes.h"
21 #include "base/logging.h"
22 #include "build/build_config.h"
23 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
24 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
25 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
27 #if defined(OS_ANDROID)
28 #if !defined(F_DUPFD_CLOEXEC)
29 #define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
33 #if defined(__arm__) && !defined(MAP_STACK)
34 #define MAP_STACK 0x20000 // Daisy build environment has old headers.
39 inline bool IsArchitectureX86_64() {
40 #if defined(__x86_64__)
47 inline bool IsArchitectureI386() {
55 inline bool IsAndroid() {
56 #if defined(OS_ANDROID)
67 // Allow Glibc's and Android pthread creation flags, crash on any other
68 // thread creation attempts and EPERM attempts to use neither
69 // CLONE_VM, nor CLONE_THREAD, which includes all fork() implementations.
70 ErrorCode RestrictCloneToThreadsAndEPERMFork(SandboxBPF* sandbox) {
72 const uint64_t kGlibcPthreadFlags =
73 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD |
74 CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID |
77 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
79 ErrorCode(ErrorCode::ERR_ALLOWED),
80 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS,
81 CLONE_VM | CLONE_THREAD,
82 sandbox->Trap(SIGSYSCloneFailure, NULL),
85 const uint64_t kAndroidCloneMask = CLONE_VM | CLONE_FS | CLONE_FILES |
86 CLONE_SIGHAND | CLONE_THREAD |
88 const uint64_t kObsoleteAndroidCloneMask =
89 kAndroidCloneMask | CLONE_DETACHED;
91 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
93 ErrorCode(ErrorCode::ERR_ALLOWED),
94 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
95 kObsoleteAndroidCloneMask,
96 ErrorCode(ErrorCode::ERR_ALLOWED),
97 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS,
98 CLONE_VM | CLONE_THREAD,
99 sandbox->Trap(SIGSYSCloneFailure, NULL),
104 ErrorCode RestrictPrctl(SandboxBPF* sandbox) {
105 // Will need to add seccomp compositing in the future. PR_SET_PTRACER is
106 // used by breakpad but not needed anymore.
107 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
108 PR_SET_NAME, ErrorCode(ErrorCode::ERR_ALLOWED),
109 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
110 PR_SET_DUMPABLE, ErrorCode(ErrorCode::ERR_ALLOWED),
111 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
112 PR_GET_DUMPABLE, ErrorCode(ErrorCode::ERR_ALLOWED),
113 sandbox->Trap(SIGSYSPrctlFailure, NULL))));
116 ErrorCode RestrictIoctl(SandboxBPF* sandbox) {
117 return sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, TCGETS,
118 ErrorCode(ErrorCode::ERR_ALLOWED),
119 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, FIONREAD,
120 ErrorCode(ErrorCode::ERR_ALLOWED),
121 sandbox->Trap(SIGSYSIoctlFailure, NULL)));
124 ErrorCode RestrictMmapFlags(SandboxBPF* sandbox) {
125 // The flags you see are actually the allowed ones, and the variable is a
126 // "denied" mask because of the negation operator.
127 // Significantly, we don't permit MAP_HUGETLB, or the newer flags such as
129 // TODO(davidung), remove MAP_DENYWRITE with updated Tegra libraries.
130 uint32_t denied_mask = ~(MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS |
131 MAP_STACK | MAP_NORESERVE | MAP_FIXED |
133 return sandbox->Cond(3, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS,
135 sandbox->Trap(CrashSIGSYS_Handler, NULL),
136 ErrorCode(ErrorCode::ERR_ALLOWED));
139 ErrorCode RestrictMprotectFlags(SandboxBPF* sandbox) {
140 // The flags you see are actually the allowed ones, and the variable is a
141 // "denied" mask because of the negation operator.
142 // Significantly, we don't permit weird undocumented flags such as
144 uint32_t denied_mask = ~(PROT_READ | PROT_WRITE | PROT_EXEC);
145 return sandbox->Cond(2, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS,
147 sandbox->Trap(CrashSIGSYS_Handler, NULL),
148 ErrorCode(ErrorCode::ERR_ALLOWED));
151 ErrorCode RestrictFcntlCommands(SandboxBPF* sandbox) {
152 // 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
154 // allowed ones, and the variable is a "denied" mask because of the negation
156 // Glibc overrides the kernel's O_LARGEFILE value. Account for this.
157 int kOLargeFileFlag = O_LARGEFILE;
158 if (IsArchitectureX86_64() || IsArchitectureI386())
159 kOLargeFileFlag = 0100000;
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;
170 unsigned long denied_mask = ~(O_ACCMODE | O_APPEND | O_NONBLOCK | O_SYNC |
171 kOLargeFileFlag | O_CLOEXEC | O_NOATIME);
172 return sandbox->Cond(1, ErrorCode::TP_32BIT,
173 ErrorCode::OP_EQUAL, F_GETFL,
174 ErrorCode(ErrorCode::ERR_ALLOWED),
175 sandbox->Cond(1, ErrorCode::TP_32BIT,
176 ErrorCode::OP_EQUAL, F_SETFL,
177 sandbox->Cond(2, mask_long_type,
178 ErrorCode::OP_HAS_ANY_BITS, denied_mask,
179 sandbox->Trap(CrashSIGSYS_Handler, NULL),
180 ErrorCode(ErrorCode::ERR_ALLOWED)),
181 sandbox->Cond(1, ErrorCode::TP_32BIT,
182 ErrorCode::OP_EQUAL, F_GETFD,
183 ErrorCode(ErrorCode::ERR_ALLOWED),
184 sandbox->Cond(1, ErrorCode::TP_32BIT,
185 ErrorCode::OP_EQUAL, F_SETFD,
186 ErrorCode(ErrorCode::ERR_ALLOWED),
187 sandbox->Cond(1, ErrorCode::TP_32BIT,
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))))))))));
205 #if defined(__i386__)
206 ErrorCode RestrictSocketcallCommand(SandboxBPF* sandbox) {
207 // Unfortunately, we are unable to restrict the first parameter to
208 // socketpair(2). Whilst initially sounding bad, it's noteworthy that very
209 // few protocols actually support socketpair(2). The scary call that we're
210 // worried about, socket(2), remains blocked.
211 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
212 SYS_SOCKETPAIR, ErrorCode(ErrorCode::ERR_ALLOWED),
213 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
214 SYS_SEND, ErrorCode(ErrorCode::ERR_ALLOWED),
215 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
216 SYS_RECV, ErrorCode(ErrorCode::ERR_ALLOWED),
217 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
218 SYS_SENDTO, ErrorCode(ErrorCode::ERR_ALLOWED),
219 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
220 SYS_RECVFROM, ErrorCode(ErrorCode::ERR_ALLOWED),
221 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
222 SYS_SHUTDOWN, ErrorCode(ErrorCode::ERR_ALLOWED),
223 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
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)))))))));
231 ErrorCode RestrictKillTarget(pid_t target_pid, SandboxBPF* sandbox, int sysno) {
235 return sandbox->Cond(0,
239 ErrorCode(ErrorCode::ERR_ALLOWED),
240 sandbox->Trap(SIGSYSKillFailure, NULL));
242 return sandbox->Trap(SIGSYSKillFailure, NULL);
245 return sandbox->Trap(CrashSIGSYS_Handler, NULL);
249 } // namespace sandbox.