Home | History | Annotate | Download | only in liblog
      1 /*
      2 ** Copyright 2014, The Android Open Source Project
      3 **
      4 ** Licensed under the Apache License, Version 2.0 (the "License");
      5 ** you may not use this file except in compliance with the License.
      6 ** You may obtain a copy of the License at
      7 **
      8 **     http://www.apache.org/licenses/LICENSE-2.0
      9 **
     10 ** Unless required by applicable law or agreed to in writing, software
     11 ** distributed under the License is distributed on an "AS IS" BASIS,
     12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 ** See the License for the specific language governing permissions and
     14 ** limitations under the License.
     15 */
     16 
     17 #include <ctype.h>
     18 #include <pthread.h>
     19 #include <stdbool.h>
     20 #include <stdlib.h>
     21 #include <string.h>
     22 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
     23 #include <sys/_system_properties.h>
     24 #include <unistd.h>
     25 
     26 #include <private/android_logger.h>
     27 
     28 #include "log_portability.h"
     29 
     30 static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
     31 
     32 static int lock() {
     33   /*
     34    * If we trigger a signal handler in the middle of locked activity and the
     35    * signal handler logs a message, we could get into a deadlock state.
     36    */
     37   /*
     38    *  Any contention, and we can turn around and use the non-cached method
     39    * in less time than the system call associated with a mutex to deal with
     40    * the contention.
     41    */
     42   return pthread_mutex_trylock(&lock_loggable);
     43 }
     44 
     45 static void unlock() {
     46   pthread_mutex_unlock(&lock_loggable);
     47 }
     48 
     49 struct cache {
     50   const prop_info* pinfo;
     51   uint32_t serial;
     52 };
     53 
     54 struct cache_char {
     55   struct cache cache;
     56   unsigned char c;
     57 };
     58 
     59 static int check_cache(struct cache* cache) {
     60   return cache->pinfo && __system_property_serial(cache->pinfo) != cache->serial;
     61 }
     62 
     63 #define BOOLEAN_TRUE 0xFF
     64 #define BOOLEAN_FALSE 0xFE
     65 
     66 static void refresh_cache(struct cache_char* cache, const char* key) {
     67   char buf[PROP_VALUE_MAX];
     68 
     69   if (!cache->cache.pinfo) {
     70     cache->cache.pinfo = __system_property_find(key);
     71     if (!cache->cache.pinfo) {
     72       return;
     73     }
     74   }
     75   cache->cache.serial = __system_property_serial(cache->cache.pinfo);
     76   __system_property_read(cache->cache.pinfo, 0, buf);
     77   switch (buf[0]) {
     78     case 't':
     79     case 'T':
     80       cache->c = strcasecmp(buf + 1, "rue") ? buf[0] : BOOLEAN_TRUE;
     81       break;
     82     case 'f':
     83     case 'F':
     84       cache->c = strcasecmp(buf + 1, "alse") ? buf[0] : BOOLEAN_FALSE;
     85       break;
     86     default:
     87       cache->c = buf[0];
     88   }
     89 }
     90 
     91 static int __android_log_level(const char* tag, size_t len, int default_prio) {
     92   /* sizeof() is used on this array below */
     93   static const char log_namespace[] = "persist.log.tag.";
     94   static const size_t base_offset = 8; /* skip "persist." */
     95   /* calculate the size of our key temporary buffer */
     96   const size_t taglen = tag ? len : 0;
     97   /* sizeof(log_namespace) = strlen(log_namespace) + 1 */
     98   char key[sizeof(log_namespace) + taglen];
     99   char* kp;
    100   size_t i;
    101   char c = 0;
    102   /*
    103    * Single layer cache of four properties. Priorities are:
    104    *    log.tag.<tag>
    105    *    persist.log.tag.<tag>
    106    *    log.tag
    107    *    persist.log.tag
    108    * Where the missing tag matches all tags and becomes the
    109    * system global default. We do not support ro.log.tag* .
    110    */
    111   static char* last_tag;
    112   static size_t last_tag_len;
    113   static uint32_t global_serial;
    114   /* some compilers erroneously see uninitialized use. !not_locked */
    115   uint32_t current_global_serial = 0;
    116   static struct cache_char tag_cache[2];
    117   static struct cache_char global_cache[2];
    118   int change_detected;
    119   int global_change_detected;
    120   int not_locked;
    121 
    122   strcpy(key, log_namespace);
    123 
    124   global_change_detected = change_detected = not_locked = lock();
    125 
    126   if (!not_locked) {
    127     /*
    128      *  check all known serial numbers to changes.
    129      */
    130     for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
    131       if (check_cache(&tag_cache[i].cache)) {
    132         change_detected = 1;
    133       }
    134     }
    135     for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
    136       if (check_cache(&global_cache[i].cache)) {
    137         global_change_detected = 1;
    138       }
    139     }
    140 
    141     current_global_serial = __system_property_area_serial();
    142     if (current_global_serial != global_serial) {
    143       change_detected = 1;
    144       global_change_detected = 1;
    145     }
    146   }
    147 
    148   if (taglen) {
    149     int local_change_detected = change_detected;
    150     if (!not_locked) {
    151       if (!last_tag || !last_tag[0] || (last_tag[0] != tag[0]) ||
    152           strncmp(last_tag + 1, tag + 1, last_tag_len - 1)) {
    153         /* invalidate log.tag.<tag> cache */
    154         for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
    155           tag_cache[i].cache.pinfo = NULL;
    156           tag_cache[i].c = '\0';
    157         }
    158         if (last_tag) last_tag[0] = '\0';
    159         local_change_detected = 1;
    160       }
    161       if (!last_tag || !last_tag[0]) {
    162         if (!last_tag) {
    163           last_tag = calloc(1, len + 1);
    164           last_tag_len = 0;
    165           if (last_tag) last_tag_len = len + 1;
    166         } else if (len >= last_tag_len) {
    167           last_tag = realloc(last_tag, len + 1);
    168           last_tag_len = 0;
    169           if (last_tag) last_tag_len = len + 1;
    170         }
    171         if (last_tag) {
    172           strncpy(last_tag, tag, len);
    173           last_tag[len] = '\0';
    174         }
    175       }
    176     }
    177     strncpy(key + sizeof(log_namespace) - 1, tag, len);
    178     key[sizeof(log_namespace) - 1 + len] = '\0';
    179 
    180     kp = key;
    181     for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
    182       struct cache_char* cache = &tag_cache[i];
    183       struct cache_char temp_cache;
    184 
    185       if (not_locked) {
    186         temp_cache.cache.pinfo = NULL;
    187         temp_cache.c = '\0';
    188         cache = &temp_cache;
    189       }
    190       if (local_change_detected) {
    191         refresh_cache(cache, kp);
    192       }
    193 
    194       if (cache->c) {
    195         c = cache->c;
    196         break;
    197       }
    198 
    199       kp = key + base_offset;
    200     }
    201   }
    202 
    203   switch (toupper(c)) { /* if invalid, resort to global */
    204     case 'V':
    205     case 'D':
    206     case 'I':
    207     case 'W':
    208     case 'E':
    209     case 'F': /* Not officially supported */
    210     case 'A':
    211     case 'S':
    212     case BOOLEAN_FALSE: /* Not officially supported */
    213       break;
    214     default:
    215       /* clear '.' after log.tag */
    216       key[sizeof(log_namespace) - 2] = '\0';
    217 
    218       kp = key;
    219       for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
    220         struct cache_char* cache = &global_cache[i];
    221         struct cache_char temp_cache;
    222 
    223         if (not_locked) {
    224           temp_cache = *cache;
    225           if (temp_cache.cache.pinfo != cache->cache.pinfo) { /* check atomic */
    226             temp_cache.cache.pinfo = NULL;
    227             temp_cache.c = '\0';
    228           }
    229           cache = &temp_cache;
    230         }
    231         if (global_change_detected) {
    232           refresh_cache(cache, kp);
    233         }
    234 
    235         if (cache->c) {
    236           c = cache->c;
    237           break;
    238         }
    239 
    240         kp = key + base_offset;
    241       }
    242       break;
    243   }
    244 
    245   if (!not_locked) {
    246     global_serial = current_global_serial;
    247     unlock();
    248   }
    249 
    250   switch (toupper(c)) {
    251     /* clang-format off */
    252     case 'V': return ANDROID_LOG_VERBOSE;
    253     case 'D': return ANDROID_LOG_DEBUG;
    254     case 'I': return ANDROID_LOG_INFO;
    255     case 'W': return ANDROID_LOG_WARN;
    256     case 'E': return ANDROID_LOG_ERROR;
    257     case 'F': /* FALLTHRU */ /* Not officially supported */
    258     case 'A': return ANDROID_LOG_FATAL;
    259     case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
    260     case 'S': return -1; /* ANDROID_LOG_SUPPRESS */
    261     /* clang-format on */
    262   }
    263   return default_prio;
    264 }
    265 
    266 LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, const char* tag,
    267                                                     size_t len,
    268                                                     int default_prio) {
    269   int logLevel = __android_log_level(tag, len, default_prio);
    270   return logLevel >= 0 && prio >= logLevel;
    271 }
    272 
    273 LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, const char* tag,
    274                                                 int default_prio) {
    275   int logLevel =
    276       __android_log_level(tag, (tag && *tag) ? strlen(tag) : 0, default_prio);
    277   return logLevel >= 0 && prio >= logLevel;
    278 }
    279 
    280 LIBLOG_ABI_PUBLIC int __android_log_is_debuggable() {
    281   static uint32_t serial;
    282   static struct cache_char tag_cache;
    283   static const char key[] = "ro.debuggable";
    284   int ret;
    285 
    286   if (tag_cache.c) { /* ro property does not change after set */
    287     ret = tag_cache.c == '1';
    288   } else if (lock()) {
    289     struct cache_char temp_cache = { { NULL, -1 }, '\0' };
    290     refresh_cache(&temp_cache, key);
    291     ret = temp_cache.c == '1';
    292   } else {
    293     int change_detected = check_cache(&tag_cache.cache);
    294     uint32_t current_serial = __system_property_area_serial();
    295     if (current_serial != serial) {
    296       change_detected = 1;
    297     }
    298     if (change_detected) {
    299       refresh_cache(&tag_cache, key);
    300       serial = current_serial;
    301     }
    302     ret = tag_cache.c == '1';
    303 
    304     unlock();
    305   }
    306 
    307   return ret;
    308 }
    309 
    310 /*
    311  * For properties that are read often, but generally remain constant.
    312  * Since a change is rare, we will accept a trylock failure gracefully.
    313  * Use a separate lock from is_loggable to keep contention down b/25563384.
    314  */
    315 struct cache2_char {
    316   pthread_mutex_t lock;
    317   uint32_t serial;
    318   const char* key_persist;
    319   struct cache_char cache_persist;
    320   const char* key_ro;
    321   struct cache_char cache_ro;
    322   unsigned char (*const evaluate)(const struct cache2_char* self);
    323 };
    324 
    325 static inline unsigned char do_cache2_char(struct cache2_char* self) {
    326   uint32_t current_serial;
    327   int change_detected;
    328   unsigned char c;
    329 
    330   if (pthread_mutex_trylock(&self->lock)) {
    331     /* We are willing to accept some race in this context */
    332     return self->evaluate(self);
    333   }
    334 
    335   change_detected = check_cache(&self->cache_persist.cache) ||
    336                     check_cache(&self->cache_ro.cache);
    337   current_serial = __system_property_area_serial();
    338   if (current_serial != self->serial) {
    339     change_detected = 1;
    340   }
    341   if (change_detected) {
    342     refresh_cache(&self->cache_persist, self->key_persist);
    343     refresh_cache(&self->cache_ro, self->key_ro);
    344     self->serial = current_serial;
    345   }
    346   c = self->evaluate(self);
    347 
    348   pthread_mutex_unlock(&self->lock);
    349 
    350   return c;
    351 }
    352 
    353 static unsigned char evaluate_persist_ro(const struct cache2_char* self) {
    354   unsigned char c = self->cache_persist.c;
    355 
    356   if (c) {
    357     return c;
    358   }
    359 
    360   return self->cache_ro.c;
    361 }
    362 
    363 /*
    364  * Timestamp state generally remains constant, but can change at any time
    365  * to handle developer requirements.
    366  */
    367 LIBLOG_ABI_PUBLIC clockid_t android_log_clockid() {
    368   static struct cache2_char clockid = {
    369     PTHREAD_MUTEX_INITIALIZER, 0,
    370     "persist.logd.timestamp",  { { NULL, -1 }, '\0' },
    371     "ro.logd.timestamp",       { { NULL, -1 }, '\0' },
    372     evaluate_persist_ro
    373   };
    374 
    375   return (tolower(do_cache2_char(&clockid)) == 'm') ? CLOCK_MONOTONIC
    376                                                     : CLOCK_REALTIME;
    377 }
    378 
    379 /*
    380  * Security state generally remains constant, but the DO must be able
    381  * to turn off logging should it become spammy after an attack is detected.
    382  */
    383 static unsigned char evaluate_security(const struct cache2_char* self) {
    384   unsigned char c = self->cache_ro.c;
    385 
    386   return (c != BOOLEAN_FALSE) && c && (self->cache_persist.c == BOOLEAN_TRUE);
    387 }
    388 
    389 LIBLOG_ABI_PUBLIC int __android_log_security() {
    390   static struct cache2_char security = {
    391     PTHREAD_MUTEX_INITIALIZER, 0,
    392     "persist.logd.security",   { { NULL, -1 }, BOOLEAN_FALSE },
    393     "ro.device_owner",         { { NULL, -1 }, BOOLEAN_FALSE },
    394     evaluate_security
    395   };
    396 
    397   return do_cache2_char(&security);
    398 }
    399 
    400 /*
    401  * Interface that represents the logd buffer size determination so that others
    402  * need not guess our intentions.
    403  */
    404 
    405 /* Property helper */
    406 static bool check_flag(const char* prop, const char* flag) {
    407   const char* cp = strcasestr(prop, flag);
    408   if (!cp) {
    409     return false;
    410   }
    411   /* We only will document comma (,) */
    412   static const char sep[] = ",:;|+ \t\f";
    413   if ((cp != prop) && !strchr(sep, cp[-1])) {
    414     return false;
    415   }
    416   cp += strlen(flag);
    417   return !*cp || !!strchr(sep, *cp);
    418 }
    419 
    420 /* cache structure */
    421 struct cache_property {
    422   struct cache cache;
    423   char property[PROP_VALUE_MAX];
    424 };
    425 
    426 static void refresh_cache_property(struct cache_property* cache,
    427                                    const char* key) {
    428   if (!cache->cache.pinfo) {
    429     cache->cache.pinfo = __system_property_find(key);
    430     if (!cache->cache.pinfo) {
    431       return;
    432     }
    433   }
    434   cache->cache.serial = __system_property_serial(cache->cache.pinfo);
    435   __system_property_read(cache->cache.pinfo, 0, cache->property);
    436 }
    437 
    438 /* get boolean with the logger twist that supports eng adjustments */
    439 LIBLOG_ABI_PRIVATE bool __android_logger_property_get_bool(const char* key,
    440                                                            int flag) {
    441   struct cache_property property = { { NULL, -1 }, { 0 } };
    442   if (flag & BOOL_DEFAULT_FLAG_PERSIST) {
    443     char newkey[strlen("persist.") + strlen(key) + 1];
    444     snprintf(newkey, sizeof(newkey), "ro.%s", key);
    445     refresh_cache_property(&property, newkey);
    446     property.cache.pinfo = NULL;
    447     property.cache.serial = -1;
    448     snprintf(newkey, sizeof(newkey), "persist.%s", key);
    449     refresh_cache_property(&property, newkey);
    450     property.cache.pinfo = NULL;
    451     property.cache.serial = -1;
    452   }
    453 
    454   refresh_cache_property(&property, key);
    455 
    456   if (check_flag(property.property, "true")) {
    457     return true;
    458   }
    459   if (check_flag(property.property, "false")) {
    460     return false;
    461   }
    462   if (property.property[0]) {
    463     flag &= ~(BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE);
    464   }
    465   if (check_flag(property.property, "eng")) {
    466     flag |= BOOL_DEFAULT_FLAG_ENG;
    467   }
    468   /* this is really a "not" flag */
    469   if (check_flag(property.property, "svelte")) {
    470     flag |= BOOL_DEFAULT_FLAG_SVELTE;
    471   }
    472 
    473   /* Sanity Check */
    474   if (flag & (BOOL_DEFAULT_FLAG_SVELTE | BOOL_DEFAULT_FLAG_ENG)) {
    475     flag &= ~BOOL_DEFAULT_FLAG_TRUE_FALSE;
    476     flag |= BOOL_DEFAULT_TRUE;
    477   }
    478 
    479   if ((flag & BOOL_DEFAULT_FLAG_SVELTE) &&
    480       __android_logger_property_get_bool("ro.config.low_ram",
    481                                          BOOL_DEFAULT_FALSE)) {
    482     return false;
    483   }
    484   if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) {
    485     return false;
    486   }
    487 
    488   return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
    489 }
    490 
    491 LIBLOG_ABI_PRIVATE bool __android_logger_valid_buffer_size(unsigned long value) {
    492   static long pages, pagesize;
    493   unsigned long maximum;
    494 
    495   if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
    496     return false;
    497   }
    498 
    499   if (!pages) {
    500     pages = sysconf(_SC_PHYS_PAGES);
    501   }
    502   if (pages < 1) {
    503     return true;
    504   }
    505 
    506   if (!pagesize) {
    507     pagesize = sysconf(_SC_PAGESIZE);
    508     if (pagesize <= 1) {
    509       pagesize = PAGE_SIZE;
    510     }
    511   }
    512 
    513   /* maximum memory impact a somewhat arbitrary ~3% */
    514   pages = (pages + 31) / 32;
    515   maximum = pages * pagesize;
    516 
    517   if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
    518     return true;
    519   }
    520 
    521   return value <= maximum;
    522 }
    523 
    524 struct cache2_property_size {
    525   pthread_mutex_t lock;
    526   uint32_t serial;
    527   const char* key_persist;
    528   struct cache_property cache_persist;
    529   const char* key_ro;
    530   struct cache_property cache_ro;
    531   unsigned long (*const evaluate)(const struct cache2_property_size* self);
    532 };
    533 
    534 static inline unsigned long do_cache2_property_size(
    535     struct cache2_property_size* self) {
    536   uint32_t current_serial;
    537   int change_detected;
    538   unsigned long v;
    539 
    540   if (pthread_mutex_trylock(&self->lock)) {
    541     /* We are willing to accept some race in this context */
    542     return self->evaluate(self);
    543   }
    544 
    545   change_detected = check_cache(&self->cache_persist.cache) ||
    546                     check_cache(&self->cache_ro.cache);
    547   current_serial = __system_property_area_serial();
    548   if (current_serial != self->serial) {
    549     change_detected = 1;
    550   }
    551   if (change_detected) {
    552     refresh_cache_property(&self->cache_persist, self->key_persist);
    553     refresh_cache_property(&self->cache_ro, self->key_ro);
    554     self->serial = current_serial;
    555   }
    556   v = self->evaluate(self);
    557 
    558   pthread_mutex_unlock(&self->lock);
    559 
    560   return v;
    561 }
    562 
    563 static unsigned long property_get_size_from_cache(
    564     const struct cache_property* cache) {
    565   char* cp;
    566   unsigned long value = strtoul(cache->property, &cp, 10);
    567 
    568   switch (*cp) {
    569     case 'm':
    570     case 'M':
    571       value *= 1024;
    572     /* FALLTHRU */
    573     case 'k':
    574     case 'K':
    575       value *= 1024;
    576     /* FALLTHRU */
    577     case '\0':
    578       break;
    579 
    580     default:
    581       value = 0;
    582   }
    583 
    584   if (!__android_logger_valid_buffer_size(value)) {
    585     value = 0;
    586   }
    587 
    588   return value;
    589 }
    590 
    591 static unsigned long evaluate_property_get_size(
    592     const struct cache2_property_size* self) {
    593   unsigned long size = property_get_size_from_cache(&self->cache_persist);
    594   if (size) {
    595     return size;
    596   }
    597   return property_get_size_from_cache(&self->cache_ro);
    598 }
    599 
    600 LIBLOG_ABI_PRIVATE unsigned long __android_logger_get_buffer_size(log_id_t logId) {
    601   static const char global_tunable[] = "persist.logd.size"; /* Settings App */
    602   static const char global_default[] = "ro.logd.size";      /* BoardConfig.mk */
    603   static struct cache2_property_size global = {
    604     /* clang-format off */
    605     PTHREAD_MUTEX_INITIALIZER, 0,
    606     global_tunable, { { NULL, -1 }, {} },
    607     global_default, { { NULL, -1 }, {} },
    608     evaluate_property_get_size
    609     /* clang-format on */
    610   };
    611   char key_persist[strlen(global_tunable) + strlen(".security") + 1];
    612   char key_ro[strlen(global_default) + strlen(".security") + 1];
    613   struct cache2_property_size local = {
    614     /* clang-format off */
    615     PTHREAD_MUTEX_INITIALIZER, 0,
    616     key_persist, { { NULL, -1 }, {} },
    617     key_ro,      { { NULL, -1 }, {} },
    618     evaluate_property_get_size
    619     /* clang-format on */
    620   };
    621   unsigned long property_size, default_size;
    622 
    623   default_size = do_cache2_property_size(&global);
    624   if (!default_size) {
    625     default_size = __android_logger_property_get_bool("ro.config.low_ram",
    626                                                       BOOL_DEFAULT_FALSE)
    627                        ? LOG_BUFFER_MIN_SIZE /* 64K  */
    628                        : LOG_BUFFER_SIZE;    /* 256K */
    629   }
    630 
    631   snprintf(key_persist, sizeof(key_persist), "%s.%s", global_tunable,
    632            android_log_id_to_name(logId));
    633   snprintf(key_ro, sizeof(key_ro), "%s.%s", global_default,
    634            android_log_id_to_name(logId));
    635   property_size = do_cache2_property_size(&local);
    636 
    637   if (!property_size) {
    638     property_size = default_size;
    639   }
    640 
    641   if (!property_size) {
    642     property_size = LOG_BUFFER_SIZE;
    643   }
    644 
    645   return property_size;
    646 }
    647