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