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