Home | History | Annotate | Download | only in liblog
      1 /*
      2  * Copyright (C) 2017 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 <fcntl.h>
     19 #include <pthread.h>
     20 #if !defined(__MINGW32__)
     21 #include <pwd.h>
     22 #endif
     23 #include <log/uio.h>
     24 #include <sched.h>
     25 #include <stdlib.h>
     26 #include <string.h>
     27 #include <sys/types.h>
     28 
     29 #include <cutils/list.h> /* template, no library dependency */
     30 #include <log/log_transport.h>
     31 #include <private/android_filesystem_config.h>
     32 #include <private/android_logger.h>
     33 #include <system/thread_defs.h>
     34 
     35 #include "config_read.h"
     36 #include "config_write.h"
     37 #include "log_portability.h"
     38 #include "logger.h"
     39 
     40 static const char baseServiceName[] = "android.logd";
     41 
     42 static int writeToLocalInit();
     43 static int writeToLocalAvailable(log_id_t logId);
     44 static void writeToLocalReset();
     45 static int writeToLocalWrite(log_id_t logId, struct timespec* ts,
     46                              struct iovec* vec, size_t nr);
     47 
     48 LIBLOG_HIDDEN struct android_log_transport_write localLoggerWrite = {
     49   .node = { &localLoggerWrite.node, &localLoggerWrite.node },
     50   .context.priv = NULL,
     51   .name = "local",
     52   .available = writeToLocalAvailable,
     53   .open = writeToLocalInit,
     54   .close = writeToLocalReset,
     55   .write = writeToLocalWrite,
     56 };
     57 
     58 static int writeToLocalVersion(struct android_log_logger* logger,
     59                                struct android_log_transport_context* transp);
     60 static int writeToLocalRead(struct android_log_logger_list* logger_list,
     61                             struct android_log_transport_context* transp,
     62                             struct log_msg* log_msg);
     63 static int writeToLocalPoll(struct android_log_logger_list* logger_list,
     64                             struct android_log_transport_context* transp);
     65 static void writeToLocalClose(struct android_log_logger_list* logger_list,
     66                               struct android_log_transport_context* transp);
     67 static int writeToLocalClear(struct android_log_logger* logger,
     68                              struct android_log_transport_context* transp);
     69 static ssize_t writeToLocalGetSize(struct android_log_logger* logger,
     70                                    struct android_log_transport_context* transp);
     71 static ssize_t writeToLocalSetSize(
     72     struct android_log_logger* logger,
     73     struct android_log_transport_context* transp __unused, size_t size);
     74 static ssize_t writeToLocalGetReadbleSize(
     75     struct android_log_logger* logger,
     76     struct android_log_transport_context* transp);
     77 
     78 struct android_log_transport_read localLoggerRead = {
     79   .node = { &localLoggerRead.node, &localLoggerRead.node },
     80   .name = "local",
     81   .available = writeToLocalAvailable,
     82   .version = writeToLocalVersion,
     83   .read = writeToLocalRead,
     84   .poll = writeToLocalPoll,
     85   .close = writeToLocalClose,
     86   .clear = writeToLocalClear,
     87   .getSize = writeToLocalGetSize,
     88   .setSize = writeToLocalSetSize,
     89   .getReadableSize = writeToLocalGetReadbleSize,
     90   .getPrune = NULL,
     91   .setPrune = NULL,
     92   .getStats = NULL,
     93 };
     94 
     95 struct LogBufferElement {
     96   struct listnode node;
     97   log_id_t logId;
     98   pid_t tid;
     99   log_time timestamp;
    100   unsigned short len;
    101   char msg[];
    102 };
    103 
    104 static const size_t MAX_SIZE_DEFAULT = 32768;
    105 
    106 /*
    107  * Number of log buffers we support with the following assumption:
    108  *  . . .
    109  *   LOG_ID_SECURITY = 5, // security logs go to the system logs only
    110  *   LOG_ID_KERNEL = 6,   // place last, third-parties can not use it
    111  *   LOG_ID_MAX
    112  * } log_id_t;
    113  *
    114  * Confirm the following should <log/log_id.h> be adjusted in the future.
    115  */
    116 #define NUMBER_OF_LOG_BUFFERS \
    117   ((LOG_ID_SECURITY == (LOG_ID_MAX - 2)) ? LOG_ID_SECURITY : LOG_ID_KERNEL)
    118 #define BLOCK_LOG_BUFFERS(id) \
    119   (((id) == LOG_ID_SECURITY) || ((id) == LOG_ID_KERNEL))
    120 
    121 static struct LogBuffer {
    122   struct listnode head;
    123   pthread_rwlock_t listLock;
    124   char* serviceName; /* Also indicates ready by having a value */
    125   /* Order and proximity important for memset */
    126   size_t number[NUMBER_OF_LOG_BUFFERS];         /* clear memset          */
    127   size_t size[NUMBER_OF_LOG_BUFFERS];           /* clear memset          */
    128   size_t totalSize[NUMBER_OF_LOG_BUFFERS];      /* init memset           */
    129   size_t maxSize[NUMBER_OF_LOG_BUFFERS];        /* init MAX_SIZE_DEFAULT */
    130   struct listnode* last[NUMBER_OF_LOG_BUFFERS]; /* init &head            */
    131 } logbuf = {
    132   .head = { &logbuf.head, &logbuf.head }, .listLock = PTHREAD_RWLOCK_INITIALIZER,
    133 };
    134 
    135 static void LogBufferInit(struct LogBuffer* log) {
    136   size_t i;
    137 
    138   pthread_rwlock_wrlock(&log->listLock);
    139   list_init(&log->head);
    140   memset(log->number, 0,
    141          sizeof(log->number) + sizeof(log->size) + sizeof(log->totalSize));
    142   for (i = 0; i < NUMBER_OF_LOG_BUFFERS; ++i) {
    143     log->maxSize[i] = MAX_SIZE_DEFAULT;
    144     log->last[i] = &log->head;
    145   }
    146 #ifdef __BIONIC__
    147   asprintf(&log->serviceName, "%s@%d:%d", baseServiceName, __android_log_uid(),
    148            getpid());
    149 #else
    150   char buffer[sizeof(baseServiceName) + 1 + 5 + 1 + 5 + 8];
    151   snprintf(buffer, sizeof(buffer), "%s@%d:%d", baseServiceName,
    152            __android_log_uid(), getpid());
    153   log->serviceName = strdup(buffer);
    154 #endif
    155   pthread_rwlock_unlock(&log->listLock);
    156 }
    157 
    158 static void LogBufferClear(struct LogBuffer* log) {
    159   size_t i;
    160   struct listnode* node;
    161 
    162   pthread_rwlock_wrlock(&log->listLock);
    163   memset(log->number, 0, sizeof(log->number) + sizeof(log->size));
    164   for (i = 0; i < NUMBER_OF_LOG_BUFFERS; ++i) {
    165     log->last[i] = &log->head;
    166   }
    167   while ((node = list_head(&log->head)) != &log->head) {
    168     struct LogBufferElement* element;
    169 
    170     element = node_to_item(node, struct LogBufferElement, node);
    171     list_remove(node);
    172     free(element);
    173   }
    174   pthread_rwlock_unlock(&log->listLock);
    175 }
    176 
    177 static inline void LogBufferFree(struct LogBuffer* log) {
    178   pthread_rwlock_wrlock(&log->listLock);
    179   free(log->serviceName);
    180   log->serviceName = NULL;
    181   pthread_rwlock_unlock(&log->listLock);
    182   LogBufferClear(log);
    183 }
    184 
    185 static int LogBufferLog(struct LogBuffer* log,
    186                         struct LogBufferElement* element) {
    187   log_id_t logId = element->logId;
    188 
    189   pthread_rwlock_wrlock(&log->listLock);
    190   log->number[logId]++;
    191   log->size[logId] += element->len;
    192   log->totalSize[logId] += element->len;
    193   /* prune entry(s) until enough space is available */
    194   if (log->last[logId] == &log->head) {
    195     log->last[logId] = list_tail(&log->head);
    196   }
    197   while (log->size[logId] > log->maxSize[logId]) {
    198     struct listnode* node = log->last[logId];
    199     struct LogBufferElement* e;
    200     struct android_log_logger_list* logger_list;
    201 
    202     e = node_to_item(node, struct LogBufferElement, node);
    203     log->number[logId]--;
    204     log->size[logId] -= e->len;
    205     logger_list_rdlock();
    206     logger_list_for_each(logger_list) {
    207       struct android_log_transport_context* transp;
    208 
    209       transport_context_for_each(transp, logger_list) {
    210         if ((transp->transport == &localLoggerRead) &&
    211             (transp->context.node == node)) {
    212           if (node == &log->head) {
    213             transp->context.node = &log->head;
    214           } else {
    215             transp->context.node = node->next;
    216           }
    217         }
    218       }
    219     }
    220     logger_list_unlock();
    221     if (node != &log->head) {
    222       log->last[logId] = node->prev;
    223     }
    224     list_remove(node);
    225     free(e);
    226   }
    227   /* add entry to list */
    228   list_add_head(&log->head, &element->node);
    229   /* ToDo: wake up all readers */
    230   pthread_rwlock_unlock(&log->listLock);
    231 
    232   return element->len;
    233 }
    234 
    235 /*
    236  * return zero if permitted to log directly to logd,
    237  * return 1 if binder server started and
    238  * return negative error number if failed to start binder server.
    239  */
    240 static int writeToLocalInit() {
    241   pthread_attr_t attr;
    242   struct LogBuffer* log;
    243 
    244   if (writeToLocalAvailable(LOG_ID_MAIN) < 0) {
    245     return -EPERM;
    246   }
    247 
    248   log = &logbuf;
    249   if (!log->serviceName) {
    250     LogBufferInit(log);
    251   }
    252 
    253   if (!log->serviceName) {
    254     LogBufferFree(log);
    255     return -ENOMEM;
    256   }
    257 
    258   return EPERM; /* successful local-only logging */
    259 }
    260 
    261 static void writeToLocalReset() {
    262   LogBufferFree(&logbuf);
    263 }
    264 
    265 static int writeToLocalAvailable(log_id_t logId) {
    266 #if !defined(__MINGW32__)
    267   uid_t uid;
    268 #endif
    269 
    270   if ((logId >= NUMBER_OF_LOG_BUFFERS) || BLOCK_LOG_BUFFERS(logId)) {
    271     return -EINVAL;
    272   }
    273 
    274 /* Android hard coded permitted, system goes to logd */
    275 #if !defined(__MINGW32__)
    276   if (__android_log_transport == LOGGER_DEFAULT) {
    277     uid = __android_log_uid();
    278     if ((uid < AID_APP) && (getpwuid(uid) != NULL)) {
    279       return -EPERM;
    280     }
    281   }
    282 #endif
    283 
    284   /* ToDo: Ask package manager for LOGD permissions */
    285   /* Assume we do _not_ have permissions to go to LOGD, so must go local */
    286   return 0;
    287 }
    288 
    289 static int writeToLocalWrite(log_id_t logId, struct timespec* ts,
    290                              struct iovec* vec, size_t nr) {
    291   size_t len, i;
    292   struct LogBufferElement* element;
    293 
    294   if ((logId >= NUMBER_OF_LOG_BUFFERS) || BLOCK_LOG_BUFFERS(logId)) {
    295     return -EINVAL;
    296   }
    297 
    298   len = 0;
    299   for (i = 0; i < nr; ++i) {
    300     len += vec[i].iov_len;
    301   }
    302 
    303   if (len > LOGGER_ENTRY_MAX_PAYLOAD) {
    304     len = LOGGER_ENTRY_MAX_PAYLOAD;
    305   }
    306   element = (struct LogBufferElement*)calloc(
    307       1, sizeof(struct LogBufferElement) + len + 1);
    308   if (!element) {
    309     return errno ? -errno : -ENOMEM;
    310   }
    311   element->timestamp.tv_sec = ts->tv_sec;
    312   element->timestamp.tv_nsec = ts->tv_nsec;
    313 #ifdef __BIONIC__
    314   element->tid = gettid();
    315 #else
    316   element->tid = getpid();
    317 #endif
    318   element->logId = logId;
    319   element->len = len;
    320 
    321   char* cp = element->msg;
    322   for (i = 0; i < nr; ++i) {
    323     size_t iov_len = vec[i].iov_len;
    324     if (iov_len > len) {
    325       iov_len = len;
    326     }
    327     memcpy(cp, vec[i].iov_base, iov_len);
    328     len -= iov_len;
    329     if (len == 0) {
    330       break;
    331     }
    332     cp += iov_len;
    333   }
    334 
    335   return LogBufferLog(&logbuf, element);
    336 }
    337 
    338 static int writeToLocalVersion(struct android_log_logger* logger __unused,
    339                                struct android_log_transport_context* transp
    340                                    __unused) {
    341   return 3;
    342 }
    343 
    344 /* within reader lock, serviceName already validated */
    345 static struct listnode* writeToLocalNode(
    346     struct android_log_logger_list* logger_list,
    347     struct android_log_transport_context* transp) {
    348   struct listnode* node;
    349   unsigned logMask;
    350   unsigned int tail;
    351 
    352   node = transp->context.node;
    353   if (node) {
    354     return node;
    355   }
    356 
    357   if (!logger_list->tail) {
    358     return transp->context.node = &logbuf.head;
    359   }
    360 
    361   logMask = transp->logMask;
    362   tail = logger_list->tail;
    363 
    364   for (node = list_head(&logbuf.head); node != &logbuf.head; node = node->next) {
    365     struct LogBufferElement* element;
    366     log_id_t logId;
    367 
    368     element = node_to_item(node, struct LogBufferElement, node);
    369     logId = element->logId;
    370 
    371     if ((logMask & (1 << logId)) && !--tail) {
    372       node = node->next;
    373       break;
    374     }
    375   }
    376   return transp->context.node = node;
    377 }
    378 
    379 static int writeToLocalRead(struct android_log_logger_list* logger_list,
    380                             struct android_log_transport_context* transp,
    381                             struct log_msg* log_msg) {
    382   int ret;
    383   struct listnode* node;
    384   unsigned logMask;
    385 
    386   pthread_rwlock_rdlock(&logbuf.listLock);
    387   if (!logbuf.serviceName) {
    388     pthread_rwlock_unlock(&logbuf.listLock);
    389     return (logger_list->mode & ANDROID_LOG_NONBLOCK) ? -ENODEV : 0;
    390   }
    391 
    392   logMask = transp->logMask;
    393 
    394   node = writeToLocalNode(logger_list, transp);
    395 
    396   ret = 0;
    397 
    398   while (node != list_head(&logbuf.head)) {
    399     struct LogBufferElement* element;
    400     log_id_t logId;
    401 
    402     node = node->prev;
    403     element = node_to_item(node, struct LogBufferElement, node);
    404     logId = element->logId;
    405 
    406     if (logMask & (1 << logId)) {
    407       ret = log_msg->entry_v3.len = element->len;
    408       log_msg->entry_v3.hdr_size = sizeof(log_msg->entry_v3);
    409       log_msg->entry_v3.pid = getpid();
    410       log_msg->entry_v3.tid = element->tid;
    411       log_msg->entry_v3.sec = element->timestamp.tv_sec;
    412       log_msg->entry_v3.nsec = element->timestamp.tv_nsec;
    413       log_msg->entry_v3.lid = logId;
    414       memcpy(log_msg->entry_v3.msg, element->msg, ret);
    415       ret += log_msg->entry_v3.hdr_size;
    416       break;
    417     }
    418   }
    419 
    420   transp->context.node = node;
    421 
    422   /* ToDo: if blocking, and no entry, put reader to sleep */
    423   pthread_rwlock_unlock(&logbuf.listLock);
    424   return ret;
    425 }
    426 
    427 static int writeToLocalPoll(struct android_log_logger_list* logger_list,
    428                             struct android_log_transport_context* transp) {
    429   int ret = (logger_list->mode & ANDROID_LOG_NONBLOCK) ? -ENODEV : 0;
    430 
    431   pthread_rwlock_rdlock(&logbuf.listLock);
    432 
    433   if (logbuf.serviceName) {
    434     unsigned logMask = transp->logMask;
    435     struct listnode* node = writeToLocalNode(logger_list, transp);
    436 
    437     ret = (node != list_head(&logbuf.head));
    438     if (ret) {
    439       do {
    440         ret = !!(logMask &
    441                  (1 << (node_to_item(node->prev, struct LogBufferElement, node))
    442                            ->logId));
    443       } while (!ret && ((node = node->prev) != list_head(&logbuf.head)));
    444     }
    445 
    446     transp->context.node = node;
    447   }
    448 
    449   pthread_rwlock_unlock(&logbuf.listLock);
    450 
    451   return ret;
    452 }
    453 
    454 static void writeToLocalClose(struct android_log_logger_list* logger_list
    455                                   __unused,
    456                               struct android_log_transport_context* transp) {
    457   pthread_rwlock_wrlock(&logbuf.listLock);
    458   transp->context.node = list_head(&logbuf.head);
    459   pthread_rwlock_unlock(&logbuf.listLock);
    460 }
    461 
    462 static int writeToLocalClear(struct android_log_logger* logger,
    463                              struct android_log_transport_context* unused
    464                                  __unused) {
    465   log_id_t logId = logger->logId;
    466   struct listnode *node, *n;
    467 
    468   if ((logId >= NUMBER_OF_LOG_BUFFERS) || BLOCK_LOG_BUFFERS(logId)) {
    469     return -EINVAL;
    470   }
    471 
    472   pthread_rwlock_wrlock(&logbuf.listLock);
    473   logbuf.number[logId] = 0;
    474   logbuf.last[logId] = &logbuf.head;
    475   list_for_each_safe(node, n, &logbuf.head) {
    476     struct LogBufferElement* element;
    477     element = node_to_item(node, struct LogBufferElement, node);
    478 
    479     if (logId == element->logId) {
    480       struct android_log_logger_list* logger_list;
    481 
    482       logger_list_rdlock();
    483       logger_list_for_each(logger_list) {
    484         struct android_log_transport_context* transp;
    485 
    486         transport_context_for_each(transp, logger_list) {
    487           if ((transp->transport == &localLoggerRead) &&
    488               (transp->context.node == node)) {
    489             transp->context.node = node->next;
    490           }
    491         }
    492       }
    493       logger_list_unlock();
    494       list_remove(node);
    495       free(element);
    496     }
    497   }
    498 
    499   pthread_rwlock_unlock(&logbuf.listLock);
    500 
    501   return 0;
    502 }
    503 
    504 static ssize_t writeToLocalGetSize(struct android_log_logger* logger,
    505                                    struct android_log_transport_context* transp
    506                                        __unused) {
    507   ssize_t ret = -EINVAL;
    508   log_id_t logId = logger->logId;
    509 
    510   if ((logId < NUMBER_OF_LOG_BUFFERS) && !BLOCK_LOG_BUFFERS(logId)) {
    511     pthread_rwlock_rdlock(&logbuf.listLock);
    512     ret = logbuf.maxSize[logId];
    513     pthread_rwlock_unlock(&logbuf.listLock);
    514   }
    515 
    516   return ret;
    517 }
    518 
    519 static ssize_t writeToLocalSetSize(
    520     struct android_log_logger* logger,
    521     struct android_log_transport_context* transp __unused, size_t size) {
    522   ssize_t ret = -EINVAL;
    523 
    524   if ((size > LOGGER_ENTRY_MAX_LEN) || (size < (4 * 1024 * 1024))) {
    525     log_id_t logId = logger->logId;
    526     if ((logId < NUMBER_OF_LOG_BUFFERS) || !BLOCK_LOG_BUFFERS(logId)) {
    527       pthread_rwlock_wrlock(&logbuf.listLock);
    528       ret = logbuf.maxSize[logId] = size;
    529       pthread_rwlock_unlock(&logbuf.listLock);
    530     }
    531   }
    532 
    533   return ret;
    534 }
    535 
    536 static ssize_t writeToLocalGetReadbleSize(
    537     struct android_log_logger* logger,
    538     struct android_log_transport_context* transp __unused) {
    539   ssize_t ret = -EINVAL;
    540   log_id_t logId = logger->logId;
    541 
    542   if ((logId < NUMBER_OF_LOG_BUFFERS) && !BLOCK_LOG_BUFFERS(logId)) {
    543     pthread_rwlock_rdlock(&logbuf.listLock);
    544     ret = logbuf.serviceName ? (ssize_t)logbuf.size[logId] : -EBADF;
    545     pthread_rwlock_unlock(&logbuf.listLock);
    546   }
    547 
    548   return ret;
    549 }
    550