blob: 603ba2469f7bc568bc3dd619148c9393d94efee0 [file] [log] [blame]
Mark Salyzyn018a96d2016-03-01 13:45:42 -08001/*
2 * Copyright (C) 2007-2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <endian.h>
18#include <errno.h>
19#include <fcntl.h>
20#include <inttypes.h>
21#include <poll.h>
22#include <stdarg.h>
23#include <stdatomic.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080027#include <sys/socket.h>
Mark Salyzyn018a96d2016-03-01 13:45:42 -080028#include <sys/stat.h>
29#include <sys/types.h>
Mark Salyzyn018a96d2016-03-01 13:45:42 -080030#include <sys/un.h>
31#include <time.h>
32#include <unistd.h>
33
34#include <cutils/sockets.h>
Mark Salyzyn018a96d2016-03-01 13:45:42 -080035#include <private/android_filesystem_config.h>
36#include <private/android_logger.h>
37
38#include "config_read.h"
39#include "log_portability.h"
Mark Salyzync9e5f372016-09-21 09:24:13 -070040#include "logd_reader.h"
Mark Salyzyn018a96d2016-03-01 13:45:42 -080041#include "logger.h"
42
43/* branchless on many architectures. */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080044#define min(x, y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
Mark Salyzyn018a96d2016-03-01 13:45:42 -080045
46static int logdAvailable(log_id_t LogId);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080047static int logdVersion(struct android_log_logger* logger,
48 struct android_log_transport_context* transp);
49static int logdRead(struct android_log_logger_list* logger_list,
50 struct android_log_transport_context* transp,
51 struct log_msg* log_msg);
52static int logdPoll(struct android_log_logger_list* logger_list,
53 struct android_log_transport_context* transp);
54static void logdClose(struct android_log_logger_list* logger_list,
55 struct android_log_transport_context* transp);
56static int logdClear(struct android_log_logger* logger,
57 struct android_log_transport_context* transp);
58static ssize_t logdSetSize(struct android_log_logger* logger,
59 struct android_log_transport_context* transp,
Mark Salyzyn018a96d2016-03-01 13:45:42 -080060 size_t size);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080061static ssize_t logdGetSize(struct android_log_logger* logger,
62 struct android_log_transport_context* transp);
63static ssize_t logdGetReadableSize(struct android_log_logger* logger,
64 struct android_log_transport_context* transp);
65static ssize_t logdGetPrune(struct android_log_logger_list* logger,
66 struct android_log_transport_context* transp,
67 char* buf, size_t len);
68static ssize_t logdSetPrune(struct android_log_logger_list* logger,
69 struct android_log_transport_context* transp,
70 char* buf, size_t len);
71static ssize_t logdGetStats(struct android_log_logger_list* logger,
72 struct android_log_transport_context* transp,
73 char* buf, size_t len);
Mark Salyzyn018a96d2016-03-01 13:45:42 -080074
75LIBLOG_HIDDEN struct android_log_transport_read logdLoggerRead = {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080076 .node = { &logdLoggerRead.node, &logdLoggerRead.node },
77 .name = "logd",
78 .available = logdAvailable,
79 .version = logdVersion,
80 .read = logdRead,
81 .poll = logdPoll,
82 .close = logdClose,
83 .clear = logdClear,
84 .getSize = logdGetSize,
85 .setSize = logdSetSize,
86 .getReadableSize = logdGetReadableSize,
87 .getPrune = logdGetPrune,
88 .setPrune = logdSetPrune,
89 .getStats = logdGetStats,
Mark Salyzyn018a96d2016-03-01 13:45:42 -080090};
91
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080092static int logdAvailable(log_id_t logId) {
93 if (logId >= LOG_ID_MAX) {
94 return -EINVAL;
95 }
96 if (logId == LOG_ID_SECURITY) {
97 uid_t uid = __android_log_uid();
98 if (uid != AID_SYSTEM) {
99 return -EPERM;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800100 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800101 }
102 if (access("/dev/socket/logdw", W_OK) == 0) {
103 return 0;
104 }
105 return -EBADF;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800106}
107
108/* Private copy of ../libcutils/socket_local_client.c prevent library loops */
109
110#if defined(_WIN32)
111
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800112LIBLOG_WEAK int socket_local_client(const char* name, int namespaceId,
113 int type) {
114 errno = ENOSYS;
115 return -ENOSYS;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800116}
117
118#else /* !_WIN32 */
119
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800120#include <sys/select.h>
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800121#include <sys/socket.h>
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800122#include <sys/types.h>
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800123#include <sys/un.h>
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800124
125/* Private copy of ../libcutils/socket_local.h prevent library loops */
126#define FILESYSTEM_SOCKET_PREFIX "/tmp/"
127#define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
128/* End of ../libcutils/socket_local.h */
129
130#define LISTEN_BACKLOG 4
131
132/* Documented in header file. */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800133LIBLOG_WEAK int socket_make_sockaddr_un(const char* name, int namespaceId,
134 struct sockaddr_un* p_addr,
135 socklen_t* alen) {
136 memset(p_addr, 0, sizeof(*p_addr));
137 size_t namelen;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800138
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800139 switch (namespaceId) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800140 case ANDROID_SOCKET_NAMESPACE_ABSTRACT:
141#if defined(__linux__)
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800142 namelen = strlen(name);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800143
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800144 /* Test with length +1 for the *initial* '\0'. */
145 if ((namelen + 1) > sizeof(p_addr->sun_path)) {
146 goto error;
147 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800148
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800149 /*
150 * Note: The path in this case is *not* supposed to be
151 * '\0'-terminated. ("man 7 unix" for the gory details.)
152 */
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800153
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800154 p_addr->sun_path[0] = 0;
155 memcpy(p_addr->sun_path + 1, name, namelen);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800156#else
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800157 /* this OS doesn't have the Linux abstract namespace */
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800158
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800159 namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
160 /* unix_path_max appears to be missing on linux */
161 if (namelen >
162 sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
163 goto error;
164 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800165
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800166 strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
167 strcat(p_addr->sun_path, name);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800168#endif
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800169 break;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800170
171 case ANDROID_SOCKET_NAMESPACE_RESERVED:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800172 namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
173 /* unix_path_max appears to be missing on linux */
174 if (namelen >
175 sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
176 goto error;
177 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800178
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800179 strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);
180 strcat(p_addr->sun_path, name);
181 break;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800182
183 case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800184 namelen = strlen(name);
185 /* unix_path_max appears to be missing on linux */
186 if (namelen >
187 sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
188 goto error;
189 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800190
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800191 strcpy(p_addr->sun_path, name);
192 break;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800193
194 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800195 /* invalid namespace id */
196 return -1;
197 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800198
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800199 p_addr->sun_family = AF_LOCAL;
200 *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
201 return 0;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800202error:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800203 return -1;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800204}
205
206/**
207 * connect to peer named "name" on fd
208 * returns same fd or -1 on error.
209 * fd is not closed on error. that's your job.
210 *
211 * Used by AndroidSocketImpl
212 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800213LIBLOG_WEAK int socket_local_client_connect(int fd, const char* name,
214 int namespaceId, int type __unused) {
215 struct sockaddr_un addr;
216 socklen_t alen;
217 int err;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800218
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800219 err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800220
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800221 if (err < 0) {
222 goto error;
223 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800224
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800225 if (connect(fd, (struct sockaddr*)&addr, alen) < 0) {
226 goto error;
227 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800228
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800229 return fd;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800230
231error:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800232 return -1;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800233}
234
235/**
236 * connect to peer named "name"
237 * returns fd or -1 on error
238 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800239LIBLOG_WEAK int socket_local_client(const char* name, int namespaceId,
240 int type) {
241 int s;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800242
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800243 s = socket(AF_LOCAL, type, 0);
244 if (s < 0) return -1;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800245
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800246 if (0 > socket_local_client_connect(s, name, namespaceId, type)) {
247 close(s);
248 return -1;
249 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800250
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800251 return s;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800252}
253
254#endif /* !_WIN32 */
255/* End of ../libcutils/socket_local_client.c */
256
257/* worker for sending the command to the logger */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800258static ssize_t send_log_msg(struct android_log_logger* logger, const char* msg,
259 char* buf, size_t buf_size) {
260 ssize_t ret;
261 size_t len;
262 char* cp;
263 int errno_save = 0;
264 int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
265 SOCK_STREAM);
266 if (sock < 0) {
267 return sock;
268 }
269
270 if (msg) {
271 snprintf(buf, buf_size, msg, logger ? logger->logId : (unsigned)-1);
272 }
273
274 len = strlen(buf) + 1;
275 ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
276 if (ret <= 0) {
277 goto done;
278 }
279
280 len = buf_size;
281 cp = buf;
282 while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) {
283 struct pollfd p;
284
285 if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) {
286 break;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800287 }
288
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800289 len -= ret;
290 cp += ret;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800291
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800292 memset(&p, 0, sizeof(p));
293 p.fd = sock;
294 p.events = POLLIN;
295
296 /* Give other side 20ms to refill pipe */
297 ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20));
298
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800299 if (ret <= 0) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800300 break;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800301 }
302
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800303 if (!(p.revents & POLLIN)) {
304 ret = 0;
305 break;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800306 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800307 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800308
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800309 if (ret >= 0) {
310 ret += buf_size - len;
311 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800312
313done:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800314 if ((ret == -1) && errno) {
315 errno_save = errno;
316 }
317 close(sock);
318 if (errno_save) {
319 errno = errno_save;
320 }
321 return ret;
322}
323
324LIBLOG_HIDDEN ssize_t __send_log_msg(char* buf, size_t buf_size) {
325 return send_log_msg(NULL, NULL, buf, buf_size);
326}
327
328static int check_log_success(char* buf, ssize_t ret) {
329 if (ret < 0) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800330 return ret;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800331 }
332
333 if (strncmp(buf, "success", 7)) {
334 errno = EINVAL;
335 return -1;
336 }
337
338 return 0;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800339}
340
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800341static int logdClear(struct android_log_logger* logger,
342 struct android_log_transport_context* transp __unused) {
343 char buf[512];
Mark Salyzync9e5f372016-09-21 09:24:13 -0700344
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800345 return check_log_success(buf,
346 send_log_msg(logger, "clear %d", buf, sizeof(buf)));
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800347}
348
349/* returns the total size of the log's ring buffer */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800350static ssize_t logdGetSize(struct android_log_logger* logger,
351 struct android_log_transport_context* transp __unused) {
352 char buf[512];
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800353
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800354 ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
355 if (ret < 0) {
356 return ret;
357 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800358
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800359 if ((buf[0] < '0') || ('9' < buf[0])) {
360 return -1;
361 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800362
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800363 return atol(buf);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800364}
365
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800366static ssize_t logdSetSize(struct android_log_logger* logger,
367 struct android_log_transport_context* transp __unused,
368 size_t size) {
369 char buf[512];
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800370
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800371 snprintf(buf, sizeof(buf), "setLogSize %d %zu", logger->logId, size);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800372
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800373 return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800374}
375
376/*
377 * returns the readable size of the log's ring buffer (that is, amount of the
378 * log consumed)
379 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800380static ssize_t logdGetReadableSize(struct android_log_logger* logger,
381 struct android_log_transport_context* transp
382 __unused) {
383 char buf[512];
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800384
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800385 ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
386 if (ret < 0) {
387 return ret;
388 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800389
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800390 if ((buf[0] < '0') || ('9' < buf[0])) {
391 return -1;
392 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800393
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800394 return atol(buf);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800395}
396
397/*
398 * returns the logger version
399 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800400static int logdVersion(struct android_log_logger* logger __unused,
401 struct android_log_transport_context* transp __unused) {
402 uid_t uid = __android_log_uid();
403 return ((uid != AID_ROOT) && (uid != AID_LOG) && (uid != AID_SYSTEM)) ? 3 : 4;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800404}
405
406/*
407 * returns statistics
408 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800409static ssize_t logdGetStats(struct android_log_logger_list* logger_list,
410 struct android_log_transport_context* transp __unused,
411 char* buf, size_t len) {
412 struct android_log_logger* logger;
413 char* cp = buf;
414 size_t remaining = len;
415 size_t n;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800416
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800417 n = snprintf(cp, remaining, "getStatistics");
418 n = min(n, remaining);
419 remaining -= n;
420 cp += n;
421
422 logger_for_each(logger, logger_list) {
423 n = snprintf(cp, remaining, " %d", logger->logId);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800424 n = min(n, remaining);
425 remaining -= n;
426 cp += n;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800427 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800428
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800429 if (logger_list->pid) {
430 snprintf(cp, remaining, " pid=%u", logger_list->pid);
431 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800432
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800433 return send_log_msg(NULL, NULL, buf, len);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800434}
435
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800436static ssize_t logdGetPrune(struct android_log_logger_list* logger_list __unused,
437 struct android_log_transport_context* transp __unused,
438 char* buf, size_t len) {
439 return send_log_msg(NULL, "getPruneList", buf, len);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800440}
441
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800442static ssize_t logdSetPrune(struct android_log_logger_list* logger_list __unused,
443 struct android_log_transport_context* transp __unused,
444 char* buf, size_t len) {
445 const char cmd[] = "setPruneList ";
446 const size_t cmdlen = sizeof(cmd) - 1;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800447
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800448 if (strlen(buf) > (len - cmdlen)) {
449 return -ENOMEM; /* KISS */
450 }
451 memmove(buf + cmdlen, buf, len - cmdlen);
452 buf[len - 1] = '\0';
453 memcpy(buf, cmd, cmdlen);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800454
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800455 return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800456}
457
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800458static void caught_signal(int signum __unused) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800459}
460
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800461static int logdOpen(struct android_log_logger_list* logger_list,
462 struct android_log_transport_context* transp) {
463 struct android_log_logger* logger;
464 struct sigaction ignore;
465 struct sigaction old_sigaction;
466 unsigned int old_alarm = 0;
467 char buffer[256], *cp, c;
468 int e, ret, remaining, sock;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800469
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800470 if (!logger_list) {
471 return -EINVAL;
472 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800473
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800474 sock = atomic_load(&transp->context.sock);
475 if (sock > 0) {
476 return sock;
477 }
Mark Salyzyndb8a2662016-10-10 07:27:42 -0700478
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800479 sock = socket_local_client("logdr", ANDROID_SOCKET_NAMESPACE_RESERVED,
480 SOCK_SEQPACKET);
481 if (sock == 0) {
482 /* Guarantee not file descriptor zero */
483 int newsock = socket_local_client(
484 "logdr", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET);
485 close(sock);
486 sock = newsock;
487 }
488 if (sock <= 0) {
489 if ((sock == -1) && errno) {
490 return -errno;
Mark Salyzyndb8a2662016-10-10 07:27:42 -0700491 }
492 return sock;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800493 }
494
495 strcpy(buffer, (logger_list->mode & ANDROID_LOG_NONBLOCK) ? "dumpAndClose"
496 : "stream");
497 cp = buffer + strlen(buffer);
498
499 strcpy(cp, " lids");
500 cp += 5;
501 c = '=';
502 remaining = sizeof(buffer) - (cp - buffer);
503 logger_for_each(logger, logger_list) {
504 ret = snprintf(cp, remaining, "%c%u", c, logger->logId);
505 ret = min(ret, remaining);
506 remaining -= ret;
507 cp += ret;
508 c = ',';
509 }
510
511 if (logger_list->tail) {
512 ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
513 ret = min(ret, remaining);
514 remaining -= ret;
515 cp += ret;
516 }
517
518 if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
519 if (logger_list->mode & ANDROID_LOG_WRAP) {
520 // ToDo: alternate API to allow timeout to be adjusted.
521 ret = snprintf(cp, remaining, " timeout=%u",
522 ANDROID_LOG_WRAP_DEFAULT_TIMEOUT);
523 ret = min(ret, remaining);
524 remaining -= ret;
525 cp += ret;
526 }
527 ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
528 logger_list->start.tv_sec, logger_list->start.tv_nsec);
529 ret = min(ret, remaining);
530 remaining -= ret;
531 cp += ret;
532 }
533
534 if (logger_list->pid) {
535 ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
536 ret = min(ret, remaining);
537 cp += ret;
538 }
539
540 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
541 /* Deal with an unresponsive logd */
542 memset(&ignore, 0, sizeof(ignore));
543 ignore.sa_handler = caught_signal;
544 sigemptyset(&ignore.sa_mask);
545 /* particularily useful if tombstone is reporting for logd */
546 sigaction(SIGALRM, &ignore, &old_sigaction);
547 old_alarm = alarm(30);
548 }
549 ret = write(sock, buffer, cp - buffer);
550 e = errno;
551 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
552 if (e == EINTR) {
553 e = ETIMEDOUT;
554 }
555 alarm(old_alarm);
556 sigaction(SIGALRM, &old_sigaction, NULL);
557 }
558
559 if (ret <= 0) {
560 close(sock);
561 if ((ret == -1) && e) {
562 return -e;
563 }
564 if (ret == 0) {
565 return -EIO;
566 }
567 return ret;
568 }
569
570 ret = atomic_exchange(&transp->context.sock, sock);
571 if ((ret > 0) && (ret != sock)) {
572 close(ret);
573 }
574 return sock;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800575}
576
577/* Read from the selected logs */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800578static int logdRead(struct android_log_logger_list* logger_list,
579 struct android_log_transport_context* transp,
580 struct log_msg* log_msg) {
581 int ret, e;
582 struct sigaction ignore;
583 struct sigaction old_sigaction;
584 unsigned int old_alarm = 0;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800585
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800586 ret = logdOpen(logger_list, transp);
587 if (ret < 0) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800588 return ret;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800589 }
590
591 memset(log_msg, 0, sizeof(*log_msg));
592
Alan Stokes64acdf72017-08-01 16:43:02 +0100593 unsigned int new_alarm = 0;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800594 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Alan Stokes64acdf72017-08-01 16:43:02 +0100595 if ((logger_list->mode & ANDROID_LOG_WRAP) &&
596 (logger_list->start.tv_sec || logger_list->start.tv_nsec)) {
597 /* b/64143705 */
598 new_alarm = (ANDROID_LOG_WRAP_DEFAULT_TIMEOUT * 11) / 10 + 10;
599 logger_list->mode &= ~ANDROID_LOG_WRAP;
600 } else {
601 new_alarm = 30;
602 }
603
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800604 memset(&ignore, 0, sizeof(ignore));
605 ignore.sa_handler = caught_signal;
606 sigemptyset(&ignore.sa_mask);
607 /* particularily useful if tombstone is reporting for logd */
608 sigaction(SIGALRM, &ignore, &old_sigaction);
Alan Stokes64acdf72017-08-01 16:43:02 +0100609 old_alarm = alarm(new_alarm);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800610 }
611
612 /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
613 ret = recv(ret, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
614 e = errno;
615
Alan Stokes64acdf72017-08-01 16:43:02 +0100616 if (new_alarm) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800617 if ((ret == 0) || (e == EINTR)) {
618 e = EAGAIN;
619 ret = -1;
620 }
621 alarm(old_alarm);
622 sigaction(SIGALRM, &old_sigaction, NULL);
623 }
624
625 if ((ret == -1) && e) {
626 return -e;
627 }
628 return ret;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800629}
630
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800631static int logdPoll(struct android_log_logger_list* logger_list,
632 struct android_log_transport_context* transp) {
633 struct pollfd p;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800634
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800635 int ret = logdOpen(logger_list, transp);
636 if (ret < 0) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800637 return ret;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800638 }
639
640 memset(&p, 0, sizeof(p));
641 p.fd = ret;
642 p.events = POLLIN;
643 ret = poll(&p, 1, 20);
644 if ((ret > 0) && !(p.revents & POLLIN)) {
645 ret = 0;
646 }
647 if ((ret == -1) && errno) {
648 return -errno;
649 }
650 return ret;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800651}
652
653/* Close all the logs */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800654static void logdClose(struct android_log_logger_list* logger_list __unused,
655 struct android_log_transport_context* transp) {
656 int sock = atomic_exchange(&transp->context.sock, -1);
657 if (sock > 0) {
658 close(sock);
659 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800660}