blob: 9c4af30d0a08180736b8556218aad2fec5fea030 [file] [log] [blame]
Mark Salyzyn42958412013-11-22 10:50:27 -08001/*
Mark Salyzynd0a83fd2014-01-09 07:45:30 -08002** Copyright 2013-2014, The Android Open Source Project
Mark Salyzyn42958412013-11-22 10:50:27 -08003**
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
Mark Salyzyn42958412013-11-22 10:50:27 -080017#include <errno.h>
18#include <fcntl.h>
Mark Salyzynfa3716b2014-02-14 16:05:05 -080019#include <inttypes.h>
Mark Salyzyn696817d2014-04-18 14:49:28 -070020#include <poll.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080021#include <signal.h>
Mark Salyzyn6eef4172014-12-15 09:51:39 -080022#include <stdbool.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080023#include <stddef.h>
24#define NOMINMAX /* for windows to suppress definition of min in stdlib.h */
Mark Salyzyn42958412013-11-22 10:50:27 -080025#include <stdlib.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080026#include <string.h>
Mark Salyzyna04464a2014-04-30 08:50:53 -070027#include <sys/cdefs.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080028#include <unistd.h>
29
Mark Salyzyn42958412013-11-22 10:50:27 -080030#include <cutils/list.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080031#include <cutils/sockets.h>
Mark Salyzyn42958412013-11-22 10:50:27 -080032#include <log/log.h>
33#include <log/logger.h>
Mark Salyzyn6eef4172014-12-15 09:51:39 -080034#include <private/android_filesystem_config.h>
35#include <private/android_logger.h>
Mark Salyzyn42958412013-11-22 10:50:27 -080036
Mark Salyzyn154f4602014-02-20 14:59:07 -080037/* branchless on many architectures. */
38#define min(x,y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
Mark Salyzyn1345f382014-01-14 08:41:27 -080039
Mark Salyzyn95687052014-10-02 11:12:28 -070040#if (defined(USE_MINGW) || defined(HAVE_WINSOCK))
41#define WEAK static
42#else
Mark Salyzyn154f4602014-02-20 14:59:07 -080043#define WEAK __attribute__((weak))
Mark Salyzyn95687052014-10-02 11:12:28 -070044#endif
Mark Salyzyna04464a2014-04-30 08:50:53 -070045#ifndef __unused
46#define __unused __attribute__((unused))
47#endif
Mark Salyzyn1345f382014-01-14 08:41:27 -080048
Mark Salyzyn154f4602014-02-20 14:59:07 -080049/* Private copy of ../libcutils/socket_local_client.c prevent library loops */
Mark Salyzyn1345f382014-01-14 08:41:27 -080050
Mark Salyzyn154f4602014-02-20 14:59:07 -080051#ifdef HAVE_WINSOCK
Mark Salyzyn42958412013-11-22 10:50:27 -080052
Mark Salyzyn154f4602014-02-20 14:59:07 -080053int WEAK socket_local_client(const char *name, int namespaceId, int type)
54{
55 errno = ENOSYS;
56 return -ENOSYS;
57}
Mark Salyzyn42958412013-11-22 10:50:27 -080058
Mark Salyzyn154f4602014-02-20 14:59:07 -080059#else /* !HAVE_WINSOCK */
60
61#include <sys/socket.h>
62#include <sys/un.h>
63#include <sys/select.h>
64#include <sys/types.h>
65
66/* Private copy of ../libcutils/socket_local.h prevent library loops */
67#define FILESYSTEM_SOCKET_PREFIX "/tmp/"
68#define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
69/* End of ../libcutils/socket_local.h */
70
71#define LISTEN_BACKLOG 4
72
73/* Documented in header file. */
74int WEAK socket_make_sockaddr_un(const char *name, int namespaceId,
75 struct sockaddr_un *p_addr, socklen_t *alen)
76{
77 memset (p_addr, 0, sizeof (*p_addr));
78 size_t namelen;
79
80 switch (namespaceId) {
81 case ANDROID_SOCKET_NAMESPACE_ABSTRACT:
Elliott Hughes9768d242014-11-21 22:50:20 -080082#if defined(__linux__)
Mark Salyzyn154f4602014-02-20 14:59:07 -080083 namelen = strlen(name);
84
85 /* Test with length +1 for the *initial* '\0'. */
86 if ((namelen + 1) > sizeof(p_addr->sun_path)) {
87 goto error;
88 }
89
90 /*
91 * Note: The path in this case is *not* supposed to be
92 * '\0'-terminated. ("man 7 unix" for the gory details.)
93 */
94
95 p_addr->sun_path[0] = 0;
96 memcpy(p_addr->sun_path + 1, name, namelen);
Elliott Hughes9768d242014-11-21 22:50:20 -080097#else
Mark Salyzyn154f4602014-02-20 14:59:07 -080098 /* this OS doesn't have the Linux abstract namespace */
99
100 namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
101 /* unix_path_max appears to be missing on linux */
102 if (namelen > sizeof(*p_addr)
103 - offsetof(struct sockaddr_un, sun_path) - 1) {
104 goto error;
105 }
106
107 strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
108 strcat(p_addr->sun_path, name);
Elliott Hughes9768d242014-11-21 22:50:20 -0800109#endif
Mark Salyzyn154f4602014-02-20 14:59:07 -0800110 break;
111
112 case ANDROID_SOCKET_NAMESPACE_RESERVED:
113 namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
114 /* unix_path_max appears to be missing on linux */
115 if (namelen > sizeof(*p_addr)
116 - offsetof(struct sockaddr_un, sun_path) - 1) {
117 goto error;
118 }
119
120 strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);
121 strcat(p_addr->sun_path, name);
122 break;
123
124 case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
125 namelen = strlen(name);
126 /* unix_path_max appears to be missing on linux */
127 if (namelen > sizeof(*p_addr)
128 - offsetof(struct sockaddr_un, sun_path) - 1) {
129 goto error;
130 }
131
132 strcpy(p_addr->sun_path, name);
133 break;
134
135 default:
136 /* invalid namespace id */
137 return -1;
138 }
139
140 p_addr->sun_family = AF_LOCAL;
141 *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
142 return 0;
143error:
144 return -1;
145}
146
147/**
148 * connect to peer named "name" on fd
149 * returns same fd or -1 on error.
150 * fd is not closed on error. that's your job.
151 *
152 * Used by AndroidSocketImpl
153 */
154int WEAK socket_local_client_connect(int fd, const char *name, int namespaceId,
Mark Salyzyna04464a2014-04-30 08:50:53 -0700155 int type __unused)
Mark Salyzyn154f4602014-02-20 14:59:07 -0800156{
157 struct sockaddr_un addr;
158 socklen_t alen;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800159 int err;
160
161 err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
162
163 if (err < 0) {
164 goto error;
165 }
166
167 if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {
168 goto error;
169 }
170
171 return fd;
172
173error:
174 return -1;
175}
176
177/**
178 * connect to peer named "name"
179 * returns fd or -1 on error
180 */
181int WEAK socket_local_client(const char *name, int namespaceId, int type)
182{
183 int s;
184
185 s = socket(AF_LOCAL, type, 0);
186 if(s < 0) return -1;
187
188 if ( 0 > socket_local_client_connect(s, name, namespaceId, type)) {
189 close(s);
190 return -1;
191 }
192
193 return s;
194}
195
196#endif /* !HAVE_WINSOCK */
197/* End of ../libcutils/socket_local_client.c */
Mark Salyzyn42958412013-11-22 10:50:27 -0800198
199#define logger_for_each(logger, logger_list) \
200 for (logger = node_to_item((logger_list)->node.next, struct logger, node); \
201 logger != node_to_item(&(logger_list)->node, struct logger, node); \
202 logger = node_to_item((logger)->node.next, struct logger, node))
203
204/* In the future, we would like to make this list extensible */
205static const char *LOG_NAME[LOG_ID_MAX] = {
206 [LOG_ID_MAIN] = "main",
207 [LOG_ID_RADIO] = "radio",
208 [LOG_ID_EVENTS] = "events",
Mark Salyzyn99f47a92014-04-07 14:58:08 -0700209 [LOG_ID_SYSTEM] = "system",
210 [LOG_ID_CRASH] = "crash",
Mark Salyzyn440e1092014-10-10 15:13:15 -0700211 [LOG_ID_KERNEL] = "kernel",
Mark Salyzyn42958412013-11-22 10:50:27 -0800212};
213
Mark Salyzyn154f4602014-02-20 14:59:07 -0800214const char *android_log_id_to_name(log_id_t log_id)
215{
Mark Salyzyn42958412013-11-22 10:50:27 -0800216 if (log_id >= LOG_ID_MAX) {
217 log_id = LOG_ID_MAIN;
218 }
219 return LOG_NAME[log_id];
220}
221
Mark Salyzyn154f4602014-02-20 14:59:07 -0800222log_id_t android_name_to_log_id(const char *logName)
Mark Salyzyn42958412013-11-22 10:50:27 -0800223{
Mark Salyzyn42958412013-11-22 10:50:27 -0800224 const char *b;
Mark Salyzyn42958412013-11-22 10:50:27 -0800225 int ret;
226
227 if (!logName) {
228 return -1; /* NB: log_id_t is unsigned */
229 }
230 b = strrchr(logName, '/');
231 if (!b) {
232 b = logName;
233 } else {
234 ++b;
235 }
236
Mark Salyzyn42958412013-11-22 10:50:27 -0800237 for(ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) {
238 const char *l = LOG_NAME[ret];
239 if (l && !strcmp(b, l)) {
240 return ret;
241 }
242 }
243 return -1; /* should never happen */
244}
245
246struct logger_list {
247 struct listnode node;
248 int mode;
249 unsigned int tail;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800250 log_time start;
Mark Salyzyn42958412013-11-22 10:50:27 -0800251 pid_t pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800252 int sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800253};
254
255struct logger {
256 struct listnode node;
257 struct logger_list *top;
Mark Salyzyn42958412013-11-22 10:50:27 -0800258 log_id_t id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800259};
260
261/* android_logger_alloc unimplemented, no use case */
262/* android_logger_free not exported */
263static void android_logger_free(struct logger *logger)
264{
265 if (!logger) {
266 return;
267 }
268
Mark Salyzyn42958412013-11-22 10:50:27 -0800269 list_remove(&logger->node);
270
271 free(logger);
272}
273
Mark Salyzyn154f4602014-02-20 14:59:07 -0800274/* android_logger_alloc unimplemented, no use case */
275
276/* method for getting the associated sublog id */
Mark Salyzyn42958412013-11-22 10:50:27 -0800277log_id_t android_logger_get_id(struct logger *logger)
278{
279 return logger->id;
280}
281
282/* worker for sending the command to the logger */
Mark Salyzyn154f4602014-02-20 14:59:07 -0800283static ssize_t send_log_msg(struct logger *logger,
284 const char *msg, char *buf, size_t buf_size)
Mark Salyzyn42958412013-11-22 10:50:27 -0800285{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800286 ssize_t ret;
Mark Salyzyn696817d2014-04-18 14:49:28 -0700287 size_t len;
288 char *cp;
Greg Hackmann8084a532014-03-17 13:08:31 -0700289 int errno_save = 0;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800290 int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
291 SOCK_STREAM);
292 if (sock < 0) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700293 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800294 }
295
Mark Salyzyn154f4602014-02-20 14:59:07 -0800296 if (msg) {
297 snprintf(buf, buf_size, msg, logger ? logger->id : (unsigned) -1);
Mark Salyzyn42958412013-11-22 10:50:27 -0800298 }
299
Mark Salyzyn696817d2014-04-18 14:49:28 -0700300 len = strlen(buf) + 1;
301 ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
Mark Salyzyn154f4602014-02-20 14:59:07 -0800302 if (ret <= 0) {
303 goto done;
Mark Salyzyn42958412013-11-22 10:50:27 -0800304 }
305
Mark Salyzyn696817d2014-04-18 14:49:28 -0700306 len = buf_size;
307 cp = buf;
308 while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) {
309 struct pollfd p;
310
311 if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) {
312 break;
313 }
314
315 len -= ret;
316 cp += ret;
317
318 memset(&p, 0, sizeof(p));
319 p.fd = sock;
320 p.events = POLLIN;
321
322 /* Give other side 20ms to refill pipe */
323 ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20));
324
325 if (ret <= 0) {
326 break;
327 }
328
329 if (!(p.revents & POLLIN)) {
330 ret = 0;
331 break;
332 }
333 }
334
335 if (ret >= 0) {
336 ret += buf_size - len;
337 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800338
339done:
340 if ((ret == -1) && errno) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700341 errno_save = errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800342 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800343 close(sock);
Greg Hackmann8084a532014-03-17 13:08:31 -0700344 if (errno_save) {
345 errno = errno_save;
346 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800347 return ret;
348}
349
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800350static int check_log_success(char *buf, ssize_t ret)
Mark Salyzyn42958412013-11-22 10:50:27 -0800351{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800352 if (ret < 0) {
353 return ret;
354 }
355
356 if (strncmp(buf, "success", 7)) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700357 errno = EINVAL;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800358 return -1;
359 }
360
361 return 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800362}
363
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800364/* Determine the credentials of the caller */
365static bool uid_has_log_permission(uid_t uid)
366{
367 return (uid == AID_SYSTEM) || (uid == AID_LOG) || (uid == AID_ROOT);
368}
369
370static uid_t get_best_effective_uid()
371{
372 uid_t euid;
373 uid_t uid;
374 gid_t gid;
375 ssize_t i;
376 static uid_t last_uid = (uid_t) -1;
377
378 if (last_uid != (uid_t) -1) {
379 return last_uid;
380 }
381 uid = getuid();
382 if (uid_has_log_permission(uid)) {
383 return last_uid = uid;
384 }
385 euid = geteuid();
386 if (uid_has_log_permission(euid)) {
387 return last_uid = euid;
388 }
389 gid = getgid();
390 if (uid_has_log_permission(gid)) {
391 return last_uid = gid;
392 }
393 gid = getegid();
394 if (uid_has_log_permission(gid)) {
395 return last_uid = gid;
396 }
397 i = getgroups((size_t) 0, NULL);
398 if (i > 0) {
399 gid_t list[i];
400
401 getgroups(i, list);
402 while (--i >= 0) {
403 if (uid_has_log_permission(list[i])) {
404 return last_uid = list[i];
405 }
406 }
407 }
408 return last_uid = uid;
409}
410
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800411int android_logger_clear(struct logger *logger)
412{
413 char buf[512];
414
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800415 if (logger->top->mode & ANDROID_LOG_PSTORE) {
416 if (uid_has_log_permission(get_best_effective_uid())) {
417 return unlink("/sys/fs/pstore/pmsg-ramoops-0");
418 }
419 errno = EPERM;
420 return -1;
421 }
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800422 return check_log_success(buf,
423 send_log_msg(logger, "clear %d", buf, sizeof(buf)));
424}
425
Mark Salyzyn42958412013-11-22 10:50:27 -0800426/* returns the total size of the log's ring buffer */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800427long android_logger_get_log_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800428{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800429 char buf[512];
430
431 ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
432 if (ret < 0) {
433 return ret;
434 }
435
436 if ((buf[0] < '0') || ('9' < buf[0])) {
437 return -1;
438 }
439
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800440 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800441}
442
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800443int android_logger_set_log_size(struct logger *logger, unsigned long size)
444{
445 char buf[512];
446
447 snprintf(buf, sizeof(buf), "setLogSize %d %lu",
448 logger ? logger->id : (unsigned) -1, size);
449
450 return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
451}
452
Mark Salyzyn42958412013-11-22 10:50:27 -0800453/*
454 * returns the readable size of the log's ring buffer (that is, amount of the
455 * log consumed)
456 */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800457long android_logger_get_log_readable_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800458{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800459 char buf[512];
460
461 ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
462 if (ret < 0) {
463 return ret;
464 }
465
466 if ((buf[0] < '0') || ('9' < buf[0])) {
467 return -1;
468 }
469
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800470 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800471}
472
473/*
474 * returns the logger version
475 */
Mark Salyzyna04464a2014-04-30 08:50:53 -0700476int android_logger_get_log_version(struct logger *logger __unused)
Mark Salyzyn42958412013-11-22 10:50:27 -0800477{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800478 return 3;
Mark Salyzyn42958412013-11-22 10:50:27 -0800479}
480
Mark Salyzyn34facab2014-02-06 14:48:50 -0800481/*
482 * returns statistics
483 */
484ssize_t android_logger_get_statistics(struct logger_list *logger_list,
485 char *buf, size_t len)
486{
Mark Salyzyn34facab2014-02-06 14:48:50 -0800487 struct logger *logger;
488 char *cp = buf;
489 size_t remaining = len;
490 size_t n;
491
492 n = snprintf(cp, remaining, "getStatistics");
493 n = min(n, remaining);
494 remaining -= n;
495 cp += n;
496
497 logger_for_each(logger, logger_list) {
498 n = snprintf(cp, remaining, " %d", logger->id);
499 n = min(n, remaining);
500 remaining -= n;
501 cp += n;
502 }
503 return send_log_msg(NULL, NULL, buf, len);
504}
505
Mark Salyzyna04464a2014-04-30 08:50:53 -0700506ssize_t android_logger_get_prune_list(struct logger_list *logger_list __unused,
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800507 char *buf, size_t len)
508{
509 return send_log_msg(NULL, "getPruneList", buf, len);
510}
511
Mark Salyzyna04464a2014-04-30 08:50:53 -0700512int android_logger_set_prune_list(struct logger_list *logger_list __unused,
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800513 char *buf, size_t len)
514{
515 const char cmd[] = "setPruneList ";
516 const size_t cmdlen = sizeof(cmd) - 1;
517
518 if (strlen(buf) > (len - cmdlen)) {
519 return -ENOMEM; /* KISS */
520 }
521 memmove(buf + cmdlen, buf, len - cmdlen);
522 buf[len - 1] = '\0';
523 memcpy(buf, cmd, cmdlen);
524
525 return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
526}
527
Mark Salyzyn42958412013-11-22 10:50:27 -0800528struct logger_list *android_logger_list_alloc(int mode,
529 unsigned int tail,
530 pid_t pid)
531{
532 struct logger_list *logger_list;
533
534 logger_list = calloc(1, sizeof(*logger_list));
535 if (!logger_list) {
536 return NULL;
537 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800538
Mark Salyzyn42958412013-11-22 10:50:27 -0800539 list_init(&logger_list->node);
540 logger_list->mode = mode;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800541 logger_list->start.tv_sec = 0;
542 logger_list->start.tv_nsec = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800543 logger_list->tail = tail;
544 logger_list->pid = pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800545 logger_list->sock = -1;
546
Mark Salyzyn42958412013-11-22 10:50:27 -0800547 return logger_list;
548}
549
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800550struct logger_list *android_logger_list_alloc_time(int mode,
551 log_time start,
552 pid_t pid)
553{
554 struct logger_list *logger_list;
555
556 logger_list = calloc(1, sizeof(*logger_list));
557 if (!logger_list) {
558 return NULL;
559 }
560
561 list_init(&logger_list->node);
562 logger_list->mode = mode;
563 logger_list->start = start;
564 logger_list->tail = 0;
565 logger_list->pid = pid;
566 logger_list->sock = -1;
567
568 return logger_list;
569}
570
Mark Salyzyn42958412013-11-22 10:50:27 -0800571/* android_logger_list_register unimplemented, no use case */
572/* android_logger_list_unregister unimplemented, no use case */
573
574/* Open the named log and add it to the logger list */
575struct logger *android_logger_open(struct logger_list *logger_list,
576 log_id_t id)
577{
Mark Salyzyn42958412013-11-22 10:50:27 -0800578 struct logger *logger;
Mark Salyzyn42958412013-11-22 10:50:27 -0800579
580 if (!logger_list || (id >= LOG_ID_MAX)) {
581 goto err;
582 }
583
584 logger_for_each(logger, logger_list) {
585 if (logger->id == id) {
586 goto ok;
587 }
588 }
589
590 logger = calloc(1, sizeof(*logger));
591 if (!logger) {
592 goto err;
593 }
594
Mark Salyzyn42958412013-11-22 10:50:27 -0800595 logger->id = id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800596 list_add_tail(&logger_list->node, &logger->node);
597 logger->top = logger_list;
Mark Salyzyn42958412013-11-22 10:50:27 -0800598 goto ok;
599
Mark Salyzyn42958412013-11-22 10:50:27 -0800600err:
601 logger = NULL;
602ok:
603 return logger;
604}
605
606/* Open the single named log and make it part of a new logger list */
607struct logger_list *android_logger_list_open(log_id_t id,
608 int mode,
609 unsigned int tail,
610 pid_t pid)
611{
612 struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid);
613 if (!logger_list) {
614 return NULL;
615 }
616
617 if (!android_logger_open(logger_list, id)) {
618 android_logger_list_free(logger_list);
619 return NULL;
620 }
621
622 return logger_list;
623}
624
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800625static int android_logger_list_read_pstore(struct logger_list *logger_list,
626 struct log_msg *log_msg)
627{
628 ssize_t ret;
629 off_t current, next;
630 uid_t uid;
631 struct logger *logger;
632 struct __attribute__((__packed__)) {
633 android_pmsg_log_header_t p;
634 android_log_header_t l;
635 } buf;
636 static uint8_t preread_count;
637
638 memset(log_msg, 0, sizeof(*log_msg));
639
640 if (logger_list->sock < 0) {
641 int fd = open("/sys/fs/pstore/pmsg-ramoops-0", O_RDONLY);
642
643 if (fd < 0) {
644 return -errno;
645 }
646 logger_list->sock = fd;
647 preread_count = 0;
648 }
649
650 ret = 0;
651 while(1) {
652 if (preread_count < sizeof(buf)) {
653 ret = TEMP_FAILURE_RETRY(read(logger_list->sock,
654 &buf.p.magic + preread_count,
655 sizeof(buf) - preread_count));
656 if (ret < 0) {
657 return -errno;
658 }
659 preread_count += ret;
660 }
661 if (preread_count != sizeof(buf)) {
662 return preread_count ? -EIO : -EAGAIN;
663 }
664 if ((buf.p.magic != LOGGER_MAGIC)
665 || (buf.p.len <= sizeof(buf))
666 || (buf.p.len > (sizeof(buf) + LOGGER_ENTRY_MAX_PAYLOAD))
667 || (buf.l.id >= LOG_ID_MAX)
668 || (buf.l.realtime.tv_nsec >= NS_PER_SEC)) {
669 do {
670 memmove(&buf.p.magic, &buf.p.magic + 1, --preread_count);
671 } while (preread_count && (buf.p.magic != LOGGER_MAGIC));
672 continue;
673 }
674 preread_count = 0;
675
676 logger_for_each(logger, logger_list) {
677 if (buf.l.id != logger->id) {
678 continue;
679 }
680
681 if ((logger_list->start.tv_sec || logger_list->start.tv_nsec)
682 && ((logger_list->start.tv_sec > buf.l.realtime.tv_sec)
683 || ((logger_list->start.tv_sec == buf.l.realtime.tv_sec)
684 && (logger_list->start.tv_nsec > buf.l.realtime.tv_nsec)))) {
685 break;
686 }
687
688 if (logger_list->pid && (logger_list->pid != buf.p.pid)) {
689 break;
690 }
691
692 uid = get_best_effective_uid();
693 if (!uid_has_log_permission(uid) && (uid != buf.p.uid)) {
694 break;
695 }
696
697 ret = TEMP_FAILURE_RETRY(read(logger_list->sock,
698 log_msg->entry_v3.msg,
699 buf.p.len - sizeof(buf)));
700 if (ret < 0) {
701 return -errno;
702 }
703 if (ret != (ssize_t)(buf.p.len - sizeof(buf))) {
704 return -EIO;
705 }
706
707 log_msg->entry_v3.len = buf.p.len - sizeof(buf);
708 log_msg->entry_v3.hdr_size = sizeof(log_msg->entry_v3);
709 log_msg->entry_v3.pid = buf.p.pid;
710 log_msg->entry_v3.tid = buf.l.tid;
711 log_msg->entry_v3.sec = buf.l.realtime.tv_sec;
712 log_msg->entry_v3.nsec = buf.l.realtime.tv_nsec;
713 log_msg->entry_v3.lid = buf.l.id;
714
715 return ret;
716 }
717
718 current = TEMP_FAILURE_RETRY(lseek(logger_list->sock,
719 (off_t)0, SEEK_CUR));
720 if (current < 0) {
721 return -errno;
722 }
723 next = TEMP_FAILURE_RETRY(lseek(logger_list->sock,
724 (off_t)(buf.p.len - sizeof(buf)),
725 SEEK_CUR));
726 if (next < 0) {
727 return -errno;
728 }
729 if ((next - current) != (ssize_t)(buf.p.len - sizeof(buf))) {
730 return -EIO;
731 }
732 }
733}
734
Mark Salyzyna04464a2014-04-30 08:50:53 -0700735static void caught_signal(int signum __unused)
Mark Salyzyn42958412013-11-22 10:50:27 -0800736{
Mark Salyzyn42958412013-11-22 10:50:27 -0800737}
738
739/* Read from the selected logs */
740int android_logger_list_read(struct logger_list *logger_list,
741 struct log_msg *log_msg)
742{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800743 int ret, e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800744 struct logger *logger;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800745 struct sigaction ignore;
746 struct sigaction old_sigaction;
747 unsigned int old_alarm = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800748
749 if (!logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800750 return -EINVAL;
Mark Salyzyn42958412013-11-22 10:50:27 -0800751 }
752
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800753 if (logger_list->mode & ANDROID_LOG_PSTORE) {
754 return android_logger_list_read_pstore(logger_list, log_msg);
755 }
756
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800757 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800758 memset(&ignore, 0, sizeof(ignore));
759 ignore.sa_handler = caught_signal;
760 sigemptyset(&ignore.sa_mask);
Mark Salyzyn42958412013-11-22 10:50:27 -0800761 }
762
Mark Salyzyn154f4602014-02-20 14:59:07 -0800763 if (logger_list->sock < 0) {
764 char buffer[256], *cp, c;
Mark Salyzyn42958412013-11-22 10:50:27 -0800765
Mark Salyzyn154f4602014-02-20 14:59:07 -0800766 int sock = socket_local_client("logdr",
767 ANDROID_SOCKET_NAMESPACE_RESERVED,
768 SOCK_SEQPACKET);
769 if (sock < 0) {
770 if ((sock == -1) && errno) {
771 return -errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800772 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800773 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800774 }
775
Mark Salyzyn154f4602014-02-20 14:59:07 -0800776 strcpy(buffer,
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800777 (logger_list->mode & ANDROID_LOG_NONBLOCK) ? "dumpAndClose" : "stream");
Mark Salyzyn154f4602014-02-20 14:59:07 -0800778 cp = buffer + strlen(buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800779
Mark Salyzyn154f4602014-02-20 14:59:07 -0800780 strcpy(cp, " lids");
781 cp += 5;
782 c = '=';
783 int remaining = sizeof(buffer) - (cp - buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800784 logger_for_each(logger, logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800785 ret = snprintf(cp, remaining, "%c%u", c, logger->id);
786 ret = min(ret, remaining);
787 remaining -= ret;
788 cp += ret;
789 c = ',';
790 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800791
Mark Salyzyn154f4602014-02-20 14:59:07 -0800792 if (logger_list->tail) {
793 ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
794 ret = min(ret, remaining);
795 remaining -= ret;
796 cp += ret;
797 }
798
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800799 if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
800 ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
801 logger_list->start.tv_sec,
802 logger_list->start.tv_nsec);
803 ret = min(ret, remaining);
804 remaining -= ret;
805 cp += ret;
806 }
807
Mark Salyzyn154f4602014-02-20 14:59:07 -0800808 if (logger_list->pid) {
809 ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
810 ret = min(ret, remaining);
811 remaining -= ret;
812 cp += ret;
813 }
814
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800815 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800816 /* Deal with an unresponsive logd */
817 sigaction(SIGALRM, &ignore, &old_sigaction);
818 old_alarm = alarm(30);
819 }
820 ret = write(sock, buffer, cp - buffer);
821 e = errno;
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800822 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800823 if (e == EINTR) {
824 e = ETIMEDOUT;
Mark Salyzyn42958412013-11-22 10:50:27 -0800825 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800826 alarm(old_alarm);
827 sigaction(SIGALRM, &old_sigaction, NULL);
Mark Salyzyn42958412013-11-22 10:50:27 -0800828 }
829
830 if (ret <= 0) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800831 close(sock);
832 if ((ret == -1) && e) {
833 return -e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800834 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800835 if (ret == 0) {
836 return -EIO;
837 }
838 return ret;
Mark Salyzyn42958412013-11-22 10:50:27 -0800839 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800840
841 logger_list->sock = sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800842 }
843
Mark Salyzyn154f4602014-02-20 14:59:07 -0800844 ret = 0;
845 while(1) {
846 memset(log_msg, 0, sizeof(*log_msg));
847
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800848 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800849 /* particularily useful if tombstone is reporting for logd */
850 sigaction(SIGALRM, &ignore, &old_sigaction);
851 old_alarm = alarm(30);
852 }
853 /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
854 ret = recv(logger_list->sock, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
855 e = errno;
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800856 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800857 if ((ret == 0) || (e == EINTR)) {
858 e = EAGAIN;
859 ret = -1;
860 }
861 alarm(old_alarm);
862 sigaction(SIGALRM, &old_sigaction, NULL);
863 }
864
865 if (ret <= 0) {
866 if ((ret == -1) && e) {
867 return -e;
868 }
869 return ret;
870 }
871
872 logger_for_each(logger, logger_list) {
873 if (log_msg->entry.lid == logger->id) {
874 return ret;
875 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800876 }
877 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800878 /* NOTREACH */
Mark Salyzyn42958412013-11-22 10:50:27 -0800879 return ret;
880}
881
882/* Close all the logs */
883void android_logger_list_free(struct logger_list *logger_list)
884{
885 if (logger_list == NULL) {
886 return;
887 }
888
889 while (!list_empty(&logger_list->node)) {
890 struct listnode *node = list_head(&logger_list->node);
891 struct logger *logger = node_to_item(node, struct logger, node);
892 android_logger_free(logger);
893 }
894
Mark Salyzyn154f4602014-02-20 14:59:07 -0800895 if (logger_list->sock >= 0) {
896 close (logger_list->sock);
897 }
898
Mark Salyzyn42958412013-11-22 10:50:27 -0800899 free(logger_list);
900}