blob: 4b839443d761771d14e8770f7d750015784682cf [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>
27#include <unistd.h>
28
Mark Salyzyn42958412013-11-22 10:50:27 -080029#include <cutils/list.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080030#include <cutils/sockets.h>
Mark Salyzyn42958412013-11-22 10:50:27 -080031#include <log/log.h>
32#include <log/logger.h>
Mark Salyzyn6eef4172014-12-15 09:51:39 -080033#include <private/android_filesystem_config.h>
34#include <private/android_logger.h>
Mark Salyzyn42958412013-11-22 10:50:27 -080035
Mark Salyzynbe1d3c22016-03-10 08:25:33 -080036#include "log_cdefs.h"
37
Mark Salyzyn154f4602014-02-20 14:59:07 -080038/* branchless on many architectures. */
39#define min(x,y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
Mark Salyzyn1345f382014-01-14 08:41:27 -080040
Mark Salyzyn154f4602014-02-20 14:59:07 -080041/* Private copy of ../libcutils/socket_local_client.c prevent library loops */
Mark Salyzyn1345f382014-01-14 08:41:27 -080042
Elliott Hughesadbf4422015-07-29 17:45:24 -070043#if defined(_WIN32)
Mark Salyzyn42958412013-11-22 10:50:27 -080044
Mark Salyzynbe1d3c22016-03-10 08:25:33 -080045LIBLOG_WEAK int socket_local_client(const char *name, int namespaceId, int type)
Mark Salyzyn154f4602014-02-20 14:59:07 -080046{
47 errno = ENOSYS;
48 return -ENOSYS;
49}
Mark Salyzyn42958412013-11-22 10:50:27 -080050
Elliott Hughesadbf4422015-07-29 17:45:24 -070051#else /* !_WIN32 */
Mark Salyzyn154f4602014-02-20 14:59:07 -080052
53#include <sys/socket.h>
54#include <sys/un.h>
55#include <sys/select.h>
56#include <sys/types.h>
57
58/* Private copy of ../libcutils/socket_local.h prevent library loops */
59#define FILESYSTEM_SOCKET_PREFIX "/tmp/"
60#define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
61/* End of ../libcutils/socket_local.h */
62
63#define LISTEN_BACKLOG 4
64
65/* Documented in header file. */
Mark Salyzynbe1d3c22016-03-10 08:25:33 -080066LIBLOG_WEAK int socket_make_sockaddr_un(const char *name, int namespaceId,
67 struct sockaddr_un *p_addr,
68 socklen_t *alen)
Mark Salyzyn154f4602014-02-20 14:59:07 -080069{
70 memset (p_addr, 0, sizeof (*p_addr));
71 size_t namelen;
72
73 switch (namespaceId) {
74 case ANDROID_SOCKET_NAMESPACE_ABSTRACT:
Elliott Hughes9768d242014-11-21 22:50:20 -080075#if defined(__linux__)
Mark Salyzyn154f4602014-02-20 14:59:07 -080076 namelen = strlen(name);
77
78 /* Test with length +1 for the *initial* '\0'. */
79 if ((namelen + 1) > sizeof(p_addr->sun_path)) {
80 goto error;
81 }
82
83 /*
84 * Note: The path in this case is *not* supposed to be
85 * '\0'-terminated. ("man 7 unix" for the gory details.)
86 */
87
88 p_addr->sun_path[0] = 0;
89 memcpy(p_addr->sun_path + 1, name, namelen);
Elliott Hughes9768d242014-11-21 22:50:20 -080090#else
Mark Salyzyn154f4602014-02-20 14:59:07 -080091 /* this OS doesn't have the Linux abstract namespace */
92
93 namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
94 /* unix_path_max appears to be missing on linux */
95 if (namelen > sizeof(*p_addr)
96 - offsetof(struct sockaddr_un, sun_path) - 1) {
97 goto error;
98 }
99
100 strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
101 strcat(p_addr->sun_path, name);
Elliott Hughes9768d242014-11-21 22:50:20 -0800102#endif
Mark Salyzyn154f4602014-02-20 14:59:07 -0800103 break;
104
105 case ANDROID_SOCKET_NAMESPACE_RESERVED:
106 namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
107 /* unix_path_max appears to be missing on linux */
108 if (namelen > sizeof(*p_addr)
109 - offsetof(struct sockaddr_un, sun_path) - 1) {
110 goto error;
111 }
112
113 strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);
114 strcat(p_addr->sun_path, name);
115 break;
116
117 case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
118 namelen = strlen(name);
119 /* unix_path_max appears to be missing on linux */
120 if (namelen > sizeof(*p_addr)
121 - offsetof(struct sockaddr_un, sun_path) - 1) {
122 goto error;
123 }
124
125 strcpy(p_addr->sun_path, name);
126 break;
127
128 default:
129 /* invalid namespace id */
130 return -1;
131 }
132
133 p_addr->sun_family = AF_LOCAL;
134 *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
135 return 0;
136error:
137 return -1;
138}
139
140/**
141 * connect to peer named "name" on fd
142 * returns same fd or -1 on error.
143 * fd is not closed on error. that's your job.
144 *
145 * Used by AndroidSocketImpl
146 */
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800147LIBLOG_WEAK int socket_local_client_connect(int fd, const char *name,
148 int namespaceId, int type __unused)
Mark Salyzyn154f4602014-02-20 14:59:07 -0800149{
150 struct sockaddr_un addr;
151 socklen_t alen;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800152 int err;
153
154 err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
155
156 if (err < 0) {
157 goto error;
158 }
159
160 if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {
161 goto error;
162 }
163
164 return fd;
165
166error:
167 return -1;
168}
169
170/**
171 * connect to peer named "name"
172 * returns fd or -1 on error
173 */
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800174LIBLOG_WEAK int socket_local_client(const char *name, int namespaceId, int type)
Mark Salyzyn154f4602014-02-20 14:59:07 -0800175{
176 int s;
177
178 s = socket(AF_LOCAL, type, 0);
179 if(s < 0) return -1;
180
181 if ( 0 > socket_local_client_connect(s, name, namespaceId, type)) {
182 close(s);
183 return -1;
184 }
185
186 return s;
187}
188
Elliott Hughesadbf4422015-07-29 17:45:24 -0700189#endif /* !_WIN32 */
Mark Salyzyn154f4602014-02-20 14:59:07 -0800190/* End of ../libcutils/socket_local_client.c */
Mark Salyzyn42958412013-11-22 10:50:27 -0800191
192#define logger_for_each(logger, logger_list) \
193 for (logger = node_to_item((logger_list)->node.next, struct logger, node); \
194 logger != node_to_item(&(logger_list)->node, struct logger, node); \
195 logger = node_to_item((logger)->node.next, struct logger, node))
196
197/* In the future, we would like to make this list extensible */
198static const char *LOG_NAME[LOG_ID_MAX] = {
199 [LOG_ID_MAIN] = "main",
200 [LOG_ID_RADIO] = "radio",
201 [LOG_ID_EVENTS] = "events",
Mark Salyzyn99f47a92014-04-07 14:58:08 -0700202 [LOG_ID_SYSTEM] = "system",
203 [LOG_ID_CRASH] = "crash",
Mark Salyzyn083b0372015-12-04 10:59:45 -0800204 [LOG_ID_SECURITY] = "security",
Mark Salyzyn440e1092014-10-10 15:13:15 -0700205 [LOG_ID_KERNEL] = "kernel",
Mark Salyzyn42958412013-11-22 10:50:27 -0800206};
207
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800208LIBLOG_ABI_PUBLIC const char *android_log_id_to_name(log_id_t log_id)
Mark Salyzyn154f4602014-02-20 14:59:07 -0800209{
Mark Salyzyn42958412013-11-22 10:50:27 -0800210 if (log_id >= LOG_ID_MAX) {
211 log_id = LOG_ID_MAIN;
212 }
213 return LOG_NAME[log_id];
214}
215
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800216LIBLOG_ABI_PUBLIC log_id_t android_name_to_log_id(const char *logName)
Mark Salyzyn42958412013-11-22 10:50:27 -0800217{
Mark Salyzyn42958412013-11-22 10:50:27 -0800218 const char *b;
Mark Salyzyn42958412013-11-22 10:50:27 -0800219 int ret;
220
221 if (!logName) {
222 return -1; /* NB: log_id_t is unsigned */
223 }
224 b = strrchr(logName, '/');
225 if (!b) {
226 b = logName;
227 } else {
228 ++b;
229 }
230
Mark Salyzyn42958412013-11-22 10:50:27 -0800231 for(ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) {
232 const char *l = LOG_NAME[ret];
233 if (l && !strcmp(b, l)) {
234 return ret;
235 }
236 }
237 return -1; /* should never happen */
238}
239
240struct logger_list {
241 struct listnode node;
242 int mode;
243 unsigned int tail;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800244 log_time start;
Mark Salyzyn42958412013-11-22 10:50:27 -0800245 pid_t pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800246 int sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800247};
248
249struct logger {
250 struct listnode node;
251 struct logger_list *top;
Mark Salyzyn42958412013-11-22 10:50:27 -0800252 log_id_t id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800253};
254
255/* android_logger_alloc unimplemented, no use case */
256/* android_logger_free not exported */
257static void android_logger_free(struct logger *logger)
258{
259 if (!logger) {
260 return;
261 }
262
Mark Salyzyn42958412013-11-22 10:50:27 -0800263 list_remove(&logger->node);
264
265 free(logger);
266}
267
Mark Salyzyn154f4602014-02-20 14:59:07 -0800268/* android_logger_alloc unimplemented, no use case */
269
270/* method for getting the associated sublog id */
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800271LIBLOG_ABI_PUBLIC log_id_t android_logger_get_id(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800272{
273 return logger->id;
274}
275
276/* worker for sending the command to the logger */
Mark Salyzyn154f4602014-02-20 14:59:07 -0800277static ssize_t send_log_msg(struct logger *logger,
278 const char *msg, char *buf, size_t buf_size)
Mark Salyzyn42958412013-11-22 10:50:27 -0800279{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800280 ssize_t ret;
Mark Salyzyn696817d2014-04-18 14:49:28 -0700281 size_t len;
282 char *cp;
Greg Hackmann8084a532014-03-17 13:08:31 -0700283 int errno_save = 0;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800284 int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
285 SOCK_STREAM);
286 if (sock < 0) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700287 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800288 }
289
Mark Salyzyn154f4602014-02-20 14:59:07 -0800290 if (msg) {
291 snprintf(buf, buf_size, msg, logger ? logger->id : (unsigned) -1);
Mark Salyzyn42958412013-11-22 10:50:27 -0800292 }
293
Mark Salyzyn696817d2014-04-18 14:49:28 -0700294 len = strlen(buf) + 1;
295 ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
Mark Salyzyn154f4602014-02-20 14:59:07 -0800296 if (ret <= 0) {
297 goto done;
Mark Salyzyn42958412013-11-22 10:50:27 -0800298 }
299
Mark Salyzyn696817d2014-04-18 14:49:28 -0700300 len = buf_size;
301 cp = buf;
302 while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) {
303 struct pollfd p;
304
305 if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) {
306 break;
307 }
308
309 len -= ret;
310 cp += ret;
311
312 memset(&p, 0, sizeof(p));
313 p.fd = sock;
314 p.events = POLLIN;
315
316 /* Give other side 20ms to refill pipe */
317 ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20));
318
319 if (ret <= 0) {
320 break;
321 }
322
323 if (!(p.revents & POLLIN)) {
324 ret = 0;
325 break;
326 }
327 }
328
329 if (ret >= 0) {
330 ret += buf_size - len;
331 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800332
333done:
334 if ((ret == -1) && errno) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700335 errno_save = errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800336 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800337 close(sock);
Greg Hackmann8084a532014-03-17 13:08:31 -0700338 if (errno_save) {
339 errno = errno_save;
340 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800341 return ret;
342}
343
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800344static int check_log_success(char *buf, ssize_t ret)
Mark Salyzyn42958412013-11-22 10:50:27 -0800345{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800346 if (ret < 0) {
347 return ret;
348 }
349
350 if (strncmp(buf, "success", 7)) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700351 errno = EINVAL;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800352 return -1;
353 }
354
355 return 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800356}
357
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800358/* Determine the credentials of the caller */
359static bool uid_has_log_permission(uid_t uid)
360{
361 return (uid == AID_SYSTEM) || (uid == AID_LOG) || (uid == AID_ROOT);
362}
363
364static uid_t get_best_effective_uid()
365{
366 uid_t euid;
367 uid_t uid;
368 gid_t gid;
369 ssize_t i;
370 static uid_t last_uid = (uid_t) -1;
371
372 if (last_uid != (uid_t) -1) {
373 return last_uid;
374 }
375 uid = getuid();
376 if (uid_has_log_permission(uid)) {
377 return last_uid = uid;
378 }
379 euid = geteuid();
380 if (uid_has_log_permission(euid)) {
381 return last_uid = euid;
382 }
383 gid = getgid();
384 if (uid_has_log_permission(gid)) {
385 return last_uid = gid;
386 }
387 gid = getegid();
388 if (uid_has_log_permission(gid)) {
389 return last_uid = gid;
390 }
391 i = getgroups((size_t) 0, NULL);
392 if (i > 0) {
393 gid_t list[i];
394
395 getgroups(i, list);
396 while (--i >= 0) {
397 if (uid_has_log_permission(list[i])) {
398 return last_uid = list[i];
399 }
400 }
401 }
402 return last_uid = uid;
403}
404
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800405LIBLOG_ABI_PUBLIC int android_logger_clear(struct logger *logger)
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800406{
407 char buf[512];
408
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800409 if (logger->top->mode & ANDROID_LOG_PSTORE) {
410 if (uid_has_log_permission(get_best_effective_uid())) {
411 return unlink("/sys/fs/pstore/pmsg-ramoops-0");
412 }
413 errno = EPERM;
414 return -1;
415 }
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800416 return check_log_success(buf,
417 send_log_msg(logger, "clear %d", buf, sizeof(buf)));
418}
419
Mark Salyzyn42958412013-11-22 10:50:27 -0800420/* returns the total size of the log's ring buffer */
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800421LIBLOG_ABI_PUBLIC long android_logger_get_log_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800422{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800423 char buf[512];
424
425 ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
426 if (ret < 0) {
427 return ret;
428 }
429
430 if ((buf[0] < '0') || ('9' < buf[0])) {
431 return -1;
432 }
433
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800434 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800435}
436
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800437LIBLOG_ABI_PUBLIC int android_logger_set_log_size(struct logger *logger,
438 unsigned long size)
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800439{
440 char buf[512];
441
442 snprintf(buf, sizeof(buf), "setLogSize %d %lu",
443 logger ? logger->id : (unsigned) -1, size);
444
445 return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
446}
447
Mark Salyzyn42958412013-11-22 10:50:27 -0800448/*
449 * returns the readable size of the log's ring buffer (that is, amount of the
450 * log consumed)
451 */
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800452LIBLOG_ABI_PUBLIC long android_logger_get_log_readable_size(
453 struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800454{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800455 char buf[512];
456
457 ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
458 if (ret < 0) {
459 return ret;
460 }
461
462 if ((buf[0] < '0') || ('9' < buf[0])) {
463 return -1;
464 }
465
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800466 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800467}
468
469/*
470 * returns the logger version
471 */
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800472LIBLOG_ABI_PUBLIC int android_logger_get_log_version(
473 struct logger *logger __unused)
Mark Salyzyn42958412013-11-22 10:50:27 -0800474{
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800475 return 4;
Mark Salyzyn42958412013-11-22 10:50:27 -0800476}
477
Mark Salyzyn34facab2014-02-06 14:48:50 -0800478/*
479 * returns statistics
480 */
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800481LIBLOG_ABI_PUBLIC ssize_t android_logger_get_statistics(
482 struct logger_list *logger_list,
483 char *buf, size_t len)
Mark Salyzyn34facab2014-02-06 14:48:50 -0800484{
Mark Salyzyn34facab2014-02-06 14:48:50 -0800485 struct logger *logger;
486 char *cp = buf;
487 size_t remaining = len;
488 size_t n;
489
490 n = snprintf(cp, remaining, "getStatistics");
491 n = min(n, remaining);
492 remaining -= n;
493 cp += n;
494
495 logger_for_each(logger, logger_list) {
496 n = snprintf(cp, remaining, " %d", logger->id);
497 n = min(n, remaining);
498 remaining -= n;
499 cp += n;
500 }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800501
502 if (logger_list->pid) {
Mark Salyzynb5258842016-02-19 13:08:59 -0800503 snprintf(cp, remaining, " pid=%u", logger_list->pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800504 }
505
Mark Salyzyn34facab2014-02-06 14:48:50 -0800506 return send_log_msg(NULL, NULL, buf, len);
507}
508
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800509LIBLOG_ABI_PUBLIC ssize_t android_logger_get_prune_list(
510 struct logger_list *logger_list __unused,
511 char *buf, size_t len)
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800512{
513 return send_log_msg(NULL, "getPruneList", buf, len);
514}
515
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800516LIBLOG_ABI_PUBLIC int android_logger_set_prune_list(
517 struct logger_list *logger_list __unused,
518 char *buf, size_t len)
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800519{
520 const char cmd[] = "setPruneList ";
521 const size_t cmdlen = sizeof(cmd) - 1;
522
523 if (strlen(buf) > (len - cmdlen)) {
524 return -ENOMEM; /* KISS */
525 }
526 memmove(buf + cmdlen, buf, len - cmdlen);
527 buf[len - 1] = '\0';
528 memcpy(buf, cmd, cmdlen);
529
530 return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
531}
532
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800533LIBLOG_ABI_PUBLIC struct logger_list *android_logger_list_alloc(
534 int mode,
535 unsigned int tail,
536 pid_t pid)
Mark Salyzyn42958412013-11-22 10:50:27 -0800537{
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 Salyzynbe1d3c22016-03-10 08:25:33 -0800556LIBLOG_ABI_PUBLIC struct logger_list *android_logger_list_alloc_time(
557 int mode,
558 log_time start,
559 pid_t pid)
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800560{
561 struct logger_list *logger_list;
562
563 logger_list = calloc(1, sizeof(*logger_list));
564 if (!logger_list) {
565 return NULL;
566 }
567
568 list_init(&logger_list->node);
569 logger_list->mode = mode;
570 logger_list->start = start;
571 logger_list->tail = 0;
572 logger_list->pid = pid;
573 logger_list->sock = -1;
574
575 return logger_list;
576}
577
Mark Salyzyn42958412013-11-22 10:50:27 -0800578/* android_logger_list_register unimplemented, no use case */
579/* android_logger_list_unregister unimplemented, no use case */
580
581/* Open the named log and add it to the logger list */
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800582LIBLOG_ABI_PUBLIC struct logger *android_logger_open(
583 struct logger_list *logger_list,
584 log_id_t id)
Mark Salyzyn42958412013-11-22 10:50:27 -0800585{
Mark Salyzyn42958412013-11-22 10:50:27 -0800586 struct logger *logger;
Mark Salyzyn42958412013-11-22 10:50:27 -0800587
588 if (!logger_list || (id >= LOG_ID_MAX)) {
589 goto err;
590 }
591
592 logger_for_each(logger, logger_list) {
593 if (logger->id == id) {
594 goto ok;
595 }
596 }
597
598 logger = calloc(1, sizeof(*logger));
599 if (!logger) {
600 goto err;
601 }
602
Mark Salyzyn42958412013-11-22 10:50:27 -0800603 logger->id = id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800604 list_add_tail(&logger_list->node, &logger->node);
605 logger->top = logger_list;
Mark Salyzyn42958412013-11-22 10:50:27 -0800606 goto ok;
607
Mark Salyzyn42958412013-11-22 10:50:27 -0800608err:
609 logger = NULL;
610ok:
611 return logger;
612}
613
614/* Open the single named log and make it part of a new logger list */
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800615LIBLOG_ABI_PUBLIC struct logger_list *android_logger_list_open(
616 log_id_t id,
617 int mode,
618 unsigned int tail,
619 pid_t pid)
Mark Salyzyn42958412013-11-22 10:50:27 -0800620{
621 struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid);
622 if (!logger_list) {
623 return NULL;
624 }
625
626 if (!android_logger_open(logger_list, id)) {
627 android_logger_list_free(logger_list);
628 return NULL;
629 }
630
631 return logger_list;
632}
633
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800634static int android_logger_list_read_pstore(struct logger_list *logger_list,
635 struct log_msg *log_msg)
636{
637 ssize_t ret;
638 off_t current, next;
639 uid_t uid;
640 struct logger *logger;
641 struct __attribute__((__packed__)) {
642 android_pmsg_log_header_t p;
643 android_log_header_t l;
644 } buf;
645 static uint8_t preread_count;
Mark Salyzyn8646a542015-12-07 08:45:12 -0800646 bool is_system;
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800647
648 memset(log_msg, 0, sizeof(*log_msg));
649
650 if (logger_list->sock < 0) {
651 int fd = open("/sys/fs/pstore/pmsg-ramoops-0", O_RDONLY);
652
653 if (fd < 0) {
654 return -errno;
655 }
656 logger_list->sock = fd;
657 preread_count = 0;
658 }
659
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800660 while(1) {
661 if (preread_count < sizeof(buf)) {
662 ret = TEMP_FAILURE_RETRY(read(logger_list->sock,
663 &buf.p.magic + preread_count,
664 sizeof(buf) - preread_count));
665 if (ret < 0) {
666 return -errno;
667 }
668 preread_count += ret;
669 }
670 if (preread_count != sizeof(buf)) {
671 return preread_count ? -EIO : -EAGAIN;
672 }
673 if ((buf.p.magic != LOGGER_MAGIC)
674 || (buf.p.len <= sizeof(buf))
675 || (buf.p.len > (sizeof(buf) + LOGGER_ENTRY_MAX_PAYLOAD))
676 || (buf.l.id >= LOG_ID_MAX)
677 || (buf.l.realtime.tv_nsec >= NS_PER_SEC)) {
678 do {
679 memmove(&buf.p.magic, &buf.p.magic + 1, --preread_count);
680 } while (preread_count && (buf.p.magic != LOGGER_MAGIC));
681 continue;
682 }
683 preread_count = 0;
684
685 logger_for_each(logger, logger_list) {
686 if (buf.l.id != logger->id) {
687 continue;
688 }
689
690 if ((logger_list->start.tv_sec || logger_list->start.tv_nsec)
691 && ((logger_list->start.tv_sec > buf.l.realtime.tv_sec)
692 || ((logger_list->start.tv_sec == buf.l.realtime.tv_sec)
693 && (logger_list->start.tv_nsec > buf.l.realtime.tv_nsec)))) {
694 break;
695 }
696
697 if (logger_list->pid && (logger_list->pid != buf.p.pid)) {
698 break;
699 }
700
701 uid = get_best_effective_uid();
Mark Salyzyn8646a542015-12-07 08:45:12 -0800702 is_system = uid_has_log_permission(uid);
703 if (!is_system && (uid != buf.p.uid)) {
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800704 break;
705 }
706
707 ret = TEMP_FAILURE_RETRY(read(logger_list->sock,
Mark Salyzyn8646a542015-12-07 08:45:12 -0800708 is_system ?
709 log_msg->entry_v4.msg :
710 log_msg->entry_v3.msg,
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800711 buf.p.len - sizeof(buf)));
712 if (ret < 0) {
713 return -errno;
714 }
715 if (ret != (ssize_t)(buf.p.len - sizeof(buf))) {
716 return -EIO;
717 }
718
Mark Salyzyn8646a542015-12-07 08:45:12 -0800719 log_msg->entry_v4.len = buf.p.len - sizeof(buf);
720 log_msg->entry_v4.hdr_size = is_system ?
721 sizeof(log_msg->entry_v4) :
722 sizeof(log_msg->entry_v3);
723 log_msg->entry_v4.pid = buf.p.pid;
724 log_msg->entry_v4.tid = buf.l.tid;
725 log_msg->entry_v4.sec = buf.l.realtime.tv_sec;
726 log_msg->entry_v4.nsec = buf.l.realtime.tv_nsec;
727 log_msg->entry_v4.lid = buf.l.id;
728 if (is_system) {
729 log_msg->entry_v4.uid = buf.p.uid;
730 }
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800731
732 return ret;
733 }
734
735 current = TEMP_FAILURE_RETRY(lseek(logger_list->sock,
736 (off_t)0, SEEK_CUR));
737 if (current < 0) {
738 return -errno;
739 }
740 next = TEMP_FAILURE_RETRY(lseek(logger_list->sock,
741 (off_t)(buf.p.len - sizeof(buf)),
742 SEEK_CUR));
743 if (next < 0) {
744 return -errno;
745 }
746 if ((next - current) != (ssize_t)(buf.p.len - sizeof(buf))) {
747 return -EIO;
748 }
749 }
750}
751
Mark Salyzyna04464a2014-04-30 08:50:53 -0700752static void caught_signal(int signum __unused)
Mark Salyzyn42958412013-11-22 10:50:27 -0800753{
Mark Salyzyn42958412013-11-22 10:50:27 -0800754}
755
756/* Read from the selected logs */
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800757LIBLOG_ABI_PUBLIC int android_logger_list_read(
758 struct logger_list *logger_list,
759 struct log_msg *log_msg)
Mark Salyzyn42958412013-11-22 10:50:27 -0800760{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800761 int ret, e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800762 struct logger *logger;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800763 struct sigaction ignore;
764 struct sigaction old_sigaction;
765 unsigned int old_alarm = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800766
767 if (!logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800768 return -EINVAL;
Mark Salyzyn42958412013-11-22 10:50:27 -0800769 }
770
Mark Salyzyn6eef4172014-12-15 09:51:39 -0800771 if (logger_list->mode & ANDROID_LOG_PSTORE) {
772 return android_logger_list_read_pstore(logger_list, log_msg);
773 }
774
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800775 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800776 memset(&ignore, 0, sizeof(ignore));
777 ignore.sa_handler = caught_signal;
778 sigemptyset(&ignore.sa_mask);
Mark Salyzyn42958412013-11-22 10:50:27 -0800779 }
780
Mark Salyzyn154f4602014-02-20 14:59:07 -0800781 if (logger_list->sock < 0) {
782 char buffer[256], *cp, c;
Mark Salyzyn42958412013-11-22 10:50:27 -0800783
Mark Salyzyn154f4602014-02-20 14:59:07 -0800784 int sock = socket_local_client("logdr",
785 ANDROID_SOCKET_NAMESPACE_RESERVED,
786 SOCK_SEQPACKET);
787 if (sock < 0) {
788 if ((sock == -1) && errno) {
789 return -errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800790 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800791 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800792 }
793
Mark Salyzyn154f4602014-02-20 14:59:07 -0800794 strcpy(buffer,
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800795 (logger_list->mode & ANDROID_LOG_NONBLOCK) ? "dumpAndClose" : "stream");
Mark Salyzyn154f4602014-02-20 14:59:07 -0800796 cp = buffer + strlen(buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800797
Mark Salyzyn154f4602014-02-20 14:59:07 -0800798 strcpy(cp, " lids");
799 cp += 5;
800 c = '=';
801 int remaining = sizeof(buffer) - (cp - buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800802 logger_for_each(logger, logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800803 ret = snprintf(cp, remaining, "%c%u", c, logger->id);
804 ret = min(ret, remaining);
805 remaining -= ret;
806 cp += ret;
807 c = ',';
808 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800809
Mark Salyzyn154f4602014-02-20 14:59:07 -0800810 if (logger_list->tail) {
811 ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
812 ret = min(ret, remaining);
813 remaining -= ret;
814 cp += ret;
815 }
816
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800817 if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
Mark Salyzynf8e546e2015-11-30 11:36:09 -0800818 if (logger_list->mode & ANDROID_LOG_WRAP) {
819 // ToDo: alternate API to allow timeout to be adjusted.
820 ret = snprintf(cp, remaining, " timeout=%u",
821 ANDROID_LOG_WRAP_DEFAULT_TIMEOUT);
822 ret = min(ret, remaining);
823 remaining -= ret;
824 cp += ret;
825 }
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800826 ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
827 logger_list->start.tv_sec,
828 logger_list->start.tv_nsec);
829 ret = min(ret, remaining);
830 remaining -= ret;
831 cp += ret;
832 }
833
Mark Salyzyn154f4602014-02-20 14:59:07 -0800834 if (logger_list->pid) {
835 ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
836 ret = min(ret, remaining);
Mark Salyzyn154f4602014-02-20 14:59:07 -0800837 cp += ret;
838 }
839
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800840 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800841 /* Deal with an unresponsive logd */
842 sigaction(SIGALRM, &ignore, &old_sigaction);
843 old_alarm = alarm(30);
844 }
845 ret = write(sock, buffer, cp - buffer);
846 e = errno;
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800847 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800848 if (e == EINTR) {
849 e = ETIMEDOUT;
Mark Salyzyn42958412013-11-22 10:50:27 -0800850 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800851 alarm(old_alarm);
852 sigaction(SIGALRM, &old_sigaction, NULL);
Mark Salyzyn42958412013-11-22 10:50:27 -0800853 }
854
855 if (ret <= 0) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800856 close(sock);
857 if ((ret == -1) && e) {
858 return -e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800859 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800860 if (ret == 0) {
861 return -EIO;
862 }
863 return ret;
Mark Salyzyn42958412013-11-22 10:50:27 -0800864 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800865
866 logger_list->sock = sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800867 }
868
Mark Salyzyn154f4602014-02-20 14:59:07 -0800869 while(1) {
870 memset(log_msg, 0, sizeof(*log_msg));
871
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800872 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800873 /* particularily useful if tombstone is reporting for logd */
874 sigaction(SIGALRM, &ignore, &old_sigaction);
875 old_alarm = alarm(30);
876 }
877 /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
878 ret = recv(logger_list->sock, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
879 e = errno;
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800880 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800881 if ((ret == 0) || (e == EINTR)) {
882 e = EAGAIN;
883 ret = -1;
884 }
885 alarm(old_alarm);
886 sigaction(SIGALRM, &old_sigaction, NULL);
887 }
888
Mark Salyzyn43e92812015-02-26 11:21:47 -0800889 if ((ret == -1) && e) {
890 return -e;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800891 }
Mark Salyzyn43e92812015-02-26 11:21:47 -0800892 return ret;
Mark Salyzyn42958412013-11-22 10:50:27 -0800893 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800894 /* NOTREACH */
Mark Salyzyn42958412013-11-22 10:50:27 -0800895 return ret;
896}
897
898/* Close all the logs */
Mark Salyzynbe1d3c22016-03-10 08:25:33 -0800899LIBLOG_ABI_PUBLIC void android_logger_list_free(
900 struct logger_list *logger_list)
Mark Salyzyn42958412013-11-22 10:50:27 -0800901{
902 if (logger_list == NULL) {
903 return;
904 }
905
906 while (!list_empty(&logger_list->node)) {
907 struct listnode *node = list_head(&logger_list->node);
908 struct logger *logger = node_to_item(node, struct logger, node);
909 android_logger_free(logger);
910 }
911
Mark Salyzyn154f4602014-02-20 14:59:07 -0800912 if (logger_list->sock >= 0) {
913 close (logger_list->sock);
914 }
915
Mark Salyzyn42958412013-11-22 10:50:27 -0800916 free(logger_list);
917}