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

Side by Side Diff: util/mach/exception_types.cc

Issue 1066243002: Accept non-fatal resource exceptions without generating crash reports (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Swallow non-fatal EXC_RESOURCE 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 | « util/mach/exception_types.h ('k') | util/mach/exception_types_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "util/mach/exception_types.h"
16
17 #include <Availability.h>
18 #include <AvailabilityMacros.h>
19 #include <dlfcn.h>
20 #include <errno.h>
21 #include <libproc.h>
22 #include <kern/exc_resource.h>
23
24 #include "base/logging.h"
25 #include "base/mac/mach_logging.h"
26 #include "util/mac/mac_util.h"
27
28 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
29
30 extern "C" {
31
32 // proc_get_wakemon_params() is present in the Mac OS X 10.9 SDK, but no
33 // declaration is provided. This provides a declaration and marks it for weak
34 // import if the deployment target is below 10.9.
35 int proc_get_wakemon_params(pid_t pid, int* rate_hz, int* flags)
36 __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0);
37
38 } // extern "C"
39
40 #else
41
42 namespace {
43
44 using ProcGetWakemonParamsType = int (*)(pid_t, int*, int*);
45
46 // The SDK doesn’t have proc_get_wakemon_params() to link against, even with
47 // weak import. This function returns a function pointer to it if it exists at
48 // runtime, or nullptr if it doesn’t. proc_get_wakemon_params() is looked up in
49 // the same module that provides proc_pidinfo().
50 ProcGetWakemonParamsType GetProcGetWakemonParams() {
51 Dl_info dl_info;
52 if (!dladdr(reinterpret_cast<void*>(proc_pidinfo), &dl_info)) {
53 return nullptr;
54 }
55
56 void* dl_handle =
57 dlopen(dl_info.dli_fname, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
58 if (!dl_handle) {
59 return nullptr;
60 }
61
62 ProcGetWakemonParamsType proc_get_wakemon_params =
63 reinterpret_cast<ProcGetWakemonParamsType>(
64 dlsym(dl_handle, "proc_get_wakemon_params"));
65 return proc_get_wakemon_params;
66 }
67
68 } // namespace
69
70 #endif
71
72 namespace {
73
74 // Wraps proc_get_wakemon_params(), calling it if the system provides it. It’s
75 // present on Mac OS X 10.9 and later. If it’s not available, sets errno to
76 // ENOSYS and returns -1.
77 int ProcGetWakemonParams(pid_t pid, int* rate_hz, int* flags) {
78 #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_9
79 // proc_get_wakemon_params() isn’t in the SDK. Look it up dynamically.
80 static ProcGetWakemonParamsType proc_get_wakemon_params =
81 GetProcGetWakemonParams();
82 #endif
83
84 #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9
85 // proc_get_wakemon_params() is definitely available if the deployment target
86 // is 10.9 or newer.
87 if (!proc_get_wakemon_params) {
88 errno = ENOSYS;
89 return -1;
90 }
91 #endif
92
93 return proc_get_wakemon_params(pid, rate_hz, flags);
94 }
95
96 } // namespace
97
98 namespace crashpad {
99
100 exception_type_t ExcCrashRecoverOriginalException(
101 mach_exception_code_t code_0,
102 mach_exception_code_t* original_code_0,
103 int* signal) {
104 // 10.9.4 xnu-2422.110.17/bsd/kern/kern_exit.c proc_prepareexit() sets code[0]
105 // based on the signal value, original exception type, and low 20 bits of the
106 // original code[0] before calling xnu-2422.110.17/osfmk/kern/exception.c
107 // task_exception_notify() to raise an EXC_CRASH.
108 //
109 // The list of core-generating signals (as used in proc_prepareexit()’s call
110 // to hassigprop()) is in 10.9.4 xnu-2422.110.17/bsd/sys/signalvar.h sigprop:
111 // entires with SA_CORE are in the set. These signals are SIGQUIT, SIGILL,
112 // SIGTRAP, SIGABRT, SIGEMT, SIGFPE, SIGBUS, SIGSEGV, and SIGSYS. Processes
113 // killed for code-signing reasons will be killed by SIGKILL and are also
114 // eligible for EXC_CRASH handling, but processes killed by SIGKILL for other
115 // reasons are not.
116 if (signal) {
117 *signal = (code_0 >> 24) & 0xff;
118 }
119
120 if (original_code_0) {
121 *original_code_0 = code_0 & 0xfffff;
122 }
123
124 return (code_0 >> 20) & 0xf;
125 }
126
127 bool IsExceptionNonfatalResource(exception_type_t exception,
128 mach_exception_code_t code_0,
129 pid_t pid) {
130 if (exception != EXC_RESOURCE) {
131 return false;
132 }
133
134 const int resource_type = EXC_RESOURCE_DECODE_RESOURCE_TYPE(code_0);
135 const int resource_flavor = EXC_RESOURCE_DECODE_FLAVOR(code_0);
136
137 if (resource_type == RESOURCE_TYPE_CPU &&
138 (resource_flavor == FLAVOR_CPU_MONITOR ||
139 resource_flavor == FLAVOR_CPU_MONITOR_FATAL)) {
140 // These exceptions may be fatal. They are not fatal by default at task
141 // creation but can be made fatal by calling proc_rlimit_control() with
142 // RLIMIT_CPU_USAGE_MONITOR as the second argument and CPUMON_MAKE_FATAL set
143 // in the flags.
144 if (MacOSXMinorVersion() >= 10) {
145 // In Mac OS X 10.10, the exception code indicates whether the exception
146 // is fatal. See 10.10 xnu-2782.1.97/osfmk/kern/thread.c
147 // THIS_THREAD_IS_CONSUMING_TOO_MUCH_CPU__SENDING_EXC_RESOURCE().
148 return resource_flavor == FLAVOR_CPU_MONITOR;
149 }
150
151 // In Mac OS X 10.9, there’s no way to determine whether the exception is
152 // fatal. Unlike RESOURCE_TYPE_WAKEUPS below, there’s no way to determine
153 // this outside the kernel. proc_rlimit_control()’s RLIMIT_CPU_USAGE_MONITOR
154 // is the only interface to modify CPUMON_MAKE_FATAL, but it’s only able to
155 // set this bit, not obtain its current value.
156 //
157 // Default to assuming that these exceptions are nonfatal. They are nonfatal
158 // by default and no users of proc_rlimit_control() were found on 10.9.5
159 // 13F1066 in /System and /usr outside of Metadata.framework and associated
160 // tools.
161 return true;
162 }
163
164 if (resource_type == RESOURCE_TYPE_WAKEUPS &&
165 resource_flavor == FLAVOR_WAKEUPS_MONITOR) {
166 // These exceptions may be fatal. They are not fatal by default at task
167 // creation, but can be made fatal by calling proc_rlimit_control() with
168 // RLIMIT_WAKEUPS_MONITOR as the second argument and WAKEMON_MAKE_FATAL set
169 // in the flags.
170 //
171 // proc_get_wakemon_params() (which calls
172 // through to proc_rlimit_control() with RLIMIT_WAKEUPS_MONITOR) determines
173 // whether these exceptions are fatal. See 10.10
174 // xnu-2782.1.97/osfmk/kern/task.c
175 // THIS_PROCESS_IS_CAUSING_TOO_MANY_WAKEUPS__SENDING_EXC_RESOURCE().
176 //
177 // If proc_get_wakemon_params() fails, default to assuming that these
178 // exceptions are nonfatal. They are nonfatal by default and no users of
179 // proc_rlimit_control() were found on 10.9.5 13F1066 in /System and /usr
180 // outside of Metadata.framework and associated tools.
181 int wm_rate;
182 int wm_flags;
183 int rv = ProcGetWakemonParams(pid, &wm_rate, &wm_flags);
184 if (rv < 0) {
185 PLOG(WARNING) << "ProcGetWakemonParams";
186 return true;
187 }
188
189 return !(wm_flags & WAKEMON_MAKE_FATAL);
190 }
191
192 if (resource_type == RESOURCE_TYPE_MEMORY &&
193 resource_flavor == FLAVOR_HIGH_WATERMARK) {
194 // These exceptions are never fatal. See 10.10
195 // xnu-2782.1.97/osfmk/kern/task.c
196 // THIS_PROCESS_CROSSED_HIGH_WATERMARK__SENDING_EXC_RESOURCE().
197 return true;
198 }
199
200 // Treat unknown exceptions as fatal. This is the conservative approach: it
201 // may result in more crash reports being generated, but the type-flavor
202 // combinations can be evaluated to determine appropriate handling.
203 LOG(WARNING) << "unknown resource type " << resource_type << " flavor "
204 << resource_flavor;
205 return false;
206 }
207
208 } // namespace crashpad
OLDNEW
« no previous file with comments | « util/mach/exception_types.h ('k') | util/mach/exception_types_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698