blob: cc515426d140882857adf4240b6233d28d6e4559 [file] [log] [blame]
Mark Salyzyn0175b072014-02-26 09:50:16 -08001/*
2 * Copyright (C) 2012-2013 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 Salyzynfa3716b2014-02-14 16:05:05 -080017#include <ctype.h>
Mark Salyzynfa3add32016-12-29 07:26:30 -080018#include <inttypes.h>
Mark Salyzyn0175b072014-02-26 09:50:16 -080019#include <poll.h>
Mark Salyzyn8daa9af2014-04-28 14:07:23 -070020#include <sys/prctl.h>
Mark Salyzyn0175b072014-02-26 09:50:16 -080021#include <sys/socket.h>
Mark Salyzyn5c77ad52016-02-23 08:55:43 -080022#include <sys/types.h>
Mark Salyzyndfc47e82014-03-24 10:26:47 -070023
Tom Cherry68630a02020-05-11 16:29:29 -070024#include <chrono>
25
Mark Salyzyn0175b072014-02-26 09:50:16 -080026#include <cutils/sockets.h>
Mark Salyzynaeaaf812016-09-30 13:30:33 -070027#include <private/android_logger.h>
Mark Salyzyn0175b072014-02-26 09:50:16 -080028
Mark Salyzyn2ad0bd02016-02-23 08:55:43 -080029#include "LogBuffer.h"
30#include "LogBufferElement.h"
31#include "LogReader.h"
32#include "LogUtils.h"
Mark Salyzyn0175b072014-02-26 09:50:16 -080033
Tom Cherry79d54f72020-05-04 11:13:55 -070034static bool CanReadSecurityLogs(SocketClient* client) {
35 return client->getUid() == AID_SYSTEM || client->getGid() == AID_SYSTEM;
36}
37
Tom Cherry68630a02020-05-11 16:29:29 -070038LogReader::LogReader(LogBuffer* logbuf, LogReaderList* reader_list)
39 : SocketListener(getLogSocket(), true), log_buffer_(logbuf), reader_list_(reader_list) {}
Mark Salyzyn0175b072014-02-26 09:50:16 -080040
Tom Cherry4f227862018-10-08 17:33:50 -070041// Note returning false will release the SocketClient instance.
Mark Salyzyn501c3732017-03-10 14:31:54 -080042bool LogReader::onDataAvailable(SocketClient* cli) {
Mark Salyzyne3aeeee2015-03-17 07:56:32 -070043 static bool name_set;
44 if (!name_set) {
45 prctl(PR_SET_NAME, "logd.reader");
46 name_set = true;
47 }
Mark Salyzyn8daa9af2014-04-28 14:07:23 -070048
Mark Salyzyn0175b072014-02-26 09:50:16 -080049 char buffer[255];
50
51 int len = read(cli->getSocket(), buffer, sizeof(buffer) - 1);
52 if (len <= 0) {
53 doSocketDelete(cli);
54 return false;
55 }
56 buffer[len] = '\0';
57
Tom Cherry4f227862018-10-08 17:33:50 -070058 // Clients are only allowed to send one command, disconnect them if they
59 // send another.
Tom Cherry68630a02020-05-11 16:29:29 -070060 {
61 auto lock = std::lock_guard{reader_list_->reader_threads_lock()};
62 for (const auto& entry : reader_list_->reader_threads()) {
63 if (entry->client() == cli) {
64 entry->release_Locked();
65 return false;
66 }
Tom Cherry4f227862018-10-08 17:33:50 -070067 }
68 }
Tom Cherry4f227862018-10-08 17:33:50 -070069
Mark Salyzyn0175b072014-02-26 09:50:16 -080070 unsigned long tail = 0;
71 static const char _tail[] = " tail=";
Mark Salyzyn501c3732017-03-10 14:31:54 -080072 char* cp = strstr(buffer, _tail);
Mark Salyzyn0175b072014-02-26 09:50:16 -080073 if (cp) {
74 tail = atol(cp + sizeof(_tail) - 1);
75 }
76
Mark Salyzynfa3716b2014-02-14 16:05:05 -080077 log_time start(log_time::EPOCH);
78 static const char _start[] = " start=";
79 cp = strstr(buffer, _start);
80 if (cp) {
81 // Parse errors will result in current time
82 start.strptime(cp + sizeof(_start) - 1, "%s.%q");
83 }
84
Tom Cherry68630a02020-05-11 16:29:29 -070085 std::chrono::steady_clock::time_point deadline = {};
Mark Salyzynb75cce02015-11-30 11:35:56 -080086 static const char _timeout[] = " timeout=";
87 cp = strstr(buffer, _timeout);
88 if (cp) {
Tom Cherry68630a02020-05-11 16:29:29 -070089 long timeout_seconds = atol(cp + sizeof(_timeout) - 1);
90 deadline = std::chrono::steady_clock::now() + std::chrono::seconds(timeout_seconds);
Mark Salyzynb75cce02015-11-30 11:35:56 -080091 }
92
Mark Salyzyn0175b072014-02-26 09:50:16 -080093 unsigned int logMask = -1;
94 static const char _logIds[] = " lids=";
95 cp = strstr(buffer, _logIds);
96 if (cp) {
97 logMask = 0;
98 cp += sizeof(_logIds) - 1;
99 while (*cp && *cp != '\0') {
100 int val = 0;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800101 while (isdigit(*cp)) {
102 val = val * 10 + *cp - '0';
Mark Salyzyn0175b072014-02-26 09:50:16 -0800103 ++cp;
104 }
105 logMask |= 1 << val;
106 if (*cp != ',') {
107 break;
108 }
109 ++cp;
110 }
111 }
112
113 pid_t pid = 0;
114 static const char _pid[] = " pid=";
115 cp = strstr(buffer, _pid);
116 if (cp) {
117 pid = atol(cp + sizeof(_pid) - 1);
118 }
119
120 bool nonBlock = false;
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800121 if (!fastcmp<strncmp>(buffer, "dumpAndClose", 12)) {
Mark Salyzynf669acb2014-09-16 09:19:47 -0700122 // Allow writer to get some cycles, and wait for pending notifications
123 sched_yield();
Tom Cherry68630a02020-05-11 16:29:29 -0700124 reader_list_->reader_threads_lock().lock();
125 reader_list_->reader_threads_lock().unlock();
Mark Salyzynf669acb2014-09-16 09:19:47 -0700126 sched_yield();
Mark Salyzyn0175b072014-02-26 09:50:16 -0800127 nonBlock = true;
128 }
129
Tom Cherry79d54f72020-05-04 11:13:55 -0700130 bool privileged = clientHasLogCredentials(cli);
131 bool can_read_security = CanReadSecurityLogs(cli);
132
Tom Cherry10d086e2019-08-21 14:16:34 -0700133 uint64_t sequence = 1;
134 // Convert realtime to sequence number
135 if (start != log_time::EPOCH) {
Tom Cherry320f5962020-05-04 17:25:34 -0700136 bool start_time_set = false;
Tom Cherry320f5962020-05-04 17:25:34 -0700137 uint64_t last = sequence;
Tom Cherryf2c27462020-04-08 14:36:05 -0700138 auto log_find_start = [pid, logMask, start, &sequence, &start_time_set,
Tom Cherry68630a02020-05-11 16:29:29 -0700139 &last](const LogBufferElement* element) -> FlushToResult {
Tom Cherry320f5962020-05-04 17:25:34 -0700140 if (pid && pid != element->getPid()) {
Tom Cherry68630a02020-05-11 16:29:29 -0700141 return FlushToResult::kSkip;
Mark Salyzyna1c60cf2014-02-19 07:33:12 -0800142 }
Tom Cherry320f5962020-05-04 17:25:34 -0700143 if ((logMask & (1 << element->getLogId())) == 0) {
Tom Cherry68630a02020-05-11 16:29:29 -0700144 return FlushToResult::kSkip;
Tom Cherry320f5962020-05-04 17:25:34 -0700145 }
146 if (start == element->getRealTime()) {
147 sequence = element->getSequence();
148 start_time_set = true;
Tom Cherry68630a02020-05-11 16:29:29 -0700149 return FlushToResult::kStop;
Tom Cherryf2c27462020-04-08 14:36:05 -0700150 } else {
Tom Cherry320f5962020-05-04 17:25:34 -0700151 if (start < element->getRealTime()) {
152 sequence = last;
153 start_time_set = true;
Tom Cherry68630a02020-05-11 16:29:29 -0700154 return FlushToResult::kStop;
Tom Cherry320f5962020-05-04 17:25:34 -0700155 }
156 last = element->getSequence();
Tom Cherry320f5962020-05-04 17:25:34 -0700157 }
Tom Cherry68630a02020-05-11 16:29:29 -0700158 return FlushToResult::kSkip;
Tom Cherry320f5962020-05-04 17:25:34 -0700159 };
Mark Salyzyna1c60cf2014-02-19 07:33:12 -0800160
Tom Cherry68630a02020-05-11 16:29:29 -0700161 log_buffer_->flushTo(cli, sequence, nullptr, privileged, can_read_security, log_find_start);
Mark Salyzyna1c60cf2014-02-19 07:33:12 -0800162
Tom Cherry320f5962020-05-04 17:25:34 -0700163 if (!start_time_set) {
Tom Cherry10d086e2019-08-21 14:16:34 -0700164 if (nonBlock) {
165 doSocketDelete(cli);
166 return false;
167 }
168 sequence = LogBufferElement::getCurrentSequence();
Mark Salyzyna1c60cf2014-02-19 07:33:12 -0800169 }
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800170 }
171
Mark Salyzynfa3add32016-12-29 07:26:30 -0800172 android::prdebug(
Tom Cherry10d086e2019-08-21 14:16:34 -0700173 "logdr: UID=%d GID=%d PID=%d %c tail=%lu logMask=%x pid=%d "
Tom Cherry68630a02020-05-11 16:29:29 -0700174 "start=%" PRIu64 "ns deadline=%" PRIi64 "ns\n",
Tom Cherry10d086e2019-08-21 14:16:34 -0700175 cli->getUid(), cli->getGid(), cli->getPid(), nonBlock ? 'n' : 'b', tail, logMask,
Tom Cherry68630a02020-05-11 16:29:29 -0700176 (int)pid, start.nsec(), static_cast<int64_t>(deadline.time_since_epoch().count()));
Mark Salyzynfa3add32016-12-29 07:26:30 -0800177
Tom Cherry10d086e2019-08-21 14:16:34 -0700178 if (start == log_time::EPOCH) {
Tom Cherry68630a02020-05-11 16:29:29 -0700179 deadline = {};
Tom Cherrye2d30d12018-10-19 13:51:35 -0700180 }
181
Tom Cherry68630a02020-05-11 16:29:29 -0700182 auto lock = std::lock_guard{reader_list_->reader_threads_lock()};
183 auto entry = std::make_unique<LogReaderThread>(*this, *reader_list_, cli, nonBlock, tail,
184 logMask, pid, start, sequence, deadline,
185 privileged, can_read_security);
Tom Cherry4f227862018-10-08 17:33:50 -0700186 if (!entry->startReader_Locked()) {
Tom Cherry4f227862018-10-08 17:33:50 -0700187 return false;
188 }
189
190 // release client and entry reference counts once done
191 cli->incRef();
Tom Cherry68630a02020-05-11 16:29:29 -0700192 reader_list_->reader_threads().emplace_front(std::move(entry));
Mark Salyzyn5c77ad52016-02-23 08:55:43 -0800193
194 // Set acceptable upper limit to wait for slow reader processing b/27242723
195 struct timeval t = { LOGD_SNDTIMEO, 0 };
Mark Salyzyn501c3732017-03-10 14:31:54 -0800196 setsockopt(cli->getSocket(), SOL_SOCKET, SO_SNDTIMEO, (const char*)&t,
197 sizeof(t));
Mark Salyzyn5c77ad52016-02-23 08:55:43 -0800198
Mark Salyzyn0175b072014-02-26 09:50:16 -0800199 return true;
200}
201
Mark Salyzyn501c3732017-03-10 14:31:54 -0800202void LogReader::doSocketDelete(SocketClient* cli) {
Tom Cherry68630a02020-05-11 16:29:29 -0700203 auto lock = std::lock_guard{reader_list_->reader_threads_lock()};
204 auto it = reader_list_->reader_threads().begin();
205 while (it != reader_list_->reader_threads().end()) {
Tom Cherry6ec71e92020-05-04 12:53:36 -0700206 LogReaderThread* entry = it->get();
Tom Cherrycef47bb2020-05-04 17:10:16 -0700207 if (entry->client() == cli) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800208 entry->release_Locked();
209 break;
210 }
211 it++;
212 }
Mark Salyzyn0175b072014-02-26 09:50:16 -0800213}
Mark Salyzyndfc47e82014-03-24 10:26:47 -0700214
215int LogReader::getLogSocket() {
216 static const char socketName[] = "logdr";
217 int sock = android_get_control_socket(socketName);
218
219 if (sock < 0) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800220 sock = socket_local_server(
221 socketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET);
Mark Salyzyndfc47e82014-03-24 10:26:47 -0700222 }
223
224 return sock;
225}