Update To 11.40.268.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/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"
34
35 #if defined(OS_ANDROID)
36
37 #include "sandbox/linux/services/android_futex.h"
38
39 #if !defined(F_DUPFD_CLOEXEC)
40 #define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
41 #endif
42
43 #endif  // defined(OS_ANDROID)
44
45 #if defined(__arm__) && !defined(MAP_STACK)
46 #define MAP_STACK 0x20000  // Daisy build environment has old headers.
47 #endif
48
49 #if defined(__mips__) && !defined(MAP_STACK)
50 #define MAP_STACK 0x40000
51 #endif
52 namespace {
53
54 inline bool IsArchitectureX86_64() {
55 #if defined(__x86_64__)
56   return true;
57 #else
58   return false;
59 #endif
60 }
61
62 inline bool IsArchitectureI386() {
63 #if defined(__i386__)
64   return true;
65 #else
66   return false;
67 #endif
68 }
69
70 inline bool IsAndroid() {
71 #if defined(OS_ANDROID)
72   return true;
73 #else
74   return false;
75 #endif
76 }
77
78 inline bool IsArchitectureMips() {
79 #if defined(__mips__)
80   return true;
81 #else
82   return false;
83 #endif
84 }
85
86 }  // namespace.
87
88 #define CASES SANDBOX_BPF_DSL_CASES
89
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;
96
97 namespace sandbox {
98
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);
104
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;
110
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;
115
116   const BoolExpr android_test = flags == kAndroidCloneMask ||
117                                 flags == kObsoleteAndroidCloneMask ||
118                                 flags == kGlibcPthreadFlags;
119
120   return If(IsAndroid() ? android_test : glibc_test, Allow())
121       .ElseIf((flags & (CLONE_VM | CLONE_THREAD)) == 0, Error(EPERM))
122       .Else(CrashSIGSYSClone());
123 }
124
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());
133 }
134
135 ResultExpr RestrictIoctl() {
136   const Arg<int> request(1);
137   return Switch(request).CASES((TCGETS, FIONREAD), Allow()).Default(
138       CrashSIGSYSIoctl());
139 }
140
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());
152 }
153
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());
162 }
163
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;
173
174   const Arg<int> cmd(1);
175   const Arg<long> long_arg(2);
176
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());
192 }
193
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));
212 }
213 #endif
214
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());
221     }
222     case __NR_tkill:
223       return CrashSIGSYSKill();
224     default:
225       NOTREACHED();
226       return CrashSIGSYS();
227   }
228 }
229
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());
243 }
244
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());
251 }
252
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());
266 }
267
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());
282     }
283     default:
284       NOTREACHED();
285       return CrashSIGSYS();
286   }
287 }
288
289
290 }  // namespace sandbox.