Home | History | Annotate | Download | only in liblog
      1 /*
      2  * Copyright (C) 2007-2016 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 <errno.h>
     18 #include <stdatomic.h>
     19 #include <stdlib.h>
     20 #include <string.h>
     21 #include <sys/time.h>
     22 
     23 #ifdef __BIONIC__
     24 #include <android/set_abort_message.h>
     25 #endif
     26 
     27 #include <log/event_tag_map.h>
     28 #include <log/logd.h>
     29 #include <log/logger.h>
     30 #include <log/log_read.h>
     31 #include <private/android_filesystem_config.h>
     32 #include <private/android_logger.h>
     33 
     34 #include "config_write.h"
     35 #include "log_portability.h"
     36 #include "logger.h"
     37 
     38 #define LOG_BUF_SIZE 1024
     39 
     40 static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr);
     41 static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;
     42 
     43 /*
     44  * This is used by the C++ code to decide if it should write logs through
     45  * the C code.  Basically, if /dev/socket/logd is available, we're running in
     46  * the simulator rather than a desktop tool and want to use the device.
     47  */
     48 static enum {
     49     kLogUninitialized, kLogNotAvailable, kLogAvailable
     50 } g_log_status = kLogUninitialized;
     51 
     52 static int check_log_uid_permissions()
     53 {
     54 #if defined(__BIONIC__)
     55     uid_t uid = __android_log_uid();
     56 
     57     /* Matches clientHasLogCredentials() in logd */
     58     if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) {
     59         uid = geteuid();
     60         if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) {
     61             gid_t gid = getgid();
     62             if ((gid != AID_SYSTEM) &&
     63                     (gid != AID_ROOT) &&
     64                     (gid != AID_LOG)) {
     65                 gid = getegid();
     66                 if ((gid != AID_SYSTEM) &&
     67                         (gid != AID_ROOT) &&
     68                         (gid != AID_LOG)) {
     69                     int num_groups;
     70                     gid_t *groups;
     71 
     72                     num_groups = getgroups(0, NULL);
     73                     if (num_groups <= 0) {
     74                         return -EPERM;
     75                     }
     76                     groups = calloc(num_groups, sizeof(gid_t));
     77                     if (!groups) {
     78                         return -ENOMEM;
     79                     }
     80                     num_groups = getgroups(num_groups, groups);
     81                     while (num_groups > 0) {
     82                         if (groups[num_groups - 1] == AID_LOG) {
     83                             break;
     84                         }
     85                         --num_groups;
     86                     }
     87                     free(groups);
     88                     if (num_groups <= 0) {
     89                         return -EPERM;
     90                     }
     91                 }
     92             }
     93         }
     94     }
     95 #endif
     96     return 0;
     97 }
     98 
     99 static void __android_log_cache_available(
    100         struct android_log_transport_write *node)
    101 {
    102     size_t i;
    103 
    104     if (node->logMask) {
    105         return;
    106     }
    107 
    108     for (i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
    109         if (node->write &&
    110                 (i != LOG_ID_KERNEL) &&
    111                 ((i != LOG_ID_SECURITY) ||
    112                     (check_log_uid_permissions() == 0)) &&
    113                 (!node->available || ((*node->available)(i) >= 0))) {
    114             node->logMask |= 1 << i;
    115         }
    116     }
    117 }
    118 
    119 LIBLOG_ABI_PUBLIC int __android_log_dev_available()
    120 {
    121     struct android_log_transport_write *node;
    122 
    123     if (list_empty(&__android_log_transport_write)) {
    124         return kLogUninitialized;
    125     }
    126 
    127     write_transport_for_each(node, &__android_log_transport_write) {
    128         __android_log_cache_available(node);
    129         if (node->logMask) {
    130             return kLogAvailable;
    131         }
    132     }
    133     return kLogNotAvailable;
    134 }
    135 
    136 /* log_init_lock assumed */
    137 static int __write_to_log_initialize()
    138 {
    139     struct android_log_transport_write *transport;
    140     struct listnode *n;
    141     int i = 0, ret = 0;
    142 
    143     __android_log_config_write();
    144     write_transport_for_each_safe(transport, n, &__android_log_transport_write) {
    145         __android_log_cache_available(transport);
    146         if (!transport->logMask) {
    147             list_remove(&transport->node);
    148             continue;
    149         }
    150         if (!transport->open || ((*transport->open)() < 0)) {
    151             if (transport->close) {
    152                 (*transport->close)();
    153             }
    154             list_remove(&transport->node);
    155             continue;
    156         }
    157         ++ret;
    158     }
    159     write_transport_for_each_safe(transport, n, &__android_log_persist_write) {
    160         __android_log_cache_available(transport);
    161         if (!transport->logMask) {
    162             list_remove(&transport->node);
    163             continue;
    164         }
    165         if (!transport->open || ((*transport->open)() < 0)) {
    166             if (transport->close) {
    167                 (*transport->close)();
    168             }
    169             list_remove(&transport->node);
    170             continue;
    171         }
    172         ++i;
    173     }
    174     if (!ret && !i) {
    175         return -ENODEV;
    176     }
    177 
    178     return ret;
    179 }
    180 
    181 /*
    182  * Extract a 4-byte value from a byte stream. le32toh open coded
    183  */
    184 static inline uint32_t get4LE(const uint8_t* src)
    185 {
    186     return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
    187 }
    188 
    189 static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
    190 {
    191     struct android_log_transport_write *node;
    192     int ret;
    193     struct timespec ts;
    194     size_t len, i;
    195 
    196     for (len = i = 0; i < nr; ++i) {
    197         len += vec[i].iov_len;
    198     }
    199     if (!len) {
    200         return -EINVAL;
    201     }
    202 
    203 #if defined(__BIONIC__)
    204     if (log_id == LOG_ID_SECURITY) {
    205         if (vec[0].iov_len < 4) {
    206             return -EINVAL;
    207         }
    208 
    209         ret = check_log_uid_permissions();
    210         if (ret < 0) {
    211             return ret;
    212         }
    213         if (!__android_log_security()) {
    214             /* If only we could reset downstream logd counter */
    215             return -EPERM;
    216         }
    217     } else if (log_id == LOG_ID_EVENTS) {
    218         static atomic_uintptr_t map;
    219         const char *tag;
    220         EventTagMap *m, *f;
    221 
    222         if (vec[0].iov_len < 4) {
    223             return -EINVAL;
    224         }
    225 
    226         tag = NULL;
    227         f = NULL;
    228         m = (EventTagMap *)atomic_load(&map);
    229 
    230         if (!m) {
    231             ret = __android_log_trylock();
    232             m = (EventTagMap *)atomic_load(&map); /* trylock flush cache */
    233             if (!m) {
    234                 m = android_openEventTagMap(EVENT_TAG_MAP_FILE);
    235                 if (ret) { /* trylock failed, use local copy, mark for close */
    236                     f = m;
    237                 } else {
    238                     if (!m) { /* One chance to open map file */
    239                         m = (EventTagMap *)(uintptr_t)-1LL;
    240                     }
    241                     atomic_store(&map, (uintptr_t)m);
    242                 }
    243             }
    244             if (!ret) { /* trylock succeeded, unlock */
    245                 __android_log_unlock();
    246             }
    247         }
    248         if (m && (m != (EventTagMap *)(uintptr_t)-1LL)) {
    249             tag = android_lookupEventTag(m, get4LE(vec[0].iov_base));
    250         }
    251         ret = __android_log_is_loggable(ANDROID_LOG_INFO,
    252                                         tag,
    253                                         ANDROID_LOG_VERBOSE);
    254         if (f) { /* local copy marked for close */
    255             android_closeEventTagMap(f);
    256         }
    257         if (!ret) {
    258             return -EPERM;
    259         }
    260     } else {
    261         /* Validate the incoming tag, tag content can not split across iovec */
    262         char prio = ANDROID_LOG_VERBOSE;
    263         const char *tag = vec[0].iov_base;
    264         size_t len = vec[0].iov_len;
    265         if (!tag) {
    266             len = 0;
    267         }
    268         if (len > 0) {
    269             prio = *tag;
    270             if (len > 1) {
    271                 --len;
    272                 ++tag;
    273             } else {
    274                 len = vec[1].iov_len;
    275                 tag = ((const char *)vec[1].iov_base);
    276                 if (!tag) {
    277                     len = 0;
    278                 }
    279             }
    280         }
    281         /* tag must be nul terminated */
    282         if (strnlen(tag, len) >= len) {
    283             tag = NULL;
    284         }
    285 
    286         if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
    287             return -EPERM;
    288         }
    289     }
    290 
    291     clock_gettime(android_log_clockid(), &ts);
    292 #else
    293     /* simulate clock_gettime(CLOCK_REALTIME, &ts); */
    294     {
    295         struct timeval tv;
    296         gettimeofday(&tv, NULL);
    297         ts.tv_sec = tv.tv_sec;
    298         ts.tv_nsec = tv.tv_usec * 1000;
    299     }
    300 #endif
    301 
    302     ret = 0;
    303     i = 1 << log_id;
    304     write_transport_for_each(node, &__android_log_transport_write) {
    305         if (node->logMask & i) {
    306             ssize_t retval;
    307             retval = (*node->write)(log_id, &ts, vec, nr);
    308             if (ret >= 0) {
    309                 ret = retval;
    310             }
    311         }
    312     }
    313 
    314     write_transport_for_each(node, &__android_log_persist_write) {
    315         if (node->logMask & i) {
    316             (void)(*node->write)(log_id, &ts, vec, nr);
    317         }
    318     }
    319 
    320     return ret;
    321 }
    322 
    323 static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
    324 {
    325     __android_log_lock();
    326 
    327     if (write_to_log == __write_to_log_init) {
    328         int ret;
    329 
    330         ret = __write_to_log_initialize();
    331         if (ret < 0) {
    332             __android_log_unlock();
    333             if (!list_empty(&__android_log_persist_write)) {
    334                 __write_to_log_daemon(log_id, vec, nr);
    335             }
    336             return ret;
    337         }
    338 
    339         write_to_log = __write_to_log_daemon;
    340     }
    341 
    342     __android_log_unlock();
    343 
    344     return write_to_log(log_id, vec, nr);
    345 }
    346 
    347 LIBLOG_ABI_PUBLIC int __android_log_write(int prio, const char *tag,
    348                                           const char *msg)
    349 {
    350     return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
    351 }
    352 
    353 LIBLOG_ABI_PUBLIC int __android_log_buf_write(int bufID, int prio,
    354                                               const char *tag, const char *msg)
    355 {
    356     struct iovec vec[3];
    357     char tmp_tag[32];
    358 
    359     if (!tag)
    360         tag = "";
    361 
    362     /* XXX: This needs to go! */
    363     if ((bufID != LOG_ID_RADIO) &&
    364          (!strcmp(tag, "HTC_RIL") ||
    365         !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
    366         !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
    367         !strcmp(tag, "AT") ||
    368         !strcmp(tag, "GSM") ||
    369         !strcmp(tag, "STK") ||
    370         !strcmp(tag, "CDMA") ||
    371         !strcmp(tag, "PHONE") ||
    372         !strcmp(tag, "SMS"))) {
    373             bufID = LOG_ID_RADIO;
    374             /* Inform third party apps/ril/radio.. to use Rlog or RLOG */
    375             snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
    376             tag = tmp_tag;
    377     }
    378 
    379 #if __BIONIC__
    380     if (prio == ANDROID_LOG_FATAL) {
    381         android_set_abort_message(msg);
    382     }
    383 #endif
    384 
    385     vec[0].iov_base = (unsigned char *)&prio;
    386     vec[0].iov_len  = 1;
    387     vec[1].iov_base = (void *)tag;
    388     vec[1].iov_len  = strlen(tag) + 1;
    389     vec[2].iov_base = (void *)msg;
    390     vec[2].iov_len  = strlen(msg) + 1;
    391 
    392     return write_to_log(bufID, vec, 3);
    393 }
    394 
    395 LIBLOG_ABI_PUBLIC int __android_log_vprint(int prio, const char *tag,
    396                                            const char *fmt, va_list ap)
    397 {
    398     char buf[LOG_BUF_SIZE];
    399 
    400     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
    401 
    402     return __android_log_write(prio, tag, buf);
    403 }
    404 
    405 LIBLOG_ABI_PUBLIC int __android_log_print(int prio, const char *tag,
    406                                           const char *fmt, ...)
    407 {
    408     va_list ap;
    409     char buf[LOG_BUF_SIZE];
    410 
    411     va_start(ap, fmt);
    412     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
    413     va_end(ap);
    414 
    415     return __android_log_write(prio, tag, buf);
    416 }
    417 
    418 LIBLOG_ABI_PUBLIC int __android_log_buf_print(int bufID, int prio,
    419                                               const char *tag,
    420                                               const char *fmt, ...)
    421 {
    422     va_list ap;
    423     char buf[LOG_BUF_SIZE];
    424 
    425     va_start(ap, fmt);
    426     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
    427     va_end(ap);
    428 
    429     return __android_log_buf_write(bufID, prio, tag, buf);
    430 }
    431 
    432 LIBLOG_ABI_PUBLIC void __android_log_assert(const char *cond, const char *tag,
    433                                             const char *fmt, ...)
    434 {
    435     char buf[LOG_BUF_SIZE];
    436 
    437     if (fmt) {
    438         va_list ap;
    439         va_start(ap, fmt);
    440         vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
    441         va_end(ap);
    442     } else {
    443         /* Msg not provided, log condition.  N.B. Do not use cond directly as
    444          * format string as it could contain spurious '%' syntax (e.g.
    445          * "%d" in "blocks%devs == 0").
    446          */
    447         if (cond)
    448             snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond);
    449         else
    450             strcpy(buf, "Unspecified assertion failed");
    451     }
    452 
    453     __android_log_write(ANDROID_LOG_FATAL, tag, buf);
    454     abort(); /* abort so we have a chance to debug the situation */
    455     /* NOTREACHED */
    456 }
    457 
    458 LIBLOG_ABI_PUBLIC int __android_log_bwrite(int32_t tag,
    459                                            const void *payload, size_t len)
    460 {
    461     struct iovec vec[2];
    462 
    463     vec[0].iov_base = &tag;
    464     vec[0].iov_len = sizeof(tag);
    465     vec[1].iov_base = (void*)payload;
    466     vec[1].iov_len = len;
    467 
    468     return write_to_log(LOG_ID_EVENTS, vec, 2);
    469 }
    470 
    471 LIBLOG_ABI_PUBLIC int __android_log_security_bwrite(int32_t tag,
    472                                                     const void *payload,
    473                                                     size_t len)
    474 {
    475     struct iovec vec[2];
    476 
    477     vec[0].iov_base = &tag;
    478     vec[0].iov_len = sizeof(tag);
    479     vec[1].iov_base = (void*)payload;
    480     vec[1].iov_len = len;
    481 
    482     return write_to_log(LOG_ID_SECURITY, vec, 2);
    483 }
    484 
    485 /*
    486  * Like __android_log_bwrite, but takes the type as well.  Doesn't work
    487  * for the general case where we're generating lists of stuff, but very
    488  * handy if we just want to dump an integer into the log.
    489  */
    490 LIBLOG_ABI_PUBLIC int __android_log_btwrite(int32_t tag, char type,
    491                                             const void *payload, size_t len)
    492 {
    493     struct iovec vec[3];
    494 
    495     vec[0].iov_base = &tag;
    496     vec[0].iov_len = sizeof(tag);
    497     vec[1].iov_base = &type;
    498     vec[1].iov_len = sizeof(type);
    499     vec[2].iov_base = (void*)payload;
    500     vec[2].iov_len = len;
    501 
    502     return write_to_log(LOG_ID_EVENTS, vec, 3);
    503 }
    504 
    505 /*
    506  * Like __android_log_bwrite, but used for writing strings to the
    507  * event log.
    508  */
    509 LIBLOG_ABI_PUBLIC int __android_log_bswrite(int32_t tag, const char *payload)
    510 {
    511     struct iovec vec[4];
    512     char type = EVENT_TYPE_STRING;
    513     uint32_t len = strlen(payload);
    514 
    515     vec[0].iov_base = &tag;
    516     vec[0].iov_len = sizeof(tag);
    517     vec[1].iov_base = &type;
    518     vec[1].iov_len = sizeof(type);
    519     vec[2].iov_base = &len;
    520     vec[2].iov_len = sizeof(len);
    521     vec[3].iov_base = (void*)payload;
    522     vec[3].iov_len = len;
    523 
    524     return write_to_log(LOG_ID_EVENTS, vec, 4);
    525 }
    526 
    527 /*
    528  * Like __android_log_security_bwrite, but used for writing strings to the
    529  * security log.
    530  */
    531 LIBLOG_ABI_PUBLIC int __android_log_security_bswrite(int32_t tag,
    532                                                      const char *payload)
    533 {
    534     struct iovec vec[4];
    535     char type = EVENT_TYPE_STRING;
    536     uint32_t len = strlen(payload);
    537 
    538     vec[0].iov_base = &tag;
    539     vec[0].iov_len = sizeof(tag);
    540     vec[1].iov_base = &type;
    541     vec[1].iov_len = sizeof(type);
    542     vec[2].iov_base = &len;
    543     vec[2].iov_len = sizeof(len);
    544     vec[3].iov_base = (void*)payload;
    545     vec[3].iov_len = len;
    546 
    547     return write_to_log(LOG_ID_SECURITY, vec, 4);
    548 }
    549