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 <assert.h> 30 #include <ctype.h> 31 #include <errno.h> 32 #include <fcntl.h> 33 #include <pthread.h> 34 #include <stdarg.h> 35 #include <stddef.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <sys/mman.h> 39 #include <sys/socket.h> 40 #include <sys/types.h> 41 #include <sys/uio.h> 42 #include <sys/un.h> 43 #include <time.h> 44 #include <unistd.h> 45 46 #include <android/set_abort_message.h> 47 #include <async_safe/log.h> 48 49 #include "private/CachedProperty.h" 50 #include "private/ErrnoRestorer.h" 51 #include "private/ScopedPthreadMutexLocker.h" 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 EVENT_TYPE_FLOAT = 4, 60 }; 61 62 struct BufferOutputStream { 63 public: 64 BufferOutputStream(char* buffer, size_t size) : total(0), pos_(buffer), avail_(size) { 65 if (avail_ > 0) pos_[0] = '\0'; 66 } 67 ~BufferOutputStream() = default; 68 69 void Send(const char* data, int len) { 70 if (len < 0) { 71 len = strlen(data); 72 } 73 total += len; 74 75 if (avail_ <= 1) { 76 // No space to put anything else. 77 return; 78 } 79 80 if (static_cast<size_t>(len) >= avail_) { 81 len = avail_ - 1; 82 } 83 memcpy(pos_, data, len); 84 pos_ += len; 85 pos_[0] = '\0'; 86 avail_ -= len; 87 } 88 89 size_t total; 90 91 private: 92 char* pos_; 93 size_t avail_; 94 }; 95 96 struct FdOutputStream { 97 public: 98 explicit FdOutputStream(int fd) : total(0), fd_(fd) {} 99 100 void Send(const char* data, int len) { 101 if (len < 0) { 102 len = strlen(data); 103 } 104 total += len; 105 106 while (len > 0) { 107 ssize_t bytes = TEMP_FAILURE_RETRY(write(fd_, data, len)); 108 if (bytes == -1) { 109 return; 110 } 111 data += bytes; 112 len -= bytes; 113 } 114 } 115 116 size_t total; 117 118 private: 119 int fd_; 120 }; 121 122 /*** formatted output implementation 123 ***/ 124 125 /* Parse a decimal string from 'format + *ppos', 126 * return the value, and writes the new position past 127 * the decimal string in '*ppos' on exit. 128 * 129 * NOTE: Does *not* handle a sign prefix. 130 */ 131 static unsigned parse_decimal(const char* format, int* ppos) { 132 const char* p = format + *ppos; 133 unsigned result = 0; 134 135 for (;;) { 136 int ch = *p; 137 unsigned d = static_cast<unsigned>(ch - '0'); 138 139 if (d >= 10U) { 140 break; 141 } 142 143 result = result * 10 + d; 144 p++; 145 } 146 *ppos = p - format; 147 return result; 148 } 149 150 // Writes number 'value' in base 'base' into buffer 'buf' of size 'buf_size' bytes. 151 // Assumes that buf_size > 0. 152 static void format_unsigned(char* buf, size_t buf_size, uint64_t value, int base, bool caps) { 153 char* p = buf; 154 char* end = buf + buf_size - 1; 155 156 // Generate digit string in reverse order. 157 while (value) { 158 unsigned d = value % base; 159 value /= base; 160 if (p != end) { 161 char ch; 162 if (d < 10) { 163 ch = '0' + d; 164 } else { 165 ch = (caps ? 'A' : 'a') + (d - 10); 166 } 167 *p++ = ch; 168 } 169 } 170 171 // Special case for 0. 172 if (p == buf) { 173 if (p != end) { 174 *p++ = '0'; 175 } 176 } 177 *p = '\0'; 178 179 // Reverse digit string in-place. 180 size_t length = p - buf; 181 for (size_t i = 0, j = length - 1; i < j; ++i, --j) { 182 char ch = buf[i]; 183 buf[i] = buf[j]; 184 buf[j] = ch; 185 } 186 } 187 188 static void format_integer(char* buf, size_t buf_size, uint64_t value, char conversion) { 189 // Decode the conversion specifier. 190 int is_signed = (conversion == 'd' || conversion == 'i' || conversion == 'o'); 191 int base = 10; 192 if (conversion == 'x' || conversion == 'X') { 193 base = 16; 194 } else if (conversion == 'o') { 195 base = 8; 196 } 197 bool caps = (conversion == 'X'); 198 199 if (is_signed && static_cast<int64_t>(value) < 0) { 200 buf[0] = '-'; 201 buf += 1; 202 buf_size -= 1; 203 value = static_cast<uint64_t>(-static_cast<int64_t>(value)); 204 } 205 format_unsigned(buf, buf_size, value, base, caps); 206 } 207 208 template <typename Out> 209 static void SendRepeat(Out& o, char ch, int count) { 210 char pad[8]; 211 memset(pad, ch, sizeof(pad)); 212 213 const int pad_size = static_cast<int>(sizeof(pad)); 214 while (count > 0) { 215 int avail = count; 216 if (avail > pad_size) { 217 avail = pad_size; 218 } 219 o.Send(pad, avail); 220 count -= avail; 221 } 222 } 223 224 /* Perform formatted output to an output target 'o' */ 225 template <typename Out> 226 static void out_vformat(Out& o, const char* format, va_list args) { 227 int nn = 0; 228 229 for (;;) { 230 int mm; 231 int padZero = 0; 232 int padLeft = 0; 233 char sign = '\0'; 234 int width = -1; 235 int prec = -1; 236 size_t bytelen = sizeof(int); 237 int slen; 238 char buffer[32]; /* temporary buffer used to format numbers */ 239 240 char c; 241 242 /* first, find all characters that are not 0 or '%' */ 243 /* then send them to the output directly */ 244 mm = nn; 245 do { 246 c = format[mm]; 247 if (c == '\0' || c == '%') break; 248 mm++; 249 } while (1); 250 251 if (mm > nn) { 252 o.Send(format + nn, mm - nn); 253 nn = mm; 254 } 255 256 /* is this it ? then exit */ 257 if (c == '\0') break; 258 259 /* nope, we are at a '%' modifier */ 260 nn++; // skip it 261 262 /* parse flags */ 263 for (;;) { 264 c = format[nn++]; 265 if (c == '\0') { /* single trailing '%' ? */ 266 c = '%'; 267 o.Send(&c, 1); 268 return; 269 } else if (c == '0') { 270 padZero = 1; 271 continue; 272 } else if (c == '-') { 273 padLeft = 1; 274 continue; 275 } else if (c == ' ' || c == '+') { 276 sign = c; 277 continue; 278 } 279 break; 280 } 281 282 /* parse field width */ 283 if ((c >= '0' && c <= '9')) { 284 nn--; 285 width = static_cast<int>(parse_decimal(format, &nn)); 286 c = format[nn++]; 287 } 288 289 /* parse precision */ 290 if (c == '.') { 291 prec = static_cast<int>(parse_decimal(format, &nn)); 292 c = format[nn++]; 293 } 294 295 /* length modifier */ 296 switch (c) { 297 case 'h': 298 bytelen = sizeof(short); 299 if (format[nn] == 'h') { 300 bytelen = sizeof(char); 301 nn += 1; 302 } 303 c = format[nn++]; 304 break; 305 case 'l': 306 bytelen = sizeof(long); 307 if (format[nn] == 'l') { 308 bytelen = sizeof(long long); 309 nn += 1; 310 } 311 c = format[nn++]; 312 break; 313 case 'z': 314 bytelen = sizeof(size_t); 315 c = format[nn++]; 316 break; 317 case 't': 318 bytelen = sizeof(ptrdiff_t); 319 c = format[nn++]; 320 break; 321 default:; 322 } 323 324 /* conversion specifier */ 325 const char* str = buffer; 326 if (c == 's') { 327 /* string */ 328 str = va_arg(args, const char*); 329 if (str == NULL) { 330 str = "(null)"; 331 } 332 } else if (c == 'c') { 333 /* character */ 334 /* NOTE: char is promoted to int when passed through the stack */ 335 buffer[0] = static_cast<char>(va_arg(args, int)); 336 buffer[1] = '\0'; 337 } else if (c == 'p') { 338 uint64_t value = reinterpret_cast<uintptr_t>(va_arg(args, void*)); 339 buffer[0] = '0'; 340 buffer[1] = 'x'; 341 format_integer(buffer + 2, sizeof(buffer) - 2, value, 'x'); 342 } else if (c == 'd' || c == 'i' || c == 'o' || c == 'u' || c == 'x' || c == 'X') { 343 /* integers - first read value from stack */ 344 uint64_t value; 345 int is_signed = (c == 'd' || c == 'i' || c == 'o'); 346 347 /* NOTE: int8_t and int16_t are promoted to int when passed 348 * through the stack 349 */ 350 switch (bytelen) { 351 case 1: 352 value = static_cast<uint8_t>(va_arg(args, int)); 353 break; 354 case 2: 355 value = static_cast<uint16_t>(va_arg(args, int)); 356 break; 357 case 4: 358 value = va_arg(args, uint32_t); 359 break; 360 case 8: 361 value = va_arg(args, uint64_t); 362 break; 363 default: 364 return; /* should not happen */ 365 } 366 367 /* sign extension, if needed */ 368 if (is_signed) { 369 int shift = 64 - 8 * bytelen; 370 value = static_cast<uint64_t>((static_cast<int64_t>(value << shift)) >> shift); 371 } 372 373 /* format the number properly into our buffer */ 374 format_integer(buffer, sizeof(buffer), value, c); 375 } else if (c == '%') { 376 buffer[0] = '%'; 377 buffer[1] = '\0'; 378 } else { 379 __assert(__FILE__, __LINE__, "conversion specifier unsupported"); 380 } 381 382 /* if we are here, 'str' points to the content that must be 383 * outputted. handle padding and alignment now */ 384 385 slen = strlen(str); 386 387 if (sign != '\0' || prec != -1) { 388 __assert(__FILE__, __LINE__, "sign/precision unsupported"); 389 } 390 391 if (slen < width && !padLeft) { 392 char padChar = padZero ? '0' : ' '; 393 SendRepeat(o, padChar, width - slen); 394 } 395 396 o.Send(str, slen); 397 398 if (slen < width && padLeft) { 399 char padChar = padZero ? '0' : ' '; 400 SendRepeat(o, padChar, width - slen); 401 } 402 } 403 } 404 405 int async_safe_format_buffer_va_list(char* buffer, size_t buffer_size, const char* format, 406 va_list args) { 407 BufferOutputStream os(buffer, buffer_size); 408 out_vformat(os, format, args); 409 return os.total; 410 } 411 412 int async_safe_format_buffer(char* buffer, size_t buffer_size, const char* format, ...) { 413 va_list args; 414 va_start(args, format); 415 int buffer_len = async_safe_format_buffer_va_list(buffer, buffer_size, format, args); 416 va_end(args); 417 return buffer_len; 418 } 419 420 int async_safe_format_fd(int fd, const char* format, ...) { 421 FdOutputStream os(fd); 422 va_list args; 423 va_start(args, format); 424 out_vformat(os, format, args); 425 va_end(args); 426 return os.total; 427 } 428 429 static int write_stderr(const char* tag, const char* msg) { 430 iovec vec[4]; 431 vec[0].iov_base = const_cast<char*>(tag); 432 vec[0].iov_len = strlen(tag); 433 vec[1].iov_base = const_cast<char*>(": "); 434 vec[1].iov_len = 2; 435 vec[2].iov_base = const_cast<char*>(msg); 436 vec[2].iov_len = strlen(msg); 437 vec[3].iov_base = const_cast<char*>("\n"); 438 vec[3].iov_len = 1; 439 440 int result = TEMP_FAILURE_RETRY(writev(STDERR_FILENO, vec, 4)); 441 return result; 442 } 443 444 static int open_log_socket() { 445 // ToDo: Ideally we want this to fail if the gid of the current 446 // process is AID_LOGD, but will have to wait until we have 447 // registered this in private/android_filesystem_config.h. We have 448 // found that all logd crashes thus far have had no problem stuffing 449 // the UNIX domain socket and moving on so not critical *today*. 450 451 int log_fd = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)); 452 if (log_fd == -1) { 453 return -1; 454 } 455 456 union { 457 struct sockaddr addr; 458 struct sockaddr_un addrUn; 459 } u; 460 memset(&u, 0, sizeof(u)); 461 u.addrUn.sun_family = AF_UNIX; 462 strlcpy(u.addrUn.sun_path, "/dev/socket/logdw", sizeof(u.addrUn.sun_path)); 463 464 if (TEMP_FAILURE_RETRY(connect(log_fd, &u.addr, sizeof(u.addrUn))) != 0) { 465 close(log_fd); 466 return -1; 467 } 468 469 return log_fd; 470 } 471 472 struct log_time { // Wire format 473 uint32_t tv_sec; 474 uint32_t tv_nsec; 475 }; 476 477 int async_safe_write_log(int priority, const char* tag, const char* msg) { 478 int main_log_fd = open_log_socket(); 479 if (main_log_fd == -1) { 480 // Try stderr instead. 481 return write_stderr(tag, msg); 482 } 483 484 iovec vec[6]; 485 char log_id = (priority == ANDROID_LOG_FATAL) ? LOG_ID_CRASH : LOG_ID_MAIN; 486 vec[0].iov_base = &log_id; 487 vec[0].iov_len = sizeof(log_id); 488 uint16_t tid = gettid(); 489 vec[1].iov_base = &tid; 490 vec[1].iov_len = sizeof(tid); 491 timespec ts; 492 clock_gettime(CLOCK_REALTIME, &ts); 493 log_time realtime_ts; 494 realtime_ts.tv_sec = ts.tv_sec; 495 realtime_ts.tv_nsec = ts.tv_nsec; 496 vec[2].iov_base = &realtime_ts; 497 vec[2].iov_len = sizeof(realtime_ts); 498 499 vec[3].iov_base = &priority; 500 vec[3].iov_len = 1; 501 vec[4].iov_base = const_cast<char*>(tag); 502 vec[4].iov_len = strlen(tag) + 1; 503 vec[5].iov_base = const_cast<char*>(msg); 504 vec[5].iov_len = strlen(msg) + 1; 505 506 int result = TEMP_FAILURE_RETRY(writev(main_log_fd, vec, sizeof(vec) / sizeof(vec[0]))); 507 close(main_log_fd); 508 return result; 509 } 510 511 int async_safe_format_log_va_list(int priority, const char* tag, const char* format, va_list args) { 512 ErrnoRestorer errno_restorer; 513 char buffer[1024]; 514 BufferOutputStream os(buffer, sizeof(buffer)); 515 out_vformat(os, format, args); 516 return async_safe_write_log(priority, tag, buffer); 517 } 518 519 int async_safe_format_log(int priority, const char* tag, const char* format, ...) { 520 va_list args; 521 va_start(args, format); 522 int result = async_safe_format_log_va_list(priority, tag, format, args); 523 va_end(args); 524 return result; 525 } 526 527 void async_safe_fatal_va_list(const char* prefix, const char* format, va_list args) { 528 char msg[1024]; 529 BufferOutputStream os(msg, sizeof(msg)); 530 531 if (prefix) { 532 os.Send(prefix, strlen(prefix)); 533 os.Send(": ", 2); 534 } 535 536 out_vformat(os, format, args); 537 538 // Log to stderr for the benefit of "adb shell" users and gtests. 539 struct iovec iov[2] = { 540 {msg, os.total}, {const_cast<char*>("\n"), 1}, 541 }; 542 TEMP_FAILURE_RETRY(writev(2, iov, 2)); 543 544 // Log to the log for the benefit of regular app developers (whose stdout and stderr are closed). 545 async_safe_write_log(ANDROID_LOG_FATAL, "libc", msg); 546 547 android_set_abort_message(msg); 548 } 549 550 void async_safe_fatal_no_abort(const char* fmt, ...) { 551 va_list args; 552 va_start(args, fmt); 553 async_safe_fatal_va_list(nullptr, fmt, args); 554 va_end(args); 555 } 556