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     LOG_ALWAYS_FATAL_IF(node == log->last[logId], "corrupted list");
    226     free(e);
    227   }
    228   /* add entry to list */
    229   list_add_head(&log->head, &element->node);
    230   /* ToDo: wake up all readers */
    231   pthread_rwlock_unlock(&log->listLock);
    232 
    233   return element->len;
    234 }
    235 
    236 /*
    237  * return zero if permitted to log directly to logd,
    238  * return 1 if binder server started and
    239  * return negative error number if failed to start binder server.
    240  */
    241 static int writeToLocalInit() {
    242   pthread_attr_t attr;
    243   struct LogBuffer* log;
    244 
    245   if (writeToLocalAvailable(LOG_ID_MAIN) < 0) {
    246     return -EPERM;
    247   }
    248 
    249   log = &logbuf;
    250   if (!log->serviceName) {
    251     LogBufferInit(log);
    252   }
    253 
    254   if (!log->serviceName) {
    255     LogBufferFree(log);
    256     return -ENOMEM;
    257   }
    258 
    259   return EPERM; /* successful local-only logging */
    260 }
    261 
    262 static void writeToLocalReset() {
    263   LogBufferFree(&logbuf);
    264 }
    265 
    266 static int writeToLocalAvailable(log_id_t logId) {
    267 #if !defined(__MINGW32__)
    268   uid_t uid;
    269 #endif
    270 
    271   if ((logId >= NUMBER_OF_LOG_BUFFERS) || BLOCK_LOG_BUFFERS(logId)) {
    272     return -EINVAL;
    273   }
    274 
    275 /* Android hard coded permitted, system goes to logd */
    276 #if !defined(__MINGW32__)
    277   if (__android_log_transport == LOGGER_DEFAULT) {
    278     uid = __android_log_uid();
    279     if ((uid < AID_APP) && (getpwuid(uid) != NULL)) {
    280       return -EPERM;
    281     }
    282   }
    283 #endif
    284 
    285   /* ToDo: Ask package manager for LOGD permissions */
    286   /* Assume we do _not_ have permissions to go to LOGD, so must go local */
    287   return 0;
    288 }
    289 
    290 static int writeToLocalWrite(log_id_t logId, struct timespec* ts,
    291                              struct iovec* vec, size_t nr) {
    292   size_t len, i;
    293   struct LogBufferElement* element;
    294 
    295   if ((logId >= NUMBER_OF_LOG_BUFFERS) || BLOCK_LOG_BUFFERS(logId)) {
    296     return -EINVAL;
    297   }
    298 
    299   len = 0;
    300   for (i = 0; i < nr; ++i) {
    301     len += vec[i].iov_len;
    302   }
    303 
    304   if (len > LOGGER_ENTRY_MAX_PAYLOAD) {
    305     len = LOGGER_ENTRY_MAX_PAYLOAD;
    306   }
    307   element = (struct LogBufferElement*)calloc(
    308       1, sizeof(struct LogBufferElement) + len + 1);
    309   if (!element) {
    310     return errno ? -errno : -ENOMEM;
    311   }
    312   element->timestamp.tv_sec = ts->tv_sec;
    313   element->timestamp.tv_nsec = ts->tv_nsec;
    314 #ifdef __BIONIC__
    315   element->tid = gettid();
    316 #else
    317   element->tid = getpid();
    318 #endif
    319   element->logId = logId;
    320   element->len = len;
    321 
    322   char* cp = element->msg;
    323   for (i = 0; i < nr; ++i) {
    324     size_t iov_len = vec[i].iov_len;
    325     if (iov_len > len) {
    326       iov_len = len;
    327     }
    328     memcpy(cp, vec[i].iov_base, iov_len);
    329     len -= iov_len;
    330     if (len == 0) {
    331       break;
    332     }
    333     cp += iov_len;
    334   }
    335 
    336   return LogBufferLog(&logbuf, element);
    337 }
    338 
    339 static int writeToLocalVersion(struct android_log_logger* logger __unused,
    340                                struct android_log_transport_context* transp
    341                                    __unused) {
    342   return 3;
    343 }
    344 
    345 /* within reader lock, serviceName already validated */
    346 static struct listnode* writeToLocalNode(
    347     struct android_log_logger_list* logger_list,
    348     struct android_log_transport_context* transp) {
    349   struct listnode* node;
    350   unsigned logMask;
    351   unsigned int tail;
    352 
    353   node = transp->context.node;
    354   if (node) {
    355     return node;
    356   }
    357 
    358   if (!logger_list->tail) {
    359     return transp->context.node = &logbuf.head;
    360   }
    361 
    362   logMask = transp->logMask;
    363   tail = logger_list->tail;
    364 
    365   for (node = list_head(&logbuf.head); node != &logbuf.head; node = node->next) {
    366     struct LogBufferElement* element;
    367     log_id_t logId;
    368 
    369     element = node_to_item(node, struct LogBufferElement, node);
    370     logId = element->logId;
    371 
    372     if ((logMask & (1 << logId)) && !--tail) {
    373       node = node->next;
    374       break;
    375     }
    376   }
    377   return transp->context.node = node;
    378 }
    379 
    380 static int writeToLocalRead(struct android_log_logger_list* logger_list,
    381                             struct android_log_transport_context* transp,
    382                             struct log_msg* log_msg) {
    383   int ret;
    384   struct listnode* node;
    385   unsigned logMask;
    386 
    387   pthread_rwlock_rdlock(&logbuf.listLock);
    388   if (!logbuf.serviceName) {
    389     pthread_rwlock_unlock(&logbuf.listLock);
    390     return (logger_list->mode & ANDROID_LOG_NONBLOCK) ? -ENODEV : 0;
    391   }
    392 
    393   logMask = transp->logMask;
    394 
    395   node = writeToLocalNode(logger_list, transp);
    396 
    397   ret = 0;
    398 
    399   while (node != list_head(&logbuf.head)) {
    400     struct LogBufferElement* element;
    401     log_id_t logId;
    402 
    403     node = node->prev;
    404     element = node_to_item(node, struct LogBufferElement, node);
    405     logId = element->logId;
    406 
    407     if (logMask & (1 << logId)) {
    408       ret = log_msg->entry_v3.len = element->len;
    409       log_msg->entry_v3.hdr_size = sizeof(log_msg->entry_v3);
    410       log_msg->entry_v3.pid = getpid();
    411       log_msg->entry_v3.tid = element->tid;
    412       log_msg->entry_v3.sec = element->timestamp.tv_sec;
    413       log_msg->entry_v3.nsec = element->timestamp.tv_nsec;
    414       log_msg->entry_v3.lid = logId;
    415       memcpy(log_msg->entry_v3.msg, element->msg, ret);
    416       ret += log_msg->entry_v3.hdr_size;
    417       break;
    418     }
    419   }
    420 
    421   transp->context.node = node;
    422 
    423   /* ToDo: if blocking, and no entry, put reader to sleep */
    424   pthread_rwlock_unlock(&logbuf.listLock);
    425   return ret;
    426 }
    427 
    428 static int writeToLocalPoll(struct android_log_logger_list* logger_list,
    429                             struct android_log_transport_context* transp) {
    430   int ret = (logger_list->mode & ANDROID_LOG_NONBLOCK) ? -ENODEV : 0;
    431 
    432   pthread_rwlock_rdlock(&logbuf.listLock);
    433 
    434   if (logbuf.serviceName) {
    435     unsigned logMask = transp->logMask;
    436     struct listnode* node = writeToLocalNode(logger_list, transp);
    437 
    438     ret = (node != list_head(&logbuf.head));
    439     if (ret) {
    440       do {
    441         ret = !!(logMask &
    442                  (1 << (node_to_item(node->prev, struct LogBufferElement, node))
    443                            ->logId));
    444       } while (!ret && ((node = node->prev) != list_head(&logbuf.head)));
    445     }
    446 
    447     transp->context.node = node;
    448   }
    449 
    450   pthread_rwlock_unlock(&logbuf.listLock);
    451 
    452   return ret;
    453 }
    454 
    455 static void writeToLocalClose(struct android_log_logger_list* logger_list
    456                                   __unused,
    457                               struct android_log_transport_context* transp) {
    458   pthread_rwlock_wrlock(&logbuf.listLock);
    459   transp->context.node = list_head(&logbuf.head);
    460   pthread_rwlock_unlock(&logbuf.listLock);
    461 }
    462 
    463 static int writeToLocalClear(struct android_log_logger* logger,
    464                              struct android_log_transport_context* unused
    465                                  __unused) {
    466   log_id_t logId = logger->logId;
    467   struct listnode *node, *n;
    468 
    469   if ((logId >= NUMBER_OF_LOG_BUFFERS) || BLOCK_LOG_BUFFERS(logId)) {
    470     return -EINVAL;
    471   }
    472 
    473   pthread_rwlock_wrlock(&logbuf.listLock);
    474   logbuf.number[logId] = 0;
    475   logbuf.last[logId] = &logbuf.head;
    476   list_for_each_safe(node, n, &logbuf.head) {
    477     struct LogBufferElement* element;
    478     element = node_to_item(node, struct LogBufferElement, node);
    479 
    480     if (logId == element->logId) {
    481       struct android_log_logger_list* logger_list;
    482 
    483       logger_list_rdlock();
    484       logger_list_for_each(logger_list) {
    485         struct android_log_transport_context* transp;
    486 
    487         transport_context_for_each(transp, logger_list) {
    488           if ((transp->transport == &localLoggerRead) &&
    489               (transp->context.node == node)) {
    490             transp->context.node = node->next;
    491           }
    492         }
    493       }
    494       logger_list_unlock();
    495       list_remove(node);
    496       free(element);
    497     }
    498   }
    499 
    500   pthread_rwlock_unlock(&logbuf.listLock);
    501 
    502   return 0;
    503 }
    504 
    505 static ssize_t writeToLocalGetSize(struct android_log_logger* logger,
    506                                    struct android_log_transport_context* transp
    507                                        __unused) {
    508   ssize_t ret = -EINVAL;
    509   log_id_t logId = logger->logId;
    510 
    511   if ((logId < NUMBER_OF_LOG_BUFFERS) && !BLOCK_LOG_BUFFERS(logId)) {
    512     pthread_rwlock_rdlock(&logbuf.listLock);
    513     ret = logbuf.maxSize[logId];
    514     pthread_rwlock_unlock(&logbuf.listLock);
    515   }
    516 
    517   return ret;
    518 }
    519 
    520 static ssize_t writeToLocalSetSize(
    521     struct android_log_logger* logger,
    522     struct android_log_transport_context* transp __unused, size_t size) {
    523   ssize_t ret = -EINVAL;
    524 
    525   if ((size > LOGGER_ENTRY_MAX_LEN) || (size < (4 * 1024 * 1024))) {
    526     log_id_t logId = logger->logId;
    527     if ((logId < NUMBER_OF_LOG_BUFFERS) || !BLOCK_LOG_BUFFERS(logId)) {
    528       pthread_rwlock_wrlock(&logbuf.listLock);
    529       ret = logbuf.maxSize[logId] = size;
    530       pthread_rwlock_unlock(&logbuf.listLock);
    531     }
    532   }
    533 
    534   return ret;
    535 }
    536 
    537 static ssize_t writeToLocalGetReadbleSize(
    538     struct android_log_logger* logger,
    539     struct android_log_transport_context* transp __unused) {
    540   ssize_t ret = -EINVAL;
    541   log_id_t logId = logger->logId;
    542 
    543   if ((logId < NUMBER_OF_LOG_BUFFERS) && !BLOCK_LOG_BUFFERS(logId)) {
    544     pthread_rwlock_rdlock(&logbuf.listLock);
    545     ret = logbuf.serviceName ? (ssize_t)logbuf.size[logId] : -EBADF;
    546     pthread_rwlock_unlock(&logbuf.listLock);
    547   }
    548 
    549   return ret;
    550 }
    551