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