blob: fc63d2cf9f8fae92bf90b0458de864b7f3ebd4b7 [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
Elliott Hughesadbf4422015-07-29 17:45:24 -070040#if defined(_WIN32)
Mark Salyzyn95687052014-10-02 11:12:28 -070041#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
Elliott Hughesadbf4422015-07-29 17:45:24 -070051#if defined(_WIN32)
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
Elliott Hughesadbf4422015-07-29 17:45:24 -070059#else /* !_WIN32 */
Mark Salyzyn154f4602014-02-20 14:59:07 -080060
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
Elliott Hughesadbf4422015-07-29 17:45:24 -0700196#endif /* !_WIN32 */
Mark Salyzyn154f4602014-02-20 14:59:07 -0800197/* 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 Salyzyn083b0372015-12-04 10:59:45 -0800211 [LOG_ID_SECURITY] = "security",
Mark Salyzyn440e1092014-10-10 15:13:15 -0700212 [LOG_ID_KERNEL] = "kernel",
Mark Salyzyn42958412013-11-22 10:50:27 -0800213};
214
Mark Salyzyn154f4602014-02-20 14:59:07 -0800215const char *android_log_id_to_name(log_id_t log_id)
216{
Mark Salyzyn42958412013-11-22 10:50:27 -0800217 if (log_id >= LOG_ID_MAX) {
218 log_id = LOG_ID_MAIN;
219 }
220 return LOG_NAME[log_id];
221}
222
Mark Salyzyn154f4602014-02-20 14:59:07 -0800223log_id_t android_name_to_log_id(const char *logName)
Mark Salyzyn42958412013-11-22 10:50:27 -0800224{
Mark Salyzyn42958412013-11-22 10:50:27 -0800225 const char *b;
Mark Salyzyn42958412013-11-22 10:50:27 -0800226 int ret;
227
228 if (!logName) {
229 return -1; /* NB: log_id_t is unsigned */
230 }
231 b = strrchr(logName, '/');
232 if (!b) {
233 b = logName;
234 } else {
235 ++b;
236 }
237
Mark Salyzyn42958412013-11-22 10:50:27 -0800238 for(ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) {
239 const char *l = LOG_NAME[ret];
240 if (l && !strcmp(b, l)) {
241 return ret;
242 }
243 }
244 return -1; /* should never happen */
245}
246
247struct logger_list {
248 struct listnode node;
249 int mode;
250 unsigned int tail;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800251 log_time start;
Mark Salyzyn42958412013-11-22 10:50:27 -0800252 pid_t pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800253 int sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800254};
255
256struct logger {
257 struct listnode node;
258 struct logger_list *top;
Mark Salyzyn42958412013-11-22 10:50:27 -0800259 log_id_t id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800260};
261
262/* android_logger_alloc unimplemented, no use case */
263/* android_logger_free not exported */
264static void android_logger_free(struct logger *logger)
265{
266 if (!logger) {
267 return;
268 }
269
Mark Salyzyn42958412013-11-22 10:50:27 -0800270 list_remove(&logger->node);
271
272 free(logger);
273}
274
Mark Salyzyn154f4602014-02-20 14:59:07 -0800275/* android_logger_alloc unimplemented, no use case */
276
277/* method for getting the associated sublog id */
Mark Salyzyn42958412013-11-22 10:50:27 -0800278log_id_t android_logger_get_id(struct logger *logger)
279{
280 return logger->id;
281}
282
283/* worker for sending the command to the logger */
Mark Salyzyn154f4602014-02-20 14:59:07 -0800284static ssize_t send_log_msg(struct logger *logger,
285 const char *msg, char *buf, size_t buf_size)
Mark Salyzyn42958412013-11-22 10:50:27 -0800286{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800287 ssize_t ret;
Mark Salyzyn696817d2014-04-18 14:49:28 -0700288 size_t len;
289 char *cp;
Greg Hackmann8084a532014-03-17 13:08:31 -0700290 int errno_save = 0;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800291 int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
292 SOCK_STREAM);
293 if (sock < 0) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700294 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800295 }
296
Mark Salyzyn154f4602014-02-20 14:59:07 -0800297 if (msg) {
298 snprintf(buf, buf_size, msg, logger ? logger->id : (unsigned) -1);
Mark Salyzyn42958412013-11-22 10:50:27 -0800299 }
300
Mark Salyzyn696817d2014-04-18 14:49:28 -0700301 len = strlen(buf) + 1;
302 ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
Mark Salyzyn154f4602014-02-20 14:59:07 -0800303 if (ret <= 0) {
304 goto done;
Mark Salyzyn42958412013-11-22 10:50:27 -0800305 }
306
Mark Salyzyn696817d2014-04-18 14:49:28 -0700307 len = buf_size;
308 cp = buf;
309 while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) {
310 struct pollfd p;
311
312 if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) {
313 break;
314 }
315
316 len -= ret;
317 cp += ret;
318
319 memset(&p, 0, sizeof(p));
320 p.fd = sock;
321 p.events = POLLIN;
322
323 /* Give other side 20ms to refill pipe */
324 ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20));
325
326 if (ret <= 0) {
327 break;
328 }
329
330 if (!(p.revents & POLLIN)) {
331 ret = 0;
332 break;
333 }
334 }
335
336 if (ret >= 0) {
337 ret += buf_size - len;
338 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800339
340done:
341 if ((ret == -1) && errno) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700342 errno_save = errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800343 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800344 close(sock);
Greg Hackmann8084a532014-03-17 13:08:31 -0700345 if (errno_save) {
346 errno = errno_save;
347 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800348 return ret;
349}
350
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800351static int check_log_success(char *buf, ssize_t ret)
Mark Salyzyn42958412013-11-22 10:50:27 -0800352{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800353 if (ret < 0) {
354 return ret;
355 }
356
357 if (strncmp(buf, "success", 7)) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700358 errno = EINVAL;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800359 return -1;
360 }
361
362 return 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800363}
364
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800365/* Determine the credentials of the caller */
366static bool uid_has_log_permission(uid_t uid)
367{
368 return (uid == AID_SYSTEM) || (uid == AID_LOG) || (uid == AID_ROOT);
369}
370
371static uid_t get_best_effective_uid()
372{
373 uid_t euid;
374 uid_t uid;
375 gid_t gid;
376 ssize_t i;
377 static uid_t last_uid = (uid_t) -1;
378
379 if (last_uid != (uid_t) -1) {
380 return last_uid;
381 }
382 uid = getuid();
383 if (uid_has_log_permission(uid)) {
384 return last_uid = uid;
385 }
386 euid = geteuid();
387 if (uid_has_log_permission(euid)) {
388 return last_uid = euid;
389 }
390 gid = getgid();
391 if (uid_has_log_permission(gid)) {
392 return last_uid = gid;
393 }
394 gid = getegid();
395 if (uid_has_log_permission(gid)) {
396 return last_uid = gid;
397 }
398 i = getgroups((size_t) 0, NULL);
399 if (i > 0) {
400 gid_t list[i];
401
402 getgroups(i, list);
403 while (--i >= 0) {
404 if (uid_has_log_permission(list[i])) {
405 return last_uid = list[i];
406 }
407 }
408 }
409 return last_uid = uid;
410}
411
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800412int android_logger_clear(struct logger *logger)
413{
414 char buf[512];
415
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800416 if (logger->top->mode & ANDROID_LOG_PSTORE) {
417 if (uid_has_log_permission(get_best_effective_uid())) {
418 return unlink("/sys/fs/pstore/pmsg-ramoops-0");
419 }
420 errno = EPERM;
421 return -1;
422 }
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800423 return check_log_success(buf,
424 send_log_msg(logger, "clear %d", buf, sizeof(buf)));
425}
426
Mark Salyzyn42958412013-11-22 10:50:27 -0800427/* returns the total size of the log's ring buffer */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800428long android_logger_get_log_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800429{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800430 char buf[512];
431
432 ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
433 if (ret < 0) {
434 return ret;
435 }
436
437 if ((buf[0] < '0') || ('9' < buf[0])) {
438 return -1;
439 }
440
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800441 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800442}
443
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800444int android_logger_set_log_size(struct logger *logger, unsigned long size)
445{
446 char buf[512];
447
448 snprintf(buf, sizeof(buf), "setLogSize %d %lu",
449 logger ? logger->id : (unsigned) -1, size);
450
451 return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
452}
453
Mark Salyzyn42958412013-11-22 10:50:27 -0800454/*
455 * returns the readable size of the log's ring buffer (that is, amount of the
456 * log consumed)
457 */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800458long android_logger_get_log_readable_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800459{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800460 char buf[512];
461
462 ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
463 if (ret < 0) {
464 return ret;
465 }
466
467 if ((buf[0] < '0') || ('9' < buf[0])) {
468 return -1;
469 }
470
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800471 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800472}
473
474/*
475 * returns the logger version
476 */
Mark Salyzyna04464a2014-04-30 08:50:53 -0700477int android_logger_get_log_version(struct logger *logger __unused)
Mark Salyzyn42958412013-11-22 10:50:27 -0800478{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800479 return 3;
Mark Salyzyn42958412013-11-22 10:50:27 -0800480}
481
Mark Salyzyn34facab2014-02-06 14:48:50 -0800482/*
483 * returns statistics
484 */
485ssize_t android_logger_get_statistics(struct logger_list *logger_list,
486 char *buf, size_t len)
487{
Mark Salyzyn34facab2014-02-06 14:48:50 -0800488 struct logger *logger;
489 char *cp = buf;
490 size_t remaining = len;
491 size_t n;
492
493 n = snprintf(cp, remaining, "getStatistics");
494 n = min(n, remaining);
495 remaining -= n;
496 cp += n;
497
498 logger_for_each(logger, logger_list) {
499 n = snprintf(cp, remaining, " %d", logger->id);
500 n = min(n, remaining);
501 remaining -= n;
502 cp += n;
503 }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800504
505 if (logger_list->pid) {
Mark Salyzynb7a01662016-02-19 13:08:59 -0800506 snprintf(cp, remaining, " pid=%u", logger_list->pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800507 }
508
Mark Salyzyn34facab2014-02-06 14:48:50 -0800509 return send_log_msg(NULL, NULL, buf, len);
510}
511
Mark Salyzyna04464a2014-04-30 08:50:53 -0700512ssize_t android_logger_get_prune_list(struct logger_list *logger_list __unused,
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800513 char *buf, size_t len)
514{
515 return send_log_msg(NULL, "getPruneList", buf, len);
516}
517
Mark Salyzyna04464a2014-04-30 08:50:53 -0700518int android_logger_set_prune_list(struct logger_list *logger_list __unused,
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800519 char *buf, size_t len)
520{
521 const char cmd[] = "setPruneList ";
522 const size_t cmdlen = sizeof(cmd) - 1;
523
524 if (strlen(buf) > (len - cmdlen)) {
525 return -ENOMEM; /* KISS */
526 }
527 memmove(buf + cmdlen, buf, len - cmdlen);
528 buf[len - 1] = '\0';
529 memcpy(buf, cmd, cmdlen);
530
531 return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
532}
533
Mark Salyzyn42958412013-11-22 10:50:27 -0800534struct logger_list *android_logger_list_alloc(int mode,
535 unsigned int tail,
536 pid_t pid)
537{
538 struct logger_list *logger_list;
539
540 logger_list = calloc(1, sizeof(*logger_list));
541 if (!logger_list) {
542 return NULL;
543 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800544
Mark Salyzyn42958412013-11-22 10:50:27 -0800545 list_init(&logger_list->node);
546 logger_list->mode = mode;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800547 logger_list->start.tv_sec = 0;
548 logger_list->start.tv_nsec = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800549 logger_list->tail = tail;
550 logger_list->pid = pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800551 logger_list->sock = -1;
552
Mark Salyzyn42958412013-11-22 10:50:27 -0800553 return logger_list;
554}
555
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800556struct logger_list *android_logger_list_alloc_time(int mode,
557 log_time start,
558 pid_t pid)
559{
560 struct logger_list *logger_list;
561
562 logger_list = calloc(1, sizeof(*logger_list));
563 if (!logger_list) {
564 return NULL;
565 }
566
567 list_init(&logger_list->node);
568 logger_list->mode = mode;
569 logger_list->start = start;
570 logger_list->tail = 0;
571 logger_list->pid = pid;
572 logger_list->sock = -1;
573
574 return logger_list;
575}
576
Mark Salyzyn42958412013-11-22 10:50:27 -0800577/* android_logger_list_register unimplemented, no use case */
578/* android_logger_list_unregister unimplemented, no use case */
579
580/* Open the named log and add it to the logger list */
581struct logger *android_logger_open(struct logger_list *logger_list,
582 log_id_t id)
583{
Mark Salyzyn42958412013-11-22 10:50:27 -0800584 struct logger *logger;
Mark Salyzyn42958412013-11-22 10:50:27 -0800585
586 if (!logger_list || (id >= LOG_ID_MAX)) {
587 goto err;
588 }
589
590 logger_for_each(logger, logger_list) {
591 if (logger->id == id) {
592 goto ok;
593 }
594 }
595
596 logger = calloc(1, sizeof(*logger));
597 if (!logger) {
598 goto err;
599 }
600
Mark Salyzyn42958412013-11-22 10:50:27 -0800601 logger->id = id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800602 list_add_tail(&logger_list->node, &logger->node);
603 logger->top = logger_list;
Mark Salyzyn42958412013-11-22 10:50:27 -0800604 goto ok;
605
Mark Salyzyn42958412013-11-22 10:50:27 -0800606err:
607 logger = NULL;
608ok:
609 return logger;
610}
611
612/* Open the single named log and make it part of a new logger list */
613struct logger_list *android_logger_list_open(log_id_t id,
614 int mode,
615 unsigned int tail,
616 pid_t pid)
617{
618 struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid);
619 if (!logger_list) {
620 return NULL;
621 }
622
623 if (!android_logger_open(logger_list, id)) {
624 android_logger_list_free(logger_list);
625 return NULL;
626 }
627
628 return logger_list;
629}
630
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800631static int android_logger_list_read_pstore(struct logger_list *logger_list,
632 struct log_msg *log_msg)
633{
634 ssize_t ret;
635 off_t current, next;
636 uid_t uid;
637 struct logger *logger;
638 struct __attribute__((__packed__)) {
639 android_pmsg_log_header_t p;
640 android_log_header_t l;
641 } buf;
642 static uint8_t preread_count;
Mark Salyzyn8646a542015-12-07 08:45:12 -0800643 bool is_system;
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800644
645 memset(log_msg, 0, sizeof(*log_msg));
646
647 if (logger_list->sock < 0) {
648 int fd = open("/sys/fs/pstore/pmsg-ramoops-0", O_RDONLY);
649
650 if (fd < 0) {
651 return -errno;
652 }
653 logger_list->sock = fd;
654 preread_count = 0;
655 }
656
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800657 while(1) {
658 if (preread_count < sizeof(buf)) {
659 ret = TEMP_FAILURE_RETRY(read(logger_list->sock,
660 &buf.p.magic + preread_count,
661 sizeof(buf) - preread_count));
662 if (ret < 0) {
663 return -errno;
664 }
665 preread_count += ret;
666 }
667 if (preread_count != sizeof(buf)) {
668 return preread_count ? -EIO : -EAGAIN;
669 }
670 if ((buf.p.magic != LOGGER_MAGIC)
671 || (buf.p.len <= sizeof(buf))
672 || (buf.p.len > (sizeof(buf) + LOGGER_ENTRY_MAX_PAYLOAD))
673 || (buf.l.id >= LOG_ID_MAX)
674 || (buf.l.realtime.tv_nsec >= NS_PER_SEC)) {
675 do {
676 memmove(&buf.p.magic, &buf.p.magic + 1, --preread_count);
677 } while (preread_count && (buf.p.magic != LOGGER_MAGIC));
678 continue;
679 }
680 preread_count = 0;
681
682 logger_for_each(logger, logger_list) {
683 if (buf.l.id != logger->id) {
684 continue;
685 }
686
687 if ((logger_list->start.tv_sec || logger_list->start.tv_nsec)
688 && ((logger_list->start.tv_sec > buf.l.realtime.tv_sec)
689 || ((logger_list->start.tv_sec == buf.l.realtime.tv_sec)
690 && (logger_list->start.tv_nsec > buf.l.realtime.tv_nsec)))) {
691 break;
692 }
693
694 if (logger_list->pid && (logger_list->pid != buf.p.pid)) {
695 break;
696 }
697
698 uid = get_best_effective_uid();
Mark Salyzyn8646a542015-12-07 08:45:12 -0800699 is_system = uid_has_log_permission(uid);
700 if (!is_system && (uid != buf.p.uid)) {
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800701 break;
702 }
703
704 ret = TEMP_FAILURE_RETRY(read(logger_list->sock,
Mark Salyzyn8646a542015-12-07 08:45:12 -0800705 is_system ?
706 log_msg->entry_v4.msg :
707 log_msg->entry_v3.msg,
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800708 buf.p.len - sizeof(buf)));
709 if (ret < 0) {
710 return -errno;
711 }
712 if (ret != (ssize_t)(buf.p.len - sizeof(buf))) {
713 return -EIO;
714 }
715
Mark Salyzyn8646a542015-12-07 08:45:12 -0800716 log_msg->entry_v4.len = buf.p.len - sizeof(buf);
717 log_msg->entry_v4.hdr_size = is_system ?
718 sizeof(log_msg->entry_v4) :
719 sizeof(log_msg->entry_v3);
720 log_msg->entry_v4.pid = buf.p.pid;
721 log_msg->entry_v4.tid = buf.l.tid;
722 log_msg->entry_v4.sec = buf.l.realtime.tv_sec;
723 log_msg->entry_v4.nsec = buf.l.realtime.tv_nsec;
724 log_msg->entry_v4.lid = buf.l.id;
725 if (is_system) {
726 log_msg->entry_v4.uid = buf.p.uid;
727 }
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800728
729 return ret;
730 }
731
732 current = TEMP_FAILURE_RETRY(lseek(logger_list->sock,
733 (off_t)0, SEEK_CUR));
734 if (current < 0) {
735 return -errno;
736 }
737 next = TEMP_FAILURE_RETRY(lseek(logger_list->sock,
738 (off_t)(buf.p.len - sizeof(buf)),
739 SEEK_CUR));
740 if (next < 0) {
741 return -errno;
742 }
743 if ((next - current) != (ssize_t)(buf.p.len - sizeof(buf))) {
744 return -EIO;
745 }
746 }
747}
748
Mark Salyzyna04464a2014-04-30 08:50:53 -0700749static void caught_signal(int signum __unused)
Mark Salyzyn42958412013-11-22 10:50:27 -0800750{
Mark Salyzyn42958412013-11-22 10:50:27 -0800751}
752
753/* Read from the selected logs */
754int android_logger_list_read(struct logger_list *logger_list,
755 struct log_msg *log_msg)
756{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800757 int ret, e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800758 struct logger *logger;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800759 struct sigaction ignore;
760 struct sigaction old_sigaction;
761 unsigned int old_alarm = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800762
763 if (!logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800764 return -EINVAL;
Mark Salyzyn42958412013-11-22 10:50:27 -0800765 }
766
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800767 if (logger_list->mode & ANDROID_LOG_PSTORE) {
768 return android_logger_list_read_pstore(logger_list, log_msg);
769 }
770
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800771 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800772 memset(&ignore, 0, sizeof(ignore));
773 ignore.sa_handler = caught_signal;
774 sigemptyset(&ignore.sa_mask);
Mark Salyzyn42958412013-11-22 10:50:27 -0800775 }
776
Mark Salyzyn154f4602014-02-20 14:59:07 -0800777 if (logger_list->sock < 0) {
778 char buffer[256], *cp, c;
Mark Salyzyn42958412013-11-22 10:50:27 -0800779
Mark Salyzyn154f4602014-02-20 14:59:07 -0800780 int sock = socket_local_client("logdr",
781 ANDROID_SOCKET_NAMESPACE_RESERVED,
782 SOCK_SEQPACKET);
783 if (sock < 0) {
784 if ((sock == -1) && errno) {
785 return -errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800786 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800787 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800788 }
789
Mark Salyzyn154f4602014-02-20 14:59:07 -0800790 strcpy(buffer,
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800791 (logger_list->mode & ANDROID_LOG_NONBLOCK) ? "dumpAndClose" : "stream");
Mark Salyzyn154f4602014-02-20 14:59:07 -0800792 cp = buffer + strlen(buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800793
Mark Salyzyn154f4602014-02-20 14:59:07 -0800794 strcpy(cp, " lids");
795 cp += 5;
796 c = '=';
797 int remaining = sizeof(buffer) - (cp - buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800798 logger_for_each(logger, logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800799 ret = snprintf(cp, remaining, "%c%u", c, logger->id);
800 ret = min(ret, remaining);
801 remaining -= ret;
802 cp += ret;
803 c = ',';
804 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800805
Mark Salyzyn154f4602014-02-20 14:59:07 -0800806 if (logger_list->tail) {
807 ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
808 ret = min(ret, remaining);
809 remaining -= ret;
810 cp += ret;
811 }
812
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800813 if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
Mark Salyzynf8e546e2015-11-30 11:36:09 -0800814 if (logger_list->mode & ANDROID_LOG_WRAP) {
815 // ToDo: alternate API to allow timeout to be adjusted.
816 ret = snprintf(cp, remaining, " timeout=%u",
817 ANDROID_LOG_WRAP_DEFAULT_TIMEOUT);
818 ret = min(ret, remaining);
819 remaining -= ret;
820 cp += ret;
821 }
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800822 ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
823 logger_list->start.tv_sec,
824 logger_list->start.tv_nsec);
825 ret = min(ret, remaining);
826 remaining -= ret;
827 cp += ret;
828 }
829
Mark Salyzyn154f4602014-02-20 14:59:07 -0800830 if (logger_list->pid) {
831 ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
832 ret = min(ret, remaining);
Mark Salyzyn154f4602014-02-20 14:59:07 -0800833 cp += ret;
834 }
835
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800836 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800837 /* Deal with an unresponsive logd */
838 sigaction(SIGALRM, &ignore, &old_sigaction);
839 old_alarm = alarm(30);
840 }
841 ret = write(sock, buffer, cp - buffer);
842 e = errno;
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800843 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800844 if (e == EINTR) {
845 e = ETIMEDOUT;
Mark Salyzyn42958412013-11-22 10:50:27 -0800846 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800847 alarm(old_alarm);
848 sigaction(SIGALRM, &old_sigaction, NULL);
Mark Salyzyn42958412013-11-22 10:50:27 -0800849 }
850
851 if (ret <= 0) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800852 close(sock);
853 if ((ret == -1) && e) {
854 return -e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800855 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800856 if (ret == 0) {
857 return -EIO;
858 }
859 return ret;
Mark Salyzyn42958412013-11-22 10:50:27 -0800860 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800861
862 logger_list->sock = sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800863 }
864
Mark Salyzyn154f4602014-02-20 14:59:07 -0800865 while(1) {
866 memset(log_msg, 0, sizeof(*log_msg));
867
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800868 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800869 /* particularily useful if tombstone is reporting for logd */
870 sigaction(SIGALRM, &ignore, &old_sigaction);
871 old_alarm = alarm(30);
872 }
873 /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
874 ret = recv(logger_list->sock, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
875 e = errno;
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800876 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800877 if ((ret == 0) || (e == EINTR)) {
878 e = EAGAIN;
879 ret = -1;
880 }
881 alarm(old_alarm);
882 sigaction(SIGALRM, &old_sigaction, NULL);
883 }
884
Mark Salyzyn43e92812015-02-26 11:21:47 -0800885 if ((ret == -1) && e) {
886 return -e;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800887 }
Mark Salyzyn43e92812015-02-26 11:21:47 -0800888 return ret;
Mark Salyzyn42958412013-11-22 10:50:27 -0800889 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800890 /* NOTREACH */
Mark Salyzyn42958412013-11-22 10:50:27 -0800891 return ret;
892}
893
894/* Close all the logs */
895void android_logger_list_free(struct logger_list *logger_list)
896{
897 if (logger_list == NULL) {
898 return;
899 }
900
901 while (!list_empty(&logger_list->node)) {
902 struct listnode *node = list_head(&logger_list->node);
903 struct logger *logger = node_to_item(node, struct logger, node);
904 android_logger_free(logger);
905 }
906
Mark Salyzyn154f4602014-02-20 14:59:07 -0800907 if (logger_list->sock >= 0) {
908 close (logger_list->sock);
909 }
910
Mark Salyzyn42958412013-11-22 10:50:27 -0800911 free(logger_list);
912}