Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(179)

Side by Side Diff: sandbox/linux/seccomp-bpf/trap.cc

Issue 1102543003: Revert of Reland: Introduce sys_sigprocmask and sys_sigaction. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sandbox/linux/seccomp-bpf/trap.h ('k') | sandbox/linux/seccomp-bpf/trap_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "sandbox/linux/seccomp-bpf/trap.h" 5 #include "sandbox/linux/seccomp-bpf/trap.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <signal.h> 8 #include <signal.h>
9 #include <string.h> 9 #include <string.h>
10 #include <sys/syscall.h> 10 #include <sys/syscall.h>
11 11
12 #include <algorithm> 12 #include <algorithm>
13 #include <limits> 13 #include <limits>
14 14
15 #include "base/compiler_specific.h"
16 #include "base/logging.h" 15 #include "base/logging.h"
17 #include "build/build_config.h" 16 #include "build/build_config.h"
18 #include "sandbox/linux/bpf_dsl/seccomp_macros.h" 17 #include "sandbox/linux/bpf_dsl/seccomp_macros.h"
19 #include "sandbox/linux/seccomp-bpf/die.h" 18 #include "sandbox/linux/seccomp-bpf/die.h"
20 #include "sandbox/linux/seccomp-bpf/syscall.h" 19 #include "sandbox/linux/seccomp-bpf/syscall.h"
21 #include "sandbox/linux/services/syscall_wrappers.h"
22 #include "sandbox/linux/system_headers/linux_seccomp.h" 20 #include "sandbox/linux/system_headers/linux_seccomp.h"
23 #include "sandbox/linux/system_headers/linux_signal.h" 21
22 // Android's signal.h doesn't define ucontext etc.
23 #if defined(OS_ANDROID)
24 #include "sandbox/linux/system_headers/android_ucontext.h"
25 #endif
24 26
25 namespace { 27 namespace {
26 28
27 struct arch_sigsys { 29 struct arch_sigsys {
28 void* ip; 30 void* ip;
29 int nr; 31 int nr;
30 unsigned int arch; 32 unsigned int arch;
31 }; 33 };
32 34
33 const int kCapacityIncrement = 20; 35 const int kCapacityIncrement = 20;
(...skipping 10 matching lines...) Expand all
44 // a lot of complexity. Instead, we co-opt one bit in the signal mask. 46 // a lot of complexity. Instead, we co-opt one bit in the signal mask.
45 // If BUS is blocked, we assume that we have been called recursively. 47 // If BUS is blocked, we assume that we have been called recursively.
46 // There is a possibility for collision with other code that needs to do 48 // There is a possibility for collision with other code that needs to do
47 // this, but in practice the risks are low. 49 // this, but in practice the risks are low.
48 // If SIGBUS turns out to be a problem, we could instead co-opt one of the 50 // If SIGBUS turns out to be a problem, we could instead co-opt one of the
49 // realtime signals. There are plenty of them. Unfortunately, there is no 51 // realtime signals. There are plenty of them. Unfortunately, there is no
50 // way to mark a signal as allocated. So, the potential for collision is 52 // way to mark a signal as allocated. So, the potential for collision is
51 // possibly even worse. 53 // possibly even worse.
52 bool GetIsInSigHandler(const ucontext_t* ctx) { 54 bool GetIsInSigHandler(const ucontext_t* ctx) {
53 // Note: on Android, sigismember does not take a pointer to const. 55 // Note: on Android, sigismember does not take a pointer to const.
54 return sigismember(const_cast<sigset_t*>(&ctx->uc_sigmask), LINUX_SIGBUS); 56 return sigismember(const_cast<sigset_t*>(&ctx->uc_sigmask), SIGBUS);
55 } 57 }
56 58
57 void SetIsInSigHandler() { 59 void SetIsInSigHandler() {
58 sigset_t mask; 60 sigset_t mask;
59 if (sigemptyset(&mask) || sigaddset(&mask, LINUX_SIGBUS) || 61 if (sigemptyset(&mask) || sigaddset(&mask, SIGBUS) ||
60 sandbox::sys_sigprocmask(LINUX_SIG_BLOCK, &mask, NULL)) { 62 sigprocmask(SIG_BLOCK, &mask, NULL)) {
61 SANDBOX_DIE("Failed to block SIGBUS"); 63 SANDBOX_DIE("Failed to block SIGBUS");
62 } 64 }
63 } 65 }
64 66
65 bool IsDefaultSignalAction(const struct sigaction& sa) { 67 bool IsDefaultSignalAction(const struct sigaction& sa) {
66 if (sa.sa_flags & SA_SIGINFO || sa.sa_handler != SIG_DFL) { 68 if (sa.sa_flags & SA_SIGINFO || sa.sa_handler != SIG_DFL) {
67 return false; 69 return false;
68 } 70 }
69 return true; 71 return true;
70 } 72 }
71 73
72 } // namespace 74 } // namespace
73 75
74 namespace sandbox { 76 namespace sandbox {
75 77
76 Trap::Trap() 78 Trap::Trap()
77 : trap_array_(NULL), 79 : trap_array_(NULL),
78 trap_array_size_(0), 80 trap_array_size_(0),
79 trap_array_capacity_(0), 81 trap_array_capacity_(0),
80 has_unsafe_traps_(false) { 82 has_unsafe_traps_(false) {
81 // Set new SIGSYS handler 83 // Set new SIGSYS handler
82 struct sigaction sa = {}; 84 struct sigaction sa = {};
83 // In some toolchain, sa_sigaction is not declared in struct sigaction. 85 sa.sa_sigaction = SigSysAction;
84 // So, here cast the pointer to the sa_handler's type. This works because 86 sa.sa_flags = SA_SIGINFO | SA_NODEFER;
85 // |sa_handler| and |sa_sigaction| shares the same memory. 87 struct sigaction old_sa;
86 sa.sa_handler = reinterpret_cast<void (*)(int)>(SigSysAction); 88 if (sigaction(SIGSYS, &sa, &old_sa) < 0) {
87 sa.sa_flags = LINUX_SA_SIGINFO | LINUX_SA_NODEFER;
88 struct sigaction old_sa = {};
89 if (sys_sigaction(LINUX_SIGSYS, &sa, &old_sa) < 0) {
90 SANDBOX_DIE("Failed to configure SIGSYS handler"); 89 SANDBOX_DIE("Failed to configure SIGSYS handler");
91 } 90 }
92 91
93 if (!IsDefaultSignalAction(old_sa)) { 92 if (!IsDefaultSignalAction(old_sa)) {
94 static const char kExistingSIGSYSMsg[] = 93 static const char kExistingSIGSYSMsg[] =
95 "Existing signal handler when trying to install SIGSYS. SIGSYS needs " 94 "Existing signal handler when trying to install SIGSYS. SIGSYS needs "
96 "to be reserved for seccomp-bpf."; 95 "to be reserved for seccomp-bpf.";
97 DLOG(FATAL) << kExistingSIGSYSMsg; 96 DLOG(FATAL) << kExistingSIGSYSMsg;
98 LOG(ERROR) << kExistingSIGSYSMsg; 97 LOG(ERROR) << kExistingSIGSYSMsg;
99 } 98 }
100 99
101 // Unmask SIGSYS 100 // Unmask SIGSYS
102 sigset_t mask; 101 sigset_t mask;
103 if (sigemptyset(&mask) || sigaddset(&mask, LINUX_SIGSYS) || 102 if (sigemptyset(&mask) || sigaddset(&mask, SIGSYS) ||
104 sys_sigprocmask(LINUX_SIG_UNBLOCK, &mask, NULL)) { 103 sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
105 SANDBOX_DIE("Failed to configure SIGSYS handler"); 104 SANDBOX_DIE("Failed to configure SIGSYS handler");
106 } 105 }
107 } 106 }
108 107
109 bpf_dsl::TrapRegistry* Trap::Registry() { 108 bpf_dsl::TrapRegistry* Trap::Registry() {
110 // Note: This class is not thread safe. It is the caller's responsibility 109 // Note: This class is not thread safe. It is the caller's responsibility
111 // to avoid race conditions. Normally, this is a non-issue as the sandbox 110 // to avoid race conditions. Normally, this is a non-issue as the sandbox
112 // can only be initialized if there are no other threads present. 111 // can only be initialized if there are no other threads present.
113 // Also, this is not a normal singleton. Once created, the global trap 112 // Also, this is not a normal singleton. Once created, the global trap
114 // object must never be destroyed again. 113 // object must never be destroyed again.
115 if (!global_trap_) { 114 if (!global_trap_) {
116 global_trap_ = new Trap(); 115 global_trap_ = new Trap();
117 if (!global_trap_) { 116 if (!global_trap_) {
118 SANDBOX_DIE("Failed to allocate global trap handler"); 117 SANDBOX_DIE("Failed to allocate global trap handler");
119 } 118 }
120 } 119 }
121 return global_trap_; 120 return global_trap_;
122 } 121 }
123 122
124 void Trap::SigSysAction(int nr, LinuxSigInfo* info, void* void_context) { 123 void Trap::SigSysAction(int nr, siginfo_t* info, void* void_context) {
125 if (info) {
126 MSAN_UNPOISON(info, sizeof(*info));
127 }
128 if (void_context) {
129 MSAN_UNPOISON(void_context, sizeof(ucontext_t));
130 }
131
132 if (!global_trap_) { 124 if (!global_trap_) {
133 RAW_SANDBOX_DIE( 125 RAW_SANDBOX_DIE(
134 "This can't happen. Found no global singleton instance " 126 "This can't happen. Found no global singleton instance "
135 "for Trap() handling."); 127 "for Trap() handling.");
136 } 128 }
137 global_trap_->SigSys(nr, info, void_context); 129 global_trap_->SigSys(nr, info, void_context);
138 } 130 }
139 131
140 void Trap::SigSys(int nr, LinuxSigInfo* info, void* void_context) { 132 void Trap::SigSys(int nr, siginfo_t* info, void* void_context) {
141 // Signal handlers should always preserve "errno". Otherwise, we could 133 // Signal handlers should always preserve "errno". Otherwise, we could
142 // trigger really subtle bugs. 134 // trigger really subtle bugs.
143 const int old_errno = errno; 135 const int old_errno = errno;
144 136
145 // Various sanity checks to make sure we actually received a signal 137 // Various sanity checks to make sure we actually received a signal
146 // triggered by a BPF filter. If something else triggered SIGSYS 138 // triggered by a BPF filter. If something else triggered SIGSYS
147 // (e.g. kill()), there is really nothing we can do with this signal. 139 // (e.g. kill()), there is really nothing we can do with this signal.
148 if (nr != LINUX_SIGSYS || info->si_code != SYS_SECCOMP || !void_context || 140 if (nr != SIGSYS || info->si_code != SYS_SECCOMP || !void_context ||
149 info->si_errno <= 0 || 141 info->si_errno <= 0 ||
150 static_cast<size_t>(info->si_errno) > trap_array_size_) { 142 static_cast<size_t>(info->si_errno) > trap_array_size_) {
151 // ATI drivers seem to send SIGSYS, so this cannot be FATAL. 143 // ATI drivers seem to send SIGSYS, so this cannot be FATAL.
152 // See crbug.com/178166. 144 // See crbug.com/178166.
153 // TODO(jln): add a DCHECK or move back to FATAL. 145 // TODO(jln): add a DCHECK or move back to FATAL.
154 RAW_LOG(ERROR, "Unexpected SIGSYS received."); 146 RAW_LOG(ERROR, "Unexpected SIGSYS received.");
155 errno = old_errno; 147 errno = old_errno;
156 return; 148 return;
157 } 149 }
158 150
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 "CHROME_SANDBOX_DEBUGGING is turned on first"); 372 "CHROME_SANDBOX_DEBUGGING is turned on first");
381 } 373 }
382 } 374 }
383 // Returns the, possibly updated, value of has_unsafe_traps_. 375 // Returns the, possibly updated, value of has_unsafe_traps_.
384 return has_unsafe_traps_; 376 return has_unsafe_traps_;
385 } 377 }
386 378
387 Trap* Trap::global_trap_; 379 Trap* Trap::global_trap_;
388 380
389 } // namespace sandbox 381 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/linux/seccomp-bpf/trap.h ('k') | sandbox/linux/seccomp-bpf/trap_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698