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