1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include "../private/libc_logging.h" // Relative path so we can #include this .cpp file for testing. 30 #include "../private/ScopedPthreadMutexLocker.h" 31 32 #include <android/set_abort_message.h> 33 #include <assert.h> 34 #include <errno.h> 35 #include <fcntl.h> 36 #include <pthread.h> 37 #include <stdarg.h> 38 #include <stddef.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <sys/mman.h> 42 #include <sys/socket.h> 43 #include <sys/types.h> 44 #include <sys/uio.h> 45 #include <sys/un.h> 46 #include <time.h> 47 #include <unistd.h> 48 49 static pthread_mutex_t g_abort_msg_lock = PTHREAD_MUTEX_INITIALIZER; 50 51 __LIBC_HIDDEN__ abort_msg_t** __abort_message_ptr; // Accessible to __libc_init_common. 52 53 // Must be kept in sync with frameworks/base/core/java/android/util/EventLog.java. 54 enum AndroidEventLogType { 55 EVENT_TYPE_INT = 0, 56 EVENT_TYPE_LONG = 1, 57 EVENT_TYPE_STRING = 2, 58 EVENT_TYPE_LIST = 3, 59 }; 60 61 struct BufferOutputStream { 62 public: 63 BufferOutputStream(char* buffer, size_t size) : total(0) { 64 buffer_ = buffer; 65 end_ = buffer + size - 1; 66 pos_ = buffer_; 67 pos_[0] = '\0'; 68 } 69 70 ~BufferOutputStream() { 71 } 72 73 void Send(const char* data, int len) { 74 if (len < 0) { 75 len = strlen(data); 76 } 77 78 while (len > 0) { 79 int avail = end_ - pos_; 80 if (avail == 0) { 81 break; 82 } 83 if (avail > len) { 84 avail = len; 85 } 86 memcpy(pos_, data, avail); 87 pos_ += avail; 88 pos_[0] = '\0'; 89 len -= avail; 90 total += avail; 91 } 92 } 93 94 int total; 95 96 private: 97 char* buffer_; 98 char* pos_; 99 char* end_; 100 }; 101 102 struct FdOutputStream { 103 public: 104 FdOutputStream(int fd) : total(0), fd_(fd) { 105 } 106 107 void Send(const char* data, int len) { 108 if (len < 0) { 109 len = strlen(data); 110 } 111 112 while (len > 0) { 113 int rc = TEMP_FAILURE_RETRY(write(fd_, data, len)); 114 if (rc == -1) { 115 break; 116 } 117 data += rc; 118 len -= rc; 119 total += rc; 120 } 121 } 122 123 int total; 124 125 private: 126 int fd_; 127 }; 128 129 /*** formatted output implementation 130 ***/ 131 132 /* Parse a decimal string from 'format + *ppos', 133 * return the value, and writes the new position past 134 * the decimal string in '*ppos' on exit. 135 * 136 * NOTE: Does *not* handle a sign prefix. 137 */ 138 static unsigned parse_decimal(const char *format, int *ppos) { 139 const char* p = format + *ppos; 140 unsigned result = 0; 141 142 for (;;) { 143 int ch = *p; 144 unsigned d = static_cast<unsigned>(ch - '0'); 145 146 if (d >= 10U) { 147 break; 148 } 149 150 result = result*10 + d; 151 p++; 152 } 153 *ppos = p - format; 154 return result; 155 } 156 157 // Writes number 'value' in base 'base' into buffer 'buf' of size 'buf_size' bytes. 158 // Assumes that buf_size > 0. 159 static void format_unsigned(char* buf, size_t buf_size, uint64_t value, int base, bool caps) { 160 char* p = buf; 161 char* end = buf + buf_size - 1; 162 163 // Generate digit string in reverse order. 164 while (value) { 165 unsigned d = value % base; 166 value /= base; 167 if (p != end) { 168 char ch; 169 if (d < 10) { 170 ch = '0' + d; 171 } else { 172 ch = (caps ? 'A' : 'a') + (d - 10); 173 } 174 *p++ = ch; 175 } 176 } 177 178 // Special case for 0. 179 if (p == buf) { 180 if (p != end) { 181 *p++ = '0'; 182 } 183 } 184 *p = '\0'; 185 186 // Reverse digit string in-place. 187 size_t length = p - buf; 188 for (size_t i = 0, j = length - 1; i < j; ++i, --j) { 189 char ch = buf[i]; 190 buf[i] = buf[j]; 191 buf[j] = ch; 192 } 193 } 194 195 static void format_integer(char* buf, size_t buf_size, uint64_t value, char conversion) { 196 // Decode the conversion specifier. 197 int is_signed = (conversion == 'd' || conversion == 'i' || conversion == 'o'); 198 int base = 10; 199 if (conversion == 'x' || conversion == 'X') { 200 base = 16; 201 } else if (conversion == 'o') { 202 base = 8; 203 } 204 bool caps = (conversion == 'X'); 205 206 if (is_signed && static_cast<int64_t>(value) < 0) { 207 buf[0] = '-'; 208 buf += 1; 209 buf_size -= 1; 210 value = static_cast<uint64_t>(-static_cast<int64_t>(value)); 211 } 212 format_unsigned(buf, buf_size, value, base, caps); 213 } 214 215 template <typename Out> 216 static void SendRepeat(Out& o, char ch, int count) { 217 char pad[8]; 218 memset(pad, ch, sizeof(pad)); 219 220 const int pad_size = static_cast<int>(sizeof(pad)); 221 while (count > 0) { 222 int avail = count; 223 if (avail > pad_size) { 224 avail = pad_size; 225 } 226 o.Send(pad, avail); 227 count -= avail; 228 } 229 } 230 231 /* Perform formatted output to an output target 'o' */ 232 template <typename Out> 233 static void out_vformat(Out& o, const char* format, va_list args) { 234 int nn = 0; 235 236 for (;;) { 237 int mm; 238 int padZero = 0; 239 int padLeft = 0; 240 char sign = '\0'; 241 int width = -1; 242 int prec = -1; 243 size_t bytelen = sizeof(int); 244 int slen; 245 char buffer[32]; /* temporary buffer used to format numbers */ 246 247 char c; 248 249 /* first, find all characters that are not 0 or '%' */ 250 /* then send them to the output directly */ 251 mm = nn; 252 do { 253 c = format[mm]; 254 if (c == '\0' || c == '%') 255 break; 256 mm++; 257 } while (1); 258 259 if (mm > nn) { 260 o.Send(format+nn, mm-nn); 261 nn = mm; 262 } 263 264 /* is this it ? then exit */ 265 if (c == '\0') 266 break; 267 268 /* nope, we are at a '%' modifier */ 269 nn++; // skip it 270 271 /* parse flags */ 272 for (;;) { 273 c = format[nn++]; 274 if (c == '\0') { /* single trailing '%' ? */ 275 c = '%'; 276 o.Send(&c, 1); 277 return; 278 } 279 else if (c == '0') { 280 padZero = 1; 281 continue; 282 } 283 else if (c == '-') { 284 padLeft = 1; 285 continue; 286 } 287 else if (c == ' ' || c == '+') { 288 sign = c; 289 continue; 290 } 291 break; 292 } 293 294 /* parse field width */ 295 if ((c >= '0' && c <= '9')) { 296 nn --; 297 width = static_cast<int>(parse_decimal(format, &nn)); 298 c = format[nn++]; 299 } 300 301 /* parse precision */ 302 if (c == '.') { 303 prec = static_cast<int>(parse_decimal(format, &nn)); 304 c = format[nn++]; 305 } 306 307 /* length modifier */ 308 switch (c) { 309 case 'h': 310 bytelen = sizeof(short); 311 if (format[nn] == 'h') { 312 bytelen = sizeof(char); 313 nn += 1; 314 } 315 c = format[nn++]; 316 break; 317 case 'l': 318 bytelen = sizeof(long); 319 if (format[nn] == 'l') { 320 bytelen = sizeof(long long); 321 nn += 1; 322 } 323 c = format[nn++]; 324 break; 325 case 'z': 326 bytelen = sizeof(size_t); 327 c = format[nn++]; 328 break; 329 case 't': 330 bytelen = sizeof(ptrdiff_t); 331 c = format[nn++]; 332 break; 333 default: 334 ; 335 } 336 337 /* conversion specifier */ 338 const char* str = buffer; 339 if (c == 's') { 340 /* string */ 341 str = va_arg(args, const char*); 342 if (str == NULL) { 343 str = "(null)"; 344 } 345 } else if (c == 'c') { 346 /* character */ 347 /* NOTE: char is promoted to int when passed through the stack */ 348 buffer[0] = static_cast<char>(va_arg(args, int)); 349 buffer[1] = '\0'; 350 } else if (c == 'p') { 351 uint64_t value = reinterpret_cast<uintptr_t>(va_arg(args, void*)); 352 buffer[0] = '0'; 353 buffer[1] = 'x'; 354 format_integer(buffer + 2, sizeof(buffer) - 2, value, 'x'); 355 } else if (c == 'd' || c == 'i' || c == 'o' || c == 'u' || c == 'x' || c == 'X') { 356 /* integers - first read value from stack */ 357 uint64_t value; 358 int is_signed = (c == 'd' || c == 'i' || c == 'o'); 359 360 /* NOTE: int8_t and int16_t are promoted to int when passed 361 * through the stack 362 */ 363 switch (bytelen) { 364 case 1: value = static_cast<uint8_t>(va_arg(args, int)); break; 365 case 2: value = static_cast<uint16_t>(va_arg(args, int)); break; 366 case 4: value = va_arg(args, uint32_t); break; 367 case 8: value = va_arg(args, uint64_t); break; 368 default: return; /* should not happen */ 369 } 370 371 /* sign extension, if needed */ 372 if (is_signed) { 373 int shift = 64 - 8*bytelen; 374 value = static_cast<uint64_t>((static_cast<int64_t>(value << shift)) >> shift); 375 } 376 377 /* format the number properly into our buffer */ 378 format_integer(buffer, sizeof(buffer), value, c); 379 } else if (c == '%') { 380 buffer[0] = '%'; 381 buffer[1] = '\0'; 382 } else { 383 __assert(__FILE__, __LINE__, "conversion specifier unsupported"); 384 } 385 386 /* if we are here, 'str' points to the content that must be 387 * outputted. handle padding and alignment now */ 388 389 slen = strlen(str); 390 391 if (sign != '\0' || prec != -1) { 392 __assert(__FILE__, __LINE__, "sign/precision unsupported"); 393 } 394 395 if (slen < width && !padLeft) { 396 char padChar = padZero ? '0' : ' '; 397 SendRepeat(o, padChar, width - slen); 398 } 399 400 o.Send(str, slen); 401 402 if (slen < width && padLeft) { 403 char padChar = padZero ? '0' : ' '; 404 SendRepeat(o, padChar, width - slen); 405 } 406 } 407 } 408 409 int __libc_format_buffer(char* buffer, size_t buffer_size, const char* format, ...) { 410 BufferOutputStream os(buffer, buffer_size); 411 va_list args; 412 va_start(args, format); 413 out_vformat(os, format, args); 414 va_end(args); 415 return os.total; 416 } 417 418 int __libc_format_fd(int fd, const char* format, ...) { 419 FdOutputStream os(fd); 420 va_list args; 421 va_start(args, format); 422 out_vformat(os, format, args); 423 va_end(args); 424 return os.total; 425 } 426 427 static int __libc_write_stderr(const char* tag, const char* msg) { 428 int fd = TEMP_FAILURE_RETRY(open("/dev/stderr", O_CLOEXEC | O_WRONLY)); 429 if (fd == -1) { 430 return -1; 431 } 432 433 iovec vec[4]; 434 vec[0].iov_base = const_cast<char*>(tag); 435 vec[0].iov_len = strlen(tag); 436 vec[1].iov_base = const_cast<char*>(": "); 437 vec[1].iov_len = 2; 438 vec[2].iov_base = const_cast<char*>(msg); 439 vec[2].iov_len = strlen(msg) + 1; 440 vec[3].iov_base = const_cast<char*>("\n"); 441 vec[3].iov_len = 1; 442 443 int result = TEMP_FAILURE_RETRY(writev(fd, vec, 4)); 444 close(fd); 445 return result; 446 } 447 448 #ifdef TARGET_USES_LOGD 449 static int __libc_open_log_socket() 450 { 451 // ToDo: Ideally we want this to fail if the gid of the current 452 // process is AID_LOGD, but will have to wait until we have 453 // registered this in private/android_filesystem_config.h. We have 454 // found that all logd crashes thus far have had no problem stuffing 455 // the UNIX domain socket and moving on so not critical *today*. 456 457 int log_fd = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0)); 458 if (log_fd < 0) { 459 return -1; 460 } 461 462 if (fcntl(log_fd, F_SETFL, O_NONBLOCK) == -1) { 463 close(log_fd); 464 return -1; 465 } 466 467 union { 468 struct sockaddr addr; 469 struct sockaddr_un addrUn; 470 } u; 471 memset(&u, 0, sizeof(u)); 472 u.addrUn.sun_family = AF_UNIX; 473 strlcpy(u.addrUn.sun_path, "/dev/socket/logdw", sizeof(u.addrUn.sun_path)); 474 475 if (TEMP_FAILURE_RETRY(connect(log_fd, &u.addr, sizeof(u.addrUn))) != 0) { 476 close(log_fd); 477 return -1; 478 } 479 480 return log_fd; 481 } 482 483 struct log_time { // Wire format 484 uint32_t tv_sec; 485 uint32_t tv_nsec; 486 }; 487 #endif 488 489 static int __libc_write_log(int priority, const char* tag, const char* msg) { 490 #ifdef TARGET_USES_LOGD 491 int main_log_fd = __libc_open_log_socket(); 492 493 if (main_log_fd == -1) { 494 // Try stderr instead. 495 return __libc_write_stderr(tag, msg); 496 } 497 498 iovec vec[6]; 499 char log_id = (priority == ANDROID_LOG_FATAL) ? LOG_ID_CRASH : LOG_ID_MAIN; 500 vec[0].iov_base = &log_id; 501 vec[0].iov_len = sizeof(log_id); 502 uint16_t tid = gettid(); 503 vec[1].iov_base = &tid; 504 vec[1].iov_len = sizeof(tid); 505 timespec ts; 506 clock_gettime(CLOCK_REALTIME, &ts); 507 log_time realtime_ts; 508 realtime_ts.tv_sec = ts.tv_sec; 509 realtime_ts.tv_nsec = ts.tv_nsec; 510 vec[2].iov_base = &realtime_ts; 511 vec[2].iov_len = sizeof(realtime_ts); 512 513 vec[3].iov_base = &priority; 514 vec[3].iov_len = 1; 515 vec[4].iov_base = const_cast<char*>(tag); 516 vec[4].iov_len = strlen(tag) + 1; 517 vec[5].iov_base = const_cast<char*>(msg); 518 vec[5].iov_len = strlen(msg) + 1; 519 #else 520 int main_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/main", O_CLOEXEC | O_WRONLY)); 521 if (main_log_fd == -1) { 522 if (errno == ENOTDIR) { 523 // /dev/log isn't a directory? Maybe we're running on the host? Try stderr instead. 524 return __libc_write_stderr(tag, msg); 525 } 526 return -1; 527 } 528 529 iovec vec[3]; 530 vec[0].iov_base = &priority; 531 vec[0].iov_len = 1; 532 vec[1].iov_base = const_cast<char*>(tag); 533 vec[1].iov_len = strlen(tag) + 1; 534 vec[2].iov_base = const_cast<char*>(msg); 535 vec[2].iov_len = strlen(msg) + 1; 536 #endif 537 538 int result = TEMP_FAILURE_RETRY(writev(main_log_fd, vec, sizeof(vec) / sizeof(vec[0]))); 539 close(main_log_fd); 540 return result; 541 } 542 543 int __libc_format_log_va_list(int priority, const char* tag, const char* format, va_list args) { 544 char buffer[1024]; 545 BufferOutputStream os(buffer, sizeof(buffer)); 546 out_vformat(os, format, args); 547 return __libc_write_log(priority, tag, buffer); 548 } 549 550 int __libc_format_log(int priority, const char* tag, const char* format, ...) { 551 va_list args; 552 va_start(args, format); 553 int result = __libc_format_log_va_list(priority, tag, format, args); 554 va_end(args); 555 return result; 556 } 557 558 static int __libc_android_log_event(int32_t tag, char type, const void* payload, size_t len) { 559 #ifdef TARGET_USES_LOGD 560 iovec vec[6]; 561 char log_id = LOG_ID_EVENTS; 562 vec[0].iov_base = &log_id; 563 vec[0].iov_len = sizeof(log_id); 564 uint16_t tid = gettid(); 565 vec[1].iov_base = &tid; 566 vec[1].iov_len = sizeof(tid); 567 timespec ts; 568 clock_gettime(CLOCK_REALTIME, &ts); 569 log_time realtime_ts; 570 realtime_ts.tv_sec = ts.tv_sec; 571 realtime_ts.tv_nsec = ts.tv_nsec; 572 vec[2].iov_base = &realtime_ts; 573 vec[2].iov_len = sizeof(realtime_ts); 574 575 vec[3].iov_base = &tag; 576 vec[3].iov_len = sizeof(tag); 577 vec[4].iov_base = &type; 578 vec[4].iov_len = sizeof(type); 579 vec[5].iov_base = const_cast<void*>(payload); 580 vec[5].iov_len = len; 581 582 int event_log_fd = __libc_open_log_socket(); 583 #else 584 iovec vec[3]; 585 vec[0].iov_base = &tag; 586 vec[0].iov_len = sizeof(tag); 587 vec[1].iov_base = &type; 588 vec[1].iov_len = sizeof(type); 589 vec[2].iov_base = const_cast<void*>(payload); 590 vec[2].iov_len = len; 591 592 int event_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/events", O_CLOEXEC | O_WRONLY)); 593 #endif 594 595 if (event_log_fd == -1) { 596 return -1; 597 } 598 int result = TEMP_FAILURE_RETRY(writev(event_log_fd, vec, sizeof(vec) / sizeof(vec[0]))); 599 close(event_log_fd); 600 return result; 601 } 602 603 void __libc_android_log_event_int(int32_t tag, int value) { 604 __libc_android_log_event(tag, EVENT_TYPE_INT, &value, sizeof(value)); 605 } 606 607 void __libc_android_log_event_uid(int32_t tag) { 608 __libc_android_log_event_int(tag, getuid()); 609 } 610 611 void __fortify_chk_fail(const char* msg, uint32_t tag) { 612 if (tag != 0) { 613 __libc_android_log_event_uid(tag); 614 } 615 __libc_fatal("FORTIFY_SOURCE: %s. Calling abort().", msg); 616 } 617 618 static void __libc_fatal(const char* format, va_list args) { 619 char msg[1024]; 620 BufferOutputStream os(msg, sizeof(msg)); 621 out_vformat(os, format, args); 622 623 // log to stderr for the benefit of "adb shell" users. 624 struct iovec iov[2] = { 625 {msg, strlen(msg)}, 626 {const_cast<void*>(static_cast<const void*>("\n")), 1}, 627 }; 628 writev(2, iov, 2); 629 630 // Log to the log for the benefit of regular app developers (whose stdout and stderr are closed). 631 __libc_write_log(ANDROID_LOG_FATAL, "libc", msg); 632 633 android_set_abort_message(msg); 634 } 635 636 void __libc_fatal_no_abort(const char* format, ...) { 637 va_list args; 638 va_start(args, format); 639 __libc_fatal(format, args); 640 va_end(args); 641 } 642 643 void __libc_fatal(const char* format, ...) { 644 va_list args; 645 va_start(args, format); 646 __libc_fatal(format, args); 647 va_end(args); 648 abort(); 649 } 650 651 void android_set_abort_message(const char* msg) { 652 ScopedPthreadMutexLocker locker(&g_abort_msg_lock); 653 654 if (__abort_message_ptr == NULL) { 655 // We must have crashed _very_ early. 656 return; 657 } 658 659 if (*__abort_message_ptr != NULL) { 660 // We already have an abort message. 661 // Assume that the first crash is the one most worth reporting. 662 return; 663 } 664 665 size_t size = sizeof(abort_msg_t) + strlen(msg) + 1; 666 void* map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); 667 if (map == MAP_FAILED) { 668 return; 669 } 670 671 // TODO: if we stick to the current "one-shot" scheme, we can remove this code and 672 // stop storing the size. 673 if (*__abort_message_ptr != NULL) { 674 munmap(*__abort_message_ptr, (*__abort_message_ptr)->size); 675 } 676 abort_msg_t* new_abort_message = reinterpret_cast<abort_msg_t*>(map); 677 new_abort_message->size = size; 678 strcpy(new_abort_message->msg, msg); 679 *__abort_message_ptr = new_abort_message; 680 } 681