summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'debuggerd/libdebuggerd/utility.cpp')
-rw-r--r--debuggerd/libdebuggerd/utility.cpp202
1 files changed, 174 insertions, 28 deletions
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index 1b746527e..247d806ba 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -21,6 +21,8 @@
21#include <errno.h> 21#include <errno.h>
22#include <signal.h> 22#include <signal.h>
23#include <string.h> 23#include <string.h>
24#include <sys/capability.h>
25#include <sys/prctl.h>
24#include <sys/ptrace.h> 26#include <sys/ptrace.h>
25#include <sys/uio.h> 27#include <sys/uio.h>
26#include <sys/wait.h> 28#include <sys/wait.h>
@@ -34,7 +36,9 @@
34#include <android-base/strings.h> 36#include <android-base/strings.h>
35#include <android-base/unique_fd.h> 37#include <android-base/unique_fd.h>
36#include <backtrace/Backtrace.h> 38#include <backtrace/Backtrace.h>
39#include <debuggerd/handler.h>
37#include <log/log.h> 40#include <log/log.h>
41#include <unwindstack/Memory.h>
38 42
39using android::base::unique_fd; 43using android::base::unique_fd;
40 44
@@ -117,34 +121,10 @@ void _LOG(log_t* log, enum logtype ltype, const char* fmt, ...) {
117 } 121 }
118} 122}
119 123
120bool wait_for_signal(pid_t tid, siginfo_t* siginfo) {
121 while (true) {
122 int status;
123 pid_t n = TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL));
124 if (n == -1) {
125 ALOGE("waitpid failed: tid %d, %s", tid, strerror(errno));
126 return false;
127 } else if (n == tid) {
128 if (WIFSTOPPED(status)) {
129 if (ptrace(PTRACE_GETSIGINFO, tid, nullptr, siginfo) != 0) {
130 ALOGE("PTRACE_GETSIGINFO failed: %s", strerror(errno));
131 return false;
132 }
133 return true;
134 } else {
135 ALOGE("unexpected waitpid response: n=%d, status=%08x\n", n, status);
136 // This is the only circumstance under which we can allow a detach
137 // to fail with ESRCH, which indicates the tid has exited.
138 return false;
139 }
140 }
141 }
142}
143
144#define MEMORY_BYTES_TO_DUMP 256 124#define MEMORY_BYTES_TO_DUMP 256
145#define MEMORY_BYTES_PER_LINE 16 125#define MEMORY_BYTES_PER_LINE 16
146 126
147void dump_memory(log_t* log, Backtrace* backtrace, uintptr_t addr, const char* fmt, ...) { 127void dump_memory(log_t* log, unwindstack::Memory* memory, uintptr_t addr, const char* fmt, ...) {
148 std::string log_msg; 128 std::string log_msg;
149 va_list ap; 129 va_list ap;
150 va_start(ap, fmt); 130 va_start(ap, fmt);
@@ -172,7 +152,7 @@ void dump_memory(log_t* log, Backtrace* backtrace, uintptr_t addr, const char* f
172 // Dump 256 bytes 152 // Dump 256 bytes
173 uintptr_t data[MEMORY_BYTES_TO_DUMP/sizeof(uintptr_t)]; 153 uintptr_t data[MEMORY_BYTES_TO_DUMP/sizeof(uintptr_t)];
174 memset(data, 0, MEMORY_BYTES_TO_DUMP); 154 memset(data, 0, MEMORY_BYTES_TO_DUMP);
175 size_t bytes = backtrace->Read(addr, reinterpret_cast<uint8_t*>(data), sizeof(data)); 155 size_t bytes = memory->Read(addr, reinterpret_cast<uint8_t*>(data), sizeof(data));
176 if (bytes % sizeof(uintptr_t) != 0) { 156 if (bytes % sizeof(uintptr_t) != 0) {
177 // This should never happen, but just in case. 157 // This should never happen, but just in case.
178 ALOGE("Bytes read %zu, is not a multiple of %zu", bytes, sizeof(uintptr_t)); 158 ALOGE("Bytes read %zu, is not a multiple of %zu", bytes, sizeof(uintptr_t));
@@ -199,8 +179,8 @@ void dump_memory(log_t* log, Backtrace* backtrace, uintptr_t addr, const char* f
199 // into a readable map. Only requires one extra read because a map has 179 // into a readable map. Only requires one extra read because a map has
200 // to contain at least one page, and the total number of bytes to dump 180 // to contain at least one page, and the total number of bytes to dump
201 // is smaller than a page. 181 // is smaller than a page.
202 size_t bytes2 = backtrace->Read(addr + start + bytes, reinterpret_cast<uint8_t*>(data) + bytes, 182 size_t bytes2 = memory->Read(addr + start + bytes, reinterpret_cast<uint8_t*>(data) + bytes,
203 sizeof(data) - bytes - start); 183 sizeof(data) - bytes - start);
204 bytes += bytes2; 184 bytes += bytes2;
205 if (bytes2 > 0 && bytes % sizeof(uintptr_t) != 0) { 185 if (bytes2 > 0 && bytes % sizeof(uintptr_t) != 0) {
206 // This should never happen, but we'll try and continue any way. 186 // This should never happen, but we'll try and continue any way.
@@ -264,3 +244,169 @@ void read_with_default(const char* path, char* buf, size_t len, const char* defa
264 } 244 }
265 strcpy(buf, default_value); 245 strcpy(buf, default_value);
266} 246}
247
248void drop_capabilities() {
249 __user_cap_header_struct capheader;
250 memset(&capheader, 0, sizeof(capheader));
251 capheader.version = _LINUX_CAPABILITY_VERSION_3;
252 capheader.pid = 0;
253
254 __user_cap_data_struct capdata[2];
255 memset(&capdata, 0, sizeof(capdata));
256
257 if (capset(&capheader, &capdata[0]) == -1) {
258 PLOG(FATAL) << "failed to drop capabilities";
259 }
260
261 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0) {
262 PLOG(FATAL) << "failed to set PR_SET_NO_NEW_PRIVS";
263 }
264}
265
266bool signal_has_si_addr(int si_signo, int si_code) {
267 // Manually sent signals won't have si_addr.
268 if (si_code == SI_USER || si_code == SI_QUEUE || si_code == SI_TKILL) {
269 return false;
270 }
271
272 switch (si_signo) {
273 case SIGBUS:
274 case SIGFPE:
275 case SIGILL:
276 case SIGSEGV:
277 case SIGTRAP:
278 return true;
279 default:
280 return false;
281 }
282}
283
284const char* get_signame(int sig) {
285 switch (sig) {
286 case SIGABRT: return "SIGABRT";
287 case SIGBUS: return "SIGBUS";
288 case SIGFPE: return "SIGFPE";
289 case SIGILL: return "SIGILL";
290 case SIGSEGV: return "SIGSEGV";
291#if defined(SIGSTKFLT)
292 case SIGSTKFLT: return "SIGSTKFLT";
293#endif
294 case SIGSTOP: return "SIGSTOP";
295 case SIGSYS: return "SIGSYS";
296 case SIGTRAP: return "SIGTRAP";
297 case DEBUGGER_SIGNAL: return "<debuggerd signal>";
298 default: return "?";
299 }
300}
301
302const char* get_sigcode(int signo, int code) {
303 // Try the signal-specific codes...
304 switch (signo) {
305 case SIGILL:
306 switch (code) {
307 case ILL_ILLOPC: return "ILL_ILLOPC";
308 case ILL_ILLOPN: return "ILL_ILLOPN";
309 case ILL_ILLADR: return "ILL_ILLADR";
310 case ILL_ILLTRP: return "ILL_ILLTRP";
311 case ILL_PRVOPC: return "ILL_PRVOPC";
312 case ILL_PRVREG: return "ILL_PRVREG";
313 case ILL_COPROC: return "ILL_COPROC";
314 case ILL_BADSTK: return "ILL_BADSTK";
315 }
316 static_assert(NSIGILL == ILL_BADSTK, "missing ILL_* si_code");
317 break;
318 case SIGBUS:
319 switch (code) {
320 case BUS_ADRALN: return "BUS_ADRALN";
321 case BUS_ADRERR: return "BUS_ADRERR";
322 case BUS_OBJERR: return "BUS_OBJERR";
323 case BUS_MCEERR_AR: return "BUS_MCEERR_AR";
324 case BUS_MCEERR_AO: return "BUS_MCEERR_AO";
325 }
326 static_assert(NSIGBUS == BUS_MCEERR_AO, "missing BUS_* si_code");
327 break;
328 case SIGFPE:
329 switch (code) {
330 case FPE_INTDIV: return "FPE_INTDIV";
331 case FPE_INTOVF: return "FPE_INTOVF";
332 case FPE_FLTDIV: return "FPE_FLTDIV";
333 case FPE_FLTOVF: return "FPE_FLTOVF";
334 case FPE_FLTUND: return "FPE_FLTUND";
335 case FPE_FLTRES: return "FPE_FLTRES";
336 case FPE_FLTINV: return "FPE_FLTINV";
337 case FPE_FLTSUB: return "FPE_FLTSUB";
338 }
339 static_assert(NSIGFPE == FPE_FLTSUB, "missing FPE_* si_code");
340 break;
341 case SIGSEGV:
342 switch (code) {
343 case SEGV_MAPERR: return "SEGV_MAPERR";
344 case SEGV_ACCERR: return "SEGV_ACCERR";
345#if defined(SEGV_BNDERR)
346 case SEGV_BNDERR: return "SEGV_BNDERR";
347#endif
348#if defined(SEGV_PKUERR)
349 case SEGV_PKUERR: return "SEGV_PKUERR";
350#endif
351 }
352#if defined(SEGV_PKUERR)
353 static_assert(NSIGSEGV == SEGV_PKUERR, "missing SEGV_* si_code");
354#elif defined(SEGV_BNDERR)
355 static_assert(NSIGSEGV == SEGV_BNDERR, "missing SEGV_* si_code");
356#else
357 static_assert(NSIGSEGV == SEGV_ACCERR, "missing SEGV_* si_code");
358#endif
359 break;
360#if defined(SYS_SECCOMP) // Our glibc is too old, and we build this for the host too.
361 case SIGSYS:
362 switch (code) {
363 case SYS_SECCOMP: return "SYS_SECCOMP";
364 }
365 static_assert(NSIGSYS == SYS_SECCOMP, "missing SYS_* si_code");
366 break;
367#endif
368 case SIGTRAP:
369 switch (code) {
370 case TRAP_BRKPT: return "TRAP_BRKPT";
371 case TRAP_TRACE: return "TRAP_TRACE";
372 case TRAP_BRANCH: return "TRAP_BRANCH";
373 case TRAP_HWBKPT: return "TRAP_HWBKPT";
374 }
375 if ((code & 0xff) == SIGTRAP) {
376 switch ((code >> 8) & 0xff) {
377 case PTRACE_EVENT_FORK:
378 return "PTRACE_EVENT_FORK";
379 case PTRACE_EVENT_VFORK:
380 return "PTRACE_EVENT_VFORK";
381 case PTRACE_EVENT_CLONE:
382 return "PTRACE_EVENT_CLONE";
383 case PTRACE_EVENT_EXEC:
384 return "PTRACE_EVENT_EXEC";
385 case PTRACE_EVENT_VFORK_DONE:
386 return "PTRACE_EVENT_VFORK_DONE";
387 case PTRACE_EVENT_EXIT:
388 return "PTRACE_EVENT_EXIT";
389 case PTRACE_EVENT_SECCOMP:
390 return "PTRACE_EVENT_SECCOMP";
391 case PTRACE_EVENT_STOP:
392 return "PTRACE_EVENT_STOP";
393 }
394 }
395 static_assert(NSIGTRAP == TRAP_HWBKPT, "missing TRAP_* si_code");
396 break;
397 }
398 // Then the other codes...
399 switch (code) {
400 case SI_USER: return "SI_USER";
401 case SI_KERNEL: return "SI_KERNEL";
402 case SI_QUEUE: return "SI_QUEUE";
403 case SI_TIMER: return "SI_TIMER";
404 case SI_MESGQ: return "SI_MESGQ";
405 case SI_ASYNCIO: return "SI_ASYNCIO";
406 case SI_SIGIO: return "SI_SIGIO";
407 case SI_TKILL: return "SI_TKILL";
408 case SI_DETHREAD: return "SI_DETHREAD";
409 }
410 // Then give up...
411 return "?";
412}