blob: 234ddc75ba26370e5e16f81a52a5623b5dd4a37a [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
Tom Cherry283c9a12020-05-14 19:25:05 -070026#include <android-base/stringprintf.h>
Mark Salyzyn0175b072014-02-26 09:50:16 -080027#include <cutils/sockets.h>
Tom Cherryd5b38382020-05-12 13:16:41 -070028#include <private/android_filesystem_config.h>
Mark Salyzynaeaaf812016-09-30 13:30:33 -070029#include <private/android_logger.h>
Mark Salyzyn0175b072014-02-26 09:50:16 -080030
Mark Salyzyn2ad0bd02016-02-23 08:55:43 -080031#include "LogBuffer.h"
32#include "LogBufferElement.h"
Tom Cherry4e9bf952020-05-15 10:13:38 -070033#include "LogPermissions.h"
Mark Salyzyn2ad0bd02016-02-23 08:55:43 -080034#include "LogReader.h"
35#include "LogUtils.h"
Tom Cherry283c9a12020-05-14 19:25:05 -070036#include "LogWriter.h"
Mark Salyzyn0175b072014-02-26 09:50:16 -080037
Tom Cherry79d54f72020-05-04 11:13:55 -070038static bool CanReadSecurityLogs(SocketClient* client) {
39 return client->getUid() == AID_SYSTEM || client->getGid() == AID_SYSTEM;
40}
41
Tom Cherry283c9a12020-05-14 19:25:05 -070042static std::string SocketClientToName(SocketClient* client) {
43 return android::base::StringPrintf("pid %d, fd %d", client->getPid(), client->getSocket());
44}
45
46class SocketLogWriter : public LogWriter {
47 public:
48 SocketLogWriter(LogReader* reader, SocketClient* client, bool privileged,
49 bool can_read_security_logs)
50 : LogWriter(client->getUid(), privileged, can_read_security_logs),
51 reader_(reader),
52 client_(client) {}
53
54 bool Write(const logger_entry& entry, const char* msg) override {
55 struct iovec iovec[2];
56 iovec[0].iov_base = const_cast<logger_entry*>(&entry);
57 iovec[0].iov_len = entry.hdr_size;
58 iovec[1].iov_base = const_cast<char*>(msg);
59 iovec[1].iov_len = entry.len;
60
61 return client_->sendDatav(iovec, 1 + (entry.len != 0)) == 0;
62 }
63
64 void Release() override {
65 reader_->release(client_);
66 client_->decRef();
67 }
68
69 void Shutdown() override { shutdown(client_->getSocket(), SHUT_RDWR); }
70
71 std::string name() const override { return SocketClientToName(client_); }
72
73 private:
74 LogReader* reader_;
75 SocketClient* client_;
76};
77
Tom Cherry68630a02020-05-11 16:29:29 -070078LogReader::LogReader(LogBuffer* logbuf, LogReaderList* reader_list)
79 : SocketListener(getLogSocket(), true), log_buffer_(logbuf), reader_list_(reader_list) {}
Mark Salyzyn0175b072014-02-26 09:50:16 -080080
Tom Cherry4f227862018-10-08 17:33:50 -070081// Note returning false will release the SocketClient instance.
Mark Salyzyn501c3732017-03-10 14:31:54 -080082bool LogReader::onDataAvailable(SocketClient* cli) {
Mark Salyzyne3aeeee2015-03-17 07:56:32 -070083 static bool name_set;
84 if (!name_set) {
85 prctl(PR_SET_NAME, "logd.reader");
86 name_set = true;
87 }
Mark Salyzyn8daa9af2014-04-28 14:07:23 -070088
Mark Salyzyn0175b072014-02-26 09:50:16 -080089 char buffer[255];
90
91 int len = read(cli->getSocket(), buffer, sizeof(buffer) - 1);
92 if (len <= 0) {
Tom Cherry283c9a12020-05-14 19:25:05 -070093 DoSocketDelete(cli);
Mark Salyzyn0175b072014-02-26 09:50:16 -080094 return false;
95 }
96 buffer[len] = '\0';
97
Tom Cherry283c9a12020-05-14 19:25:05 -070098 // Clients are only allowed to send one command, disconnect them if they send another.
99 if (DoSocketDelete(cli)) {
100 return false;
Tom Cherry4f227862018-10-08 17:33:50 -0700101 }
Tom Cherry4f227862018-10-08 17:33:50 -0700102
Mark Salyzyn0175b072014-02-26 09:50:16 -0800103 unsigned long tail = 0;
104 static const char _tail[] = " tail=";
Mark Salyzyn501c3732017-03-10 14:31:54 -0800105 char* cp = strstr(buffer, _tail);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800106 if (cp) {
107 tail = atol(cp + sizeof(_tail) - 1);
108 }
109
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800110 log_time start(log_time::EPOCH);
111 static const char _start[] = " start=";
112 cp = strstr(buffer, _start);
113 if (cp) {
114 // Parse errors will result in current time
115 start.strptime(cp + sizeof(_start) - 1, "%s.%q");
116 }
117
Tom Cherry68630a02020-05-11 16:29:29 -0700118 std::chrono::steady_clock::time_point deadline = {};
Mark Salyzynb75cce02015-11-30 11:35:56 -0800119 static const char _timeout[] = " timeout=";
120 cp = strstr(buffer, _timeout);
121 if (cp) {
Tom Cherry68630a02020-05-11 16:29:29 -0700122 long timeout_seconds = atol(cp + sizeof(_timeout) - 1);
123 deadline = std::chrono::steady_clock::now() + std::chrono::seconds(timeout_seconds);
Mark Salyzynb75cce02015-11-30 11:35:56 -0800124 }
125
Mark Salyzyn0175b072014-02-26 09:50:16 -0800126 unsigned int logMask = -1;
127 static const char _logIds[] = " lids=";
128 cp = strstr(buffer, _logIds);
129 if (cp) {
130 logMask = 0;
131 cp += sizeof(_logIds) - 1;
132 while (*cp && *cp != '\0') {
133 int val = 0;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800134 while (isdigit(*cp)) {
135 val = val * 10 + *cp - '0';
Mark Salyzyn0175b072014-02-26 09:50:16 -0800136 ++cp;
137 }
138 logMask |= 1 << val;
139 if (*cp != ',') {
140 break;
141 }
142 ++cp;
143 }
144 }
145
146 pid_t pid = 0;
147 static const char _pid[] = " pid=";
148 cp = strstr(buffer, _pid);
149 if (cp) {
150 pid = atol(cp + sizeof(_pid) - 1);
151 }
152
153 bool nonBlock = false;
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800154 if (!fastcmp<strncmp>(buffer, "dumpAndClose", 12)) {
Mark Salyzynf669acb2014-09-16 09:19:47 -0700155 // Allow writer to get some cycles, and wait for pending notifications
156 sched_yield();
Tom Cherry68630a02020-05-11 16:29:29 -0700157 reader_list_->reader_threads_lock().lock();
158 reader_list_->reader_threads_lock().unlock();
Mark Salyzynf669acb2014-09-16 09:19:47 -0700159 sched_yield();
Mark Salyzyn0175b072014-02-26 09:50:16 -0800160 nonBlock = true;
161 }
162
Tom Cherry79d54f72020-05-04 11:13:55 -0700163 bool privileged = clientHasLogCredentials(cli);
164 bool can_read_security = CanReadSecurityLogs(cli);
165
Tom Cherry283c9a12020-05-14 19:25:05 -0700166 std::unique_ptr<LogWriter> socket_log_writer(
167 new SocketLogWriter(this, cli, privileged, can_read_security));
168
Tom Cherry10d086e2019-08-21 14:16:34 -0700169 uint64_t sequence = 1;
170 // Convert realtime to sequence number
171 if (start != log_time::EPOCH) {
Tom Cherry320f5962020-05-04 17:25:34 -0700172 bool start_time_set = false;
Tom Cherry320f5962020-05-04 17:25:34 -0700173 uint64_t last = sequence;
Tom Cherryf2c27462020-04-08 14:36:05 -0700174 auto log_find_start = [pid, logMask, start, &sequence, &start_time_set,
Tom Cherry68630a02020-05-11 16:29:29 -0700175 &last](const LogBufferElement* element) -> FlushToResult {
Tom Cherry320f5962020-05-04 17:25:34 -0700176 if (pid && pid != element->getPid()) {
Tom Cherry68630a02020-05-11 16:29:29 -0700177 return FlushToResult::kSkip;
Mark Salyzyna1c60cf2014-02-19 07:33:12 -0800178 }
Tom Cherry320f5962020-05-04 17:25:34 -0700179 if ((logMask & (1 << element->getLogId())) == 0) {
Tom Cherry68630a02020-05-11 16:29:29 -0700180 return FlushToResult::kSkip;
Tom Cherry320f5962020-05-04 17:25:34 -0700181 }
182 if (start == element->getRealTime()) {
183 sequence = element->getSequence();
184 start_time_set = true;
Tom Cherry68630a02020-05-11 16:29:29 -0700185 return FlushToResult::kStop;
Tom Cherryf2c27462020-04-08 14:36:05 -0700186 } else {
Tom Cherry320f5962020-05-04 17:25:34 -0700187 if (start < element->getRealTime()) {
188 sequence = last;
189 start_time_set = true;
Tom Cherry68630a02020-05-11 16:29:29 -0700190 return FlushToResult::kStop;
Tom Cherry320f5962020-05-04 17:25:34 -0700191 }
192 last = element->getSequence();
Tom Cherry320f5962020-05-04 17:25:34 -0700193 }
Tom Cherry68630a02020-05-11 16:29:29 -0700194 return FlushToResult::kSkip;
Tom Cherry320f5962020-05-04 17:25:34 -0700195 };
Mark Salyzyna1c60cf2014-02-19 07:33:12 -0800196
Tom Cherry283c9a12020-05-14 19:25:05 -0700197 log_buffer_->FlushTo(socket_log_writer.get(), sequence, nullptr, log_find_start);
Mark Salyzyna1c60cf2014-02-19 07:33:12 -0800198
Tom Cherry320f5962020-05-04 17:25:34 -0700199 if (!start_time_set) {
Tom Cherry10d086e2019-08-21 14:16:34 -0700200 if (nonBlock) {
Tom Cherry10d086e2019-08-21 14:16:34 -0700201 return false;
202 }
Tom Cherrya3c5ff52020-05-21 13:56:33 -0700203 sequence = log_buffer_->sequence();
Mark Salyzyna1c60cf2014-02-19 07:33:12 -0800204 }
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800205 }
206
Mark Salyzynfa3add32016-12-29 07:26:30 -0800207 android::prdebug(
Tom Cherry10d086e2019-08-21 14:16:34 -0700208 "logdr: UID=%d GID=%d PID=%d %c tail=%lu logMask=%x pid=%d "
Tom Cherry68630a02020-05-11 16:29:29 -0700209 "start=%" PRIu64 "ns deadline=%" PRIi64 "ns\n",
Tom Cherry10d086e2019-08-21 14:16:34 -0700210 cli->getUid(), cli->getGid(), cli->getPid(), nonBlock ? 'n' : 'b', tail, logMask,
Tom Cherry68630a02020-05-11 16:29:29 -0700211 (int)pid, start.nsec(), static_cast<int64_t>(deadline.time_since_epoch().count()));
Mark Salyzynfa3add32016-12-29 07:26:30 -0800212
Tom Cherry10d086e2019-08-21 14:16:34 -0700213 if (start == log_time::EPOCH) {
Tom Cherry68630a02020-05-11 16:29:29 -0700214 deadline = {};
Tom Cherrye2d30d12018-10-19 13:51:35 -0700215 }
216
Tom Cherry68630a02020-05-11 16:29:29 -0700217 auto lock = std::lock_guard{reader_list_->reader_threads_lock()};
Tom Cherry283c9a12020-05-14 19:25:05 -0700218 auto entry = std::make_unique<LogReaderThread>(log_buffer_, reader_list_,
219 std::move(socket_log_writer), nonBlock, tail,
220 logMask, pid, start, sequence, deadline);
Tom Cherry4f227862018-10-08 17:33:50 -0700221 // release client and entry reference counts once done
222 cli->incRef();
Tom Cherry68630a02020-05-11 16:29:29 -0700223 reader_list_->reader_threads().emplace_front(std::move(entry));
Mark Salyzyn5c77ad52016-02-23 08:55:43 -0800224
225 // Set acceptable upper limit to wait for slow reader processing b/27242723
226 struct timeval t = { LOGD_SNDTIMEO, 0 };
Mark Salyzyn501c3732017-03-10 14:31:54 -0800227 setsockopt(cli->getSocket(), SOL_SOCKET, SO_SNDTIMEO, (const char*)&t,
228 sizeof(t));
Mark Salyzyn5c77ad52016-02-23 08:55:43 -0800229
Mark Salyzyn0175b072014-02-26 09:50:16 -0800230 return true;
231}
232
Tom Cherry283c9a12020-05-14 19:25:05 -0700233bool LogReader::DoSocketDelete(SocketClient* cli) {
234 auto cli_name = SocketClientToName(cli);
Tom Cherry68630a02020-05-11 16:29:29 -0700235 auto lock = std::lock_guard{reader_list_->reader_threads_lock()};
Tom Cherry283c9a12020-05-14 19:25:05 -0700236 for (const auto& reader : reader_list_->reader_threads()) {
237 if (reader->name() == cli_name) {
238 reader->release_Locked();
239 return true;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800240 }
Mark Salyzyn0175b072014-02-26 09:50:16 -0800241 }
Tom Cherry283c9a12020-05-14 19:25:05 -0700242 return false;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800243}
Mark Salyzyndfc47e82014-03-24 10:26:47 -0700244
245int LogReader::getLogSocket() {
246 static const char socketName[] = "logdr";
247 int sock = android_get_control_socket(socketName);
248
249 if (sock < 0) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800250 sock = socket_local_server(
251 socketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET);
Mark Salyzyndfc47e82014-03-24 10:26:47 -0700252 }
253
254 return sock;
255}