IDB: Make readonly transactions wait for earlier readwrite transactions
[chromium-blink-merge.git] / sandbox / linux / seccomp-bpf-helpers / syscall_parameters_restrictions.cc
blob82cdc8dd9011a1bcbb468f739be23714e97e2f6c
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"
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <fcntl.h>
10 #include <linux/futex.h>
11 #include <linux/net.h>
12 #include <sched.h>
13 #include <signal.h>
14 #include <sys/ioctl.h>
15 #include <sys/mman.h>
16 #include <sys/prctl.h>
17 #include <sys/resource.h>
18 #include <sys/stat.h>
19 #include <sys/time.h>
20 #include <sys/types.h>
21 #include <time.h>
22 #include <unistd.h>
24 #include "base/basictypes.h"
25 #include "base/logging.h"
26 #include "base/macros.h"
27 #include "base/time/time.h"
28 #include "build/build_config.h"
29 #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
30 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
31 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
32 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
33 #include "sandbox/linux/services/linux_syscalls.h"
35 #if defined(OS_ANDROID)
37 #include "sandbox/linux/services/android_futex.h"
39 #if !defined(F_DUPFD_CLOEXEC)
40 #define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
41 #endif
43 #endif // defined(OS_ANDROID)
45 #if defined(__arm__) && !defined(MAP_STACK)
46 #define MAP_STACK 0x20000 // Daisy build environment has old headers.
47 #endif
49 #if defined(__mips__) && !defined(MAP_STACK)
50 #define MAP_STACK 0x40000
51 #endif
52 namespace {
54 inline bool IsArchitectureX86_64() {
55 #if defined(__x86_64__)
56 return true;
57 #else
58 return false;
59 #endif
62 inline bool IsArchitectureI386() {
63 #if defined(__i386__)
64 return true;
65 #else
66 return false;
67 #endif
70 inline bool IsAndroid() {
71 #if defined(OS_ANDROID)
72 return true;
73 #else
74 return false;
75 #endif
78 inline bool IsArchitectureMips() {
79 #if defined(__mips__)
80 return true;
81 #else
82 return false;
83 #endif
86 } // namespace.
88 #define CASES SANDBOX_BPF_DSL_CASES
90 using sandbox::bpf_dsl::Allow;
91 using sandbox::bpf_dsl::Arg;
92 using sandbox::bpf_dsl::BoolExpr;
93 using sandbox::bpf_dsl::Error;
94 using sandbox::bpf_dsl::If;
95 using sandbox::bpf_dsl::ResultExpr;
97 namespace sandbox {
99 // Allow Glibc's and Android pthread creation flags, crash on any other
100 // thread creation attempts and EPERM attempts to use neither
101 // CLONE_VM, nor CLONE_THREAD, which includes all fork() implementations.
102 ResultExpr RestrictCloneToThreadsAndEPERMFork() {
103 const Arg<unsigned long> flags(0);
105 // TODO(mdempsky): Extend DSL to support (flags & ~mask1) == mask2.
106 const uint64_t kAndroidCloneMask = CLONE_VM | CLONE_FS | CLONE_FILES |
107 CLONE_SIGHAND | CLONE_THREAD |
108 CLONE_SYSVSEM;
109 const uint64_t kObsoleteAndroidCloneMask = kAndroidCloneMask | CLONE_DETACHED;
111 const uint64_t kGlibcPthreadFlags =
112 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD |
113 CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
114 const BoolExpr glibc_test = flags == kGlibcPthreadFlags;
116 const BoolExpr android_test = flags == kAndroidCloneMask ||
117 flags == kObsoleteAndroidCloneMask ||
118 flags == kGlibcPthreadFlags;
120 return If(IsAndroid() ? android_test : glibc_test, Allow())
121 .ElseIf((flags & (CLONE_VM | CLONE_THREAD)) == 0, Error(EPERM))
122 .Else(CrashSIGSYSClone());
125 ResultExpr RestrictPrctl() {
126 // Will need to add seccomp compositing in the future. PR_SET_PTRACER is
127 // used by breakpad but not needed anymore.
128 const Arg<int> option(0);
129 return Switch(option)
130 .CASES((PR_GET_NAME, PR_SET_NAME, PR_GET_DUMPABLE, PR_SET_DUMPABLE),
131 Allow())
132 .Default(CrashSIGSYSPrctl());
135 ResultExpr RestrictIoctl() {
136 const Arg<int> request(1);
137 return Switch(request).CASES((TCGETS, FIONREAD), Allow()).Default(
138 CrashSIGSYSIoctl());
141 ResultExpr RestrictMmapFlags() {
142 // The flags you see are actually the allowed ones, and the variable is a
143 // "denied" mask because of the negation operator.
144 // Significantly, we don't permit MAP_HUGETLB, or the newer flags such as
145 // MAP_POPULATE.
146 // TODO(davidung), remove MAP_DENYWRITE with updated Tegra libraries.
147 const uint64_t kAllowedMask = MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS |
148 MAP_STACK | MAP_NORESERVE | MAP_FIXED |
149 MAP_DENYWRITE;
150 const Arg<int> flags(3);
151 return If((flags & ~kAllowedMask) == 0, Allow()).Else(CrashSIGSYS());
154 ResultExpr RestrictMprotectFlags() {
155 // The flags you see are actually the allowed ones, and the variable is a
156 // "denied" mask because of the negation operator.
157 // Significantly, we don't permit weird undocumented flags such as
158 // PROT_GROWSDOWN.
159 const uint64_t kAllowedMask = PROT_READ | PROT_WRITE | PROT_EXEC;
160 const Arg<int> prot(2);
161 return If((prot & ~kAllowedMask) == 0, Allow()).Else(CrashSIGSYS());
164 ResultExpr RestrictFcntlCommands() {
165 // We also restrict the flags in F_SETFL. We don't want to permit flags with
166 // a history of trouble such as O_DIRECT. The flags you see are actually the
167 // allowed ones, and the variable is a "denied" mask because of the negation
168 // operator.
169 // Glibc overrides the kernel's O_LARGEFILE value. Account for this.
170 uint64_t kOLargeFileFlag = O_LARGEFILE;
171 if (IsArchitectureX86_64() || IsArchitectureI386() || IsArchitectureMips())
172 kOLargeFileFlag = 0100000;
174 const Arg<int> cmd(1);
175 const Arg<long> long_arg(2);
177 const uint64_t kAllowedMask = O_ACCMODE | O_APPEND | O_NONBLOCK | O_SYNC |
178 kOLargeFileFlag | O_CLOEXEC | O_NOATIME;
179 return Switch(cmd)
180 .CASES((F_GETFL,
181 F_GETFD,
182 F_SETFD,
183 F_SETLK,
184 F_SETLKW,
185 F_GETLK,
186 F_DUPFD,
187 F_DUPFD_CLOEXEC),
188 Allow())
189 .Case(F_SETFL,
190 If((long_arg & ~kAllowedMask) == 0, Allow()).Else(CrashSIGSYS()))
191 .Default(CrashSIGSYS());
194 #if defined(__i386__) || defined(__mips__)
195 ResultExpr RestrictSocketcallCommand() {
196 // Unfortunately, we are unable to restrict the first parameter to
197 // socketpair(2). Whilst initially sounding bad, it's noteworthy that very
198 // few protocols actually support socketpair(2). The scary call that we're
199 // worried about, socket(2), remains blocked.
200 const Arg<int> call(0);
201 return Switch(call)
202 .CASES((SYS_SOCKETPAIR,
203 SYS_SHUTDOWN,
204 SYS_RECV,
205 SYS_SEND,
206 SYS_RECVFROM,
207 SYS_SENDTO,
208 SYS_RECVMSG,
209 SYS_SENDMSG),
210 Allow())
211 .Default(Error(EPERM));
213 #endif
215 ResultExpr RestrictKillTarget(pid_t target_pid, int sysno) {
216 switch (sysno) {
217 case __NR_kill:
218 case __NR_tgkill: {
219 const Arg<pid_t> pid(0);
220 return If(pid == target_pid, Allow()).Else(CrashSIGSYSKill());
222 case __NR_tkill:
223 return CrashSIGSYSKill();
224 default:
225 NOTREACHED();
226 return CrashSIGSYS();
230 ResultExpr RestrictFutex() {
231 const uint64_t kAllowedFutexFlags = FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME;
232 const Arg<int> op(1);
233 return Switch(op & ~kAllowedFutexFlags)
234 .CASES((FUTEX_WAIT,
235 FUTEX_WAKE,
236 FUTEX_REQUEUE,
237 FUTEX_CMP_REQUEUE,
238 FUTEX_WAKE_OP,
239 FUTEX_WAIT_BITSET,
240 FUTEX_WAKE_BITSET),
241 Allow())
242 .Default(CrashSIGSYSFutex());
245 ResultExpr RestrictGetSetpriority(pid_t target_pid) {
246 const Arg<int> which(0);
247 const Arg<int> who(1);
248 return If(which == PRIO_PROCESS,
249 If(who == 0 || who == target_pid, Allow()).Else(Error(EPERM)))
250 .Else(CrashSIGSYS());
253 ResultExpr RestrictClockID() {
254 COMPILE_ASSERT(4 == sizeof(clockid_t), clockid_is_not_32bit);
255 const Arg<clockid_t> clockid(0);
256 return If(
257 #if defined(OS_CHROMEOS)
258 // Allow the special clock for Chrome OS used by Chrome tracing.
259 clockid == base::TimeTicks::kClockSystemTrace ||
260 #endif
261 clockid == CLOCK_MONOTONIC ||
262 clockid == CLOCK_PROCESS_CPUTIME_ID ||
263 clockid == CLOCK_REALTIME ||
264 clockid == CLOCK_THREAD_CPUTIME_ID,
265 Allow()).Else(CrashSIGSYS());
268 ResultExpr RestrictSchedTarget(pid_t target_pid, int sysno) {
269 switch (sysno) {
270 case __NR_sched_getaffinity:
271 case __NR_sched_getattr:
272 case __NR_sched_getparam:
273 case __NR_sched_getscheduler:
274 case __NR_sched_rr_get_interval:
275 case __NR_sched_setaffinity:
276 case __NR_sched_setattr:
277 case __NR_sched_setparam:
278 case __NR_sched_setscheduler: {
279 const Arg<pid_t> pid(0);
280 return If(pid == 0 || pid == target_pid, Allow())
281 .Else(RewriteSchedSIGSYS());
283 default:
284 NOTREACHED();
285 return CrashSIGSYS();
290 } // namespace sandbox.