• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ** Copyright 2013-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 <errno.h>
18 #include <fcntl.h>
19 #include <inttypes.h>
20 #include <poll.h>
21 #include <signal.h>
22 #include <stddef.h>
23 #define NOMINMAX /* for windows to suppress definition of min in stdlib.h */
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/cdefs.h>
27 #include <unistd.h>
28 
29 #include <cutils/list.h>
30 #include <cutils/sockets.h>
31 #include <log/log.h>
32 #include <log/logger.h>
33 
34 /* branchless on many architectures. */
35 #define min(x,y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
36 
37 #define WEAK __attribute__((weak))
38 #ifndef __unused
39 #define __unused __attribute__((unused))
40 #endif
41 
42 /* Private copy of ../libcutils/socket_local_client.c prevent library loops */
43 
44 #ifdef HAVE_WINSOCK
45 
socket_local_client(const char * name,int namespaceId,int type)46 int WEAK socket_local_client(const char *name, int namespaceId, int type)
47 {
48     errno = ENOSYS;
49     return -ENOSYS;
50 }
51 
52 #else /* !HAVE_WINSOCK */
53 
54 #include <sys/socket.h>
55 #include <sys/un.h>
56 #include <sys/select.h>
57 #include <sys/types.h>
58 
59 /* Private copy of ../libcutils/socket_local.h prevent library loops */
60 #define FILESYSTEM_SOCKET_PREFIX "/tmp/"
61 #define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
62 /* End of ../libcutils/socket_local.h */
63 
64 #define LISTEN_BACKLOG 4
65 
66 /* Documented in header file. */
socket_make_sockaddr_un(const char * name,int namespaceId,struct sockaddr_un * p_addr,socklen_t * alen)67 int WEAK socket_make_sockaddr_un(const char *name, int namespaceId,
68                                  struct sockaddr_un *p_addr, socklen_t *alen)
69 {
70     memset (p_addr, 0, sizeof (*p_addr));
71     size_t namelen;
72 
73     switch (namespaceId) {
74     case ANDROID_SOCKET_NAMESPACE_ABSTRACT:
75 #ifdef HAVE_LINUX_LOCAL_SOCKET_NAMESPACE
76         namelen  = strlen(name);
77 
78         /* Test with length +1 for the *initial* '\0'. */
79         if ((namelen + 1) > sizeof(p_addr->sun_path)) {
80             goto error;
81         }
82 
83         /*
84          * Note: The path in this case is *not* supposed to be
85          * '\0'-terminated. ("man 7 unix" for the gory details.)
86          */
87 
88         p_addr->sun_path[0] = 0;
89         memcpy(p_addr->sun_path + 1, name, namelen);
90 #else /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/
91         /* this OS doesn't have the Linux abstract namespace */
92 
93         namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
94         /* unix_path_max appears to be missing on linux */
95         if (namelen > sizeof(*p_addr)
96                 - offsetof(struct sockaddr_un, sun_path) - 1) {
97             goto error;
98         }
99 
100         strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
101         strcat(p_addr->sun_path, name);
102 #endif /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/
103         break;
104 
105     case ANDROID_SOCKET_NAMESPACE_RESERVED:
106         namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
107         /* unix_path_max appears to be missing on linux */
108         if (namelen > sizeof(*p_addr)
109                 - offsetof(struct sockaddr_un, sun_path) - 1) {
110             goto error;
111         }
112 
113         strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);
114         strcat(p_addr->sun_path, name);
115         break;
116 
117     case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
118         namelen = strlen(name);
119         /* unix_path_max appears to be missing on linux */
120         if (namelen > sizeof(*p_addr)
121                 - offsetof(struct sockaddr_un, sun_path) - 1) {
122             goto error;
123         }
124 
125         strcpy(p_addr->sun_path, name);
126         break;
127 
128     default:
129         /* invalid namespace id */
130         return -1;
131     }
132 
133     p_addr->sun_family = AF_LOCAL;
134     *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
135     return 0;
136 error:
137     return -1;
138 }
139 
140 /**
141  * connect to peer named "name" on fd
142  * returns same fd or -1 on error.
143  * fd is not closed on error. that's your job.
144  *
145  * Used by AndroidSocketImpl
146  */
socket_local_client_connect(int fd,const char * name,int namespaceId,int type __unused)147 int WEAK socket_local_client_connect(int fd, const char *name, int namespaceId,
148                                      int type __unused)
149 {
150     struct sockaddr_un addr;
151     socklen_t alen;
152     int err;
153 
154     err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
155 
156     if (err < 0) {
157         goto error;
158     }
159 
160     if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {
161         goto error;
162     }
163 
164     return fd;
165 
166 error:
167     return -1;
168 }
169 
170 /**
171  * connect to peer named "name"
172  * returns fd or -1 on error
173  */
socket_local_client(const char * name,int namespaceId,int type)174 int WEAK socket_local_client(const char *name, int namespaceId, int type)
175 {
176     int s;
177 
178     s = socket(AF_LOCAL, type, 0);
179     if(s < 0) return -1;
180 
181     if ( 0 > socket_local_client_connect(s, name, namespaceId, type)) {
182         close(s);
183         return -1;
184     }
185 
186     return s;
187 }
188 
189 #endif /* !HAVE_WINSOCK */
190 /* End of ../libcutils/socket_local_client.c */
191 
192 #define logger_for_each(logger, logger_list) \
193     for (logger = node_to_item((logger_list)->node.next, struct logger, node); \
194          logger != node_to_item(&(logger_list)->node, struct logger, node); \
195          logger = node_to_item((logger)->node.next, struct logger, node))
196 
197 /* In the future, we would like to make this list extensible */
198 static const char *LOG_NAME[LOG_ID_MAX] = {
199     [LOG_ID_MAIN] = "main",
200     [LOG_ID_RADIO] = "radio",
201     [LOG_ID_EVENTS] = "events",
202     [LOG_ID_SYSTEM] = "system",
203     [LOG_ID_CRASH] = "crash",
204 };
205 
android_log_id_to_name(log_id_t log_id)206 const char *android_log_id_to_name(log_id_t log_id)
207 {
208     if (log_id >= LOG_ID_MAX) {
209         log_id = LOG_ID_MAIN;
210     }
211     return LOG_NAME[log_id];
212 }
213 
android_name_to_log_id(const char * logName)214 log_id_t android_name_to_log_id(const char *logName)
215 {
216     const char *b;
217     int ret;
218 
219     if (!logName) {
220         return -1; /* NB: log_id_t is unsigned */
221     }
222     b = strrchr(logName, '/');
223     if (!b) {
224         b = logName;
225     } else {
226         ++b;
227     }
228 
229     for(ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) {
230         const char *l = LOG_NAME[ret];
231         if (l && !strcmp(b, l)) {
232             return ret;
233         }
234     }
235     return -1;   /* should never happen */
236 }
237 
238 struct logger_list {
239     struct listnode node;
240     int mode;
241     unsigned int tail;
242     log_time start;
243     pid_t pid;
244     int sock;
245 };
246 
247 struct logger {
248     struct listnode node;
249     struct logger_list *top;
250     log_id_t id;
251 };
252 
253 /* android_logger_alloc unimplemented, no use case */
254 /* android_logger_free not exported */
android_logger_free(struct logger * logger)255 static void android_logger_free(struct logger *logger)
256 {
257     if (!logger) {
258         return;
259     }
260 
261     list_remove(&logger->node);
262 
263     free(logger);
264 }
265 
266 /* android_logger_alloc unimplemented, no use case */
267 
268 /* method for getting the associated sublog id */
android_logger_get_id(struct logger * logger)269 log_id_t android_logger_get_id(struct logger *logger)
270 {
271     return logger->id;
272 }
273 
274 /* worker for sending the command to the logger */
send_log_msg(struct logger * logger,const char * msg,char * buf,size_t buf_size)275 static ssize_t send_log_msg(struct logger *logger,
276                             const char *msg, char *buf, size_t buf_size)
277 {
278     ssize_t ret;
279     size_t len;
280     char *cp;
281     int errno_save = 0;
282     int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
283                                    SOCK_STREAM);
284     if (sock < 0) {
285         return sock;
286     }
287 
288     if (msg) {
289         snprintf(buf, buf_size, msg, logger ? logger->id : (unsigned) -1);
290     }
291 
292     len = strlen(buf) + 1;
293     ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
294     if (ret <= 0) {
295         goto done;
296     }
297 
298     len = buf_size;
299     cp = buf;
300     while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) {
301         struct pollfd p;
302 
303         if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) {
304             break;
305         }
306 
307         len -= ret;
308         cp += ret;
309 
310         memset(&p, 0, sizeof(p));
311         p.fd = sock;
312         p.events = POLLIN;
313 
314         /* Give other side 20ms to refill pipe */
315         ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20));
316 
317         if (ret <= 0) {
318             break;
319         }
320 
321         if (!(p.revents & POLLIN)) {
322             ret = 0;
323             break;
324         }
325     }
326 
327     if (ret >= 0) {
328         ret += buf_size - len;
329     }
330 
331 done:
332     if ((ret == -1) && errno) {
333         errno_save = errno;
334     }
335     close(sock);
336     if (errno_save) {
337         errno = errno_save;
338     }
339     return ret;
340 }
341 
check_log_success(char * buf,ssize_t ret)342 static int check_log_success(char *buf, ssize_t ret)
343 {
344     if (ret < 0) {
345         return ret;
346     }
347 
348     if (strncmp(buf, "success", 7)) {
349         errno = EINVAL;
350         return -1;
351     }
352 
353     return 0;
354 }
355 
android_logger_clear(struct logger * logger)356 int android_logger_clear(struct logger *logger)
357 {
358     char buf[512];
359 
360     return check_log_success(buf,
361         send_log_msg(logger, "clear %d", buf, sizeof(buf)));
362 }
363 
364 /* returns the total size of the log's ring buffer */
android_logger_get_log_size(struct logger * logger)365 long android_logger_get_log_size(struct logger *logger)
366 {
367     char buf[512];
368 
369     ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
370     if (ret < 0) {
371         return ret;
372     }
373 
374     if ((buf[0] < '0') || ('9' < buf[0])) {
375         return -1;
376     }
377 
378     return atol(buf);
379 }
380 
android_logger_set_log_size(struct logger * logger,unsigned long size)381 int android_logger_set_log_size(struct logger *logger, unsigned long size)
382 {
383     char buf[512];
384 
385     snprintf(buf, sizeof(buf), "setLogSize %d %lu",
386         logger ? logger->id : (unsigned) -1, size);
387 
388     return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
389 }
390 
391 /*
392  * returns the readable size of the log's ring buffer (that is, amount of the
393  * log consumed)
394  */
android_logger_get_log_readable_size(struct logger * logger)395 long android_logger_get_log_readable_size(struct logger *logger)
396 {
397     char buf[512];
398 
399     ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
400     if (ret < 0) {
401         return ret;
402     }
403 
404     if ((buf[0] < '0') || ('9' < buf[0])) {
405         return -1;
406     }
407 
408     return atol(buf);
409 }
410 
411 /*
412  * returns the logger version
413  */
android_logger_get_log_version(struct logger * logger __unused)414 int android_logger_get_log_version(struct logger *logger __unused)
415 {
416     return 3;
417 }
418 
419 /*
420  * returns statistics
421  */
android_logger_get_statistics(struct logger_list * logger_list,char * buf,size_t len)422 ssize_t android_logger_get_statistics(struct logger_list *logger_list,
423                                       char *buf, size_t len)
424 {
425     struct logger *logger;
426     char *cp = buf;
427     size_t remaining = len;
428     size_t n;
429 
430     n = snprintf(cp, remaining, "getStatistics");
431     n = min(n, remaining);
432     remaining -= n;
433     cp += n;
434 
435     logger_for_each(logger, logger_list) {
436         n = snprintf(cp, remaining, " %d", logger->id);
437         n = min(n, remaining);
438         remaining -= n;
439         cp += n;
440     }
441     return send_log_msg(NULL, NULL, buf, len);
442 }
443 
android_logger_get_prune_list(struct logger_list * logger_list __unused,char * buf,size_t len)444 ssize_t android_logger_get_prune_list(struct logger_list *logger_list __unused,
445                                       char *buf, size_t len)
446 {
447     return send_log_msg(NULL, "getPruneList", buf, len);
448 }
449 
android_logger_set_prune_list(struct logger_list * logger_list __unused,char * buf,size_t len)450 int android_logger_set_prune_list(struct logger_list *logger_list __unused,
451                                   char *buf, size_t len)
452 {
453     const char cmd[] = "setPruneList ";
454     const size_t cmdlen = sizeof(cmd) - 1;
455 
456     if (strlen(buf) > (len - cmdlen)) {
457         return -ENOMEM; /* KISS */
458     }
459     memmove(buf + cmdlen, buf, len - cmdlen);
460     buf[len - 1] = '\0';
461     memcpy(buf, cmd, cmdlen);
462 
463     return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
464 }
465 
android_logger_list_alloc(int mode,unsigned int tail,pid_t pid)466 struct logger_list *android_logger_list_alloc(int mode,
467                                               unsigned int tail,
468                                               pid_t pid)
469 {
470     struct logger_list *logger_list;
471 
472     logger_list = calloc(1, sizeof(*logger_list));
473     if (!logger_list) {
474         return NULL;
475     }
476 
477     list_init(&logger_list->node);
478     logger_list->mode = mode;
479     logger_list->start.tv_sec = 0;
480     logger_list->start.tv_nsec = 0;
481     logger_list->tail = tail;
482     logger_list->pid = pid;
483     logger_list->sock = -1;
484 
485     return logger_list;
486 }
487 
android_logger_list_alloc_time(int mode,log_time start,pid_t pid)488 struct logger_list *android_logger_list_alloc_time(int mode,
489                                                    log_time start,
490                                                    pid_t pid)
491 {
492     struct logger_list *logger_list;
493 
494     logger_list = calloc(1, sizeof(*logger_list));
495     if (!logger_list) {
496         return NULL;
497     }
498 
499     list_init(&logger_list->node);
500     logger_list->mode = mode;
501     logger_list->start = start;
502     logger_list->tail = 0;
503     logger_list->pid = pid;
504     logger_list->sock = -1;
505 
506     return logger_list;
507 }
508 
509 /* android_logger_list_register unimplemented, no use case */
510 /* android_logger_list_unregister unimplemented, no use case */
511 
512 /* Open the named log and add it to the logger list */
android_logger_open(struct logger_list * logger_list,log_id_t id)513 struct logger *android_logger_open(struct logger_list *logger_list,
514                                    log_id_t id)
515 {
516     struct logger *logger;
517 
518     if (!logger_list || (id >= LOG_ID_MAX)) {
519         goto err;
520     }
521 
522     logger_for_each(logger, logger_list) {
523         if (logger->id == id) {
524             goto ok;
525         }
526     }
527 
528     logger = calloc(1, sizeof(*logger));
529     if (!logger) {
530         goto err;
531     }
532 
533     logger->id = id;
534     list_add_tail(&logger_list->node, &logger->node);
535     logger->top = logger_list;
536     goto ok;
537 
538 err:
539     logger = NULL;
540 ok:
541     return logger;
542 }
543 
544 /* Open the single named log and make it part of a new logger list */
android_logger_list_open(log_id_t id,int mode,unsigned int tail,pid_t pid)545 struct logger_list *android_logger_list_open(log_id_t id,
546                                              int mode,
547                                              unsigned int tail,
548                                              pid_t pid)
549 {
550     struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid);
551     if (!logger_list) {
552         return NULL;
553     }
554 
555     if (!android_logger_open(logger_list, id)) {
556         android_logger_list_free(logger_list);
557         return NULL;
558     }
559 
560     return logger_list;
561 }
562 
caught_signal(int signum __unused)563 static void caught_signal(int signum __unused)
564 {
565 }
566 
567 /* Read from the selected logs */
android_logger_list_read(struct logger_list * logger_list,struct log_msg * log_msg)568 int android_logger_list_read(struct logger_list *logger_list,
569                              struct log_msg *log_msg)
570 {
571     int ret, e;
572     struct logger *logger;
573     struct sigaction ignore;
574     struct sigaction old_sigaction;
575     unsigned int old_alarm = 0;
576 
577     if (!logger_list) {
578         return -EINVAL;
579     }
580 
581     if (logger_list->mode & O_NONBLOCK) {
582         memset(&ignore, 0, sizeof(ignore));
583         ignore.sa_handler = caught_signal;
584         sigemptyset(&ignore.sa_mask);
585     }
586 
587     if (logger_list->sock < 0) {
588         char buffer[256], *cp, c;
589 
590         int sock = socket_local_client("logdr",
591                                        ANDROID_SOCKET_NAMESPACE_RESERVED,
592                                        SOCK_SEQPACKET);
593         if (sock < 0) {
594             if ((sock == -1) && errno) {
595                 return -errno;
596             }
597             return sock;
598         }
599 
600         strcpy(buffer,
601                (logger_list->mode & O_NONBLOCK) ? "dumpAndClose" : "stream");
602         cp = buffer + strlen(buffer);
603 
604         strcpy(cp, " lids");
605         cp += 5;
606         c = '=';
607         int remaining = sizeof(buffer) - (cp - buffer);
608         logger_for_each(logger, logger_list) {
609             ret = snprintf(cp, remaining, "%c%u", c, logger->id);
610             ret = min(ret, remaining);
611             remaining -= ret;
612             cp += ret;
613             c = ',';
614         }
615 
616         if (logger_list->tail) {
617             ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
618             ret = min(ret, remaining);
619             remaining -= ret;
620             cp += ret;
621         }
622 
623         if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
624             ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
625                            logger_list->start.tv_sec,
626                            logger_list->start.tv_nsec);
627             ret = min(ret, remaining);
628             remaining -= ret;
629             cp += ret;
630         }
631 
632         if (logger_list->pid) {
633             ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
634             ret = min(ret, remaining);
635             remaining -= ret;
636             cp += ret;
637         }
638 
639         if (logger_list->mode & O_NONBLOCK) {
640             /* Deal with an unresponsive logd */
641             sigaction(SIGALRM, &ignore, &old_sigaction);
642             old_alarm = alarm(30);
643         }
644         ret = write(sock, buffer, cp - buffer);
645         e = errno;
646         if (logger_list->mode & O_NONBLOCK) {
647             if (e == EINTR) {
648                 e = ETIMEDOUT;
649             }
650             alarm(old_alarm);
651             sigaction(SIGALRM, &old_sigaction, NULL);
652         }
653 
654         if (ret <= 0) {
655             close(sock);
656             if ((ret == -1) && e) {
657                 return -e;
658             }
659             if (ret == 0) {
660                 return -EIO;
661             }
662             return ret;
663         }
664 
665         logger_list->sock = sock;
666     }
667 
668     ret = 0;
669     while(1) {
670         memset(log_msg, 0, sizeof(*log_msg));
671 
672         if (logger_list->mode & O_NONBLOCK) {
673             /* particularily useful if tombstone is reporting for logd */
674             sigaction(SIGALRM, &ignore, &old_sigaction);
675             old_alarm = alarm(30);
676         }
677         /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
678         ret = recv(logger_list->sock, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
679         e = errno;
680         if (logger_list->mode & O_NONBLOCK) {
681             if ((ret == 0) || (e == EINTR)) {
682                 e = EAGAIN;
683                 ret = -1;
684             }
685             alarm(old_alarm);
686             sigaction(SIGALRM, &old_sigaction, NULL);
687         }
688 
689         if (ret <= 0) {
690             if ((ret == -1) && e) {
691                 return -e;
692             }
693             return ret;
694         }
695 
696         logger_for_each(logger, logger_list) {
697             if (log_msg->entry.lid == logger->id) {
698                 return ret;
699             }
700         }
701     }
702     /* NOTREACH */
703     return ret;
704 }
705 
706 /* Close all the logs */
android_logger_list_free(struct logger_list * logger_list)707 void android_logger_list_free(struct logger_list *logger_list)
708 {
709     if (logger_list == NULL) {
710         return;
711     }
712 
713     while (!list_empty(&logger_list->node)) {
714         struct listnode *node = list_head(&logger_list->node);
715         struct logger *logger = node_to_item(node, struct logger, node);
716         android_logger_free(logger);
717     }
718 
719     if (logger_list->sock >= 0) {
720         close (logger_list->sock);
721     }
722 
723     free(logger_list);
724 }
725