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>
14 #include <sys/ioctl.h>
16 #include <sys/prctl.h>
17 #include <sys/resource.h>
20 #include <sys/types.h>
24 #include "base/logging.h"
25 #include "base/macros.h"
26 #include "base/time/time.h"
27 #include "build/build_config.h"
28 #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
29 #include "sandbox/linux/bpf_dsl/seccomp_macros.h"
30 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
31 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
32 #include "sandbox/linux/system_headers/linux_futex.h"
33 #include "sandbox/linux/system_headers/linux_syscalls.h"
35 #if defined(OS_ANDROID)
37 #if !defined(F_DUPFD_CLOEXEC)
38 #define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
41 // https://android.googlesource.com/platform/bionic/+/lollipop-release/libc/private/bionic_prctl.h
42 #if !defined(PR_SET_VMA)
43 #define PR_SET_VMA 0x53564d41
46 // https://android.googlesource.com/platform/system/core/+/lollipop-release/libcutils/sched_policy.c
47 #if !defined(PR_SET_TIMERSLACK_PID)
48 #define PR_SET_TIMERSLACK_PID 41
51 #endif // defined(OS_ANDROID)
53 #if defined(__arm__) && !defined(MAP_STACK)
54 #define MAP_STACK 0x20000 // Daisy build environment has old headers.
57 #if defined(__mips__) && !defined(MAP_STACK)
58 #define MAP_STACK 0x40000
62 inline bool IsArchitectureX86_64() {
63 #if defined(__x86_64__)
70 inline bool IsArchitectureI386() {
78 inline bool IsAndroid() {
79 #if defined(OS_ANDROID)
86 inline bool IsArchitectureMips() {
96 #define CASES SANDBOX_BPF_DSL_CASES
98 using sandbox::bpf_dsl::Allow
;
99 using sandbox::bpf_dsl::Arg
;
100 using sandbox::bpf_dsl::BoolExpr
;
101 using sandbox::bpf_dsl::Error
;
102 using sandbox::bpf_dsl::If
;
103 using sandbox::bpf_dsl::ResultExpr
;
107 // Allow Glibc's and Android pthread creation flags, crash on any other
108 // thread creation attempts and EPERM attempts to use neither
109 // CLONE_VM, nor CLONE_THREAD, which includes all fork() implementations.
110 ResultExpr
RestrictCloneToThreadsAndEPERMFork() {
111 const Arg
<unsigned long> flags(0);
113 // TODO(mdempsky): Extend DSL to support (flags & ~mask1) == mask2.
114 const uint64_t kAndroidCloneMask
= CLONE_VM
| CLONE_FS
| CLONE_FILES
|
115 CLONE_SIGHAND
| CLONE_THREAD
|
117 const uint64_t kObsoleteAndroidCloneMask
= kAndroidCloneMask
| CLONE_DETACHED
;
119 const uint64_t kGlibcPthreadFlags
=
120 CLONE_VM
| CLONE_FS
| CLONE_FILES
| CLONE_SIGHAND
| CLONE_THREAD
|
121 CLONE_SYSVSEM
| CLONE_SETTLS
| CLONE_PARENT_SETTID
| CLONE_CHILD_CLEARTID
;
122 const BoolExpr glibc_test
= flags
== kGlibcPthreadFlags
;
124 const BoolExpr android_test
= flags
== kAndroidCloneMask
||
125 flags
== kObsoleteAndroidCloneMask
||
126 flags
== kGlibcPthreadFlags
;
128 return If(IsAndroid() ? android_test
: glibc_test
, Allow())
129 .ElseIf((flags
& (CLONE_VM
| CLONE_THREAD
)) == 0, Error(EPERM
))
130 .Else(CrashSIGSYSClone());
133 ResultExpr
RestrictPrctl() {
134 // Will need to add seccomp compositing in the future. PR_SET_PTRACER is
135 // used by breakpad but not needed anymore.
136 const Arg
<int> option(0);
137 return Switch(option
)
138 .CASES((PR_GET_NAME
, PR_SET_NAME
, PR_GET_DUMPABLE
, PR_SET_DUMPABLE
),
140 #if defined(OS_ANDROID)
141 .CASES((PR_SET_VMA
, PR_SET_TIMERSLACK_PID
), Allow())
143 .Default(CrashSIGSYSPrctl());
146 ResultExpr
RestrictIoctl() {
147 const Arg
<int> request(1);
148 return Switch(request
).CASES((TCGETS
, FIONREAD
), Allow()).Default(
152 ResultExpr
RestrictMmapFlags() {
153 // The flags you see are actually the allowed ones, and the variable is a
154 // "denied" mask because of the negation operator.
155 // Significantly, we don't permit MAP_HUGETLB, or the newer flags such as
157 // TODO(davidung), remove MAP_DENYWRITE with updated Tegra libraries.
158 const uint64_t kAllowedMask
= MAP_SHARED
| MAP_PRIVATE
| MAP_ANONYMOUS
|
159 MAP_STACK
| MAP_NORESERVE
| MAP_FIXED
|
161 const Arg
<int> flags(3);
162 return If((flags
& ~kAllowedMask
) == 0, Allow()).Else(CrashSIGSYS());
165 ResultExpr
RestrictMprotectFlags() {
166 // The flags you see are actually the allowed ones, and the variable is a
167 // "denied" mask because of the negation operator.
168 // Significantly, we don't permit weird undocumented flags such as
170 const uint64_t kAllowedMask
= PROT_READ
| PROT_WRITE
| PROT_EXEC
;
171 const Arg
<int> prot(2);
172 return If((prot
& ~kAllowedMask
) == 0, Allow()).Else(CrashSIGSYS());
175 ResultExpr
RestrictFcntlCommands() {
176 // We also restrict the flags in F_SETFL. We don't want to permit flags with
177 // a history of trouble such as O_DIRECT. The flags you see are actually the
178 // allowed ones, and the variable is a "denied" mask because of the negation
180 // Glibc overrides the kernel's O_LARGEFILE value. Account for this.
181 uint64_t kOLargeFileFlag
= O_LARGEFILE
;
182 if (IsArchitectureX86_64() || IsArchitectureI386() || IsArchitectureMips())
183 kOLargeFileFlag
= 0100000;
185 const Arg
<int> cmd(1);
186 const Arg
<long> long_arg(2);
188 const uint64_t kAllowedMask
= O_ACCMODE
| O_APPEND
| O_NONBLOCK
| O_SYNC
|
189 kOLargeFileFlag
| O_CLOEXEC
| O_NOATIME
;
201 If((long_arg
& ~kAllowedMask
) == 0, Allow()).Else(CrashSIGSYS()))
202 .Default(CrashSIGSYS());
205 #if defined(__i386__) || defined(__mips__)
206 ResultExpr
RestrictSocketcallCommand() {
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 const Arg
<int> call(0);
213 .CASES((SYS_SOCKETPAIR
,
222 .Default(Error(EPERM
));
226 ResultExpr
RestrictKillTarget(pid_t target_pid
, int sysno
) {
230 const Arg
<pid_t
> pid(0);
231 return If(pid
== target_pid
, Allow()).Else(CrashSIGSYSKill());
234 return CrashSIGSYSKill();
237 return CrashSIGSYS();
241 ResultExpr
RestrictFutex() {
242 const uint64_t kAllowedFutexFlags
= FUTEX_PRIVATE_FLAG
| FUTEX_CLOCK_REALTIME
;
243 const Arg
<int> op(1);
244 return Switch(op
& ~kAllowedFutexFlags
)
253 .Default(CrashSIGSYSFutex());
256 ResultExpr
RestrictGetSetpriority(pid_t target_pid
) {
257 const Arg
<int> which(0);
258 const Arg
<int> who(1);
259 return If(which
== PRIO_PROCESS
,
260 If(who
== 0 || who
== target_pid
, Allow()).Else(Error(EPERM
)))
261 .Else(CrashSIGSYS());
264 ResultExpr
RestrictClockID() {
265 static_assert(4 == sizeof(clockid_t
), "clockid_t is not 32bit");
266 const Arg
<clockid_t
> clockid(0);
268 #if defined(OS_CHROMEOS)
269 // Allow the special clock for Chrome OS used by Chrome tracing.
270 clockid
== base::TimeTicks::kClockSystemTrace
||
272 clockid
== CLOCK_MONOTONIC
||
273 clockid
== CLOCK_PROCESS_CPUTIME_ID
||
274 clockid
== CLOCK_REALTIME
||
275 clockid
== CLOCK_THREAD_CPUTIME_ID
,
276 Allow()).Else(CrashSIGSYS());
279 ResultExpr
RestrictSchedTarget(pid_t target_pid
, int sysno
) {
281 case __NR_sched_getaffinity
:
282 case __NR_sched_getattr
:
283 case __NR_sched_getparam
:
284 case __NR_sched_getscheduler
:
285 case __NR_sched_rr_get_interval
:
286 case __NR_sched_setaffinity
:
287 case __NR_sched_setattr
:
288 case __NR_sched_setparam
:
289 case __NR_sched_setscheduler
: {
290 const Arg
<pid_t
> pid(0);
291 return If(pid
== 0 || pid
== target_pid
, Allow())
292 .Else(RewriteSchedSIGSYS());
296 return CrashSIGSYS();
300 ResultExpr
RestrictPrlimit64(pid_t target_pid
) {
301 const Arg
<pid_t
> pid(0);
302 return If(pid
== 0 || pid
== target_pid
, Allow()).Else(CrashSIGSYS());
305 ResultExpr
RestrictGetrusage() {
306 const Arg
<int> who(0);
307 return If(who
== RUSAGE_SELF
, Allow()).Else(CrashSIGSYS());
310 } // namespace sandbox.