blob: 60c16d37302b880a63db88fcd2ebbbcb97f6a1da [file] [log] [blame]
James Robinson30d547e2014-10-23 18:20:06 -07001// 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.
4
5#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
6
7#include <errno.h>
8#include <fcntl.h>
9#include <fcntl.h>
James Robinson30d547e2014-10-23 18:20:06 -070010#include <linux/net.h>
11#include <sched.h>
12#include <signal.h>
James Robinson0fae0002015-05-05 16:31:51 -070013#include <stdint.h>
James Robinson30d547e2014-10-23 18:20:06 -070014#include <sys/mman.h>
15#include <sys/prctl.h>
16#include <sys/resource.h>
17#include <sys/stat.h>
18#include <sys/time.h>
19#include <sys/types.h>
20#include <time.h>
21#include <unistd.h>
22
James Robinson30d547e2014-10-23 18:20:06 -070023#include "base/logging.h"
24#include "base/macros.h"
25#include "base/time/time.h"
26#include "build/build_config.h"
James Robinson61650152014-10-26 23:24:55 -070027#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
Etienne Membrives386015a2015-02-19 17:27:12 +010028#include "sandbox/linux/bpf_dsl/seccomp_macros.h"
James Robinson30d547e2014-10-23 18:20:06 -070029#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
James Robinson30d547e2014-10-23 18:20:06 -070030#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
James Robinson0fae0002015-05-05 16:31:51 -070031#include "sandbox/linux/system_headers/linux_futex.h"
Etienne Membrives386015a2015-02-19 17:27:12 +010032#include "sandbox/linux/system_headers/linux_syscalls.h"
James Robinson30d547e2014-10-23 18:20:06 -070033
James Robinsonf19b1022015-05-05 18:12:15 -070034// PNaCl toolchain does not provide sys/ioctl.h header.
35#if !defined(OS_NACL_NONSFI)
36#include <sys/ioctl.h>
37#endif
38
James Robinson30d547e2014-10-23 18:20:06 -070039#if defined(OS_ANDROID)
40
James Robinson30d547e2014-10-23 18:20:06 -070041#if !defined(F_DUPFD_CLOEXEC)
42#define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
43#endif
44
James Robinson1027bc12014-12-04 14:51:42 -080045// https://android.googlesource.com/platform/bionic/+/lollipop-release/libc/private/bionic_prctl.h
46#if !defined(PR_SET_VMA)
47#define PR_SET_VMA 0x53564d41
48#endif
49
50// https://android.googlesource.com/platform/system/core/+/lollipop-release/libcutils/sched_policy.c
51#if !defined(PR_SET_TIMERSLACK_PID)
52#define PR_SET_TIMERSLACK_PID 41
53#endif
54
James Robinson30d547e2014-10-23 18:20:06 -070055#endif // defined(OS_ANDROID)
56
57#if defined(__arm__) && !defined(MAP_STACK)
58#define MAP_STACK 0x20000 // Daisy build environment has old headers.
59#endif
60
61#if defined(__mips__) && !defined(MAP_STACK)
62#define MAP_STACK 0x40000
63#endif
64namespace {
65
66inline bool IsArchitectureX86_64() {
67#if defined(__x86_64__)
68 return true;
69#else
70 return false;
71#endif
72}
73
74inline bool IsArchitectureI386() {
75#if defined(__i386__)
76 return true;
77#else
78 return false;
79#endif
80}
81
82inline bool IsAndroid() {
83#if defined(OS_ANDROID)
84 return true;
85#else
86 return false;
87#endif
88}
89
90inline bool IsArchitectureMips() {
91#if defined(__mips__)
92 return true;
93#else
94 return false;
95#endif
96}
97
98} // namespace.
99
100#define CASES SANDBOX_BPF_DSL_CASES
101
102using sandbox::bpf_dsl::Allow;
103using sandbox::bpf_dsl::Arg;
104using sandbox::bpf_dsl::BoolExpr;
105using sandbox::bpf_dsl::Error;
106using sandbox::bpf_dsl::If;
107using sandbox::bpf_dsl::ResultExpr;
108
109namespace sandbox {
110
James Robinsonf19b1022015-05-05 18:12:15 -0700111#if !defined(OS_NACL_NONSFI)
James Robinson30d547e2014-10-23 18:20:06 -0700112// Allow Glibc's and Android pthread creation flags, crash on any other
113// thread creation attempts and EPERM attempts to use neither
114// CLONE_VM, nor CLONE_THREAD, which includes all fork() implementations.
115ResultExpr RestrictCloneToThreadsAndEPERMFork() {
116 const Arg<unsigned long> flags(0);
117
118 // TODO(mdempsky): Extend DSL to support (flags & ~mask1) == mask2.
119 const uint64_t kAndroidCloneMask = CLONE_VM | CLONE_FS | CLONE_FILES |
120 CLONE_SIGHAND | CLONE_THREAD |
121 CLONE_SYSVSEM;
122 const uint64_t kObsoleteAndroidCloneMask = kAndroidCloneMask | CLONE_DETACHED;
123
124 const uint64_t kGlibcPthreadFlags =
125 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD |
126 CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
127 const BoolExpr glibc_test = flags == kGlibcPthreadFlags;
128
129 const BoolExpr android_test = flags == kAndroidCloneMask ||
130 flags == kObsoleteAndroidCloneMask ||
131 flags == kGlibcPthreadFlags;
132
133 return If(IsAndroid() ? android_test : glibc_test, Allow())
134 .ElseIf((flags & (CLONE_VM | CLONE_THREAD)) == 0, Error(EPERM))
135 .Else(CrashSIGSYSClone());
136}
137
138ResultExpr RestrictPrctl() {
139 // Will need to add seccomp compositing in the future. PR_SET_PTRACER is
140 // used by breakpad but not needed anymore.
141 const Arg<int> option(0);
142 return Switch(option)
143 .CASES((PR_GET_NAME, PR_SET_NAME, PR_GET_DUMPABLE, PR_SET_DUMPABLE),
144 Allow())
James Robinson1027bc12014-12-04 14:51:42 -0800145#if defined(OS_ANDROID)
146 .CASES((PR_SET_VMA, PR_SET_TIMERSLACK_PID), Allow())
147#endif
James Robinson30d547e2014-10-23 18:20:06 -0700148 .Default(CrashSIGSYSPrctl());
149}
150
151ResultExpr RestrictIoctl() {
152 const Arg<int> request(1);
153 return Switch(request).CASES((TCGETS, FIONREAD), Allow()).Default(
154 CrashSIGSYSIoctl());
155}
156
157ResultExpr RestrictMmapFlags() {
158 // The flags you see are actually the allowed ones, and the variable is a
159 // "denied" mask because of the negation operator.
160 // Significantly, we don't permit MAP_HUGETLB, or the newer flags such as
161 // MAP_POPULATE.
162 // TODO(davidung), remove MAP_DENYWRITE with updated Tegra libraries.
163 const uint64_t kAllowedMask = MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS |
164 MAP_STACK | MAP_NORESERVE | MAP_FIXED |
165 MAP_DENYWRITE;
166 const Arg<int> flags(3);
167 return If((flags & ~kAllowedMask) == 0, Allow()).Else(CrashSIGSYS());
168}
169
170ResultExpr RestrictMprotectFlags() {
171 // The flags you see are actually the allowed ones, and the variable is a
172 // "denied" mask because of the negation operator.
173 // Significantly, we don't permit weird undocumented flags such as
174 // PROT_GROWSDOWN.
175 const uint64_t kAllowedMask = PROT_READ | PROT_WRITE | PROT_EXEC;
176 const Arg<int> prot(2);
177 return If((prot & ~kAllowedMask) == 0, Allow()).Else(CrashSIGSYS());
178}
179
180ResultExpr RestrictFcntlCommands() {
181 // We also restrict the flags in F_SETFL. We don't want to permit flags with
182 // a history of trouble such as O_DIRECT. The flags you see are actually the
183 // allowed ones, and the variable is a "denied" mask because of the negation
184 // operator.
185 // Glibc overrides the kernel's O_LARGEFILE value. Account for this.
186 uint64_t kOLargeFileFlag = O_LARGEFILE;
187 if (IsArchitectureX86_64() || IsArchitectureI386() || IsArchitectureMips())
188 kOLargeFileFlag = 0100000;
189
190 const Arg<int> cmd(1);
191 const Arg<long> long_arg(2);
192
193 const uint64_t kAllowedMask = O_ACCMODE | O_APPEND | O_NONBLOCK | O_SYNC |
194 kOLargeFileFlag | O_CLOEXEC | O_NOATIME;
195 return Switch(cmd)
196 .CASES((F_GETFL,
197 F_GETFD,
198 F_SETFD,
199 F_SETLK,
200 F_SETLKW,
201 F_GETLK,
202 F_DUPFD,
203 F_DUPFD_CLOEXEC),
204 Allow())
205 .Case(F_SETFL,
206 If((long_arg & ~kAllowedMask) == 0, Allow()).Else(CrashSIGSYS()))
207 .Default(CrashSIGSYS());
208}
209
210#if defined(__i386__) || defined(__mips__)
211ResultExpr RestrictSocketcallCommand() {
212 // Unfortunately, we are unable to restrict the first parameter to
213 // socketpair(2). Whilst initially sounding bad, it's noteworthy that very
214 // few protocols actually support socketpair(2). The scary call that we're
215 // worried about, socket(2), remains blocked.
216 const Arg<int> call(0);
217 return Switch(call)
218 .CASES((SYS_SOCKETPAIR,
219 SYS_SHUTDOWN,
220 SYS_RECV,
221 SYS_SEND,
222 SYS_RECVFROM,
223 SYS_SENDTO,
224 SYS_RECVMSG,
225 SYS_SENDMSG),
226 Allow())
227 .Default(Error(EPERM));
228}
229#endif
230
231ResultExpr RestrictKillTarget(pid_t target_pid, int sysno) {
232 switch (sysno) {
233 case __NR_kill:
234 case __NR_tgkill: {
235 const Arg<pid_t> pid(0);
236 return If(pid == target_pid, Allow()).Else(CrashSIGSYSKill());
237 }
238 case __NR_tkill:
239 return CrashSIGSYSKill();
240 default:
241 NOTREACHED();
242 return CrashSIGSYS();
243 }
244}
245
246ResultExpr RestrictFutex() {
247 const uint64_t kAllowedFutexFlags = FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME;
248 const Arg<int> op(1);
249 return Switch(op & ~kAllowedFutexFlags)
250 .CASES((FUTEX_WAIT,
251 FUTEX_WAKE,
252 FUTEX_REQUEUE,
253 FUTEX_CMP_REQUEUE,
254 FUTEX_WAKE_OP,
255 FUTEX_WAIT_BITSET,
256 FUTEX_WAKE_BITSET),
257 Allow())
258 .Default(CrashSIGSYSFutex());
259}
260
261ResultExpr RestrictGetSetpriority(pid_t target_pid) {
262 const Arg<int> which(0);
263 const Arg<int> who(1);
264 return If(which == PRIO_PROCESS,
265 If(who == 0 || who == target_pid, Allow()).Else(Error(EPERM)))
266 .Else(CrashSIGSYS());
267}
268
James Robinson30d547e2014-10-23 18:20:06 -0700269ResultExpr RestrictSchedTarget(pid_t target_pid, int sysno) {
270 switch (sysno) {
271 case __NR_sched_getaffinity:
272 case __NR_sched_getattr:
273 case __NR_sched_getparam:
274 case __NR_sched_getscheduler:
275 case __NR_sched_rr_get_interval:
276 case __NR_sched_setaffinity:
277 case __NR_sched_setattr:
278 case __NR_sched_setparam:
279 case __NR_sched_setscheduler: {
280 const Arg<pid_t> pid(0);
281 return If(pid == 0 || pid == target_pid, Allow())
282 .Else(RewriteSchedSIGSYS());
283 }
284 default:
285 NOTREACHED();
286 return CrashSIGSYS();
287 }
288}
289
James Robinsonc4c1c592014-11-21 18:27:04 -0800290ResultExpr RestrictPrlimit64(pid_t target_pid) {
291 const Arg<pid_t> pid(0);
292 return If(pid == 0 || pid == target_pid, Allow()).Else(CrashSIGSYS());
293}
James Robinson30d547e2014-10-23 18:20:06 -0700294
Benjamin Lermancdfc88d2015-02-03 14:35:12 +0100295ResultExpr RestrictGetrusage() {
296 const Arg<int> who(0);
297 return If(who == RUSAGE_SELF, Allow()).Else(CrashSIGSYS());
298}
James Robinsonf19b1022015-05-05 18:12:15 -0700299#endif // !defined(OS_NACL_NONSFI)
300
301ResultExpr RestrictClockID() {
302 static_assert(4 == sizeof(clockid_t), "clockid_t is not 32bit");
303 const Arg<clockid_t> clockid(0);
304 return If(
305#if defined(OS_CHROMEOS)
306 // Allow the special clock for Chrome OS used by Chrome tracing.
307 clockid == base::TimeTicks::kClockSystemTrace ||
308#endif
309 clockid == CLOCK_MONOTONIC ||
310 clockid == CLOCK_PROCESS_CPUTIME_ID ||
311 clockid == CLOCK_REALTIME ||
312 clockid == CLOCK_THREAD_CPUTIME_ID,
313 Allow()).Else(CrashSIGSYS());
314}
Benjamin Lermancdfc88d2015-02-03 14:35:12 +0100315
James Robinson30d547e2014-10-23 18:20:06 -0700316} // namespace sandbox.