blob: 2f0af4a2e6b4d80c05d21844bcbb96413b2eeb63 [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,
Tom Cherry71ba1642019-01-10 10:37:36 -080050 struct android_log_transport_context* transp, struct log_msg* log_msg);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080051static int logdPoll(struct android_log_logger_list* logger_list,
52 struct android_log_transport_context* transp);
53static void logdClose(struct android_log_logger_list* logger_list,
54 struct android_log_transport_context* transp);
55static int logdClear(struct android_log_logger* logger,
56 struct android_log_transport_context* transp);
57static ssize_t logdSetSize(struct android_log_logger* logger,
Tom Cherry71ba1642019-01-10 10:37:36 -080058 struct android_log_transport_context* transp, size_t size);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080059static ssize_t logdGetSize(struct android_log_logger* logger,
60 struct android_log_transport_context* transp);
61static ssize_t logdGetReadableSize(struct android_log_logger* logger,
62 struct android_log_transport_context* transp);
63static ssize_t logdGetPrune(struct android_log_logger_list* logger,
Tom Cherry71ba1642019-01-10 10:37:36 -080064 struct android_log_transport_context* transp, char* buf, size_t len);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080065static ssize_t logdSetPrune(struct android_log_logger_list* logger,
Tom Cherry71ba1642019-01-10 10:37:36 -080066 struct android_log_transport_context* transp, char* buf, size_t len);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080067static ssize_t logdGetStats(struct android_log_logger_list* logger,
Tom Cherry71ba1642019-01-10 10:37:36 -080068 struct android_log_transport_context* transp, char* buf, size_t len);
Mark Salyzyn018a96d2016-03-01 13:45:42 -080069
Tom Cherry2d9779e2019-02-08 11:46:19 -080070struct android_log_transport_read logdLoggerRead = {
Tom Cherry71ba1642019-01-10 10:37:36 -080071 .node = {&logdLoggerRead.node, &logdLoggerRead.node},
72 .name = "logd",
73 .available = logdAvailable,
74 .version = logdVersion,
75 .read = logdRead,
76 .poll = logdPoll,
77 .close = logdClose,
78 .clear = logdClear,
79 .getSize = logdGetSize,
80 .setSize = logdSetSize,
81 .getReadableSize = logdGetReadableSize,
82 .getPrune = logdGetPrune,
83 .setPrune = logdSetPrune,
84 .getStats = logdGetStats,
Mark Salyzyn018a96d2016-03-01 13:45:42 -080085};
86
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080087static int logdAvailable(log_id_t logId) {
88 if (logId >= LOG_ID_MAX) {
89 return -EINVAL;
90 }
91 if (logId == LOG_ID_SECURITY) {
92 uid_t uid = __android_log_uid();
93 if (uid != AID_SYSTEM) {
94 return -EPERM;
Mark Salyzyn018a96d2016-03-01 13:45:42 -080095 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080096 }
97 if (access("/dev/socket/logdw", W_OK) == 0) {
98 return 0;
99 }
100 return -EBADF;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800101}
102
103/* Private copy of ../libcutils/socket_local_client.c prevent library loops */
104
105#if defined(_WIN32)
106
Tom Cherry71ba1642019-01-10 10:37:36 -0800107LIBLOG_WEAK int socket_local_client(const char* name, int namespaceId, int type) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800108 errno = ENOSYS;
109 return -ENOSYS;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800110}
111
112#else /* !_WIN32 */
113
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800114#include <sys/select.h>
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800115#include <sys/socket.h>
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800116#include <sys/types.h>
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800117#include <sys/un.h>
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800118
119/* Private copy of ../libcutils/socket_local.h prevent library loops */
120#define FILESYSTEM_SOCKET_PREFIX "/tmp/"
121#define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
122/* End of ../libcutils/socket_local.h */
123
124#define LISTEN_BACKLOG 4
125
126/* Documented in header file. */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800127LIBLOG_WEAK int socket_make_sockaddr_un(const char* name, int namespaceId,
Tom Cherry71ba1642019-01-10 10:37:36 -0800128 struct sockaddr_un* p_addr, socklen_t* alen) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800129 memset(p_addr, 0, sizeof(*p_addr));
130 size_t namelen;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800131
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800132 switch (namespaceId) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800133 case ANDROID_SOCKET_NAMESPACE_ABSTRACT:
134#if defined(__linux__)
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800135 namelen = strlen(name);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800136
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800137 /* Test with length +1 for the *initial* '\0'. */
138 if ((namelen + 1) > sizeof(p_addr->sun_path)) {
139 goto error;
140 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800141
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800142 /*
143 * Note: The path in this case is *not* supposed to be
144 * '\0'-terminated. ("man 7 unix" for the gory details.)
145 */
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800146
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800147 p_addr->sun_path[0] = 0;
148 memcpy(p_addr->sun_path + 1, name, namelen);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800149#else
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800150 /* this OS doesn't have the Linux abstract namespace */
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800151
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800152 namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
153 /* unix_path_max appears to be missing on linux */
Tom Cherry71ba1642019-01-10 10:37:36 -0800154 if (namelen > sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800155 goto error;
156 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800157
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800158 strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
159 strcat(p_addr->sun_path, name);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800160#endif
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800161 break;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800162
163 case ANDROID_SOCKET_NAMESPACE_RESERVED:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800164 namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
165 /* unix_path_max appears to be missing on linux */
Tom Cherry71ba1642019-01-10 10:37:36 -0800166 if (namelen > sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800167 goto error;
168 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800169
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800170 strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);
171 strcat(p_addr->sun_path, name);
172 break;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800173
174 case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800175 namelen = strlen(name);
176 /* unix_path_max appears to be missing on linux */
Tom Cherry71ba1642019-01-10 10:37:36 -0800177 if (namelen > sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800178 goto error;
179 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800180
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800181 strcpy(p_addr->sun_path, name);
182 break;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800183
184 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800185 /* invalid namespace id */
186 return -1;
187 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800188
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800189 p_addr->sun_family = AF_LOCAL;
190 *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
191 return 0;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800192error:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800193 return -1;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800194}
195
196/**
197 * connect to peer named "name" on fd
198 * returns same fd or -1 on error.
199 * fd is not closed on error. that's your job.
200 *
201 * Used by AndroidSocketImpl
202 */
Tom Cherry71ba1642019-01-10 10:37:36 -0800203LIBLOG_WEAK int socket_local_client_connect(int fd, const char* name, int namespaceId,
204 int type __unused) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800205 struct sockaddr_un addr;
206 socklen_t alen;
207 int err;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800208
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800209 err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800210
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800211 if (err < 0) {
212 goto error;
213 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800214
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800215 if (connect(fd, (struct sockaddr*)&addr, alen) < 0) {
216 goto error;
217 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800218
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800219 return fd;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800220
221error:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800222 return -1;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800223}
224
225/**
226 * connect to peer named "name"
227 * returns fd or -1 on error
228 */
Tom Cherry71ba1642019-01-10 10:37:36 -0800229LIBLOG_WEAK int socket_local_client(const char* name, int namespaceId, int type) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800230 int s;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800231
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800232 s = socket(AF_LOCAL, type, 0);
233 if (s < 0) return -1;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800234
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800235 if (0 > socket_local_client_connect(s, name, namespaceId, type)) {
236 close(s);
237 return -1;
238 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800239
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800240 return s;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800241}
242
243#endif /* !_WIN32 */
244/* End of ../libcutils/socket_local_client.c */
245
246/* worker for sending the command to the logger */
Tom Cherry71ba1642019-01-10 10:37:36 -0800247static ssize_t send_log_msg(struct android_log_logger* logger, const char* msg, char* buf,
248 size_t buf_size) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800249 ssize_t ret;
250 size_t len;
251 char* cp;
252 int errno_save = 0;
Tom Cherry71ba1642019-01-10 10:37:36 -0800253 int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800254 if (sock < 0) {
255 return sock;
256 }
257
258 if (msg) {
259 snprintf(buf, buf_size, msg, logger ? logger->logId : (unsigned)-1);
260 }
261
262 len = strlen(buf) + 1;
263 ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
264 if (ret <= 0) {
265 goto done;
266 }
267
268 len = buf_size;
269 cp = buf;
270 while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) {
271 struct pollfd p;
272
273 if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) {
274 break;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800275 }
276
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800277 len -= ret;
278 cp += ret;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800279
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800280 memset(&p, 0, sizeof(p));
281 p.fd = sock;
282 p.events = POLLIN;
283
284 /* Give other side 20ms to refill pipe */
285 ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20));
286
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800287 if (ret <= 0) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800288 break;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800289 }
290
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800291 if (!(p.revents & POLLIN)) {
292 ret = 0;
293 break;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800294 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800295 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800296
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800297 if (ret >= 0) {
298 ret += buf_size - len;
299 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800300
301done:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800302 if ((ret == -1) && errno) {
303 errno_save = errno;
304 }
305 close(sock);
306 if (errno_save) {
307 errno = errno_save;
308 }
309 return ret;
310}
311
Tom Cherry2d9779e2019-02-08 11:46:19 -0800312ssize_t __send_log_msg(char* buf, size_t buf_size) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800313 return send_log_msg(NULL, NULL, buf, buf_size);
314}
315
316static int check_log_success(char* buf, ssize_t ret) {
317 if (ret < 0) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800318 return ret;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800319 }
320
321 if (strncmp(buf, "success", 7)) {
322 errno = EINVAL;
323 return -1;
324 }
325
326 return 0;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800327}
328
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800329static int logdClear(struct android_log_logger* logger,
330 struct android_log_transport_context* transp __unused) {
331 char buf[512];
Mark Salyzync9e5f372016-09-21 09:24:13 -0700332
Tom Cherry71ba1642019-01-10 10:37:36 -0800333 return check_log_success(buf, send_log_msg(logger, "clear %d", buf, sizeof(buf)));
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800334}
335
336/* returns the total size of the log's ring buffer */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800337static ssize_t logdGetSize(struct android_log_logger* logger,
338 struct android_log_transport_context* transp __unused) {
339 char buf[512];
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800340
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800341 ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
342 if (ret < 0) {
343 return ret;
344 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800345
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800346 if ((buf[0] < '0') || ('9' < buf[0])) {
347 return -1;
348 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800349
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800350 return atol(buf);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800351}
352
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800353static ssize_t logdSetSize(struct android_log_logger* logger,
Tom Cherry71ba1642019-01-10 10:37:36 -0800354 struct android_log_transport_context* transp __unused, size_t size) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800355 char buf[512];
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800356
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800357 snprintf(buf, sizeof(buf), "setLogSize %d %zu", logger->logId, size);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800358
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800359 return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800360}
361
362/*
363 * returns the readable size of the log's ring buffer (that is, amount of the
364 * log consumed)
365 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800366static ssize_t logdGetReadableSize(struct android_log_logger* logger,
Tom Cherry71ba1642019-01-10 10:37:36 -0800367 struct android_log_transport_context* transp __unused) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800368 char buf[512];
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800369
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800370 ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
371 if (ret < 0) {
372 return ret;
373 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800374
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800375 if ((buf[0] < '0') || ('9' < buf[0])) {
376 return -1;
377 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800378
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800379 return atol(buf);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800380}
381
382/*
383 * returns the logger version
384 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800385static int logdVersion(struct android_log_logger* logger __unused,
386 struct android_log_transport_context* transp __unused) {
387 uid_t uid = __android_log_uid();
388 return ((uid != AID_ROOT) && (uid != AID_LOG) && (uid != AID_SYSTEM)) ? 3 : 4;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800389}
390
391/*
392 * returns statistics
393 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800394static ssize_t logdGetStats(struct android_log_logger_list* logger_list,
Tom Cherry71ba1642019-01-10 10:37:36 -0800395 struct android_log_transport_context* transp __unused, char* buf,
396 size_t len) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800397 struct android_log_logger* logger;
398 char* cp = buf;
399 size_t remaining = len;
400 size_t n;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800401
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800402 n = snprintf(cp, remaining, "getStatistics");
403 n = min(n, remaining);
404 remaining -= n;
405 cp += n;
406
407 logger_for_each(logger, logger_list) {
408 n = snprintf(cp, remaining, " %d", logger->logId);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800409 n = min(n, remaining);
410 remaining -= n;
411 cp += n;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800412 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800413
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800414 if (logger_list->pid) {
415 snprintf(cp, remaining, " pid=%u", logger_list->pid);
416 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800417
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800418 return send_log_msg(NULL, NULL, buf, len);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800419}
420
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800421static ssize_t logdGetPrune(struct android_log_logger_list* logger_list __unused,
Tom Cherry71ba1642019-01-10 10:37:36 -0800422 struct android_log_transport_context* transp __unused, char* buf,
423 size_t len) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800424 return send_log_msg(NULL, "getPruneList", buf, len);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800425}
426
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800427static ssize_t logdSetPrune(struct android_log_logger_list* logger_list __unused,
Tom Cherry71ba1642019-01-10 10:37:36 -0800428 struct android_log_transport_context* transp __unused, char* buf,
429 size_t len) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800430 const char cmd[] = "setPruneList ";
431 const size_t cmdlen = sizeof(cmd) - 1;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800432
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800433 if (strlen(buf) > (len - cmdlen)) {
434 return -ENOMEM; /* KISS */
435 }
436 memmove(buf + cmdlen, buf, len - cmdlen);
437 buf[len - 1] = '\0';
438 memcpy(buf, cmd, cmdlen);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800439
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800440 return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800441}
442
Tom Cherry71ba1642019-01-10 10:37:36 -0800443static void caught_signal(int signum __unused) {}
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800444
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800445static int logdOpen(struct android_log_logger_list* logger_list,
446 struct android_log_transport_context* transp) {
447 struct android_log_logger* logger;
448 struct sigaction ignore;
449 struct sigaction old_sigaction;
450 unsigned int old_alarm = 0;
451 char buffer[256], *cp, c;
452 int e, ret, remaining, sock;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800453
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800454 if (!logger_list) {
455 return -EINVAL;
456 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800457
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800458 sock = atomic_load(&transp->context.sock);
459 if (sock > 0) {
460 return sock;
461 }
Mark Salyzyndb8a2662016-10-10 07:27:42 -0700462
Tom Cherry71ba1642019-01-10 10:37:36 -0800463 sock = socket_local_client("logdr", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800464 if (sock == 0) {
465 /* Guarantee not file descriptor zero */
Tom Cherry71ba1642019-01-10 10:37:36 -0800466 int newsock = socket_local_client("logdr", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800467 close(sock);
468 sock = newsock;
469 }
470 if (sock <= 0) {
471 if ((sock == -1) && errno) {
472 return -errno;
Mark Salyzyndb8a2662016-10-10 07:27:42 -0700473 }
474 return sock;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800475 }
476
Tom Cherry71ba1642019-01-10 10:37:36 -0800477 strcpy(buffer, (logger_list->mode & ANDROID_LOG_NONBLOCK) ? "dumpAndClose" : "stream");
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800478 cp = buffer + strlen(buffer);
479
480 strcpy(cp, " lids");
481 cp += 5;
482 c = '=';
483 remaining = sizeof(buffer) - (cp - buffer);
484 logger_for_each(logger, logger_list) {
485 ret = snprintf(cp, remaining, "%c%u", c, logger->logId);
486 ret = min(ret, remaining);
487 remaining -= ret;
488 cp += ret;
489 c = ',';
490 }
491
492 if (logger_list->tail) {
493 ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
494 ret = min(ret, remaining);
495 remaining -= ret;
496 cp += ret;
497 }
498
499 if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
500 if (logger_list->mode & ANDROID_LOG_WRAP) {
501 // ToDo: alternate API to allow timeout to be adjusted.
Tom Cherry71ba1642019-01-10 10:37:36 -0800502 ret = snprintf(cp, remaining, " timeout=%u", ANDROID_LOG_WRAP_DEFAULT_TIMEOUT);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800503 ret = min(ret, remaining);
504 remaining -= ret;
505 cp += ret;
506 }
Tom Cherry71ba1642019-01-10 10:37:36 -0800507 ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32, logger_list->start.tv_sec,
508 logger_list->start.tv_nsec);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800509 ret = min(ret, remaining);
510 remaining -= ret;
511 cp += ret;
512 }
513
514 if (logger_list->pid) {
515 ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
516 ret = min(ret, remaining);
517 cp += ret;
518 }
519
520 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
521 /* Deal with an unresponsive logd */
522 memset(&ignore, 0, sizeof(ignore));
523 ignore.sa_handler = caught_signal;
524 sigemptyset(&ignore.sa_mask);
525 /* particularily useful if tombstone is reporting for logd */
526 sigaction(SIGALRM, &ignore, &old_sigaction);
527 old_alarm = alarm(30);
528 }
529 ret = write(sock, buffer, cp - buffer);
530 e = errno;
531 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
532 if (e == EINTR) {
533 e = ETIMEDOUT;
534 }
535 alarm(old_alarm);
536 sigaction(SIGALRM, &old_sigaction, NULL);
537 }
538
539 if (ret <= 0) {
540 close(sock);
541 if ((ret == -1) && e) {
542 return -e;
543 }
544 if (ret == 0) {
545 return -EIO;
546 }
547 return ret;
548 }
549
550 ret = atomic_exchange(&transp->context.sock, sock);
551 if ((ret > 0) && (ret != sock)) {
552 close(ret);
553 }
554 return sock;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800555}
556
557/* Read from the selected logs */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800558static int logdRead(struct android_log_logger_list* logger_list,
Tom Cherry71ba1642019-01-10 10:37:36 -0800559 struct android_log_transport_context* transp, struct log_msg* log_msg) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800560 int ret, e;
561 struct sigaction ignore;
562 struct sigaction old_sigaction;
563 unsigned int old_alarm = 0;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800564
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800565 ret = logdOpen(logger_list, transp);
566 if (ret < 0) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800567 return ret;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800568 }
569
570 memset(log_msg, 0, sizeof(*log_msg));
571
Alan Stokes64acdf72017-08-01 16:43:02 +0100572 unsigned int new_alarm = 0;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800573 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Alan Stokes64acdf72017-08-01 16:43:02 +0100574 if ((logger_list->mode & ANDROID_LOG_WRAP) &&
575 (logger_list->start.tv_sec || logger_list->start.tv_nsec)) {
576 /* b/64143705 */
577 new_alarm = (ANDROID_LOG_WRAP_DEFAULT_TIMEOUT * 11) / 10 + 10;
578 logger_list->mode &= ~ANDROID_LOG_WRAP;
579 } else {
580 new_alarm = 30;
581 }
582
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800583 memset(&ignore, 0, sizeof(ignore));
584 ignore.sa_handler = caught_signal;
585 sigemptyset(&ignore.sa_mask);
586 /* particularily useful if tombstone is reporting for logd */
587 sigaction(SIGALRM, &ignore, &old_sigaction);
Alan Stokes64acdf72017-08-01 16:43:02 +0100588 old_alarm = alarm(new_alarm);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800589 }
590
591 /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
592 ret = recv(ret, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
593 e = errno;
594
Alan Stokes64acdf72017-08-01 16:43:02 +0100595 if (new_alarm) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800596 if ((ret == 0) || (e == EINTR)) {
597 e = EAGAIN;
598 ret = -1;
599 }
600 alarm(old_alarm);
601 sigaction(SIGALRM, &old_sigaction, NULL);
602 }
603
604 if ((ret == -1) && e) {
605 return -e;
606 }
607 return ret;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800608}
609
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800610static int logdPoll(struct android_log_logger_list* logger_list,
611 struct android_log_transport_context* transp) {
612 struct pollfd p;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800613
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800614 int ret = logdOpen(logger_list, transp);
615 if (ret < 0) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800616 return ret;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800617 }
618
619 memset(&p, 0, sizeof(p));
620 p.fd = ret;
621 p.events = POLLIN;
622 ret = poll(&p, 1, 20);
623 if ((ret > 0) && !(p.revents & POLLIN)) {
624 ret = 0;
625 }
626 if ((ret == -1) && errno) {
627 return -errno;
628 }
629 return ret;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800630}
631
632/* Close all the logs */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800633static void logdClose(struct android_log_logger_list* logger_list __unused,
634 struct android_log_transport_context* transp) {
635 int sock = atomic_exchange(&transp->context.sock, -1);
636 if (sock > 0) {
637 close(sock);
638 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800639}