• 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, struct log_msg* log_msg);
51 static int logdPoll(struct android_log_logger_list* logger_list,
52                     struct android_log_transport_context* transp);
53 static void logdClose(struct android_log_logger_list* logger_list,
54                       struct android_log_transport_context* transp);
55 static int logdClear(struct android_log_logger* logger,
56                      struct android_log_transport_context* transp);
57 static ssize_t logdSetSize(struct android_log_logger* logger,
58                            struct android_log_transport_context* transp, size_t size);
59 static ssize_t logdGetSize(struct android_log_logger* logger,
60                            struct android_log_transport_context* transp);
61 static ssize_t logdGetReadableSize(struct android_log_logger* logger,
62                                    struct android_log_transport_context* transp);
63 static ssize_t logdGetPrune(struct android_log_logger_list* logger,
64                             struct android_log_transport_context* transp, char* buf, size_t len);
65 static ssize_t logdSetPrune(struct android_log_logger_list* logger,
66                             struct android_log_transport_context* transp, char* buf, size_t len);
67 static ssize_t logdGetStats(struct android_log_logger_list* logger,
68                             struct android_log_transport_context* transp, char* buf, size_t len);
69 
70 struct android_log_transport_read logdLoggerRead = {
71     .node = {&logdLoggerRead.node, &logdLoggerRead.node},
72     .name = "logd",
73     .available = logdAvailable,
74     .version = logdVersion,
75     .read = logdRead,
76     .poll = logdPoll,
77     .close = logdClose,
78     .clear = logdClear,
79     .getSize = logdGetSize,
80     .setSize = logdSetSize,
81     .getReadableSize = logdGetReadableSize,
82     .getPrune = logdGetPrune,
83     .setPrune = logdSetPrune,
84     .getStats = logdGetStats,
85 };
86 
logdAvailable(log_id_t logId)87 static int logdAvailable(log_id_t logId) {
88   if (logId >= LOG_ID_MAX) {
89     return -EINVAL;
90   }
91   if (logId == LOG_ID_SECURITY) {
92     uid_t uid = __android_log_uid();
93     if (uid != AID_SYSTEM) {
94       return -EPERM;
95     }
96   }
97   if (access("/dev/socket/logdw", W_OK) == 0) {
98     return 0;
99   }
100   return -EBADF;
101 }
102 
103 // Connects to /dev/socket/<name> and returns the associated fd or returns -1 on error.
104 // O_CLOEXEC is always set.
socket_local_client(const std::string & name,int type)105 static int socket_local_client(const std::string& name, int type) {
106   sockaddr_un addr = {.sun_family = AF_LOCAL};
107 
108   std::string path = "/dev/socket/" + name;
109   if (path.size() + 1 > sizeof(addr.sun_path)) {
110     return -1;
111   }
112   strlcpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path));
113 
114   int fd = socket(AF_LOCAL, type | SOCK_CLOEXEC, 0);
115   if (fd == 0) {
116     return -1;
117   }
118 
119   if (connect(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1) {
120     close(fd);
121     return -1;
122   }
123 
124   return fd;
125 }
126 
127 /* 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)128 static ssize_t send_log_msg(struct android_log_logger* logger, const char* msg, char* buf,
129                             size_t buf_size) {
130   ssize_t ret;
131   size_t len;
132   char* cp;
133   int errno_save = 0;
134   int sock = socket_local_client("logd", SOCK_STREAM);
135   if (sock < 0) {
136     return sock;
137   }
138 
139   if (msg) {
140     snprintf(buf, buf_size, msg, logger ? logger->logId : (unsigned)-1);
141   }
142 
143   len = strlen(buf) + 1;
144   ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
145   if (ret <= 0) {
146     goto done;
147   }
148 
149   len = buf_size;
150   cp = buf;
151   while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) {
152     struct pollfd p;
153 
154     if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) {
155       break;
156     }
157 
158     len -= ret;
159     cp += ret;
160 
161     memset(&p, 0, sizeof(p));
162     p.fd = sock;
163     p.events = POLLIN;
164 
165     /* Give other side 20ms to refill pipe */
166     ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20));
167 
168     if (ret <= 0) {
169       break;
170     }
171 
172     if (!(p.revents & POLLIN)) {
173       ret = 0;
174       break;
175     }
176   }
177 
178   if (ret >= 0) {
179     ret += buf_size - len;
180   }
181 
182 done:
183   if ((ret == -1) && errno) {
184     errno_save = errno;
185   }
186   close(sock);
187   if (errno_save) {
188     errno = errno_save;
189   }
190   return ret;
191 }
192 
__send_log_msg(char * buf,size_t buf_size)193 ssize_t __send_log_msg(char* buf, size_t buf_size) {
194   return send_log_msg(NULL, NULL, buf, buf_size);
195 }
196 
check_log_success(char * buf,ssize_t ret)197 static int check_log_success(char* buf, ssize_t ret) {
198   if (ret < 0) {
199     return ret;
200   }
201 
202   if (strncmp(buf, "success", 7)) {
203     errno = EINVAL;
204     return -1;
205   }
206 
207   return 0;
208 }
209 
logdClear(struct android_log_logger * logger,struct android_log_transport_context * transp __unused)210 static int logdClear(struct android_log_logger* logger,
211                      struct android_log_transport_context* transp __unused) {
212   char buf[512];
213 
214   return check_log_success(buf, send_log_msg(logger, "clear %d", buf, sizeof(buf)));
215 }
216 
217 /* returns the total size of the log's ring buffer */
logdGetSize(struct android_log_logger * logger,struct android_log_transport_context * transp __unused)218 static ssize_t logdGetSize(struct android_log_logger* logger,
219                            struct android_log_transport_context* transp __unused) {
220   char buf[512];
221 
222   ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
223   if (ret < 0) {
224     return ret;
225   }
226 
227   if ((buf[0] < '0') || ('9' < buf[0])) {
228     return -1;
229   }
230 
231   return atol(buf);
232 }
233 
logdSetSize(struct android_log_logger * logger,struct android_log_transport_context * transp __unused,size_t size)234 static ssize_t logdSetSize(struct android_log_logger* logger,
235                            struct android_log_transport_context* transp __unused, size_t size) {
236   char buf[512];
237 
238   snprintf(buf, sizeof(buf), "setLogSize %d %zu", logger->logId, size);
239 
240   return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
241 }
242 
243 /*
244  * returns the readable size of the log's ring buffer (that is, amount of the
245  * log consumed)
246  */
logdGetReadableSize(struct android_log_logger * logger,struct android_log_transport_context * transp __unused)247 static ssize_t logdGetReadableSize(struct android_log_logger* logger,
248                                    struct android_log_transport_context* transp __unused) {
249   char buf[512];
250 
251   ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
252   if (ret < 0) {
253     return ret;
254   }
255 
256   if ((buf[0] < '0') || ('9' < buf[0])) {
257     return -1;
258   }
259 
260   return atol(buf);
261 }
262 
263 /*
264  * returns the logger version
265  */
logdVersion(struct android_log_logger * logger __unused,struct android_log_transport_context * transp __unused)266 static int logdVersion(struct android_log_logger* logger __unused,
267                        struct android_log_transport_context* transp __unused) {
268   uid_t uid = __android_log_uid();
269   return ((uid != AID_ROOT) && (uid != AID_LOG) && (uid != AID_SYSTEM)) ? 3 : 4;
270 }
271 
272 /*
273  * returns statistics
274  */
logdGetStats(struct android_log_logger_list * logger_list,struct android_log_transport_context * transp __unused,char * buf,size_t len)275 static ssize_t logdGetStats(struct android_log_logger_list* logger_list,
276                             struct android_log_transport_context* transp __unused, char* buf,
277                             size_t len) {
278   struct android_log_logger* logger;
279   char* cp = buf;
280   size_t remaining = len;
281   size_t n;
282 
283   n = snprintf(cp, remaining, "getStatistics");
284   n = min(n, remaining);
285   remaining -= n;
286   cp += n;
287 
288   logger_for_each(logger, logger_list) {
289     n = snprintf(cp, remaining, " %d", logger->logId);
290     n = min(n, remaining);
291     remaining -= n;
292     cp += n;
293   }
294 
295   if (logger_list->pid) {
296     snprintf(cp, remaining, " pid=%u", logger_list->pid);
297   }
298 
299   return send_log_msg(NULL, NULL, buf, len);
300 }
301 
logdGetPrune(struct android_log_logger_list * logger_list __unused,struct android_log_transport_context * transp __unused,char * buf,size_t len)302 static ssize_t logdGetPrune(struct android_log_logger_list* logger_list __unused,
303                             struct android_log_transport_context* transp __unused, char* buf,
304                             size_t len) {
305   return send_log_msg(NULL, "getPruneList", buf, len);
306 }
307 
logdSetPrune(struct android_log_logger_list * logger_list __unused,struct android_log_transport_context * transp __unused,char * buf,size_t len)308 static ssize_t logdSetPrune(struct android_log_logger_list* logger_list __unused,
309                             struct android_log_transport_context* transp __unused, char* buf,
310                             size_t len) {
311   const char cmd[] = "setPruneList ";
312   const size_t cmdlen = sizeof(cmd) - 1;
313 
314   if (strlen(buf) > (len - cmdlen)) {
315     return -ENOMEM; /* KISS */
316   }
317   memmove(buf + cmdlen, buf, len - cmdlen);
318   buf[len - 1] = '\0';
319   memcpy(buf, cmd, cmdlen);
320 
321   return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
322 }
323 
caught_signal(int signum __unused)324 static void caught_signal(int signum __unused) {}
325 
logdOpen(struct android_log_logger_list * logger_list,struct android_log_transport_context * transp)326 static int logdOpen(struct android_log_logger_list* logger_list,
327                     struct android_log_transport_context* transp) {
328   struct android_log_logger* logger;
329   struct sigaction ignore;
330   struct sigaction old_sigaction;
331   unsigned int old_alarm = 0;
332   char buffer[256], *cp, c;
333   int e, ret, remaining, sock;
334 
335   if (!logger_list) {
336     return -EINVAL;
337   }
338 
339   sock = atomic_load(&transp->context.sock);
340   if (sock > 0) {
341     return sock;
342   }
343 
344   sock = socket_local_client("logdr", SOCK_SEQPACKET);
345   if (sock == 0) {
346     /* Guarantee not file descriptor zero */
347     int newsock = socket_local_client("logdr", SOCK_SEQPACKET);
348     close(sock);
349     sock = newsock;
350   }
351   if (sock <= 0) {
352     if ((sock == -1) && errno) {
353       return -errno;
354     }
355     return sock;
356   }
357 
358   strcpy(buffer, (logger_list->mode & ANDROID_LOG_NONBLOCK) ? "dumpAndClose" : "stream");
359   cp = buffer + strlen(buffer);
360 
361   strcpy(cp, " lids");
362   cp += 5;
363   c = '=';
364   remaining = sizeof(buffer) - (cp - buffer);
365   logger_for_each(logger, logger_list) {
366     ret = snprintf(cp, remaining, "%c%u", c, logger->logId);
367     ret = min(ret, remaining);
368     remaining -= ret;
369     cp += ret;
370     c = ',';
371   }
372 
373   if (logger_list->tail) {
374     ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
375     ret = min(ret, remaining);
376     remaining -= ret;
377     cp += ret;
378   }
379 
380   if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
381     if (logger_list->mode & ANDROID_LOG_WRAP) {
382       // ToDo: alternate API to allow timeout to be adjusted.
383       ret = snprintf(cp, remaining, " timeout=%u", ANDROID_LOG_WRAP_DEFAULT_TIMEOUT);
384       ret = min(ret, remaining);
385       remaining -= ret;
386       cp += ret;
387     }
388     ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32, logger_list->start.tv_sec,
389                    logger_list->start.tv_nsec);
390     ret = min(ret, remaining);
391     remaining -= ret;
392     cp += ret;
393   }
394 
395   if (logger_list->pid) {
396     ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
397     ret = min(ret, remaining);
398     cp += ret;
399   }
400 
401   if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
402     /* Deal with an unresponsive logd */
403     memset(&ignore, 0, sizeof(ignore));
404     ignore.sa_handler = caught_signal;
405     sigemptyset(&ignore.sa_mask);
406     /* particularily useful if tombstone is reporting for logd */
407     sigaction(SIGALRM, &ignore, &old_sigaction);
408     old_alarm = alarm(30);
409   }
410   ret = write(sock, buffer, cp - buffer);
411   e = errno;
412   if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
413     if (e == EINTR) {
414       e = ETIMEDOUT;
415     }
416     alarm(old_alarm);
417     sigaction(SIGALRM, &old_sigaction, NULL);
418   }
419 
420   if (ret <= 0) {
421     close(sock);
422     if ((ret == -1) && e) {
423       return -e;
424     }
425     if (ret == 0) {
426       return -EIO;
427     }
428     return ret;
429   }
430 
431   ret = atomic_exchange(&transp->context.sock, sock);
432   if ((ret > 0) && (ret != sock)) {
433     close(ret);
434   }
435   return sock;
436 }
437 
438 /* Read from the selected logs */
logdRead(struct android_log_logger_list * logger_list,struct android_log_transport_context * transp,struct log_msg * log_msg)439 static int logdRead(struct android_log_logger_list* logger_list,
440                     struct android_log_transport_context* transp, struct log_msg* log_msg) {
441   int ret, e;
442   struct sigaction ignore;
443   struct sigaction old_sigaction;
444   unsigned int old_alarm = 0;
445 
446   ret = logdOpen(logger_list, transp);
447   if (ret < 0) {
448     return ret;
449   }
450 
451   memset(log_msg, 0, sizeof(*log_msg));
452 
453   unsigned int new_alarm = 0;
454   if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
455     if ((logger_list->mode & ANDROID_LOG_WRAP) &&
456         (logger_list->start.tv_sec || logger_list->start.tv_nsec)) {
457       /* b/64143705 */
458       new_alarm = (ANDROID_LOG_WRAP_DEFAULT_TIMEOUT * 11) / 10 + 10;
459       logger_list->mode &= ~ANDROID_LOG_WRAP;
460     } else {
461       new_alarm = 30;
462     }
463 
464     memset(&ignore, 0, sizeof(ignore));
465     ignore.sa_handler = caught_signal;
466     sigemptyset(&ignore.sa_mask);
467     /* particularily useful if tombstone is reporting for logd */
468     sigaction(SIGALRM, &ignore, &old_sigaction);
469     old_alarm = alarm(new_alarm);
470   }
471 
472   /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
473   ret = recv(ret, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
474   e = errno;
475 
476   if (new_alarm) {
477     if ((ret == 0) || (e == EINTR)) {
478       e = EAGAIN;
479       ret = -1;
480     }
481     alarm(old_alarm);
482     sigaction(SIGALRM, &old_sigaction, NULL);
483   }
484 
485   if ((ret == -1) && e) {
486     return -e;
487   }
488   return ret;
489 }
490 
logdPoll(struct android_log_logger_list * logger_list,struct android_log_transport_context * transp)491 static int logdPoll(struct android_log_logger_list* logger_list,
492                     struct android_log_transport_context* transp) {
493   struct pollfd p;
494 
495   int ret = logdOpen(logger_list, transp);
496   if (ret < 0) {
497     return ret;
498   }
499 
500   memset(&p, 0, sizeof(p));
501   p.fd = ret;
502   p.events = POLLIN;
503   ret = poll(&p, 1, 20);
504   if ((ret > 0) && !(p.revents & POLLIN)) {
505     ret = 0;
506   }
507   if ((ret == -1) && errno) {
508     return -errno;
509   }
510   return ret;
511 }
512 
513 /* Close all the logs */
logdClose(struct android_log_logger_list * logger_list __unused,struct android_log_transport_context * transp)514 static void logdClose(struct android_log_logger_list* logger_list __unused,
515                       struct android_log_transport_context* transp) {
516   int sock = atomic_exchange(&transp->context.sock, -1);
517   if (sock > 0) {
518     close(sock);
519   }
520 }
521