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