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