Home | History | Annotate | Download | only in bionic
      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