Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / sandbox / linux / seccomp-bpf / trap.cc
1 // Copyright (c) 2012 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/trap.h"
6
7 #include <errno.h>
8 #include <signal.h>
9 #include <string.h>
10 #include <sys/syscall.h>
11
12 #include <algorithm>
13 #include <limits>
14
15 #include "base/logging.h"
16 #include "build/build_config.h"
17 #include "sandbox/linux/seccomp-bpf/die.h"
18 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
19 #include "sandbox/linux/seccomp-bpf/syscall.h"
20
21 // Android's signal.h doesn't define ucontext etc.
22 #if defined(OS_ANDROID)
23 #include "sandbox/linux/services/android_ucontext.h"
24 #endif
25
26 namespace {
27
28 struct arch_sigsys {
29   void* ip;
30   int nr;
31   unsigned int arch;
32 };
33
34 const int kCapacityIncrement = 20;
35
36 // Unsafe traps can only be turned on, if the user explicitly allowed them
37 // by setting the CHROME_SANDBOX_DEBUGGING environment variable.
38 const char kSandboxDebuggingEnv[] = "CHROME_SANDBOX_DEBUGGING";
39
40 // We need to tell whether we are performing a "normal" callback, or
41 // whether we were called recursively from within a UnsafeTrap() callback.
42 // This is a little tricky to do, because we need to somehow get access to
43 // per-thread data from within a signal context. Normal TLS storage is not
44 // safely accessible at this time. We could roll our own, but that involves
45 // a lot of complexity. Instead, we co-opt one bit in the signal mask.
46 // If BUS is blocked, we assume that we have been called recursively.
47 // There is a possibility for collision with other code that needs to do
48 // this, but in practice the risks are low.
49 // If SIGBUS turns out to be a problem, we could instead co-opt one of the
50 // realtime signals. There are plenty of them. Unfortunately, there is no
51 // way to mark a signal as allocated. So, the potential for collision is
52 // possibly even worse.
53 bool GetIsInSigHandler(const ucontext_t* ctx) {
54   // Note: on Android, sigismember does not take a pointer to const.
55   return sigismember(const_cast<sigset_t*>(&ctx->uc_sigmask), SIGBUS);
56 }
57
58 void SetIsInSigHandler() {
59   sigset_t mask;
60   if (sigemptyset(&mask) || sigaddset(&mask, SIGBUS) ||
61       sigprocmask(SIG_BLOCK, &mask, NULL)) {
62     SANDBOX_DIE("Failed to block SIGBUS");
63   }
64 }
65
66 bool IsDefaultSignalAction(const struct sigaction& sa) {
67   if (sa.sa_flags & SA_SIGINFO || sa.sa_handler != SIG_DFL) {
68     return false;
69   }
70   return true;
71 }
72
73 }  // namespace
74
75 namespace sandbox {
76
77 Trap::Trap()
78     : trap_array_(NULL),
79       trap_array_size_(0),
80       trap_array_capacity_(0),
81       has_unsafe_traps_(false) {
82   // Set new SIGSYS handler
83   struct sigaction sa = {};
84   sa.sa_sigaction = SigSysAction;
85   sa.sa_flags = SA_SIGINFO | SA_NODEFER;
86   struct sigaction old_sa;
87   if (sigaction(SIGSYS, &sa, &old_sa) < 0) {
88     SANDBOX_DIE("Failed to configure SIGSYS handler");
89   }
90
91   if (!IsDefaultSignalAction(old_sa)) {
92     static const char kExistingSIGSYSMsg[] =
93         "Existing signal handler when trying to install SIGSYS. SIGSYS needs "
94         "to be reserved for seccomp-bpf.";
95     DLOG(FATAL) << kExistingSIGSYSMsg;
96     LOG(ERROR) << kExistingSIGSYSMsg;
97   }
98
99   // Unmask SIGSYS
100   sigset_t mask;
101   if (sigemptyset(&mask) || sigaddset(&mask, SIGSYS) ||
102       sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
103     SANDBOX_DIE("Failed to configure SIGSYS handler");
104   }
105 }
106
107 Trap* Trap::GetInstance() {
108   // Note: This class is not thread safe. It is the caller's responsibility
109   // to avoid race conditions. Normally, this is a non-issue as the sandbox
110   // can only be initialized if there are no other threads present.
111   // Also, this is not a normal singleton. Once created, the global trap
112   // object must never be destroyed again.
113   if (!global_trap_) {
114     global_trap_ = new Trap();
115     if (!global_trap_) {
116       SANDBOX_DIE("Failed to allocate global trap handler");
117     }
118   }
119   return global_trap_;
120 }
121
122 void Trap::SigSysAction(int nr, siginfo_t* info, void* void_context) {
123   if (!global_trap_) {
124     RAW_SANDBOX_DIE(
125         "This can't happen. Found no global singleton instance "
126         "for Trap() handling.");
127   }
128   global_trap_->SigSys(nr, info, void_context);
129 }
130
131 void Trap::SigSys(int nr, siginfo_t* info, void* void_context) {
132   // Signal handlers should always preserve "errno". Otherwise, we could
133   // trigger really subtle bugs.
134   const int old_errno = errno;
135
136   // Various sanity checks to make sure we actually received a signal
137   // triggered by a BPF filter. If something else triggered SIGSYS
138   // (e.g. kill()), there is really nothing we can do with this signal.
139   if (nr != SIGSYS || info->si_code != SYS_SECCOMP || !void_context ||
140       info->si_errno <= 0 ||
141       static_cast<size_t>(info->si_errno) > trap_array_size_) {
142     // ATI drivers seem to send SIGSYS, so this cannot be FATAL.
143     // See crbug.com/178166.
144     // TODO(jln): add a DCHECK or move back to FATAL.
145     RAW_LOG(ERROR, "Unexpected SIGSYS received.");
146     errno = old_errno;
147     return;
148   }
149
150   // Obtain the signal context. This, most notably, gives us access to
151   // all CPU registers at the time of the signal.
152   ucontext_t* ctx = reinterpret_cast<ucontext_t*>(void_context);
153
154   // Obtain the siginfo information that is specific to SIGSYS. Unfortunately,
155   // most versions of glibc don't include this information in siginfo_t. So,
156   // we need to explicitly copy it into a arch_sigsys structure.
157   struct arch_sigsys sigsys;
158   memcpy(&sigsys, &info->_sifields, sizeof(sigsys));
159
160 #if defined(__mips__)
161   // When indirect syscall (syscall(__NR_foo, ...)) is made on Mips, the
162   // number in register SECCOMP_SYSCALL(ctx) is always __NR_syscall and the
163   // real number of a syscall (__NR_foo) is in SECCOMP_PARM1(ctx)
164   bool sigsys_nr_is_bad = sigsys.nr != static_cast<int>(SECCOMP_SYSCALL(ctx)) &&
165                           sigsys.nr != static_cast<int>(SECCOMP_PARM1(ctx));
166 #else
167   bool sigsys_nr_is_bad = sigsys.nr != static_cast<int>(SECCOMP_SYSCALL(ctx));
168 #endif
169
170   // Some more sanity checks.
171   if (sigsys.ip != reinterpret_cast<void*>(SECCOMP_IP(ctx)) ||
172       sigsys_nr_is_bad || sigsys.arch != SECCOMP_ARCH) {
173     // TODO(markus):
174     // SANDBOX_DIE() can call LOG(FATAL). This is not normally async-signal
175     // safe and can lead to bugs. We should eventually implement a different
176     // logging and reporting mechanism that is safe to be called from
177     // the sigSys() handler.
178     RAW_SANDBOX_DIE("Sanity checks are failing after receiving SIGSYS.");
179   }
180
181   intptr_t rc;
182   if (has_unsafe_traps_ && GetIsInSigHandler(ctx)) {
183     errno = old_errno;
184     if (sigsys.nr == __NR_clone) {
185       RAW_SANDBOX_DIE("Cannot call clone() from an UnsafeTrap() handler.");
186     }
187 #if defined(__mips__)
188     // Mips supports up to eight arguments for syscall.
189     // However, seccomp bpf can filter only up to six arguments, so using eight
190     // arguments has sense only when using UnsafeTrap() handler.
191     rc = Syscall::Call(SECCOMP_SYSCALL(ctx),
192                        SECCOMP_PARM1(ctx),
193                        SECCOMP_PARM2(ctx),
194                        SECCOMP_PARM3(ctx),
195                        SECCOMP_PARM4(ctx),
196                        SECCOMP_PARM5(ctx),
197                        SECCOMP_PARM6(ctx),
198                        SECCOMP_PARM7(ctx),
199                        SECCOMP_PARM8(ctx));
200 #else
201     rc = Syscall::Call(SECCOMP_SYSCALL(ctx),
202                        SECCOMP_PARM1(ctx),
203                        SECCOMP_PARM2(ctx),
204                        SECCOMP_PARM3(ctx),
205                        SECCOMP_PARM4(ctx),
206                        SECCOMP_PARM5(ctx),
207                        SECCOMP_PARM6(ctx));
208 #endif  // defined(__mips__)
209   } else {
210     const TrapKey& trap = trap_array_[info->si_errno - 1];
211     if (!trap.safe) {
212       SetIsInSigHandler();
213     }
214
215     // Copy the seccomp-specific data into a arch_seccomp_data structure. This
216     // is what we are showing to TrapFnc callbacks that the system call
217     // evaluator registered with the sandbox.
218     struct arch_seccomp_data data = {
219         static_cast<int>(SECCOMP_SYSCALL(ctx)),
220         SECCOMP_ARCH,
221         reinterpret_cast<uint64_t>(sigsys.ip),
222         {static_cast<uint64_t>(SECCOMP_PARM1(ctx)),
223          static_cast<uint64_t>(SECCOMP_PARM2(ctx)),
224          static_cast<uint64_t>(SECCOMP_PARM3(ctx)),
225          static_cast<uint64_t>(SECCOMP_PARM4(ctx)),
226          static_cast<uint64_t>(SECCOMP_PARM5(ctx)),
227          static_cast<uint64_t>(SECCOMP_PARM6(ctx))}};
228
229     // Now call the TrapFnc callback associated with this particular instance
230     // of SECCOMP_RET_TRAP.
231     rc = trap.fnc(data, const_cast<void*>(trap.aux));
232   }
233
234   // Update the CPU register that stores the return code of the system call
235   // that we just handled, and restore "errno" to the value that it had
236   // before entering the signal handler.
237   Syscall::PutValueInUcontext(rc, ctx);
238   errno = old_errno;
239
240   return;
241 }
242
243 bool Trap::TrapKey::operator<(const TrapKey& o) const {
244   if (fnc != o.fnc) {
245     return fnc < o.fnc;
246   } else if (aux != o.aux) {
247     return aux < o.aux;
248   } else {
249     return safe < o.safe;
250   }
251 }
252
253 uint16_t Trap::MakeTrap(TrapFnc fnc, const void* aux, bool safe) {
254   return GetInstance()->MakeTrapImpl(fnc, aux, safe);
255 }
256
257 uint16_t Trap::MakeTrapImpl(TrapFnc fnc, const void* aux, bool safe) {
258   if (!safe && !SandboxDebuggingAllowedByUser()) {
259     // Unless the user set the CHROME_SANDBOX_DEBUGGING environment variable,
260     // we never return an ErrorCode that is marked as "unsafe". This also
261     // means, the BPF compiler will never emit code that allow unsafe system
262     // calls to by-pass the filter (because they use the magic return address
263     // from Syscall::Call(-1)).
264
265     // This SANDBOX_DIE() can optionally be removed. It won't break security,
266     // but it might make error messages from the BPF compiler a little harder
267     // to understand. Removing the SANDBOX_DIE() allows callers to easily check
268     // whether unsafe traps are supported (by checking whether the returned
269     // ErrorCode is ET_INVALID).
270     SANDBOX_DIE(
271         "Cannot use unsafe traps unless CHROME_SANDBOX_DEBUGGING "
272         "is enabled");
273
274     return 0;
275   }
276
277   // Each unique pair of TrapFnc and auxiliary data make up a distinct instance
278   // of a SECCOMP_RET_TRAP.
279   TrapKey key(fnc, aux, safe);
280
281   // We return unique identifiers together with SECCOMP_RET_TRAP. This allows
282   // us to associate trap with the appropriate handler. The kernel allows us
283   // identifiers in the range from 0 to SECCOMP_RET_DATA (0xFFFF). We want to
284   // avoid 0, as it could be confused for a trap without any specific id.
285   // The nice thing about sequentially numbered identifiers is that we can also
286   // trivially look them up from our signal handler without making any system
287   // calls that might be async-signal-unsafe.
288   // In order to do so, we store all of our traps in a C-style trap_array_.
289
290   TrapIds::const_iterator iter = trap_ids_.find(key);
291   if (iter != trap_ids_.end()) {
292     // We have seen this pair before. Return the same id that we assigned
293     // earlier.
294     return iter->second;
295   }
296
297   // This is a new pair. Remember it and assign a new id.
298   if (trap_array_size_ >= SECCOMP_RET_DATA /* 0xFFFF */ ||
299       trap_array_size_ >= std::numeric_limits<uint16_t>::max()) {
300     // In practice, this is pretty much impossible to trigger, as there
301     // are other kernel limitations that restrict overall BPF program sizes.
302     SANDBOX_DIE("Too many SECCOMP_RET_TRAP callback instances");
303   }
304
305   // Our callers ensure that there are no other threads accessing trap_array_
306   // concurrently (typically this is done by ensuring that we are single-
307   // threaded while the sandbox is being set up). But we nonetheless are
308   // modifying a live data structure that could be accessed any time a
309   // system call is made; as system calls could be triggering SIGSYS.
310   // So, we have to be extra careful that we update trap_array_ atomically.
311   // In particular, this means we shouldn't be using realloc() to resize it.
312   // Instead, we allocate a new array, copy the values, and then switch the
313   // pointer. We only really care about the pointer being updated atomically
314   // and the data that is pointed to being valid, as these are the only
315   // values accessed from the signal handler. It is OK if trap_array_size_
316   // is inconsistent with the pointer, as it is monotonously increasing.
317   // Also, we only care about compiler barriers, as the signal handler is
318   // triggered synchronously from a system call. We don't have to protect
319   // against issues with the memory model or with completely asynchronous
320   // events.
321   if (trap_array_size_ >= trap_array_capacity_) {
322     trap_array_capacity_ += kCapacityIncrement;
323     TrapKey* old_trap_array = trap_array_;
324     TrapKey* new_trap_array = new TrapKey[trap_array_capacity_];
325     std::copy_n(old_trap_array, trap_array_size_, new_trap_array);
326
327     // Language specs are unclear on whether the compiler is allowed to move
328     // the "delete[]" above our preceding assignments and/or memory moves,
329     // iff the compiler believes that "delete[]" doesn't have any other
330     // global side-effects.
331     // We insert optimization barriers to prevent this from happening.
332     // The first barrier is probably not needed, but better be explicit in
333     // what we want to tell the compiler.
334     // The clang developer mailing list couldn't answer whether this is a
335     // legitimate worry; but they at least thought that the barrier is
336     // sufficient to prevent the (so far hypothetical) problem of re-ordering
337     // of instructions by the compiler.
338     //
339     // TODO(mdempsky): Try to clean this up using base/atomicops or C++11
340     // atomics; see crbug.com/414363.
341     asm volatile("" : "=r"(new_trap_array) : "0"(new_trap_array) : "memory");
342     trap_array_ = new_trap_array;
343     asm volatile("" : "=r"(trap_array_) : "0"(trap_array_) : "memory");
344
345     delete[] old_trap_array;
346   }
347
348   uint16_t id = trap_array_size_ + 1;
349   trap_ids_[key] = id;
350   trap_array_[trap_array_size_] = key;
351   trap_array_size_++;
352   return id;
353 }
354
355 bool Trap::SandboxDebuggingAllowedByUser() const {
356   const char* debug_flag = getenv(kSandboxDebuggingEnv);
357   return debug_flag && *debug_flag;
358 }
359
360 bool Trap::EnableUnsafeTrapsInSigSysHandler() {
361   Trap* trap = GetInstance();
362   if (!trap->has_unsafe_traps_) {
363     // Unsafe traps are a one-way fuse. Once enabled, they can never be turned
364     // off again.
365     // We only allow enabling unsafe traps, if the user explicitly set an
366     // appropriate environment variable. This prevents bugs that accidentally
367     // disable all sandboxing for all users.
368     if (trap->SandboxDebuggingAllowedByUser()) {
369       // We only ever print this message once, when we enable unsafe traps the
370       // first time.
371       SANDBOX_INFO("WARNING! Disabling sandbox for debugging purposes");
372       trap->has_unsafe_traps_ = true;
373     } else {
374       SANDBOX_INFO(
375           "Cannot disable sandbox and use unsafe traps unless "
376           "CHROME_SANDBOX_DEBUGGING is turned on first");
377     }
378   }
379   // Returns the, possibly updated, value of has_unsafe_traps_.
380   return trap->has_unsafe_traps_;
381 }
382
383 bool Trap::IsSafeTrapId(uint16_t id) {
384   if (global_trap_ && id > 0 && id <= global_trap_->trap_array_size_) {
385     return global_trap_->trap_array_[id - 1].safe;
386   }
387   return false;
388 }
389
390 Trap* Trap::global_trap_;
391
392 }  // namespace sandbox