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