1/* system/debuggerd/debuggerd.c 2** 3** Copyright 2006, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#include <stdio.h> 19#include <errno.h> 20#include <signal.h> 21#include <pthread.h> 22#include <stdarg.h> 23#include <fcntl.h> 24#include <sys/types.h> 25#include <dirent.h> 26#include <time.h> 27 28#include <sys/ptrace.h> 29#include <sys/wait.h> 30#include <sys/exec_elf.h> 31#include <sys/stat.h> 32#include <sys/poll.h> 33 34#include <cutils/sockets.h> 35#include <cutils/logd.h> 36#include <cutils/logger.h> 37#include <cutils/properties.h> 38#include <cutils/debugger.h> 39 40#include <corkscrew/backtrace.h> 41 42#include <linux/input.h> 43 44#include <private/android_filesystem_config.h> 45 46#include "backtrace.h" 47#include "getevent.h" 48#include "tombstone.h" 49#include "utility.h" 50 51typedef struct { 52 debugger_action_t action; 53 pid_t pid, tid; 54 uid_t uid, gid; 55} debugger_request_t; 56 57static int 58write_string(const char* file, const char* string) 59{ 60 int len; 61 int fd; 62 ssize_t amt; 63 fd = open(file, O_RDWR); 64 len = strlen(string); 65 if (fd < 0) 66 return -errno; 67 amt = write(fd, string, len); 68 close(fd); 69 return amt >= 0 ? 0 : -errno; 70} 71 72static 73void init_debug_led(void) 74{ 75 // trout leds 76 write_string("/sys/class/leds/red/brightness", "0"); 77 write_string("/sys/class/leds/green/brightness", "0"); 78 write_string("/sys/class/leds/blue/brightness", "0"); 79 write_string("/sys/class/leds/red/device/blink", "0"); 80 // sardine leds 81 write_string("/sys/class/leds/left/cadence", "0,0"); 82} 83 84static 85void enable_debug_led(void) 86{ 87 // trout leds 88 write_string("/sys/class/leds/red/brightness", "255"); 89 // sardine leds 90 write_string("/sys/class/leds/left/cadence", "1,0"); 91} 92 93static 94void disable_debug_led(void) 95{ 96 // trout leds 97 write_string("/sys/class/leds/red/brightness", "0"); 98 // sardine leds 99 write_string("/sys/class/leds/left/cadence", "0,0"); 100} 101 102static void wait_for_user_action(pid_t pid) { 103 /* First log a helpful message */ 104 LOG( "********************************************************\n" 105 "* Process %d has been suspended while crashing. To\n" 106 "* attach gdbserver for a gdb connection on port 5039\n" 107 "* and start gdbclient:\n" 108 "*\n" 109 "* gdbclient app_process :5039 %d\n" 110 "*\n" 111 "* Wait for gdb to start, then press HOME or VOLUME DOWN key\n" 112 "* to let the process continue crashing.\n" 113 "********************************************************\n", 114 pid, pid); 115 116 /* wait for HOME or VOLUME DOWN key */ 117 if (init_getevent() == 0) { 118 int ms = 1200 / 10; 119 int dit = 1; 120 int dah = 3*dit; 121 int _ = -dit; 122 int ___ = 3*_; 123 int _______ = 7*_; 124 const signed char codes[] = { 125 dit,_,dit,_,dit,___,dah,_,dah,_,dah,___,dit,_,dit,_,dit,_______ 126 }; 127 size_t s = 0; 128 struct input_event e; 129 bool done = false; 130 init_debug_led(); 131 enable_debug_led(); 132 do { 133 int timeout = abs((int)(codes[s])) * ms; 134 int res = get_event(&e, timeout); 135 if (res == 0) { 136 if (e.type == EV_KEY 137 && (e.code == KEY_HOME || e.code == KEY_VOLUMEDOWN) 138 && e.value == 0) { 139 done = true; 140 } 141 } else if (res == 1) { 142 if (++s >= sizeof(codes)/sizeof(*codes)) 143 s = 0; 144 if (codes[s] > 0) { 145 enable_debug_led(); 146 } else { 147 disable_debug_led(); 148 } 149 } 150 } while (!done); 151 uninit_getevent(); 152 } 153 154 /* don't forget to turn debug led off */ 155 disable_debug_led(); 156 LOG("debuggerd resuming process %d", pid); 157} 158 159static int get_process_info(pid_t tid, pid_t* out_pid, uid_t* out_uid, uid_t* out_gid) { 160 char path[64]; 161 snprintf(path, sizeof(path), "/proc/%d/status", tid); 162 163 FILE* fp = fopen(path, "r"); 164 if (!fp) { 165 return -1; 166 } 167 168 int fields = 0; 169 char line[1024]; 170 while (fgets(line, sizeof(line), fp)) { 171 size_t len = strlen(line); 172 if (len > 6 && !memcmp(line, "Tgid:\t", 6)) { 173 *out_pid = atoi(line + 6); 174 fields |= 1; 175 } else if (len > 5 && !memcmp(line, "Uid:\t", 5)) { 176 *out_uid = atoi(line + 5); 177 fields |= 2; 178 } else if (len > 5 && !memcmp(line, "Gid:\t", 5)) { 179 *out_gid = atoi(line + 5); 180 fields |= 4; 181 } 182 } 183 fclose(fp); 184 return fields == 7 ? 0 : -1; 185} 186 187static int read_request(int fd, debugger_request_t* out_request) { 188 struct ucred cr; 189 int len = sizeof(cr); 190 int status = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &len); 191 if (status != 0) { 192 LOG("cannot get credentials\n"); 193 return -1; 194 } 195 196 XLOG("reading tid\n"); 197 fcntl(fd, F_SETFL, O_NONBLOCK); 198 199 struct pollfd pollfds[1]; 200 pollfds[0].fd = fd; 201 pollfds[0].events = POLLIN; 202 pollfds[0].revents = 0; 203 status = TEMP_FAILURE_RETRY(poll(pollfds, 1, 3000)); 204 if (status != 1) { 205 LOG("timed out reading tid\n"); 206 return -1; 207 } 208 209 debugger_msg_t msg; 210 status = TEMP_FAILURE_RETRY(read(fd, &msg, sizeof(msg))); 211 if (status < 0) { 212 LOG("read failure? %s\n", strerror(errno)); 213 return -1; 214 } 215 if (status != sizeof(msg)) { 216 LOG("invalid crash request of size %d\n", status); 217 return -1; 218 } 219 220 out_request->action = msg.action; 221 out_request->tid = msg.tid; 222 out_request->pid = cr.pid; 223 out_request->uid = cr.uid; 224 out_request->gid = cr.gid; 225 226 if (msg.action == DEBUGGER_ACTION_CRASH) { 227 /* Ensure that the tid reported by the crashing process is valid. */ 228 char buf[64]; 229 struct stat s; 230 snprintf(buf, sizeof buf, "/proc/%d/task/%d", out_request->pid, out_request->tid); 231 if(stat(buf, &s)) { 232 LOG("tid %d does not exist in pid %d. ignoring debug request\n", 233 out_request->tid, out_request->pid); 234 return -1; 235 } 236 } else if (cr.uid == 0 237 || (cr.uid == AID_SYSTEM && msg.action == DEBUGGER_ACTION_DUMP_BACKTRACE)) { 238 /* Only root or system can ask us to attach to any process and dump it explicitly. 239 * However, system is only allowed to collect backtraces but cannot dump tombstones. */ 240 status = get_process_info(out_request->tid, &out_request->pid, 241 &out_request->uid, &out_request->gid); 242 if (status < 0) { 243 LOG("tid %d does not exist. ignoring explicit dump request\n", 244 out_request->tid); 245 return -1; 246 } 247 } else { 248 /* No one else is not allowed to dump arbitrary processes. */ 249 return -1; 250 } 251 return 0; 252} 253 254static bool should_attach_gdb(debugger_request_t* request) { 255 if (request->action == DEBUGGER_ACTION_CRASH) { 256 char value[PROPERTY_VALUE_MAX]; 257 property_get("debug.db.uid", value, "-1"); 258 int debug_uid = atoi(value); 259 return debug_uid >= 0 && request->uid <= (uid_t)debug_uid; 260 } 261 return false; 262} 263 264static void handle_request(int fd) { 265 XLOG("handle_request(%d)\n", fd); 266 267 debugger_request_t request; 268 int status = read_request(fd, &request); 269 if (!status) { 270 XLOG("BOOM: pid=%d uid=%d gid=%d tid=%d\n", 271 request.pid, request.uid, request.gid, request.tid); 272 273 /* At this point, the thread that made the request is blocked in 274 * a read() call. If the thread has crashed, then this gives us 275 * time to PTRACE_ATTACH to it before it has a chance to really fault. 276 * 277 * The PTRACE_ATTACH sends a SIGSTOP to the target process, but it 278 * won't necessarily have stopped by the time ptrace() returns. (We 279 * currently assume it does.) We write to the file descriptor to 280 * ensure that it can run as soon as we call PTRACE_CONT below. 281 * See details in bionic/libc/linker/debugger.c, in function 282 * debugger_signal_handler(). 283 */ 284 if (ptrace(PTRACE_ATTACH, request.tid, 0, 0)) { 285 LOG("ptrace attach failed: %s\n", strerror(errno)); 286 } else { 287 bool detach_failed = false; 288 bool attach_gdb = should_attach_gdb(&request); 289 if (TEMP_FAILURE_RETRY(write(fd, "\0", 1)) != 1) { 290 LOG("failed responding to client: %s\n", strerror(errno)); 291 } else { 292 char* tombstone_path = NULL; 293 294 if (request.action == DEBUGGER_ACTION_CRASH) { 295 close(fd); 296 fd = -1; 297 } 298 299 int total_sleep_time_usec = 0; 300 for (;;) { 301 int signal = wait_for_signal(request.tid, &total_sleep_time_usec); 302 if (signal < 0) { 303 break; 304 } 305 306 switch (signal) { 307 case SIGSTOP: 308 if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) { 309 XLOG("stopped -- dumping to tombstone\n"); 310 tombstone_path = engrave_tombstone(request.pid, request.tid, 311 signal, true, true, &detach_failed, 312 &total_sleep_time_usec); 313 } else if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE) { 314 XLOG("stopped -- dumping to fd\n"); 315 dump_backtrace(fd, request.pid, request.tid, &detach_failed, 316 &total_sleep_time_usec); 317 } else { 318 XLOG("stopped -- continuing\n"); 319 status = ptrace(PTRACE_CONT, request.tid, 0, 0); 320 if (status) { 321 LOG("ptrace continue failed: %s\n", strerror(errno)); 322 } 323 continue; /* loop again */ 324 } 325 break; 326 327 case SIGILL: 328 case SIGABRT: 329 case SIGBUS: 330 case SIGFPE: 331 case SIGSEGV: 332 case SIGPIPE: 333#ifdef SIGSTKFLT 334 case SIGSTKFLT: 335#endif 336 { 337 XLOG("stopped -- fatal signal\n"); 338 /* 339 * Send a SIGSTOP to the process to make all of 340 * the non-signaled threads stop moving. Without 341 * this we get a lot of "ptrace detach failed: 342 * No such process". 343 */ 344 kill(request.pid, SIGSTOP); 345 /* don't dump sibling threads when attaching to GDB because it 346 * makes the process less reliable, apparently... */ 347 tombstone_path = engrave_tombstone(request.pid, request.tid, 348 signal, !attach_gdb, false, &detach_failed, 349 &total_sleep_time_usec); 350 break; 351 } 352 353 default: 354 XLOG("stopped -- unexpected signal\n"); 355 LOG("process stopped due to unexpected signal %d\n", signal); 356 break; 357 } 358 break; 359 } 360 361 if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) { 362 if (tombstone_path) { 363 write(fd, tombstone_path, strlen(tombstone_path)); 364 } 365 close(fd); 366 fd = -1; 367 } 368 free(tombstone_path); 369 } 370 371 XLOG("detaching\n"); 372 if (attach_gdb) { 373 /* stop the process so we can debug */ 374 kill(request.pid, SIGSTOP); 375 376 /* detach so we can attach gdbserver */ 377 if (ptrace(PTRACE_DETACH, request.tid, 0, 0)) { 378 LOG("ptrace detach from %d failed: %s\n", request.tid, strerror(errno)); 379 detach_failed = true; 380 } 381 382 /* 383 * if debug.db.uid is set, its value indicates if we should wait 384 * for user action for the crashing process. 385 * in this case, we log a message and turn the debug LED on 386 * waiting for a gdb connection (for instance) 387 */ 388 wait_for_user_action(request.pid); 389 } else { 390 /* just detach */ 391 if (ptrace(PTRACE_DETACH, request.tid, 0, 0)) { 392 LOG("ptrace detach from %d failed: %s\n", request.tid, strerror(errno)); 393 detach_failed = true; 394 } 395 } 396 397 /* resume stopped process (so it can crash in peace). */ 398 kill(request.pid, SIGCONT); 399 400 /* If we didn't successfully detach, we're still the parent, and the 401 * actual parent won't receive a death notification via wait(2). At this point 402 * there's not much we can do about that. */ 403 if (detach_failed) { 404 LOG("debuggerd committing suicide to free the zombie!\n"); 405 kill(getpid(), SIGKILL); 406 } 407 } 408 409 } 410 if (fd >= 0) { 411 close(fd); 412 } 413} 414 415static int do_server() { 416 int s; 417 struct sigaction act; 418 int logsocket = -1; 419 420 /* 421 * debuggerd crashes can't be reported to debuggerd. Reset all of the 422 * crash handlers. 423 */ 424 signal(SIGILL, SIG_DFL); 425 signal(SIGABRT, SIG_DFL); 426 signal(SIGBUS, SIG_DFL); 427 signal(SIGFPE, SIG_DFL); 428 signal(SIGSEGV, SIG_DFL); 429 signal(SIGPIPE, SIG_DFL); 430#ifdef SIGSTKFLT 431 signal(SIGSTKFLT, SIG_DFL); 432#endif 433 434 logsocket = socket_local_client("logd", 435 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_DGRAM); 436 if(logsocket < 0) { 437 logsocket = -1; 438 } else { 439 fcntl(logsocket, F_SETFD, FD_CLOEXEC); 440 } 441 442 act.sa_handler = SIG_DFL; 443 sigemptyset(&act.sa_mask); 444 sigaddset(&act.sa_mask,SIGCHLD); 445 act.sa_flags = SA_NOCLDWAIT; 446 sigaction(SIGCHLD, &act, 0); 447 448 s = socket_local_server(DEBUGGER_SOCKET_NAME, 449 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); 450 if(s < 0) return 1; 451 fcntl(s, F_SETFD, FD_CLOEXEC); 452 453 LOG("debuggerd: " __DATE__ " " __TIME__ "\n"); 454 455 for(;;) { 456 struct sockaddr addr; 457 socklen_t alen; 458 int fd; 459 460 alen = sizeof(addr); 461 XLOG("waiting for connection\n"); 462 fd = accept(s, &addr, &alen); 463 if(fd < 0) { 464 XLOG("accept failed: %s\n", strerror(errno)); 465 continue; 466 } 467 468 fcntl(fd, F_SETFD, FD_CLOEXEC); 469 470 handle_request(fd); 471 } 472 return 0; 473} 474 475static int do_explicit_dump(pid_t tid, bool dump_backtrace) { 476 fprintf(stdout, "Sending request to dump task %d.\n", tid); 477 478 if (dump_backtrace) { 479 fflush(stdout); 480 if (dump_backtrace_to_file(tid, fileno(stdout)) < 0) { 481 fputs("Error dumping backtrace.\n", stderr); 482 return 1; 483 } 484 } else { 485 char tombstone_path[PATH_MAX]; 486 if (dump_tombstone(tid, tombstone_path, sizeof(tombstone_path)) < 0) { 487 fputs("Error dumping tombstone.\n", stderr); 488 return 1; 489 } 490 fprintf(stderr, "Tombstone written to: %s\n", tombstone_path); 491 } 492 return 0; 493} 494 495static void usage() { 496 fputs("Usage: -b [<tid>]\n" 497 " -b dump backtrace to console, otherwise dump full tombstone file\n" 498 "\n" 499 "If tid specified, sends a request to debuggerd to dump that task.\n" 500 "Otherwise, starts the debuggerd server.\n", stderr); 501} 502 503int main(int argc, char** argv) { 504 if (argc == 1) { 505 return do_server(); 506 } 507 508 bool dump_backtrace = false; 509 bool have_tid = false; 510 pid_t tid = 0; 511 for (int i = 1; i < argc; i++) { 512 if (!strcmp(argv[i], "-b")) { 513 dump_backtrace = true; 514 } else if (!have_tid) { 515 tid = atoi(argv[i]); 516 have_tid = true; 517 } else { 518 usage(); 519 return 1; 520 } 521 } 522 if (!have_tid) { 523 usage(); 524 return 1; 525 } 526 return do_explicit_dump(tid, dump_backtrace); 527} 528