blob: 5364e4f17967ca6643be2e91e75386400386b305 [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 Salyzyn42958412013-11-22 10:50:27 -0800211};
212
Mark Salyzyn154f4602014-02-20 14:59:07 -0800213const char *android_log_id_to_name(log_id_t log_id)
214{
Mark Salyzyn42958412013-11-22 10:50:27 -0800215 if (log_id >= LOG_ID_MAX) {
216 log_id = LOG_ID_MAIN;
217 }
218 return LOG_NAME[log_id];
219}
220
Mark Salyzyn154f4602014-02-20 14:59:07 -0800221log_id_t android_name_to_log_id(const char *logName)
Mark Salyzyn42958412013-11-22 10:50:27 -0800222{
Mark Salyzyn42958412013-11-22 10:50:27 -0800223 const char *b;
Mark Salyzyn42958412013-11-22 10:50:27 -0800224 int ret;
225
226 if (!logName) {
227 return -1; /* NB: log_id_t is unsigned */
228 }
229 b = strrchr(logName, '/');
230 if (!b) {
231 b = logName;
232 } else {
233 ++b;
234 }
235
Mark Salyzyn42958412013-11-22 10:50:27 -0800236 for(ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) {
237 const char *l = LOG_NAME[ret];
238 if (l && !strcmp(b, l)) {
239 return ret;
240 }
241 }
242 return -1; /* should never happen */
243}
244
245struct logger_list {
246 struct listnode node;
247 int mode;
248 unsigned int tail;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800249 log_time start;
Mark Salyzyn42958412013-11-22 10:50:27 -0800250 pid_t pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800251 int sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800252};
253
254struct logger {
255 struct listnode node;
256 struct logger_list *top;
Mark Salyzyn42958412013-11-22 10:50:27 -0800257 log_id_t id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800258};
259
260/* android_logger_alloc unimplemented, no use case */
261/* android_logger_free not exported */
262static void android_logger_free(struct logger *logger)
263{
264 if (!logger) {
265 return;
266 }
267
Mark Salyzyn42958412013-11-22 10:50:27 -0800268 list_remove(&logger->node);
269
270 free(logger);
271}
272
Mark Salyzyn154f4602014-02-20 14:59:07 -0800273/* android_logger_alloc unimplemented, no use case */
274
275/* method for getting the associated sublog id */
Mark Salyzyn42958412013-11-22 10:50:27 -0800276log_id_t android_logger_get_id(struct logger *logger)
277{
278 return logger->id;
279}
280
281/* worker for sending the command to the logger */
Mark Salyzyn154f4602014-02-20 14:59:07 -0800282static ssize_t send_log_msg(struct logger *logger,
283 const char *msg, char *buf, size_t buf_size)
Mark Salyzyn42958412013-11-22 10:50:27 -0800284{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800285 ssize_t ret;
Mark Salyzyn696817d2014-04-18 14:49:28 -0700286 size_t len;
287 char *cp;
Greg Hackmann8084a532014-03-17 13:08:31 -0700288 int errno_save = 0;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800289 int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
290 SOCK_STREAM);
291 if (sock < 0) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700292 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800293 }
294
Mark Salyzyn154f4602014-02-20 14:59:07 -0800295 if (msg) {
296 snprintf(buf, buf_size, msg, logger ? logger->id : (unsigned) -1);
Mark Salyzyn42958412013-11-22 10:50:27 -0800297 }
298
Mark Salyzyn696817d2014-04-18 14:49:28 -0700299 len = strlen(buf) + 1;
300 ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
Mark Salyzyn154f4602014-02-20 14:59:07 -0800301 if (ret <= 0) {
302 goto done;
Mark Salyzyn42958412013-11-22 10:50:27 -0800303 }
304
Mark Salyzyn696817d2014-04-18 14:49:28 -0700305 len = buf_size;
306 cp = buf;
307 while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) {
308 struct pollfd p;
309
310 if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) {
311 break;
312 }
313
314 len -= ret;
315 cp += ret;
316
317 memset(&p, 0, sizeof(p));
318 p.fd = sock;
319 p.events = POLLIN;
320
321 /* Give other side 20ms to refill pipe */
322 ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20));
323
324 if (ret <= 0) {
325 break;
326 }
327
328 if (!(p.revents & POLLIN)) {
329 ret = 0;
330 break;
331 }
332 }
333
334 if (ret >= 0) {
335 ret += buf_size - len;
336 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800337
338done:
339 if ((ret == -1) && errno) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700340 errno_save = errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800341 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800342 close(sock);
Greg Hackmann8084a532014-03-17 13:08:31 -0700343 if (errno_save) {
344 errno = errno_save;
345 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800346 return ret;
347}
348
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800349static int check_log_success(char *buf, ssize_t ret)
Mark Salyzyn42958412013-11-22 10:50:27 -0800350{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800351 if (ret < 0) {
352 return ret;
353 }
354
355 if (strncmp(buf, "success", 7)) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700356 errno = EINVAL;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800357 return -1;
358 }
359
360 return 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800361}
362
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800363/* Determine the credentials of the caller */
364static bool uid_has_log_permission(uid_t uid)
365{
366 return (uid == AID_SYSTEM) || (uid == AID_LOG) || (uid == AID_ROOT);
367}
368
369static uid_t get_best_effective_uid()
370{
371 uid_t euid;
372 uid_t uid;
373 gid_t gid;
374 ssize_t i;
375 static uid_t last_uid = (uid_t) -1;
376
377 if (last_uid != (uid_t) -1) {
378 return last_uid;
379 }
380 uid = getuid();
381 if (uid_has_log_permission(uid)) {
382 return last_uid = uid;
383 }
384 euid = geteuid();
385 if (uid_has_log_permission(euid)) {
386 return last_uid = euid;
387 }
388 gid = getgid();
389 if (uid_has_log_permission(gid)) {
390 return last_uid = gid;
391 }
392 gid = getegid();
393 if (uid_has_log_permission(gid)) {
394 return last_uid = gid;
395 }
396 i = getgroups((size_t) 0, NULL);
397 if (i > 0) {
398 gid_t list[i];
399
400 getgroups(i, list);
401 while (--i >= 0) {
402 if (uid_has_log_permission(list[i])) {
403 return last_uid = list[i];
404 }
405 }
406 }
407 return last_uid = uid;
408}
409
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800410int android_logger_clear(struct logger *logger)
411{
412 char buf[512];
413
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800414 if (logger->top->mode & ANDROID_LOG_PSTORE) {
415 if (uid_has_log_permission(get_best_effective_uid())) {
416 return unlink("/sys/fs/pstore/pmsg-ramoops-0");
417 }
418 errno = EPERM;
419 return -1;
420 }
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800421 return check_log_success(buf,
422 send_log_msg(logger, "clear %d", buf, sizeof(buf)));
423}
424
Mark Salyzyn42958412013-11-22 10:50:27 -0800425/* returns the total size of the log's ring buffer */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800426long android_logger_get_log_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800427{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800428 char buf[512];
429
430 ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
431 if (ret < 0) {
432 return ret;
433 }
434
435 if ((buf[0] < '0') || ('9' < buf[0])) {
436 return -1;
437 }
438
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800439 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800440}
441
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800442int android_logger_set_log_size(struct logger *logger, unsigned long size)
443{
444 char buf[512];
445
446 snprintf(buf, sizeof(buf), "setLogSize %d %lu",
447 logger ? logger->id : (unsigned) -1, size);
448
449 return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
450}
451
Mark Salyzyn42958412013-11-22 10:50:27 -0800452/*
453 * returns the readable size of the log's ring buffer (that is, amount of the
454 * log consumed)
455 */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800456long android_logger_get_log_readable_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800457{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800458 char buf[512];
459
460 ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
461 if (ret < 0) {
462 return ret;
463 }
464
465 if ((buf[0] < '0') || ('9' < buf[0])) {
466 return -1;
467 }
468
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800469 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800470}
471
472/*
473 * returns the logger version
474 */
Mark Salyzyna04464a2014-04-30 08:50:53 -0700475int android_logger_get_log_version(struct logger *logger __unused)
Mark Salyzyn42958412013-11-22 10:50:27 -0800476{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800477 return 3;
Mark Salyzyn42958412013-11-22 10:50:27 -0800478}
479
Mark Salyzyn34facab2014-02-06 14:48:50 -0800480/*
481 * returns statistics
482 */
483ssize_t android_logger_get_statistics(struct logger_list *logger_list,
484 char *buf, size_t len)
485{
Mark Salyzyn34facab2014-02-06 14:48:50 -0800486 struct logger *logger;
487 char *cp = buf;
488 size_t remaining = len;
489 size_t n;
490
491 n = snprintf(cp, remaining, "getStatistics");
492 n = min(n, remaining);
493 remaining -= n;
494 cp += n;
495
496 logger_for_each(logger, logger_list) {
497 n = snprintf(cp, remaining, " %d", logger->id);
498 n = min(n, remaining);
499 remaining -= n;
500 cp += n;
501 }
502 return send_log_msg(NULL, NULL, buf, len);
503}
504
Mark Salyzyna04464a2014-04-30 08:50:53 -0700505ssize_t android_logger_get_prune_list(struct logger_list *logger_list __unused,
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800506 char *buf, size_t len)
507{
508 return send_log_msg(NULL, "getPruneList", buf, len);
509}
510
Mark Salyzyna04464a2014-04-30 08:50:53 -0700511int android_logger_set_prune_list(struct logger_list *logger_list __unused,
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800512 char *buf, size_t len)
513{
514 const char cmd[] = "setPruneList ";
515 const size_t cmdlen = sizeof(cmd) - 1;
516
517 if (strlen(buf) > (len - cmdlen)) {
518 return -ENOMEM; /* KISS */
519 }
520 memmove(buf + cmdlen, buf, len - cmdlen);
521 buf[len - 1] = '\0';
522 memcpy(buf, cmd, cmdlen);
523
524 return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
525}
526
Mark Salyzyn42958412013-11-22 10:50:27 -0800527struct logger_list *android_logger_list_alloc(int mode,
528 unsigned int tail,
529 pid_t pid)
530{
531 struct logger_list *logger_list;
532
533 logger_list = calloc(1, sizeof(*logger_list));
534 if (!logger_list) {
535 return NULL;
536 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800537
Mark Salyzyn42958412013-11-22 10:50:27 -0800538 list_init(&logger_list->node);
539 logger_list->mode = mode;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800540 logger_list->start.tv_sec = 0;
541 logger_list->start.tv_nsec = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800542 logger_list->tail = tail;
543 logger_list->pid = pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800544 logger_list->sock = -1;
545
Mark Salyzyn42958412013-11-22 10:50:27 -0800546 return logger_list;
547}
548
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800549struct logger_list *android_logger_list_alloc_time(int mode,
550 log_time start,
551 pid_t pid)
552{
553 struct logger_list *logger_list;
554
555 logger_list = calloc(1, sizeof(*logger_list));
556 if (!logger_list) {
557 return NULL;
558 }
559
560 list_init(&logger_list->node);
561 logger_list->mode = mode;
562 logger_list->start = start;
563 logger_list->tail = 0;
564 logger_list->pid = pid;
565 logger_list->sock = -1;
566
567 return logger_list;
568}
569
Mark Salyzyn42958412013-11-22 10:50:27 -0800570/* android_logger_list_register unimplemented, no use case */
571/* android_logger_list_unregister unimplemented, no use case */
572
573/* Open the named log and add it to the logger list */
574struct logger *android_logger_open(struct logger_list *logger_list,
575 log_id_t id)
576{
Mark Salyzyn42958412013-11-22 10:50:27 -0800577 struct logger *logger;
Mark Salyzyn42958412013-11-22 10:50:27 -0800578
579 if (!logger_list || (id >= LOG_ID_MAX)) {
580 goto err;
581 }
582
583 logger_for_each(logger, logger_list) {
584 if (logger->id == id) {
585 goto ok;
586 }
587 }
588
589 logger = calloc(1, sizeof(*logger));
590 if (!logger) {
591 goto err;
592 }
593
Mark Salyzyn42958412013-11-22 10:50:27 -0800594 logger->id = id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800595 list_add_tail(&logger_list->node, &logger->node);
596 logger->top = logger_list;
Mark Salyzyn42958412013-11-22 10:50:27 -0800597 goto ok;
598
Mark Salyzyn42958412013-11-22 10:50:27 -0800599err:
600 logger = NULL;
601ok:
602 return logger;
603}
604
605/* Open the single named log and make it part of a new logger list */
606struct logger_list *android_logger_list_open(log_id_t id,
607 int mode,
608 unsigned int tail,
609 pid_t pid)
610{
611 struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid);
612 if (!logger_list) {
613 return NULL;
614 }
615
616 if (!android_logger_open(logger_list, id)) {
617 android_logger_list_free(logger_list);
618 return NULL;
619 }
620
621 return logger_list;
622}
623
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800624static int android_logger_list_read_pstore(struct logger_list *logger_list,
625 struct log_msg *log_msg)
626{
627 ssize_t ret;
628 off_t current, next;
629 uid_t uid;
630 struct logger *logger;
631 struct __attribute__((__packed__)) {
632 android_pmsg_log_header_t p;
633 android_log_header_t l;
634 } buf;
635 static uint8_t preread_count;
636
637 memset(log_msg, 0, sizeof(*log_msg));
638
639 if (logger_list->sock < 0) {
640 int fd = open("/sys/fs/pstore/pmsg-ramoops-0", O_RDONLY);
641
642 if (fd < 0) {
643 return -errno;
644 }
645 logger_list->sock = fd;
646 preread_count = 0;
647 }
648
649 ret = 0;
650 while(1) {
651 if (preread_count < sizeof(buf)) {
652 ret = TEMP_FAILURE_RETRY(read(logger_list->sock,
653 &buf.p.magic + preread_count,
654 sizeof(buf) - preread_count));
655 if (ret < 0) {
656 return -errno;
657 }
658 preread_count += ret;
659 }
660 if (preread_count != sizeof(buf)) {
661 return preread_count ? -EIO : -EAGAIN;
662 }
663 if ((buf.p.magic != LOGGER_MAGIC)
664 || (buf.p.len <= sizeof(buf))
665 || (buf.p.len > (sizeof(buf) + LOGGER_ENTRY_MAX_PAYLOAD))
666 || (buf.l.id >= LOG_ID_MAX)
667 || (buf.l.realtime.tv_nsec >= NS_PER_SEC)) {
668 do {
669 memmove(&buf.p.magic, &buf.p.magic + 1, --preread_count);
670 } while (preread_count && (buf.p.magic != LOGGER_MAGIC));
671 continue;
672 }
673 preread_count = 0;
674
675 logger_for_each(logger, logger_list) {
676 if (buf.l.id != logger->id) {
677 continue;
678 }
679
680 if ((logger_list->start.tv_sec || logger_list->start.tv_nsec)
681 && ((logger_list->start.tv_sec > buf.l.realtime.tv_sec)
682 || ((logger_list->start.tv_sec == buf.l.realtime.tv_sec)
683 && (logger_list->start.tv_nsec > buf.l.realtime.tv_nsec)))) {
684 break;
685 }
686
687 if (logger_list->pid && (logger_list->pid != buf.p.pid)) {
688 break;
689 }
690
691 uid = get_best_effective_uid();
692 if (!uid_has_log_permission(uid) && (uid != buf.p.uid)) {
693 break;
694 }
695
696 ret = TEMP_FAILURE_RETRY(read(logger_list->sock,
697 log_msg->entry_v3.msg,
698 buf.p.len - sizeof(buf)));
699 if (ret < 0) {
700 return -errno;
701 }
702 if (ret != (ssize_t)(buf.p.len - sizeof(buf))) {
703 return -EIO;
704 }
705
706 log_msg->entry_v3.len = buf.p.len - sizeof(buf);
707 log_msg->entry_v3.hdr_size = sizeof(log_msg->entry_v3);
708 log_msg->entry_v3.pid = buf.p.pid;
709 log_msg->entry_v3.tid = buf.l.tid;
710 log_msg->entry_v3.sec = buf.l.realtime.tv_sec;
711 log_msg->entry_v3.nsec = buf.l.realtime.tv_nsec;
712 log_msg->entry_v3.lid = buf.l.id;
713
714 return ret;
715 }
716
717 current = TEMP_FAILURE_RETRY(lseek(logger_list->sock,
718 (off_t)0, SEEK_CUR));
719 if (current < 0) {
720 return -errno;
721 }
722 next = TEMP_FAILURE_RETRY(lseek(logger_list->sock,
723 (off_t)(buf.p.len - sizeof(buf)),
724 SEEK_CUR));
725 if (next < 0) {
726 return -errno;
727 }
728 if ((next - current) != (ssize_t)(buf.p.len - sizeof(buf))) {
729 return -EIO;
730 }
731 }
732}
733
Mark Salyzyna04464a2014-04-30 08:50:53 -0700734static void caught_signal(int signum __unused)
Mark Salyzyn42958412013-11-22 10:50:27 -0800735{
Mark Salyzyn42958412013-11-22 10:50:27 -0800736}
737
738/* Read from the selected logs */
739int android_logger_list_read(struct logger_list *logger_list,
740 struct log_msg *log_msg)
741{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800742 int ret, e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800743 struct logger *logger;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800744 struct sigaction ignore;
745 struct sigaction old_sigaction;
746 unsigned int old_alarm = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800747
748 if (!logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800749 return -EINVAL;
Mark Salyzyn42958412013-11-22 10:50:27 -0800750 }
751
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800752 if (logger_list->mode & ANDROID_LOG_PSTORE) {
753 return android_logger_list_read_pstore(logger_list, log_msg);
754 }
755
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800756 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800757 memset(&ignore, 0, sizeof(ignore));
758 ignore.sa_handler = caught_signal;
759 sigemptyset(&ignore.sa_mask);
Mark Salyzyn42958412013-11-22 10:50:27 -0800760 }
761
Mark Salyzyn154f4602014-02-20 14:59:07 -0800762 if (logger_list->sock < 0) {
763 char buffer[256], *cp, c;
Mark Salyzyn42958412013-11-22 10:50:27 -0800764
Mark Salyzyn154f4602014-02-20 14:59:07 -0800765 int sock = socket_local_client("logdr",
766 ANDROID_SOCKET_NAMESPACE_RESERVED,
767 SOCK_SEQPACKET);
768 if (sock < 0) {
769 if ((sock == -1) && errno) {
770 return -errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800771 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800772 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800773 }
774
Mark Salyzyn154f4602014-02-20 14:59:07 -0800775 strcpy(buffer,
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800776 (logger_list->mode & ANDROID_LOG_NONBLOCK) ? "dumpAndClose" : "stream");
Mark Salyzyn154f4602014-02-20 14:59:07 -0800777 cp = buffer + strlen(buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800778
Mark Salyzyn154f4602014-02-20 14:59:07 -0800779 strcpy(cp, " lids");
780 cp += 5;
781 c = '=';
782 int remaining = sizeof(buffer) - (cp - buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800783 logger_for_each(logger, logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800784 ret = snprintf(cp, remaining, "%c%u", c, logger->id);
785 ret = min(ret, remaining);
786 remaining -= ret;
787 cp += ret;
788 c = ',';
789 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800790
Mark Salyzyn154f4602014-02-20 14:59:07 -0800791 if (logger_list->tail) {
792 ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
793 ret = min(ret, remaining);
794 remaining -= ret;
795 cp += ret;
796 }
797
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800798 if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
799 ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
800 logger_list->start.tv_sec,
801 logger_list->start.tv_nsec);
802 ret = min(ret, remaining);
803 remaining -= ret;
804 cp += ret;
805 }
806
Mark Salyzyn154f4602014-02-20 14:59:07 -0800807 if (logger_list->pid) {
808 ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
809 ret = min(ret, remaining);
810 remaining -= ret;
811 cp += ret;
812 }
813
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800814 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800815 /* Deal with an unresponsive logd */
816 sigaction(SIGALRM, &ignore, &old_sigaction);
817 old_alarm = alarm(30);
818 }
819 ret = write(sock, buffer, cp - buffer);
820 e = errno;
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800821 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800822 if (e == EINTR) {
823 e = ETIMEDOUT;
Mark Salyzyn42958412013-11-22 10:50:27 -0800824 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800825 alarm(old_alarm);
826 sigaction(SIGALRM, &old_sigaction, NULL);
Mark Salyzyn42958412013-11-22 10:50:27 -0800827 }
828
829 if (ret <= 0) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800830 close(sock);
831 if ((ret == -1) && e) {
832 return -e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800833 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800834 if (ret == 0) {
835 return -EIO;
836 }
837 return ret;
Mark Salyzyn42958412013-11-22 10:50:27 -0800838 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800839
840 logger_list->sock = sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800841 }
842
Mark Salyzyn154f4602014-02-20 14:59:07 -0800843 ret = 0;
844 while(1) {
845 memset(log_msg, 0, sizeof(*log_msg));
846
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800847 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800848 /* particularily useful if tombstone is reporting for logd */
849 sigaction(SIGALRM, &ignore, &old_sigaction);
850 old_alarm = alarm(30);
851 }
852 /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
853 ret = recv(logger_list->sock, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
854 e = errno;
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800855 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800856 if ((ret == 0) || (e == EINTR)) {
857 e = EAGAIN;
858 ret = -1;
859 }
860 alarm(old_alarm);
861 sigaction(SIGALRM, &old_sigaction, NULL);
862 }
863
864 if (ret <= 0) {
865 if ((ret == -1) && e) {
866 return -e;
867 }
868 return ret;
869 }
870
871 logger_for_each(logger, logger_list) {
872 if (log_msg->entry.lid == logger->id) {
873 return ret;
874 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800875 }
876 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800877 /* NOTREACH */
Mark Salyzyn42958412013-11-22 10:50:27 -0800878 return ret;
879}
880
881/* Close all the logs */
882void android_logger_list_free(struct logger_list *logger_list)
883{
884 if (logger_list == NULL) {
885 return;
886 }
887
888 while (!list_empty(&logger_list->node)) {
889 struct listnode *node = list_head(&logger_list->node);
890 struct logger *logger = node_to_item(node, struct logger, node);
891 android_logger_free(logger);
892 }
893
Mark Salyzyn154f4602014-02-20 14:59:07 -0800894 if (logger_list->sock >= 0) {
895 close (logger_list->sock);
896 }
897
Mark Salyzyn42958412013-11-22 10:50:27 -0800898 free(logger_list);
899}