Upstream version 7.36.149.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/net.h>
11 #include <sched.h>
12 #include <signal.h>
13 #include <sys/ioctl.h>
14 #include <sys/mman.h>
15 #include <sys/prctl.h>
16 #include <sys/stat.h>
17 #include <sys/types.h>
18 #include <unistd.h>
19
20 #include "base/basictypes.h"
21 #include "base/logging.h"
22 #include "build/build_config.h"
23 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
24 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
25 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
26
27 #if defined(OS_ANDROID)
28 #if !defined(F_DUPFD_CLOEXEC)
29 #define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
30 #endif
31 #endif
32
33 #if defined(__arm__) && !defined(MAP_STACK)
34 #define MAP_STACK 0x20000  // Daisy build environment has old headers.
35 #endif
36
37 namespace {
38
39 inline bool IsArchitectureX86_64() {
40 #if defined(__x86_64__)
41   return true;
42 #else
43   return false;
44 #endif
45 }
46
47 inline bool IsArchitectureI386() {
48 #if defined(__i386__)
49   return true;
50 #else
51   return false;
52 #endif
53 }
54
55 inline bool IsAndroid() {
56 #if defined(OS_ANDROID)
57   return true;
58 #else
59   return false;
60 #endif
61 }
62
63 }  // namespace.
64
65 namespace sandbox {
66
67 // Allow Glibc's and Android pthread creation flags, crash on any other
68 // thread creation attempts and EPERM attempts to use neither
69 // CLONE_VM, nor CLONE_THREAD, which includes all fork() implementations.
70 ErrorCode RestrictCloneToThreadsAndEPERMFork(SandboxBPF* sandbox) {
71   if (!IsAndroid()) {
72     const uint64_t kGlibcPthreadFlags =
73         CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD |
74         CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID |
75         CLONE_CHILD_CLEARTID;
76
77     return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
78                          kGlibcPthreadFlags,
79                          ErrorCode(ErrorCode::ERR_ALLOWED),
80            sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS,
81                          CLONE_VM | CLONE_THREAD,
82                          sandbox->Trap(SIGSYSCloneFailure, NULL),
83                          ErrorCode(EPERM)));
84   } else {
85     const uint64_t kAndroidCloneMask = CLONE_VM | CLONE_FS | CLONE_FILES |
86                                        CLONE_SIGHAND | CLONE_THREAD |
87                                        CLONE_SYSVSEM;
88     const uint64_t kObsoleteAndroidCloneMask =
89         kAndroidCloneMask | CLONE_DETACHED;
90
91     return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
92                          kAndroidCloneMask,
93                          ErrorCode(ErrorCode::ERR_ALLOWED),
94            sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
95                          kObsoleteAndroidCloneMask,
96                          ErrorCode(ErrorCode::ERR_ALLOWED),
97            sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS,
98                          CLONE_VM | CLONE_THREAD,
99                          sandbox->Trap(SIGSYSCloneFailure, NULL),
100                          ErrorCode(EPERM))));
101   }
102 }
103
104 ErrorCode RestrictPrctl(SandboxBPF* sandbox) {
105   // Will need to add seccomp compositing in the future. PR_SET_PTRACER is
106   // used by breakpad but not needed anymore.
107   return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
108                        PR_SET_NAME, ErrorCode(ErrorCode::ERR_ALLOWED),
109          sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
110                        PR_SET_DUMPABLE, ErrorCode(ErrorCode::ERR_ALLOWED),
111          sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
112                        PR_GET_DUMPABLE, ErrorCode(ErrorCode::ERR_ALLOWED),
113          sandbox->Trap(SIGSYSPrctlFailure, NULL))));
114 }
115
116 ErrorCode RestrictIoctl(SandboxBPF* sandbox) {
117   return sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, TCGETS,
118                        ErrorCode(ErrorCode::ERR_ALLOWED),
119          sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, FIONREAD,
120                        ErrorCode(ErrorCode::ERR_ALLOWED),
121                        sandbox->Trap(SIGSYSIoctlFailure, NULL)));
122 }
123
124 ErrorCode RestrictMmapFlags(SandboxBPF* sandbox) {
125   // The flags you see are actually the allowed ones, and the variable is a
126   // "denied" mask because of the negation operator.
127   // Significantly, we don't permit MAP_HUGETLB, or the newer flags such as
128   // MAP_POPULATE.
129   // TODO(davidung), remove MAP_DENYWRITE with updated Tegra libraries.
130   uint32_t denied_mask = ~(MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS |
131                            MAP_STACK | MAP_NORESERVE | MAP_FIXED |
132                            MAP_DENYWRITE);
133   return sandbox->Cond(3, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS,
134                        denied_mask,
135                        sandbox->Trap(CrashSIGSYS_Handler, NULL),
136                        ErrorCode(ErrorCode::ERR_ALLOWED));
137 }
138
139 ErrorCode RestrictMprotectFlags(SandboxBPF* sandbox) {
140   // The flags you see are actually the allowed ones, and the variable is a
141   // "denied" mask because of the negation operator.
142   // Significantly, we don't permit weird undocumented flags such as
143   // PROT_GROWSDOWN.
144   uint32_t denied_mask = ~(PROT_READ | PROT_WRITE | PROT_EXEC);
145   return sandbox->Cond(2, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS,
146                        denied_mask,
147                        sandbox->Trap(CrashSIGSYS_Handler, NULL),
148                        ErrorCode(ErrorCode::ERR_ALLOWED));
149 }
150
151 ErrorCode RestrictFcntlCommands(SandboxBPF* sandbox) {
152   // We also restrict the flags in F_SETFL. We don't want to permit flags with
153   // a history of trouble such as O_DIRECT. The flags you see are actually the
154   // allowed ones, and the variable is a "denied" mask because of the negation
155   // operator.
156   // Glibc overrides the kernel's O_LARGEFILE value. Account for this.
157   int kOLargeFileFlag = O_LARGEFILE;
158   if (IsArchitectureX86_64() || IsArchitectureI386())
159     kOLargeFileFlag = 0100000;
160
161   // TODO(jln): add TP_LONG/TP_SIZET types.
162   ErrorCode::ArgType mask_long_type;
163   if (sizeof(long) == 8)
164     mask_long_type = ErrorCode::TP_64BIT;
165   else if (sizeof(long) == 4)
166     mask_long_type = ErrorCode::TP_32BIT;
167   else
168     NOTREACHED();
169
170   unsigned long denied_mask = ~(O_ACCMODE | O_APPEND | O_NONBLOCK | O_SYNC |
171                                 kOLargeFileFlag | O_CLOEXEC | O_NOATIME);
172   return sandbox->Cond(1, ErrorCode::TP_32BIT,
173                        ErrorCode::OP_EQUAL, F_GETFL,
174                        ErrorCode(ErrorCode::ERR_ALLOWED),
175          sandbox->Cond(1, ErrorCode::TP_32BIT,
176                        ErrorCode::OP_EQUAL, F_SETFL,
177                        sandbox->Cond(2, mask_long_type,
178                                      ErrorCode::OP_HAS_ANY_BITS, denied_mask,
179                                      sandbox->Trap(CrashSIGSYS_Handler, NULL),
180                                      ErrorCode(ErrorCode::ERR_ALLOWED)),
181          sandbox->Cond(1, ErrorCode::TP_32BIT,
182                        ErrorCode::OP_EQUAL, F_GETFD,
183                        ErrorCode(ErrorCode::ERR_ALLOWED),
184          sandbox->Cond(1, ErrorCode::TP_32BIT,
185                        ErrorCode::OP_EQUAL, F_SETFD,
186                        ErrorCode(ErrorCode::ERR_ALLOWED),
187          sandbox->Cond(1, ErrorCode::TP_32BIT,
188                        ErrorCode::OP_EQUAL, F_DUPFD,
189                        ErrorCode(ErrorCode::ERR_ALLOWED),
190          sandbox->Cond(1, ErrorCode::TP_32BIT,
191                        ErrorCode::OP_EQUAL, F_SETLK,
192                        ErrorCode(ErrorCode::ERR_ALLOWED),
193          sandbox->Cond(1, ErrorCode::TP_32BIT,
194                        ErrorCode::OP_EQUAL, F_SETLKW,
195                        ErrorCode(ErrorCode::ERR_ALLOWED),
196          sandbox->Cond(1, ErrorCode::TP_32BIT,
197                        ErrorCode::OP_EQUAL, F_GETLK,
198                        ErrorCode(ErrorCode::ERR_ALLOWED),
199          sandbox->Cond(1, ErrorCode::TP_32BIT,
200                        ErrorCode::OP_EQUAL, F_DUPFD_CLOEXEC,
201                        ErrorCode(ErrorCode::ERR_ALLOWED),
202          sandbox->Trap(CrashSIGSYS_Handler, NULL))))))))));
203 }
204
205 #if defined(__i386__)
206 ErrorCode RestrictSocketcallCommand(SandboxBPF* sandbox) {
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   return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
212                        SYS_SOCKETPAIR, ErrorCode(ErrorCode::ERR_ALLOWED),
213          sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
214                        SYS_SEND, ErrorCode(ErrorCode::ERR_ALLOWED),
215          sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
216                        SYS_RECV, ErrorCode(ErrorCode::ERR_ALLOWED),
217          sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
218                        SYS_SENDTO, ErrorCode(ErrorCode::ERR_ALLOWED),
219          sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
220                        SYS_RECVFROM, ErrorCode(ErrorCode::ERR_ALLOWED),
221          sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
222                        SYS_SHUTDOWN, ErrorCode(ErrorCode::ERR_ALLOWED),
223          sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
224                        SYS_SENDMSG, ErrorCode(ErrorCode::ERR_ALLOWED),
225          sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
226                        SYS_RECVMSG, ErrorCode(ErrorCode::ERR_ALLOWED),
227          ErrorCode(EPERM)))))))));
228 }
229 #endif
230
231 ErrorCode RestrictKillTarget(pid_t target_pid, SandboxBPF* sandbox, int sysno) {
232   switch (sysno) {
233     case __NR_kill:
234     case __NR_tgkill:
235       return sandbox->Cond(0,
236                            ErrorCode::TP_32BIT,
237                            ErrorCode::OP_EQUAL,
238                            target_pid,
239                            ErrorCode(ErrorCode::ERR_ALLOWED),
240                            sandbox->Trap(SIGSYSKillFailure, NULL));
241     case __NR_tkill:
242       return sandbox->Trap(SIGSYSKillFailure, NULL);
243     default:
244       NOTREACHED();
245       return sandbox->Trap(CrashSIGSYS_Handler, NULL);
246   }
247 }
248
249 }  // namespace sandbox.