• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
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>
10 #include <linux/net.h>
11 #include <sched.h>
12 #include <signal.h>
13 #include <stdint.h>
14 #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 
23 #include "base/logging.h"
24 #include "base/macros.h"
25 #include "build/build_config.h"
26 #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
27 #include "sandbox/linux/bpf_dsl/seccomp_macros.h"
28 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
29 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
30 #include "sandbox/linux/system_headers/linux_futex.h"
31 #include "sandbox/linux/system_headers/linux_syscalls.h"
32 #include "sandbox/linux/system_headers/linux_time.h"
33 
34 // PNaCl toolchain does not provide sys/ioctl.h header.
35 #if !defined(OS_NACL_NONSFI)
36 #include <sys/ioctl.h>
37 #endif
38 
39 #if defined(OS_ANDROID)
40 
41 #if !defined(F_DUPFD_CLOEXEC)
42 #define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
43 #endif
44 
45 // 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 #ifndef PR_SET_PTRACER
51 #define PR_SET_PTRACER 0x59616d61
52 #endif
53 
54 #endif  // defined(OS_ANDROID)
55 
56 #if defined(__arm__) && !defined(MAP_STACK)
57 #define MAP_STACK 0x20000  // Daisy build environment has old headers.
58 #endif
59 
60 #if defined(__mips__) && !defined(MAP_STACK)
61 #define MAP_STACK 0x40000
62 #endif
63 namespace {
64 
IsArchitectureX86_64()65 inline bool IsArchitectureX86_64() {
66 #if defined(__x86_64__)
67   return true;
68 #else
69   return false;
70 #endif
71 }
72 
IsArchitectureI386()73 inline bool IsArchitectureI386() {
74 #if defined(__i386__)
75   return true;
76 #else
77   return false;
78 #endif
79 }
80 
IsAndroid()81 inline bool IsAndroid() {
82 #if defined(OS_ANDROID)
83   return true;
84 #else
85   return false;
86 #endif
87 }
88 
IsArchitectureMips()89 inline bool IsArchitectureMips() {
90 #if defined(__mips__)
91   return true;
92 #else
93   return false;
94 #endif
95 }
96 
97 // Ubuntu's version of glibc has a race condition in sem_post that can cause
98 // it to call futex(2) with bogus op arguments. To workaround this, we need
99 // to allow those futex(2) calls to fail with EINVAL, instead of crashing the
100 // process. See crbug.com/598471.
IsBuggyGlibcSemPost()101 inline bool IsBuggyGlibcSemPost() {
102 #if defined(LIBC_GLIBC) && !defined(OS_CHROMEOS)
103   return true;
104 #else
105   return false;
106 #endif
107 }
108 
109 }  // namespace.
110 
111 #define CASES SANDBOX_BPF_DSL_CASES
112 
113 using sandbox::bpf_dsl::Allow;
114 using sandbox::bpf_dsl::Arg;
115 using sandbox::bpf_dsl::BoolExpr;
116 using sandbox::bpf_dsl::Error;
117 using sandbox::bpf_dsl::If;
118 using sandbox::bpf_dsl::ResultExpr;
119 
120 namespace sandbox {
121 
122 #if !defined(OS_NACL_NONSFI)
123 // Allow Glibc's and Android pthread creation flags, crash on any other
124 // thread creation attempts and EPERM attempts to use neither
125 // CLONE_VM, nor CLONE_THREAD, which includes all fork() implementations.
RestrictCloneToThreadsAndEPERMFork()126 ResultExpr RestrictCloneToThreadsAndEPERMFork() {
127   const Arg<unsigned long> flags(0);
128 
129   // TODO(mdempsky): Extend DSL to support (flags & ~mask1) == mask2.
130   const uint64_t kAndroidCloneMask = CLONE_VM | CLONE_FS | CLONE_FILES |
131                                      CLONE_SIGHAND | CLONE_THREAD |
132                                      CLONE_SYSVSEM;
133   const uint64_t kObsoleteAndroidCloneMask = kAndroidCloneMask | CLONE_DETACHED;
134 
135   const uint64_t kGlibcPthreadFlags =
136       CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD |
137       CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
138   const BoolExpr glibc_test = flags == kGlibcPthreadFlags;
139 
140   const BoolExpr android_test =
141       AnyOf(flags == kAndroidCloneMask, flags == kObsoleteAndroidCloneMask,
142             flags == kGlibcPthreadFlags);
143 
144   return If(IsAndroid() ? android_test : glibc_test, Allow())
145       .ElseIf((flags & (CLONE_VM | CLONE_THREAD)) == 0, Error(EPERM))
146       .Else(CrashSIGSYSClone());
147 }
148 
RestrictPrctl()149 ResultExpr RestrictPrctl() {
150   // Will need to add seccomp compositing in the future. PR_SET_PTRACER is
151   // used by breakpad but not needed anymore.
152   const Arg<int> option(0);
153   return Switch(option)
154       .CASES((PR_GET_NAME, PR_SET_NAME, PR_GET_DUMPABLE, PR_SET_DUMPABLE
155 #if defined(OS_ANDROID)
156               , PR_SET_VMA, PR_SET_PTRACER
157 
158 // Enable PR_SET_TIMERSLACK_PID, an Android custom prctl which is used in:
159 // https://android.googlesource.com/platform/system/core/+/lollipop-release/libcutils/sched_policy.c.
160 // Depending on the Android kernel version, this prctl may have different
161 // values. Since we don't know the correct value for the running kernel, we must
162 // allow them all.
163 //
164 // The effect is:
165 // On 3.14 kernels, this allows PR_SET_TIMERSLACK_PID and 43 and 127 (invalid
166 // prctls which will return EINVAL)
167 // On 3.18 kernels, this allows PR_SET_TIMERSLACK_PID, PR_SET_THP_DISABLE, and
168 // 127 (invalid).
169 // On 4.1 kernels and up, this allows PR_SET_TIMERSLACK_PID, PR_SET_THP_DISABLE,
170 // and PR_MPX_ENABLE_MANAGEMENT.
171 
172 // https://android.googlesource.com/kernel/common/+/android-3.14/include/uapi/linux/prctl.h
173 #define PR_SET_TIMERSLACK_PID_1 41
174 
175 // https://android.googlesource.com/kernel/common/+/android-3.18/include/uapi/linux/prctl.h
176 #define PR_SET_TIMERSLACK_PID_2 43
177 
178 // https://android.googlesource.com/kernel/common/+/android-4.1/include/uapi/linux/prctl.h and up
179 #define PR_SET_TIMERSLACK_PID_3 127
180 
181               , PR_SET_TIMERSLACK_PID_1
182               , PR_SET_TIMERSLACK_PID_2
183               , PR_SET_TIMERSLACK_PID_3
184 #endif  // defined(OS_ANDROID)
185               ),
186              Allow())
187       .Default(CrashSIGSYSPrctl());
188 }
189 
RestrictIoctl()190 ResultExpr RestrictIoctl() {
191   const Arg<int> request(1);
192   return Switch(request).CASES((TCGETS, FIONREAD), Allow()).Default(
193       CrashSIGSYSIoctl());
194 }
195 
RestrictMmapFlags()196 ResultExpr RestrictMmapFlags() {
197   // The flags you see are actually the allowed ones, and the variable is a
198   // "denied" mask because of the negation operator.
199   // Significantly, we don't permit MAP_HUGETLB, or the newer flags such as
200   // MAP_POPULATE.
201   // TODO(davidung), remove MAP_DENYWRITE with updated Tegra libraries.
202   const uint64_t kAllowedMask = MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS |
203                                 MAP_STACK | MAP_NORESERVE | MAP_FIXED |
204                                 MAP_DENYWRITE;
205   const Arg<int> flags(3);
206   return If((flags & ~kAllowedMask) == 0, Allow()).Else(CrashSIGSYS());
207 }
208 
RestrictMprotectFlags()209 ResultExpr RestrictMprotectFlags() {
210   // The flags you see are actually the allowed ones, and the variable is a
211   // "denied" mask because of the negation operator.
212   // Significantly, we don't permit weird undocumented flags such as
213   // PROT_GROWSDOWN.
214   const uint64_t kAllowedMask = PROT_READ | PROT_WRITE | PROT_EXEC;
215   const Arg<int> prot(2);
216   return If((prot & ~kAllowedMask) == 0, Allow()).Else(CrashSIGSYS());
217 }
218 
RestrictFcntlCommands()219 ResultExpr RestrictFcntlCommands() {
220   // We also restrict the flags in F_SETFL. We don't want to permit flags with
221   // a history of trouble such as O_DIRECT. The flags you see are actually the
222   // allowed ones, and the variable is a "denied" mask because of the negation
223   // operator.
224   // Glibc overrides the kernel's O_LARGEFILE value. Account for this.
225   uint64_t kOLargeFileFlag = O_LARGEFILE;
226   if (IsArchitectureX86_64() || IsArchitectureI386() || IsArchitectureMips())
227     kOLargeFileFlag = 0100000;
228 
229   const Arg<int> cmd(1);
230   const Arg<long> long_arg(2);
231 
232   const uint64_t kAllowedMask = O_ACCMODE | O_APPEND | O_NONBLOCK | O_SYNC |
233                                 kOLargeFileFlag | O_CLOEXEC | O_NOATIME;
234   return Switch(cmd)
235       .CASES((F_GETFL,
236               F_GETFD,
237               F_SETFD,
238               F_SETLK,
239               F_SETLKW,
240               F_GETLK,
241               F_DUPFD,
242               F_DUPFD_CLOEXEC),
243              Allow())
244       .Case(F_SETFL,
245             If((long_arg & ~kAllowedMask) == 0, Allow()).Else(CrashSIGSYS()))
246       .Default(CrashSIGSYS());
247 }
248 
249 #if defined(__i386__) || defined(__mips__)
RestrictSocketcallCommand()250 ResultExpr RestrictSocketcallCommand() {
251   // Unfortunately, we are unable to restrict the first parameter to
252   // socketpair(2). Whilst initially sounding bad, it's noteworthy that very
253   // few protocols actually support socketpair(2). The scary call that we're
254   // worried about, socket(2), remains blocked.
255   const Arg<int> call(0);
256   return Switch(call)
257       .CASES((SYS_SOCKETPAIR,
258               SYS_SHUTDOWN,
259               SYS_RECV,
260               SYS_SEND,
261               SYS_RECVFROM,
262               SYS_SENDTO,
263               SYS_RECVMSG,
264               SYS_SENDMSG),
265              Allow())
266       .Default(Error(EPERM));
267 }
268 #endif
269 
RestrictKillTarget(pid_t target_pid,int sysno)270 ResultExpr RestrictKillTarget(pid_t target_pid, int sysno) {
271   switch (sysno) {
272     case __NR_kill:
273     case __NR_tgkill: {
274       const Arg<pid_t> pid(0);
275       return If(pid == target_pid, Allow()).Else(CrashSIGSYSKill());
276     }
277     case __NR_tkill:
278       return CrashSIGSYSKill();
279     default:
280       NOTREACHED();
281       return CrashSIGSYS();
282   }
283 }
284 
RestrictFutex()285 ResultExpr RestrictFutex() {
286   const uint64_t kAllowedFutexFlags = FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME;
287   const Arg<int> op(1);
288   return Switch(op & ~kAllowedFutexFlags)
289       .CASES((FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE, FUTEX_CMP_REQUEUE,
290               FUTEX_WAKE_OP, FUTEX_WAIT_BITSET, FUTEX_WAKE_BITSET),
291              Allow())
292       .Default(IsBuggyGlibcSemPost() ? Error(EINVAL) : CrashSIGSYSFutex());
293 }
294 
RestrictGetSetpriority(pid_t target_pid)295 ResultExpr RestrictGetSetpriority(pid_t target_pid) {
296   const Arg<int> which(0);
297   const Arg<int> who(1);
298   return If(which == PRIO_PROCESS,
299             Switch(who).CASES((0, target_pid), Allow()).Default(Error(EPERM)))
300       .Else(CrashSIGSYS());
301 }
302 
RestrictSchedTarget(pid_t target_pid,int sysno)303 ResultExpr RestrictSchedTarget(pid_t target_pid, int sysno) {
304   switch (sysno) {
305     case __NR_sched_getaffinity:
306     case __NR_sched_getattr:
307     case __NR_sched_getparam:
308     case __NR_sched_getscheduler:
309     case __NR_sched_rr_get_interval:
310     case __NR_sched_setaffinity:
311     case __NR_sched_setattr:
312     case __NR_sched_setparam:
313     case __NR_sched_setscheduler: {
314       const Arg<pid_t> pid(0);
315       return Switch(pid)
316           .CASES((0, target_pid), Allow())
317           .Default(RewriteSchedSIGSYS());
318     }
319     default:
320       NOTREACHED();
321       return CrashSIGSYS();
322   }
323 }
324 
RestrictPrlimit64(pid_t target_pid)325 ResultExpr RestrictPrlimit64(pid_t target_pid) {
326   const Arg<pid_t> pid(0);
327   return Switch(pid).CASES((0, target_pid), Allow()).Default(CrashSIGSYS());
328 }
329 
RestrictGetrusage()330 ResultExpr RestrictGetrusage() {
331   const Arg<int> who(0);
332   return If(who == RUSAGE_SELF, Allow()).Else(CrashSIGSYS());
333 }
334 #endif  // !defined(OS_NACL_NONSFI)
335 
RestrictClockID()336 ResultExpr RestrictClockID() {
337   static_assert(4 == sizeof(clockid_t), "clockid_t is not 32bit");
338   const Arg<clockid_t> clockid(0);
339   return Switch(clockid)
340       .CASES((
341 #if defined(OS_ANDROID)
342               CLOCK_BOOTTIME,
343 #endif
344               CLOCK_MONOTONIC,
345               CLOCK_MONOTONIC_COARSE,
346               CLOCK_PROCESS_CPUTIME_ID,
347               CLOCK_REALTIME,
348               CLOCK_REALTIME_COARSE,
349               CLOCK_THREAD_CPUTIME_ID),
350              Allow())
351       .Default(CrashSIGSYS());
352 }
353 
354 }  // namespace sandbox.
355