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