• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
LogBufferInit(struct LogBuffer * log)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 
LogBufferClear(struct LogBuffer * log)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 
LogBufferFree(struct LogBuffer * log)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 
LogBufferLog(struct LogBuffer * log,struct LogBufferElement * element)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  */
writeToLocalInit()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 
writeToLocalReset()261 static void writeToLocalReset() {
262   LogBufferFree(&logbuf);
263 }
264 
writeToLocalAvailable(log_id_t logId)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 
writeToLocalWrite(log_id_t logId,struct timespec * ts,struct iovec * vec,size_t nr)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 
writeToLocalVersion(struct android_log_logger * logger __unused,struct android_log_transport_context * transp __unused)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 */
writeToLocalNode(struct android_log_logger_list * logger_list,struct android_log_transport_context * transp)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 
writeToLocalRead(struct android_log_logger_list * logger_list,struct android_log_transport_context * transp,struct log_msg * log_msg)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 
writeToLocalPoll(struct android_log_logger_list * logger_list,struct android_log_transport_context * transp)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 
writeToLocalClose(struct android_log_logger_list * logger_list __unused,struct android_log_transport_context * transp)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 
writeToLocalClear(struct android_log_logger * logger,struct android_log_transport_context * unused __unused)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 
writeToLocalGetSize(struct android_log_logger * logger,struct android_log_transport_context * transp __unused)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 
writeToLocalSetSize(struct android_log_logger * logger,struct android_log_transport_context * transp __unused,size_t size)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 
writeToLocalGetReadbleSize(struct android_log_logger * logger,struct android_log_transport_context * transp __unused)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