blob: 4e2dc6665cb3a16c8f4107889271492f1ff44103 [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
Mark Salyzyn018a96d2016-03-01 13:45:42 -080017#include <errno.h>
18#include <fcntl.h>
19#include <inttypes.h>
20#include <poll.h>
21#include <stdarg.h>
22#include <stdatomic.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
Elliott Hughes6efbda72019-10-02 12:27:03 -070026#include <sys/param.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
Mark Salyzyn018a96d2016-03-01 13:45:42 -080038#include "log_portability.h"
Mark Salyzync9e5f372016-09-21 09:24:13 -070039#include "logd_reader.h"
Mark Salyzyn018a96d2016-03-01 13:45:42 -080040#include "logger.h"
41
Tom Cherry828db1a2019-11-14 10:39:40 -080042static int LogdAvailable(log_id_t LogId);
Tom Cherry828db1a2019-11-14 10:39:40 -080043static int LogdRead(struct logger_list* logger_list, struct android_log_transport_context* transp,
44 struct log_msg* log_msg);
Tom Cherry828db1a2019-11-14 10:39:40 -080045static void LogdClose(struct logger_list* logger_list,
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080046 struct android_log_transport_context* transp);
Mark Salyzyn018a96d2016-03-01 13:45:42 -080047
Tom Cherry2d9779e2019-02-08 11:46:19 -080048struct android_log_transport_read logdLoggerRead = {
Tom Cherry71ba1642019-01-10 10:37:36 -080049 .name = "logd",
Tom Cherry828db1a2019-11-14 10:39:40 -080050 .available = LogdAvailable,
Tom Cherry828db1a2019-11-14 10:39:40 -080051 .close = LogdClose,
52 .read = LogdRead,
Mark Salyzyn018a96d2016-03-01 13:45:42 -080053};
54
Tom Cherry828db1a2019-11-14 10:39:40 -080055static int LogdAvailable(log_id_t logId) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080056 if (logId >= LOG_ID_MAX) {
57 return -EINVAL;
58 }
59 if (logId == LOG_ID_SECURITY) {
60 uid_t uid = __android_log_uid();
61 if (uid != AID_SYSTEM) {
62 return -EPERM;
Mark Salyzyn018a96d2016-03-01 13:45:42 -080063 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080064 }
65 if (access("/dev/socket/logdw", W_OK) == 0) {
66 return 0;
67 }
68 return -EBADF;
Mark Salyzyn018a96d2016-03-01 13:45:42 -080069}
70
Tom Cherry05de1ba2019-02-12 11:26:23 -080071// Connects to /dev/socket/<name> and returns the associated fd or returns -1 on error.
72// O_CLOEXEC is always set.
73static int socket_local_client(const std::string& name, int type) {
74 sockaddr_un addr = {.sun_family = AF_LOCAL};
Mark Salyzyn018a96d2016-03-01 13:45:42 -080075
Tom Cherry05de1ba2019-02-12 11:26:23 -080076 std::string path = "/dev/socket/" + name;
77 if (path.size() + 1 > sizeof(addr.sun_path)) {
78 return -1;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080079 }
Tom Cherry05de1ba2019-02-12 11:26:23 -080080 strlcpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path));
Mark Salyzyn018a96d2016-03-01 13:45:42 -080081
Tom Cherry05de1ba2019-02-12 11:26:23 -080082 int fd = socket(AF_LOCAL, type | SOCK_CLOEXEC, 0);
Tom Cherry29d0e892019-10-08 10:18:20 -070083 if (fd == -1) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080084 return -1;
85 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -080086
Tom Cherry05de1ba2019-02-12 11:26:23 -080087 if (connect(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1) {
88 close(fd);
89 return -1;
90 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -080091
Tom Cherry05de1ba2019-02-12 11:26:23 -080092 return fd;
93}
Mark Salyzyn018a96d2016-03-01 13:45:42 -080094
95/* worker for sending the command to the logger */
Tom Cherry9156c532019-11-14 08:56:39 -080096ssize_t SendLogdControlMessage(char* buf, size_t buf_size) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080097 ssize_t ret;
98 size_t len;
99 char* cp;
100 int errno_save = 0;
Tom Cherry05de1ba2019-02-12 11:26:23 -0800101 int sock = socket_local_client("logd", SOCK_STREAM);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800102 if (sock < 0) {
103 return sock;
104 }
105
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800106 len = strlen(buf) + 1;
107 ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
108 if (ret <= 0) {
109 goto done;
110 }
111
112 len = buf_size;
113 cp = buf;
114 while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) {
115 struct pollfd p;
116
117 if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) {
118 break;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800119 }
120
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800121 len -= ret;
122 cp += ret;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800123
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800124 memset(&p, 0, sizeof(p));
125 p.fd = sock;
126 p.events = POLLIN;
127
128 /* Give other side 20ms to refill pipe */
129 ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20));
130
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800131 if (ret <= 0) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800132 break;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800133 }
134
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800135 if (!(p.revents & POLLIN)) {
136 ret = 0;
137 break;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800138 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800139 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800140
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800141 if (ret >= 0) {
142 ret += buf_size - len;
143 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800144
145done:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800146 if ((ret == -1) && errno) {
147 errno_save = errno;
148 }
149 close(sock);
150 if (errno_save) {
151 errno = errno_save;
152 }
153 return ret;
154}
155
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800156static int check_log_success(char* buf, ssize_t ret) {
157 if (ret < 0) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800158 return ret;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800159 }
160
161 if (strncmp(buf, "success", 7)) {
162 errno = EINVAL;
163 return -1;
164 }
165
166 return 0;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800167}
168
Tom Cherry9156c532019-11-14 08:56:39 -0800169int android_logger_clear(struct logger* logger) {
170 if (!android_logger_is_logd(logger)) {
171 return -EINVAL;
172 }
173 uint32_t log_id = android_logger_get_id(logger);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800174 char buf[512];
Tom Cherry9156c532019-11-14 08:56:39 -0800175 snprintf(buf, sizeof(buf), "clear %" PRIu32, log_id);
Mark Salyzync9e5f372016-09-21 09:24:13 -0700176
Tom Cherry9156c532019-11-14 08:56:39 -0800177 return check_log_success(buf, SendLogdControlMessage(buf, sizeof(buf)));
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800178}
179
180/* returns the total size of the log's ring buffer */
Tom Cherry9156c532019-11-14 08:56:39 -0800181long android_logger_get_log_size(struct logger* logger) {
182 if (!android_logger_is_logd(logger)) {
183 return -EINVAL;
184 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800185
Tom Cherry9156c532019-11-14 08:56:39 -0800186 uint32_t log_id = android_logger_get_id(logger);
187 char buf[512];
188 snprintf(buf, sizeof(buf), "getLogSize %" PRIu32, log_id);
189
190 ssize_t ret = SendLogdControlMessage(buf, sizeof(buf));
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800191 if (ret < 0) {
192 return ret;
193 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800194
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800195 if ((buf[0] < '0') || ('9' < buf[0])) {
196 return -1;
197 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800198
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800199 return atol(buf);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800200}
201
Tom Cherry9156c532019-11-14 08:56:39 -0800202int android_logger_set_log_size(struct logger* logger, unsigned long size) {
203 if (!android_logger_is_logd(logger)) {
204 return -EINVAL;
205 }
206
207 uint32_t log_id = android_logger_get_id(logger);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800208 char buf[512];
Tom Cherry9156c532019-11-14 08:56:39 -0800209 snprintf(buf, sizeof(buf), "setLogSize %" PRIu32 " %lu", log_id, size);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800210
Tom Cherry9156c532019-11-14 08:56:39 -0800211 return check_log_success(buf, SendLogdControlMessage(buf, sizeof(buf)));
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800212}
213
214/*
215 * returns the readable size of the log's ring buffer (that is, amount of the
216 * log consumed)
217 */
Tom Cherry9156c532019-11-14 08:56:39 -0800218long android_logger_get_log_readable_size(struct logger* logger) {
219 if (!android_logger_is_logd(logger)) {
220 return -EINVAL;
221 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800222
Tom Cherry9156c532019-11-14 08:56:39 -0800223 uint32_t log_id = android_logger_get_id(logger);
224 char buf[512];
225 snprintf(buf, sizeof(buf), "getLogSizeUsed %" PRIu32, log_id);
226
227 ssize_t ret = SendLogdControlMessage(buf, sizeof(buf));
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800228 if (ret < 0) {
229 return ret;
230 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800231
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800232 if ((buf[0] < '0') || ('9' < buf[0])) {
233 return -1;
234 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800235
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800236 return atol(buf);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800237}
238
Tom Cherry9156c532019-11-14 08:56:39 -0800239int android_logger_get_log_version(struct logger*) {
240 return 4;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800241}
242
Tom Cherry9156c532019-11-14 08:56:39 -0800243ssize_t android_logger_get_statistics(struct logger_list* logger_list, char* buf, size_t len) {
244 if (logger_list->mode & ANDROID_LOG_PSTORE) {
245 return -EINVAL;
246 }
247
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800248 char* cp = buf;
249 size_t remaining = len;
250 size_t n;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800251
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800252 n = snprintf(cp, remaining, "getStatistics");
Elliott Hughes6efbda72019-10-02 12:27:03 -0700253 n = MIN(n, remaining);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800254 remaining -= n;
255 cp += n;
256
Tom Cherry9156c532019-11-14 08:56:39 -0800257 for (size_t log_id = 0; log_id < LOG_ID_MAX; ++log_id) {
258 if ((1 << log_id) & logger_list->log_mask) {
259 n = snprintf(cp, remaining, " %zu", log_id);
260 n = MIN(n, remaining);
261 remaining -= n;
262 cp += n;
263 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800264 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800265
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800266 if (logger_list->pid) {
267 snprintf(cp, remaining, " pid=%u", logger_list->pid);
268 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800269
Tom Cherry9156c532019-11-14 08:56:39 -0800270 return SendLogdControlMessage(buf, len);
271}
272ssize_t android_logger_get_prune_list(struct logger_list* logger_list, char* buf, size_t len) {
273 if (logger_list->mode & ANDROID_LOG_PSTORE) {
274 return -EINVAL;
275 }
276
277 snprintf(buf, len, "getPruneList");
278 return SendLogdControlMessage(buf, len);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800279}
280
Tom Cherry9156c532019-11-14 08:56:39 -0800281int android_logger_set_prune_list(struct logger_list* logger_list, char* buf, size_t len) {
282 if (logger_list->mode & ANDROID_LOG_PSTORE) {
283 return -EINVAL;
284 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800285
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800286 const char cmd[] = "setPruneList ";
287 const size_t cmdlen = sizeof(cmd) - 1;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800288
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800289 if (strlen(buf) > (len - cmdlen)) {
290 return -ENOMEM; /* KISS */
291 }
292 memmove(buf + cmdlen, buf, len - cmdlen);
293 buf[len - 1] = '\0';
294 memcpy(buf, cmd, cmdlen);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800295
Tom Cherry9156c532019-11-14 08:56:39 -0800296 return check_log_success(buf, SendLogdControlMessage(buf, len));
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800297}
298
Tom Cherry828db1a2019-11-14 10:39:40 -0800299static int logdOpen(struct logger_list* logger_list, struct android_log_transport_context* transp) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800300 char buffer[256], *cp, c;
Tom Cherry53980212019-10-08 09:05:26 -0700301 int ret, remaining, sock;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800302
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800303 if (!logger_list) {
304 return -EINVAL;
305 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800306
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800307 sock = atomic_load(&transp->context.sock);
308 if (sock > 0) {
309 return sock;
310 }
Mark Salyzyndb8a2662016-10-10 07:27:42 -0700311
Tom Cherry05de1ba2019-02-12 11:26:23 -0800312 sock = socket_local_client("logdr", SOCK_SEQPACKET);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800313 if (sock <= 0) {
314 if ((sock == -1) && errno) {
315 return -errno;
Mark Salyzyndb8a2662016-10-10 07:27:42 -0700316 }
317 return sock;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800318 }
319
Tom Cherry71ba1642019-01-10 10:37:36 -0800320 strcpy(buffer, (logger_list->mode & ANDROID_LOG_NONBLOCK) ? "dumpAndClose" : "stream");
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800321 cp = buffer + strlen(buffer);
322
323 strcpy(cp, " lids");
324 cp += 5;
325 c = '=';
326 remaining = sizeof(buffer) - (cp - buffer);
Tom Cherry9156c532019-11-14 08:56:39 -0800327
328 for (size_t log_id = 0; log_id < LOG_ID_MAX; ++log_id) {
329 if ((1 << log_id) & logger_list->log_mask) {
330 ret = snprintf(cp, remaining, "%c%zu", c, log_id);
331 ret = MIN(ret, remaining);
332 remaining -= ret;
333 cp += ret;
334 c = ',';
335 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800336 }
337
338 if (logger_list->tail) {
339 ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
Elliott Hughes6efbda72019-10-02 12:27:03 -0700340 ret = MIN(ret, remaining);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800341 remaining -= ret;
342 cp += ret;
343 }
344
345 if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
346 if (logger_list->mode & ANDROID_LOG_WRAP) {
347 // ToDo: alternate API to allow timeout to be adjusted.
Tom Cherry71ba1642019-01-10 10:37:36 -0800348 ret = snprintf(cp, remaining, " timeout=%u", ANDROID_LOG_WRAP_DEFAULT_TIMEOUT);
Elliott Hughes6efbda72019-10-02 12:27:03 -0700349 ret = MIN(ret, remaining);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800350 remaining -= ret;
351 cp += ret;
352 }
Tom Cherry71ba1642019-01-10 10:37:36 -0800353 ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32, logger_list->start.tv_sec,
354 logger_list->start.tv_nsec);
Elliott Hughes6efbda72019-10-02 12:27:03 -0700355 ret = MIN(ret, remaining);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800356 remaining -= ret;
357 cp += ret;
358 }
359
360 if (logger_list->pid) {
361 ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
Elliott Hughes6efbda72019-10-02 12:27:03 -0700362 ret = MIN(ret, remaining);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800363 cp += ret;
364 }
365
Tom Cherry53980212019-10-08 09:05:26 -0700366 ret = TEMP_FAILURE_RETRY(write(sock, buffer, cp - buffer));
367 int write_errno = errno;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800368
369 if (ret <= 0) {
370 close(sock);
Tom Cherry53980212019-10-08 09:05:26 -0700371 if (ret == -1) {
372 return -write_errno;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800373 }
374 if (ret == 0) {
375 return -EIO;
376 }
377 return ret;
378 }
379
380 ret = atomic_exchange(&transp->context.sock, sock);
381 if ((ret > 0) && (ret != sock)) {
382 close(ret);
383 }
384 return sock;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800385}
386
387/* Read from the selected logs */
Tom Cherry828db1a2019-11-14 10:39:40 -0800388static int LogdRead(struct logger_list* logger_list, struct android_log_transport_context* transp,
389 struct log_msg* log_msg) {
Tom Cherry53980212019-10-08 09:05:26 -0700390 int ret = logdOpen(logger_list, transp);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800391 if (ret < 0) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800392 return ret;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800393 }
394
395 memset(log_msg, 0, sizeof(*log_msg));
396
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800397 /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
Tom Cherry53980212019-10-08 09:05:26 -0700398 ret = TEMP_FAILURE_RETRY(recv(ret, log_msg, LOGGER_ENTRY_MAX_LEN, 0));
399 if ((logger_list->mode & ANDROID_LOG_NONBLOCK) && ret == 0) {
400 return -EAGAIN;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800401 }
402
Tom Cherry53980212019-10-08 09:05:26 -0700403 if (ret == -1) {
404 return -errno;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800405 }
406 return ret;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800407}
408
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800409/* Close all the logs */
Tom Cherry828db1a2019-11-14 10:39:40 -0800410static void LogdClose(struct logger_list*, struct android_log_transport_context* transp) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800411 int sock = atomic_exchange(&transp->context.sock, -1);
412 if (sock > 0) {
413 close(sock);
414 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800415}