blob: bb54a5a1638e7b8a437ca8d1af5a699ab02ccd20 [file] [log] [blame]
Mark Salyzyn12bac902014-02-26 09:50:16 -08001/*
2 * Copyright (C) 2012-2014 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 */
Mark Salyzynb338b952016-10-24 16:22:17 -070016// for manual checking of stale entries during LogBuffer::erase()
17//#define DEBUG_CHECK_FOR_STALE_ENTRIES
Mark Salyzyn12bac902014-02-26 09:50:16 -080018
Mark Salyzyn4e756fb2014-05-06 07:34:59 -070019#include <ctype.h>
Mark Salyzyn60b99922016-12-16 16:09:15 -080020#include <endian.h>
Mark Salyzyn88fe7cc2015-02-09 08:21:05 -080021#include <errno.h>
Mark Salyzyn12bac902014-02-26 09:50:16 -080022#include <stdio.h>
23#include <string.h>
Mark Salyzynab947712016-10-24 08:20:26 -070024#include <sys/cdefs.h>
Mark Salyzyn7b85c592014-05-09 17:44:18 -070025#include <sys/user.h>
Mark Salyzyn12bac902014-02-26 09:50:16 -080026#include <time.h>
27#include <unistd.h>
28
Mark Salyzyn6a404192015-05-19 09:12:30 -070029#include <unordered_map>
Tom Cherryac228f12019-08-21 14:16:34 -070030#include <utility>
Mark Salyzyn6a404192015-05-19 09:12:30 -070031
Mark Salyzyn4e756fb2014-05-06 07:34:59 -070032#include <cutils/properties.h>
Mark Salyzynb0040832016-09-27 13:08:23 -070033#include <private/android_logger.h>
Mark Salyzyn12bac902014-02-26 09:50:16 -080034
35#include "LogBuffer.h"
Mark Salyzyn0e2fe422015-09-08 08:56:32 -070036#include "LogKlog.h"
Mark Salyzyn4e756fb2014-05-06 07:34:59 -070037#include "LogReader.h"
Mark Salyzyn24a57dc2016-12-13 10:31:29 -080038#include "LogUtils.h"
Mark Salyzyn12bac902014-02-26 09:50:16 -080039
Mark Salyzynab947712016-10-24 08:20:26 -070040#ifndef __predict_false
41#define __predict_false(exp) __builtin_expect((exp) != 0, 0)
42#endif
43
Mark Salyzync89839a2014-02-11 12:29:31 -080044// Default
Mark Salyzync89839a2014-02-11 12:29:31 -080045#define log_buffer_size(id) mMaxSize[id]
Mark Salyzyn4e756fb2014-05-06 07:34:59 -070046
Mark Salyzyn3fe25932015-03-10 16:45:17 -070047void LogBuffer::init() {
Mark Salyzync89839a2014-02-11 12:29:31 -080048 log_id_for_each(i) {
Mark Salyzynb0040832016-09-27 13:08:23 -070049 if (setSize(i, __android_logger_get_buffer_size(i))) {
Mark Salyzyn7b85c592014-05-09 17:44:18 -070050 setSize(i, LOG_BUFFER_MIN_SIZE);
51 }
Mark Salyzync89839a2014-02-11 12:29:31 -080052 }
Tom Cherry98767192020-05-01 16:45:25 -070053 // Release any sleeping reader threads to dump their current content.
Tom Cherry5ecfbf02020-05-11 16:29:29 -070054 auto reader_threads_lock = std::lock_guard{reader_list_->reader_threads_lock()};
55 for (const auto& reader_thread : reader_list_->reader_threads()) {
56 reader_thread->triggerReader_Locked();
Mark Salyzyn0e2fe422015-09-08 08:56:32 -070057 }
Mark Salyzyn12bac902014-02-26 09:50:16 -080058}
59
Tom Cherry5ecfbf02020-05-11 16:29:29 -070060LogBuffer::LogBuffer(LogReaderList* reader_list, LogTags* tags, PruneList* prune,
61 LogStatistics* stats)
62 : reader_list_(reader_list), tags_(tags), prune_(prune), stats_(stats) {
Mark Salyzynd2712b12017-04-18 14:09:45 -070063 pthread_rwlock_init(&mLogElementsLock, nullptr);
Mark Salyzyn3fe25932015-03-10 16:45:17 -070064
Mark Salyzyn24a57dc2016-12-13 10:31:29 -080065 log_id_for_each(i) {
Mark Salyzynbec7b2d2017-03-31 10:48:39 -070066 lastLoggedElements[i] = nullptr;
67 droppedElements[i] = nullptr;
Mark Salyzyn24a57dc2016-12-13 10:31:29 -080068 }
69
Mark Salyzyn3fe25932015-03-10 16:45:17 -070070 init();
71}
72
Mark Salyzyn24a57dc2016-12-13 10:31:29 -080073LogBuffer::~LogBuffer() {
74 log_id_for_each(i) {
75 delete lastLoggedElements[i];
76 delete droppedElements[i];
77 }
78}
79
Tom Cherry402364e2020-04-29 17:58:18 -070080LogBufferElementCollection::iterator LogBuffer::GetOldest(log_id_t log_id) {
81 auto it = mLogElements.begin();
Tom Cherry02017d72020-05-04 10:17:42 -070082 if (oldest_[log_id]) {
83 it = *oldest_[log_id];
Tom Cherry402364e2020-04-29 17:58:18 -070084 }
85 while (it != mLogElements.end() && (*it)->getLogId() != log_id) {
86 it++;
87 }
88 if (it != mLogElements.end()) {
Tom Cherry02017d72020-05-04 10:17:42 -070089 oldest_[log_id] = it;
Tom Cherry402364e2020-04-29 17:58:18 -070090 }
91 return it;
92}
93
Mark Salyzyn65059532017-03-10 14:31:54 -080094enum match_type { DIFFERENT, SAME, SAME_LIBLOG };
Mark Salyzyn60b99922016-12-16 16:09:15 -080095
Mark Salyzyn65059532017-03-10 14:31:54 -080096static enum match_type identical(LogBufferElement* elem,
97 LogBufferElement* last) {
Mark Salyzyn24a57dc2016-12-13 10:31:29 -080098 // is it mostly identical?
Mark Salyzyn65059532017-03-10 14:31:54 -080099 // if (!elem) return DIFFERENT;
Mark Salyzyn530bd6c2016-08-11 08:02:06 -0700100 ssize_t lenl = elem->getMsgLen();
101 if (lenl <= 0) return DIFFERENT; // value if this represents a chatty elem
Mark Salyzyn65059532017-03-10 14:31:54 -0800102 // if (!last) return DIFFERENT;
Mark Salyzyn530bd6c2016-08-11 08:02:06 -0700103 ssize_t lenr = last->getMsgLen();
104 if (lenr <= 0) return DIFFERENT; // value if this represents a chatty elem
Mark Salyzyn65059532017-03-10 14:31:54 -0800105 // if (elem->getLogId() != last->getLogId()) return DIFFERENT;
Mark Salyzyn60b99922016-12-16 16:09:15 -0800106 if (elem->getUid() != last->getUid()) return DIFFERENT;
107 if (elem->getPid() != last->getPid()) return DIFFERENT;
108 if (elem->getTid() != last->getTid()) return DIFFERENT;
Mark Salyzyn24a57dc2016-12-13 10:31:29 -0800109
110 // last is more than a minute old, stop squashing identical messages
111 if (elem->getRealTime().nsec() >
Mark Salyzyn65059532017-03-10 14:31:54 -0800112 (last->getRealTime().nsec() + 60 * NS_PER_SEC))
113 return DIFFERENT;
Mark Salyzyn24a57dc2016-12-13 10:31:29 -0800114
115 // Identical message
116 const char* msgl = elem->getMsg();
117 const char* msgr = last->getMsg();
Mark Salyzyn60b99922016-12-16 16:09:15 -0800118 if (lenl == lenr) {
119 if (!fastcmp<memcmp>(msgl, msgr, lenl)) return SAME;
120 // liblog tagged messages (content gets summed)
121 if ((elem->getLogId() == LOG_ID_EVENTS) &&
122 (lenl == sizeof(android_log_event_int_t)) &&
Mark Salyzyn65059532017-03-10 14:31:54 -0800123 !fastcmp<memcmp>(msgl, msgr, sizeof(android_log_event_int_t) -
124 sizeof(int32_t)) &&
Mark Salyzyn6b344a82017-03-13 15:41:59 -0700125 (elem->getTag() == LIBLOG_LOG_TAG)) {
Mark Salyzyn65059532017-03-10 14:31:54 -0800126 return SAME_LIBLOG;
Mark Salyzyn6b344a82017-03-13 15:41:59 -0700127 }
Mark Salyzyn60b99922016-12-16 16:09:15 -0800128 }
Mark Salyzyn24a57dc2016-12-13 10:31:29 -0800129
130 // audit message (except sequence number) identical?
Mark Salyzyn34aad622018-03-13 11:06:38 -0700131 if (last->isBinary() &&
132 (lenl > static_cast<ssize_t>(sizeof(android_log_event_string_t))) &&
133 (lenr > static_cast<ssize_t>(sizeof(android_log_event_string_t)))) {
Mark Salyzyn65059532017-03-10 14:31:54 -0800134 if (fastcmp<memcmp>(msgl, msgr, sizeof(android_log_event_string_t) -
Mark Salyzyn6b344a82017-03-13 15:41:59 -0700135 sizeof(int32_t))) {
Mark Salyzyn65059532017-03-10 14:31:54 -0800136 return DIFFERENT;
Mark Salyzyn6b344a82017-03-13 15:41:59 -0700137 }
Mark Salyzyn24a57dc2016-12-13 10:31:29 -0800138 msgl += sizeof(android_log_event_string_t);
139 lenl -= sizeof(android_log_event_string_t);
140 msgr += sizeof(android_log_event_string_t);
141 lenr -= sizeof(android_log_event_string_t);
142 }
Mark Salyzyn530bd6c2016-08-11 08:02:06 -0700143 static const char avc[] = "): avc: ";
Mark Salyzyn65059532017-03-10 14:31:54 -0800144 const char* avcl = android::strnstr(msgl, lenl, avc);
Mark Salyzyn60b99922016-12-16 16:09:15 -0800145 if (!avcl) return DIFFERENT;
Mark Salyzyn24a57dc2016-12-13 10:31:29 -0800146 lenl -= avcl - msgl;
Mark Salyzyn65059532017-03-10 14:31:54 -0800147 const char* avcr = android::strnstr(msgr, lenr, avc);
Mark Salyzyn60b99922016-12-16 16:09:15 -0800148 if (!avcr) return DIFFERENT;
Mark Salyzyn24a57dc2016-12-13 10:31:29 -0800149 lenr -= avcr - msgr;
Mark Salyzyn60b99922016-12-16 16:09:15 -0800150 if (lenl != lenr) return DIFFERENT;
Mark Salyzyn530bd6c2016-08-11 08:02:06 -0700151 if (fastcmp<memcmp>(avcl + strlen(avc), avcr + strlen(avc),
Mark Salyzyn6b344a82017-03-13 15:41:59 -0700152 lenl - strlen(avc))) {
Mark Salyzyn65059532017-03-10 14:31:54 -0800153 return DIFFERENT;
Mark Salyzyn6b344a82017-03-13 15:41:59 -0700154 }
Mark Salyzyn60b99922016-12-16 16:09:15 -0800155 return SAME;
Mark Salyzyn24a57dc2016-12-13 10:31:29 -0800156}
157
Mark Salyzyn65059532017-03-10 14:31:54 -0800158int LogBuffer::log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
Chih-Hung Hsieh9ff81552018-08-13 14:22:56 -0700159 pid_t tid, const char* msg, uint16_t len) {
Yi Kong90bcc182018-03-01 17:48:53 -0500160 if (log_id >= LOG_ID_MAX) {
Mark Salyzyn88fe7cc2015-02-09 08:21:05 -0800161 return -EINVAL;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800162 }
Mark Salyzyn0dcfae62014-10-02 13:07:05 -0700163
Mark Salyzyncb722de2017-05-18 10:06:00 -0700164 // Slip the time by 1 nsec if the incoming lands on xxxxxx000 ns.
165 // This prevents any chance that an outside source can request an
166 // exact entry with time specified in ms or us precision.
167 if ((realtime.tv_nsec % 1000) == 0) ++realtime.tv_nsec;
168
Tom Cherry6955f8b2020-02-20 13:21:51 -0800169 LogBufferElement* elem = new LogBufferElement(log_id, realtime, uid, pid, tid, msg, len);
170
171 // b/137093665: don't coalesce security messages.
172 if (log_id == LOG_ID_SECURITY) {
173 wrlock();
174 log(elem);
175 unlock();
176
177 return len;
178 }
179
180 int prio = ANDROID_LOG_INFO;
181 const char* tag = nullptr;
182 size_t tag_len = 0;
183 if (log_id == LOG_ID_EVENTS || log_id == LOG_ID_STATS) {
Tom Cherry04ad4582020-05-01 16:13:18 -0700184 tag = tags_->tagToName(elem->getTag());
Tom Cherry6955f8b2020-02-20 13:21:51 -0800185 if (tag) {
186 tag_len = strlen(tag);
Mark Salyzync9690862015-12-04 10:59:45 -0800187 }
Tom Cherry6955f8b2020-02-20 13:21:51 -0800188 } else {
189 prio = *msg;
190 tag = msg + 1;
191 tag_len = strnlen(tag, len - 1);
192 }
193 if (!__android_log_is_loggable_len(prio, tag, tag_len, ANDROID_LOG_VERBOSE)) {
194 // Log traffic received to total
Tom Cherry479b5032020-05-07 14:44:43 -0700195 stats_->AddTotal(elem);
Tom Cherry6955f8b2020-02-20 13:21:51 -0800196 delete elem;
197 return -EACCES;
Mark Salyzyn0dcfae62014-10-02 13:07:05 -0700198 }
Mark Salyzyn12bac902014-02-26 09:50:16 -0800199
Mark Salyzynd2712b12017-04-18 14:09:45 -0700200 wrlock();
Mark Salyzyn24a57dc2016-12-13 10:31:29 -0800201 LogBufferElement* currentLast = lastLoggedElements[log_id];
202 if (currentLast) {
Mark Salyzyn65059532017-03-10 14:31:54 -0800203 LogBufferElement* dropped = droppedElements[log_id];
Chih-Hung Hsieh9ff81552018-08-13 14:22:56 -0700204 uint16_t count = dropped ? dropped->getDropped() : 0;
Mark Salyzyn52ee5f52016-12-16 16:09:15 -0800205 //
206 // State Init
207 // incoming:
Mark Salyzynbec7b2d2017-03-31 10:48:39 -0700208 // dropped = nullptr
209 // currentLast = nullptr;
Mark Salyzyn52ee5f52016-12-16 16:09:15 -0800210 // elem = incoming message
211 // outgoing:
Mark Salyzynbec7b2d2017-03-31 10:48:39 -0700212 // dropped = nullptr -> State 0
Mark Salyzyn52ee5f52016-12-16 16:09:15 -0800213 // currentLast = copy of elem
214 // log elem
215 // State 0
216 // incoming:
217 // count = 0
Mark Salyzynbec7b2d2017-03-31 10:48:39 -0700218 // dropped = nullptr
Mark Salyzyn52ee5f52016-12-16 16:09:15 -0800219 // currentLast = copy of last message
220 // elem = incoming message
Mark Salyzyn60b99922016-12-16 16:09:15 -0800221 // outgoing: if match != DIFFERENT
Mark Salyzyn52ee5f52016-12-16 16:09:15 -0800222 // dropped = copy of first identical message -> State 1
223 // currentLast = reference to elem
Mark Salyzyn60b99922016-12-16 16:09:15 -0800224 // break: if match == DIFFERENT
Mark Salyzynbec7b2d2017-03-31 10:48:39 -0700225 // dropped = nullptr -> State 0
Mark Salyzyn52ee5f52016-12-16 16:09:15 -0800226 // delete copy of last message (incoming currentLast)
227 // currentLast = copy of elem
228 // log elem
229 // State 1
230 // incoming:
231 // count = 0
232 // dropped = copy of first identical message
233 // currentLast = reference to last held-back incoming
234 // message
235 // elem = incoming message
Mark Salyzyn60b99922016-12-16 16:09:15 -0800236 // outgoing: if match == SAME
Mark Salyzyn52ee5f52016-12-16 16:09:15 -0800237 // delete copy of first identical message (dropped)
238 // dropped = reference to last held-back incoming
239 // message set to chatty count of 1 -> State 2
240 // currentLast = reference to elem
Mark Salyzyn60b99922016-12-16 16:09:15 -0800241 // outgoing: if match == SAME_LIBLOG
242 // dropped = copy of first identical message -> State 1
243 // take sum of currentLast and elem
244 // if sum overflows:
245 // log currentLast
246 // currentLast = reference to elem
247 // else
248 // delete currentLast
249 // currentLast = reference to elem, sum liblog.
250 // break: if match == DIFFERENT
Mark Salyzyn52ee5f52016-12-16 16:09:15 -0800251 // delete dropped
Mark Salyzynbec7b2d2017-03-31 10:48:39 -0700252 // dropped = nullptr -> State 0
Mark Salyzyn52ee5f52016-12-16 16:09:15 -0800253 // log reference to last held-back (currentLast)
254 // currentLast = copy of elem
255 // log elem
256 // State 2
257 // incoming:
258 // count = chatty count
259 // dropped = chatty message holding count
260 // currentLast = reference to last held-back incoming
261 // message.
262 // dropped = chatty message holding count
263 // elem = incoming message
Mark Salyzyn60b99922016-12-16 16:09:15 -0800264 // outgoing: if match != DIFFERENT
Mark Salyzyn52ee5f52016-12-16 16:09:15 -0800265 // delete chatty message holding count
266 // dropped = reference to last held-back incoming
267 // message, set to chatty count + 1
268 // currentLast = reference to elem
Mark Salyzyn60b99922016-12-16 16:09:15 -0800269 // break: if match == DIFFERENT
Mark Salyzyn52ee5f52016-12-16 16:09:15 -0800270 // log dropped (chatty message)
Mark Salyzynbec7b2d2017-03-31 10:48:39 -0700271 // dropped = nullptr -> State 0
Mark Salyzyn52ee5f52016-12-16 16:09:15 -0800272 // log reference to last held-back (currentLast)
273 // currentLast = copy of elem
274 // log elem
275 //
Mark Salyzyn60b99922016-12-16 16:09:15 -0800276 enum match_type match = identical(elem, currentLast);
277 if (match != DIFFERENT) {
Mark Salyzyn24a57dc2016-12-13 10:31:29 -0800278 if (dropped) {
Mark Salyzyn60b99922016-12-16 16:09:15 -0800279 // Sum up liblog tag messages?
280 if ((count == 0) /* at Pass 1 */ && (match == SAME_LIBLOG)) {
281 android_log_event_int_t* event =
282 reinterpret_cast<android_log_event_int_t*>(
283 const_cast<char*>(currentLast->getMsg()));
284 //
285 // To unit test, differentiate with something like:
286 // event->header.tag = htole32(CHATTY_LOG_TAG);
287 // here, then instead of delete currentLast below,
288 // log(currentLast) to see the incremental sums form.
289 //
290 uint32_t swab = event->payload.data;
291 unsigned long long total = htole32(swab);
292 event = reinterpret_cast<android_log_event_int_t*>(
Mark Salyzyn65059532017-03-10 14:31:54 -0800293 const_cast<char*>(elem->getMsg()));
Mark Salyzyn60b99922016-12-16 16:09:15 -0800294 swab = event->payload.data;
295
296 lastLoggedElements[LOG_ID_EVENTS] = elem;
297 total += htole32(swab);
298 // check for overflow
299 if (total >= UINT32_MAX) {
300 log(currentLast);
Mark Salyzynd2712b12017-04-18 14:09:45 -0700301 unlock();
Mark Salyzyn60b99922016-12-16 16:09:15 -0800302 return len;
303 }
Tom Cherry479b5032020-05-07 14:44:43 -0700304 stats_->AddTotal(currentLast);
Mark Salyzyn60b99922016-12-16 16:09:15 -0800305 delete currentLast;
306 swab = total;
307 event->payload.data = htole32(swab);
Mark Salyzynd2712b12017-04-18 14:09:45 -0700308 unlock();
Mark Salyzyn60b99922016-12-16 16:09:15 -0800309 return len;
310 }
Mark Salyzyn24a57dc2016-12-13 10:31:29 -0800311 if (count == USHRT_MAX) {
312 log(dropped);
313 count = 1;
314 } else {
315 delete dropped;
316 ++count;
317 }
318 }
319 if (count) {
Tom Cherry479b5032020-05-07 14:44:43 -0700320 stats_->AddTotal(currentLast);
Mark Salyzyn24a57dc2016-12-13 10:31:29 -0800321 currentLast->setDropped(count);
322 }
323 droppedElements[log_id] = currentLast;
324 lastLoggedElements[log_id] = elem;
Mark Salyzynd2712b12017-04-18 14:09:45 -0700325 unlock();
Mark Salyzyn24a57dc2016-12-13 10:31:29 -0800326 return len;
327 }
Mark Salyzyn65059532017-03-10 14:31:54 -0800328 if (dropped) { // State 1 or 2
329 if (count) { // State 2
330 log(dropped); // report chatty
331 } else { // State 1
332 delete dropped;
Mark Salyzyn52ee5f52016-12-16 16:09:15 -0800333 }
Mark Salyzynbec7b2d2017-03-31 10:48:39 -0700334 droppedElements[log_id] = nullptr;
Mark Salyzyn65059532017-03-10 14:31:54 -0800335 log(currentLast); // report last message in the series
336 } else { // State 0
Mark Salyzyn24a57dc2016-12-13 10:31:29 -0800337 delete currentLast;
338 }
339 }
340 lastLoggedElements[log_id] = new LogBufferElement(*elem);
Mark Salyzyn12bac902014-02-26 09:50:16 -0800341
Mark Salyzyn24a57dc2016-12-13 10:31:29 -0800342 log(elem);
Mark Salyzynd2712b12017-04-18 14:09:45 -0700343 unlock();
Mark Salyzyn24a57dc2016-12-13 10:31:29 -0800344
345 return len;
346}
347
Mark Salyzynd2712b12017-04-18 14:09:45 -0700348// assumes LogBuffer::wrlock() held, owns elem, look after garbage collection
Mark Salyzyn24a57dc2016-12-13 10:31:29 -0800349void LogBuffer::log(LogBufferElement* elem) {
Tom Cherry16935b42019-08-21 13:17:12 -0700350 mLogElements.push_back(elem);
Tom Cherry479b5032020-05-07 14:44:43 -0700351 stats_->Add(elem);
Mark Salyzyn24a57dc2016-12-13 10:31:29 -0800352 maybePrune(elem->getLogId());
Tom Cherry5ecfbf02020-05-11 16:29:29 -0700353 reader_list_->NotifyNewLog(1 << elem->getLogId());
Mark Salyzyn12bac902014-02-26 09:50:16 -0800354}
355
Mark Salyzynd2712b12017-04-18 14:09:45 -0700356// LogBuffer::wrlock() must be held when this function is called.
Mark Salyzyn12bac902014-02-26 09:50:16 -0800357void LogBuffer::maybePrune(log_id_t id) {
Tom Cherry479b5032020-05-07 14:44:43 -0700358 unsigned long prune_rows;
359 if (stats_->ShouldPrune(id, log_buffer_size(id), &prune_rows)) {
360 prune(id, prune_rows);
Mark Salyzyn12bac902014-02-26 09:50:16 -0800361 }
362}
363
Mark Salyzyn1fdf71f2015-09-03 16:08:50 -0700364LogBufferElementCollection::iterator LogBuffer::erase(
Mark Salyzyn65059532017-03-10 14:31:54 -0800365 LogBufferElementCollection::iterator it, bool coalesce) {
366 LogBufferElement* element = *it;
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700367 log_id_t id = element->getLogId();
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700368
Mark Salyzyn11178182016-10-21 09:46:42 -0700369 // Remove iterator references in the various lists that will become stale
370 // after the element is erased from the main logging list.
371
Mark Salyzyn65059532017-03-10 14:31:54 -0800372 { // start of scope for found iterator
373 int key = ((id == LOG_ID_EVENTS) || (id == LOG_ID_SECURITY))
374 ? element->getTag()
375 : element->getUid();
Mark Salyzyn6fa0d032016-07-14 15:34:30 -0700376 LogBufferIteratorMap::iterator found = mLastWorst[id].find(key);
377 if ((found != mLastWorst[id].end()) && (it == found->second)) {
378 mLastWorst[id].erase(found);
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700379 }
Mark Salyzyn5af07be2015-08-19 17:06:11 -0700380 }
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700381
Mark Salyzyn65059532017-03-10 14:31:54 -0800382 { // start of scope for pid found iterator
Mark Salyzyn11178182016-10-21 09:46:42 -0700383 // element->getUid() may not be AID_SYSTEM for next-best-watermark.
Mark Salyzynab947712016-10-24 08:20:26 -0700384 // will not assume id != LOG_ID_EVENTS or LOG_ID_SECURITY for KISS and
385 // long term code stability, find() check should be fast for those ids.
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700386 LogBufferPidIteratorMap::iterator found =
387 mLastWorstPidOfSystem[id].find(element->getPid());
Mark Salyzyn65059532017-03-10 14:31:54 -0800388 if ((found != mLastWorstPidOfSystem[id].end()) &&
389 (it == found->second)) {
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700390 mLastWorstPidOfSystem[id].erase(found);
391 }
392 }
393
Mark Salyzyn75d5cf02016-01-19 16:04:41 -0800394 bool setLast[LOG_ID_MAX];
395 bool doSetLast = false;
Tom Cherry02017d72020-05-04 10:17:42 -0700396 log_id_for_each(i) { doSetLast |= setLast[i] = oldest_[i] && it == *oldest_[i]; }
Mark Salyzynb338b952016-10-24 16:22:17 -0700397#ifdef DEBUG_CHECK_FOR_STALE_ENTRIES
398 LogBufferElementCollection::iterator bad = it;
Mark Salyzyn65059532017-03-10 14:31:54 -0800399 int key = ((id == LOG_ID_EVENTS) || (id == LOG_ID_SECURITY))
400 ? element->getTag()
401 : element->getUid();
Mark Salyzynb338b952016-10-24 16:22:17 -0700402#endif
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700403 it = mLogElements.erase(it);
Mark Salyzyn75d5cf02016-01-19 16:04:41 -0800404 if (doSetLast) {
405 log_id_for_each(i) {
406 if (setLast[i]) {
Tom Cherry402364e2020-04-29 17:58:18 -0700407 if (__predict_false(it == mLogElements.end())) {
Tom Cherry02017d72020-05-04 10:17:42 -0700408 oldest_[i] = std::nullopt;
Mark Salyzyn75d5cf02016-01-19 16:04:41 -0800409 } else {
Tom Cherry02017d72020-05-04 10:17:42 -0700410 oldest_[i] = it; // Store the next iterator even if it does not correspond to
Tom Cherry402364e2020-04-29 17:58:18 -0700411 // the same log_id, as a starting point for GetOldest().
Mark Salyzyn75d5cf02016-01-19 16:04:41 -0800412 }
413 }
Mark Salyzynb7dd96e2016-01-11 10:58:09 -0800414 }
415 }
Mark Salyzynb338b952016-10-24 16:22:17 -0700416#ifdef DEBUG_CHECK_FOR_STALE_ENTRIES
417 log_id_for_each(i) {
Mark Salyzyn65059532017-03-10 14:31:54 -0800418 for (auto b : mLastWorst[i]) {
Mark Salyzynb338b952016-10-24 16:22:17 -0700419 if (bad == b.second) {
Mark Salyzyn65059532017-03-10 14:31:54 -0800420 android::prdebug("stale mLastWorst[%d] key=%d mykey=%d\n", i,
421 b.first, key);
Mark Salyzynb338b952016-10-24 16:22:17 -0700422 }
423 }
Mark Salyzyn65059532017-03-10 14:31:54 -0800424 for (auto b : mLastWorstPidOfSystem[i]) {
Mark Salyzynb338b952016-10-24 16:22:17 -0700425 if (bad == b.second) {
Mark Salyzyn65059532017-03-10 14:31:54 -0800426 android::prdebug("stale mLastWorstPidOfSystem[%d] pid=%d\n", i,
427 b.first);
Mark Salyzynb338b952016-10-24 16:22:17 -0700428 }
429 }
Mark Salyzynb338b952016-10-24 16:22:17 -0700430 }
431#endif
Mark Salyzyn5c5189a2015-09-30 07:40:09 -0700432 if (coalesce) {
Tom Cherry479b5032020-05-07 14:44:43 -0700433 stats_->Erase(element);
Mark Salyzyn5c5189a2015-09-30 07:40:09 -0700434 } else {
Tom Cherry479b5032020-05-07 14:44:43 -0700435 stats_->Subtract(element);
Mark Salyzyn1fdf71f2015-09-03 16:08:50 -0700436 }
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700437 delete element;
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700438
439 return it;
440}
441
Mark Salyzynd84b27e2015-04-17 15:38:04 -0700442// Define a temporary mechanism to report the last LogBufferElement pointer
443// for the specified uid, pid and tid. Used below to help merge-sort when
444// pruning for worst UID.
445class LogBufferElementKey {
446 const union {
447 struct {
Mark Salyzyn16aacd32016-12-13 12:44:20 -0800448 uint32_t uid;
Mark Salyzynd84b27e2015-04-17 15:38:04 -0700449 uint16_t pid;
450 uint16_t tid;
Mark Salyzynd84b27e2015-04-17 15:38:04 -0700451 } __packed;
452 uint64_t value;
453 } __packed;
454
Mark Salyzyn65059532017-03-10 14:31:54 -0800455 public:
456 LogBufferElementKey(uid_t uid, pid_t pid, pid_t tid)
457 : uid(uid), pid(pid), tid(tid) {
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700458 }
Mark Salyzyn65059532017-03-10 14:31:54 -0800459 explicit LogBufferElementKey(uint64_t key) : value(key) {
460 }
Mark Salyzynd84b27e2015-04-17 15:38:04 -0700461
Mark Salyzyn65059532017-03-10 14:31:54 -0800462 uint64_t getKey() {
463 return value;
464 }
Mark Salyzynd84b27e2015-04-17 15:38:04 -0700465};
466
Mark Salyzyn6a404192015-05-19 09:12:30 -0700467class LogBufferElementLast {
Mark Salyzyn65059532017-03-10 14:31:54 -0800468 typedef std::unordered_map<uint64_t, LogBufferElement*> LogBufferElementMap;
Mark Salyzyn6a404192015-05-19 09:12:30 -0700469 LogBufferElementMap map;
Mark Salyzynd84b27e2015-04-17 15:38:04 -0700470
Mark Salyzyn65059532017-03-10 14:31:54 -0800471 public:
Chih-Hung Hsieh9ff81552018-08-13 14:22:56 -0700472 bool coalesce(LogBufferElement* element, uint16_t dropped) {
Mark Salyzyn65059532017-03-10 14:31:54 -0800473 LogBufferElementKey key(element->getUid(), element->getPid(),
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700474 element->getTid());
Mark Salyzyn6a404192015-05-19 09:12:30 -0700475 LogBufferElementMap::iterator it = map.find(key.getKey());
476 if (it != map.end()) {
Mark Salyzyn65059532017-03-10 14:31:54 -0800477 LogBufferElement* found = it->second;
Chih-Hung Hsieh9ff81552018-08-13 14:22:56 -0700478 uint16_t moreDropped = found->getDropped();
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700479 if ((dropped + moreDropped) > USHRT_MAX) {
Mark Salyzyn6a404192015-05-19 09:12:30 -0700480 map.erase(it);
Mark Salyzynd84b27e2015-04-17 15:38:04 -0700481 } else {
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700482 found->setDropped(dropped + moreDropped);
Mark Salyzynd84b27e2015-04-17 15:38:04 -0700483 return true;
484 }
485 }
486 return false;
487 }
488
Mark Salyzyn65059532017-03-10 14:31:54 -0800489 void add(LogBufferElement* element) {
490 LogBufferElementKey key(element->getUid(), element->getPid(),
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700491 element->getTid());
492 map[key.getKey()] = element;
Mark Salyzynd84b27e2015-04-17 15:38:04 -0700493 }
494
Mark Salyzynbe1a30c2015-04-20 14:08:56 -0700495 inline void clear() {
Mark Salyzyn6a404192015-05-19 09:12:30 -0700496 map.clear();
Mark Salyzynbe1a30c2015-04-20 14:08:56 -0700497 }
498
Mark Salyzyn65059532017-03-10 14:31:54 -0800499 void clear(LogBufferElement* element) {
Tom Cherryac228f12019-08-21 14:16:34 -0700500 uint64_t current = element->getRealTime().nsec() - (EXPIRE_RATELIMIT * NS_PER_SEC);
Mark Salyzyn65059532017-03-10 14:31:54 -0800501 for (LogBufferElementMap::iterator it = map.begin(); it != map.end();) {
502 LogBufferElement* mapElement = it->second;
Tom Cherryac228f12019-08-21 14:16:34 -0700503 if (mapElement->getDropped() >= EXPIRE_THRESHOLD &&
504 current > mapElement->getRealTime().nsec()) {
Mark Salyzyn6a404192015-05-19 09:12:30 -0700505 it = map.erase(it);
506 } else {
507 ++it;
Mark Salyzynbe1a30c2015-04-20 14:08:56 -0700508 }
509 }
510 }
Mark Salyzynd84b27e2015-04-17 15:38:04 -0700511};
512
Mark Salyzyn434f3742017-05-11 13:28:33 -0700513// If the selected reader is blocking our pruning progress, decide on
514// what kind of mitigation is necessary to unblock the situation.
Tom Cherry1647cd42020-05-04 12:53:36 -0700515void LogBuffer::kickMe(LogReaderThread* me, log_id_t id, unsigned long pruneRows) {
Tom Cherry479b5032020-05-07 14:44:43 -0700516 if (stats_->Sizes(id) > (2 * log_buffer_size(id))) { // +100%
Mark Salyzyn434f3742017-05-11 13:28:33 -0700517 // A misbehaving or slow reader has its connection
518 // dropped if we hit too much memory pressure.
Tom Cherry59fc1192019-11-15 17:37:03 -0800519 android::prdebug("Kicking blocked reader, pid %d, from LogBuffer::kickMe()\n",
Tom Cherry7e3bc962020-05-04 17:10:16 -0700520 me->client()->getPid());
Mark Salyzyn434f3742017-05-11 13:28:33 -0700521 me->release_Locked();
Tom Cherry5ecfbf02020-05-11 16:29:29 -0700522 } else if (me->deadline().time_since_epoch().count() != 0) {
523 // Allow a blocked WRAP deadline reader to trigger and start reporting the log data.
Mark Salyzyn434f3742017-05-11 13:28:33 -0700524 me->triggerReader_Locked();
525 } else {
526 // tell slow reader to skip entries to catch up
Tom Cherry59fc1192019-11-15 17:37:03 -0800527 android::prdebug(
528 "Skipping %lu entries from slow reader, pid %d, from LogBuffer::kickMe()\n",
Tom Cherry7e3bc962020-05-04 17:10:16 -0700529 pruneRows, me->client()->getPid());
Mark Salyzyn434f3742017-05-11 13:28:33 -0700530 me->triggerSkip_Locked(id, pruneRows);
531 }
532}
533
Mark Salyzyn12bac902014-02-26 09:50:16 -0800534// prune "pruneRows" of type "id" from the buffer.
535//
Mark Salyzyne2827d52015-09-08 09:12:51 -0700536// This garbage collection task is used to expire log entries. It is called to
537// remove all logs (clear), all UID logs (unprivileged clear), or every
538// 256 or 10% of the total logs (whichever is less) to prune the logs.
539//
540// First there is a prep phase where we discover the reader region lock that
541// acts as a backstop to any pruning activity to stop there and go no further.
542//
543// There are three major pruning loops that follow. All expire from the oldest
544// entries. Since there are multiple log buffers, the Android logging facility
545// will appear to drop entries 'in the middle' when looking at multiple log
546// sources and buffers. This effect is slightly more prominent when we prune
547// the worst offender by logging source. Thus the logs slowly loose content
548// and value as you move back in time. This is preferred since chatty sources
549// invariably move the logs value down faster as less chatty sources would be
550// expired in the noise.
551//
552// The first loop performs blacklisting and worst offender pruning. Falling
553// through when there are no notable worst offenders and have not hit the
554// region lock preventing further worst offender pruning. This loop also looks
555// after managing the chatty log entries and merging to help provide
556// statistical basis for blame. The chatty entries are not a notification of
557// how much logs you may have, but instead represent how much logs you would
558// have had in a virtual log buffer that is extended to cover all the in-memory
559// logs without loss. They last much longer than the represented pruned logs
560// since they get multiplied by the gains in the non-chatty log sources.
561//
562// The second loop get complicated because an algorithm of watermarks and
563// history is maintained to reduce the order and keep processing time
564// down to a minimum at scale. These algorithms can be costly in the face
565// of larger log buffers, or severly limited processing time granted to a
566// background task at lowest priority.
567//
568// This second loop does straight-up expiration from the end of the logs
569// (again, remember for the specified log buffer id) but does some whitelist
570// preservation. Thus whitelist is a Hail Mary low priority, blacklists and
571// spam filtration all take priority. This second loop also checks if a region
572// lock is causing us to buffer too much in the logs to help the reader(s),
573// and will tell the slowest reader thread to skip log entries, and if
574// persistent and hits a further threshold, kill the reader thread.
575//
576// The third thread is optional, and only gets hit if there was a whitelist
577// and more needs to be pruned against the backstop of the region lock.
578//
Mark Salyzynd2712b12017-04-18 14:09:45 -0700579// LogBuffer::wrlock() must be held when this function is called.
Mark Salyzyne2827d52015-09-08 09:12:51 -0700580//
Mark Salyzyn8cf0d032015-09-16 15:34:00 -0700581bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
Tom Cherry1647cd42020-05-04 12:53:36 -0700582 LogReaderThread* oldest = nullptr;
Mark Salyzyn8cf0d032015-09-16 15:34:00 -0700583 bool busy = false;
Mark Salyzyn71541f32015-09-16 15:34:00 -0700584 bool clearAll = pruneRows == ULONG_MAX;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800585
Tom Cherry5ecfbf02020-05-11 16:29:29 -0700586 auto reader_threads_lock = std::lock_guard{reader_list_->reader_threads_lock()};
Mark Salyzyn12bac902014-02-26 09:50:16 -0800587
588 // Region locked?
Tom Cherry5ecfbf02020-05-11 16:29:29 -0700589 for (const auto& reader_thread : reader_list_->reader_threads()) {
590 if (!reader_thread->IsWatching(id)) {
591 continue;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800592 }
Tom Cherry5ecfbf02020-05-11 16:29:29 -0700593 if (!oldest || oldest->start() > reader_thread->start() ||
594 (oldest->start() == reader_thread->start() &&
595 reader_thread->deadline().time_since_epoch().count() != 0)) {
596 oldest = reader_thread.get();
597 }
Mark Salyzyn12bac902014-02-26 09:50:16 -0800598 }
599
Mark Salyzyn5c06ca42014-02-06 18:11:13 -0800600 LogBufferElementCollection::iterator it;
601
Mark Salyzyn65059532017-03-10 14:31:54 -0800602 if (__predict_false(caller_uid != AID_ROOT)) { // unlikely
Mark Salyzyn9e0c78e2016-09-01 15:48:36 -0700603 // Only here if clear all request from non system source, so chatty
604 // filter logistics is not required.
Tom Cherry402364e2020-04-29 17:58:18 -0700605 it = GetOldest(id);
Mark Salyzynb7dd96e2016-01-11 10:58:09 -0800606 while (it != mLogElements.end()) {
Mark Salyzyn65059532017-03-10 14:31:54 -0800607 LogBufferElement* element = *it;
Mark Salyzyn276d5352014-06-12 11:16:16 -0700608
Mark Salyzyn65059532017-03-10 14:31:54 -0800609 if ((element->getLogId() != id) ||
610 (element->getUid() != caller_uid)) {
Mark Salyzyn71541f32015-09-16 15:34:00 -0700611 ++it;
612 continue;
613 }
614
Tom Cherry7e3bc962020-05-04 17:10:16 -0700615 if (oldest && oldest->start() <= element->getSequence()) {
Tom Cherrybc02eff2020-04-08 10:47:26 -0700616 busy = true;
617 kickMe(oldest, id, pruneRows);
Mark Salyzyn276d5352014-06-12 11:16:16 -0700618 break;
619 }
620
Mark Salyzyn71541f32015-09-16 15:34:00 -0700621 it = erase(it);
Mark Salyzyn9e0c78e2016-09-01 15:48:36 -0700622 if (--pruneRows == 0) {
623 break;
624 }
Mark Salyzyn276d5352014-06-12 11:16:16 -0700625 }
Mark Salyzyn8cf0d032015-09-16 15:34:00 -0700626 return busy;
Mark Salyzyn276d5352014-06-12 11:16:16 -0700627 }
628
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700629 // prune by worst offenders; by blacklist, UID, and by PID of system UID
Tom Cherry4bd63ef2020-05-01 17:03:20 -0700630 bool hasBlacklist = (id != LOG_ID_SECURITY) && prune_->naughty();
Mark Salyzyn71541f32015-09-16 15:34:00 -0700631 while (!clearAll && (pruneRows > 0)) {
Mark Salyzyn5c06ca42014-02-06 18:11:13 -0800632 // recalculate the worst offender on every batched pass
Mark Salyzyn65059532017-03-10 14:31:54 -0800633 int worst = -1; // not valid for getUid() or getKey()
Mark Salyzyn5c06ca42014-02-06 18:11:13 -0800634 size_t worst_sizes = 0;
635 size_t second_worst_sizes = 0;
Mark Salyzyn65059532017-03-10 14:31:54 -0800636 pid_t worstPid = 0; // POSIX guarantees PID != 0
Mark Salyzyn5c06ca42014-02-06 18:11:13 -0800637
Tom Cherry4bd63ef2020-05-01 17:03:20 -0700638 if (worstUidEnabledForLogid(id) && prune_->worstUidEnabled()) {
Mark Salyzyn6fa0d032016-07-14 15:34:30 -0700639 // Calculate threshold as 12.5% of available storage
640 size_t threshold = log_buffer_size(id) / 8;
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700641
Tom Cherry4011d5a2020-05-07 09:13:12 -0700642 if (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) {
Tom Cherry479b5032020-05-07 14:44:43 -0700643 stats_->WorstTwoTags(threshold, &worst, &worst_sizes, &second_worst_sizes);
Mark Salyzynab947712016-10-24 08:20:26 -0700644 // per-pid filter for AID_SYSTEM sources is too complex
Mark Salyzyn6fa0d032016-07-14 15:34:30 -0700645 } else {
Tom Cherry479b5032020-05-07 14:44:43 -0700646 stats_->WorstTwoUids(id, threshold, &worst, &worst_sizes, &second_worst_sizes);
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700647
Tom Cherry4011d5a2020-05-07 09:13:12 -0700648 if (worst == AID_SYSTEM && prune_->worstPidOfSystemEnabled()) {
Tom Cherry479b5032020-05-07 14:44:43 -0700649 stats_->WorstTwoSystemPids(id, worst_sizes, &worstPid, &second_worst_sizes);
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700650 }
651 }
Mark Salyzyn5c06ca42014-02-06 18:11:13 -0800652 }
653
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700654 // skip if we have neither worst nor naughty filters
Mark Salyzyn6fa0d032016-07-14 15:34:30 -0700655 if ((worst == -1) && !hasBlacklist) {
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700656 break;
657 }
658
Mark Salyzyn5c06ca42014-02-06 18:11:13 -0800659 bool kick = false;
Tom Cherry402364e2020-04-29 17:58:18 -0700660 bool leading = true; // true if starting from the oldest log entry, false if starting from
661 // a specific chatty entry.
Mark Salyzyne2827d52015-09-08 09:12:51 -0700662 // Perform at least one mandatory garbage collection cycle in following
663 // - clear leading chatty tags
Mark Salyzyn5c5189a2015-09-30 07:40:09 -0700664 // - coalesce chatty tags
Mark Salyzyne2827d52015-09-08 09:12:51 -0700665 // - check age-out of preserved logs
666 bool gc = pruneRows <= 1;
Mark Salyzyn6fa0d032016-07-14 15:34:30 -0700667 if (!gc && (worst != -1)) {
Mark Salyzyn65059532017-03-10 14:31:54 -0800668 { // begin scope for worst found iterator
669 LogBufferIteratorMap::iterator found =
670 mLastWorst[id].find(worst);
671 if ((found != mLastWorst[id].end()) &&
672 (found->second != mLogElements.end())) {
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700673 leading = false;
674 it = found->second;
675 }
676 }
Mark Salyzyn65059532017-03-10 14:31:54 -0800677 if (worstPid) { // begin scope for pid worst found iterator
Mark Salyzynab947712016-10-24 08:20:26 -0700678 // FYI: worstPid only set if !LOG_ID_EVENTS and
679 // !LOG_ID_SECURITY, not going to make that assumption ...
Mark Salyzyn65059532017-03-10 14:31:54 -0800680 LogBufferPidIteratorMap::iterator found =
681 mLastWorstPidOfSystem[id].find(worstPid);
682 if ((found != mLastWorstPidOfSystem[id].end()) &&
683 (found->second != mLogElements.end())) {
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700684 leading = false;
685 it = found->second;
686 }
Mark Salyzyn5af07be2015-08-19 17:06:11 -0700687 }
688 }
Tom Cherry402364e2020-04-29 17:58:18 -0700689 if (leading) {
690 it = GetOldest(id);
691 }
Mark Salyzyn65059532017-03-10 14:31:54 -0800692 static const timespec too_old = { EXPIRE_HOUR_THRESHOLD * 60 * 60, 0 };
Mark Salyzyn7f62d6b2015-08-24 13:43:27 -0700693 LogBufferElementCollection::iterator lastt;
694 lastt = mLogElements.end();
695 --lastt;
Mark Salyzynd84b27e2015-04-17 15:38:04 -0700696 LogBufferElementLast last;
Mark Salyzyn5af07be2015-08-19 17:06:11 -0700697 while (it != mLogElements.end()) {
Mark Salyzyn65059532017-03-10 14:31:54 -0800698 LogBufferElement* element = *it;
Mark Salyzyn5c06ca42014-02-06 18:11:13 -0800699
Tom Cherry7e3bc962020-05-04 17:10:16 -0700700 if (oldest && oldest->start() <= element->getSequence()) {
Tom Cherrybc02eff2020-04-08 10:47:26 -0700701 busy = true;
Mark Salyzyn434f3742017-05-11 13:28:33 -0700702 // Do not let chatty eliding trigger any reader mitigation
Mark Salyzyn5c06ca42014-02-06 18:11:13 -0800703 break;
704 }
705
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700706 if (element->getLogId() != id) {
Mark Salyzync89839a2014-02-11 12:29:31 -0800707 ++it;
708 continue;
709 }
Mark Salyzyn11178182016-10-21 09:46:42 -0700710 // below this point element->getLogId() == id
Mark Salyzync89839a2014-02-11 12:29:31 -0800711
Chih-Hung Hsieh9ff81552018-08-13 14:22:56 -0700712 uint16_t dropped = element->getDropped();
Mark Salyzync89839a2014-02-11 12:29:31 -0800713
Mark Salyzyna69d5a42015-03-16 12:04:09 -0700714 // remove any leading drops
715 if (leading && dropped) {
716 it = erase(it);
717 continue;
718 }
719
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700720 if (dropped && last.coalesce(element, dropped)) {
Mark Salyzyn5c5189a2015-09-30 07:40:09 -0700721 it = erase(it, true);
Mark Salyzyna69d5a42015-03-16 12:04:09 -0700722 continue;
723 }
724
Mark Salyzyn65059532017-03-10 14:31:54 -0800725 int key = ((id == LOG_ID_EVENTS) || (id == LOG_ID_SECURITY))
726 ? element->getTag()
727 : element->getUid();
Mark Salyzyn6fa0d032016-07-14 15:34:30 -0700728
Tom Cherry4bd63ef2020-05-01 17:03:20 -0700729 if (hasBlacklist && prune_->naughty(element)) {
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700730 last.clear(element);
Mark Salyzyna69d5a42015-03-16 12:04:09 -0700731 it = erase(it);
732 if (dropped) {
733 continue;
734 }
735
736 pruneRows--;
737 if (pruneRows == 0) {
738 break;
739 }
740
Mark Salyzyn6fa0d032016-07-14 15:34:30 -0700741 if (key == worst) {
Mark Salyzyna69d5a42015-03-16 12:04:09 -0700742 kick = true;
743 if (worst_sizes < second_worst_sizes) {
744 break;
745 }
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700746 worst_sizes -= element->getMsgLen();
Mark Salyzyna69d5a42015-03-16 12:04:09 -0700747 }
748 continue;
749 }
750
Mark Salyzyn65059532017-03-10 14:31:54 -0800751 if ((element->getRealTime() < ((*lastt)->getRealTime() - too_old)) ||
752 (element->getRealTime() > (*lastt)->getRealTime())) {
Mark Salyzyn7f62d6b2015-08-24 13:43:27 -0700753 break;
754 }
755
Mark Salyzyna69d5a42015-03-16 12:04:09 -0700756 if (dropped) {
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700757 last.add(element);
Mark Salyzyn65059532017-03-10 14:31:54 -0800758 if (worstPid &&
759 ((!gc && (element->getPid() == worstPid)) ||
760 (mLastWorstPidOfSystem[id].find(element->getPid()) ==
761 mLastWorstPidOfSystem[id].end()))) {
Mark Salyzyn11178182016-10-21 09:46:42 -0700762 // element->getUid() may not be AID_SYSTEM, next best
Mark Salyzynab947712016-10-24 08:20:26 -0700763 // watermark if current one empty. id is not LOG_ID_EVENTS
764 // or LOG_ID_SECURITY because of worstPid check.
Mark Salyzynce50dec2016-09-01 07:28:44 -0700765 mLastWorstPidOfSystem[id][element->getPid()] = it;
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700766 }
Mark Salyzyn65059532017-03-10 14:31:54 -0800767 if ((!gc && !worstPid && (key == worst)) ||
768 (mLastWorst[id].find(key) == mLastWorst[id].end())) {
Mark Salyzyn6fa0d032016-07-14 15:34:30 -0700769 mLastWorst[id][key] = it;
Mark Salyzyn76aab492015-08-24 13:43:27 -0700770 }
Mark Salyzyn5c06ca42014-02-06 18:11:13 -0800771 ++it;
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700772 continue;
Mark Salyzyn5c06ca42014-02-06 18:11:13 -0800773 }
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700774
Mark Salyzyn65059532017-03-10 14:31:54 -0800775 if ((key != worst) ||
776 (worstPid && (element->getPid() != worstPid))) {
Mark Salyzynfd318a82015-06-01 09:41:19 -0700777 leading = false;
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700778 last.clear(element);
Mark Salyzyna69d5a42015-03-16 12:04:09 -0700779 ++it;
780 continue;
781 }
Mark Salyzyn11178182016-10-21 09:46:42 -0700782 // key == worst below here
783 // If worstPid set, then element->getPid() == worstPid below here
Mark Salyzyna69d5a42015-03-16 12:04:09 -0700784
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700785 pruneRows--;
786 if (pruneRows == 0) {
787 break;
788 }
789
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700790 kick = true;
Mark Salyzyna69d5a42015-03-16 12:04:09 -0700791
Chih-Hung Hsieh9ff81552018-08-13 14:22:56 -0700792 uint16_t len = element->getMsgLen();
Mark Salyzyn65ec8602015-05-22 10:03:31 -0700793
794 // do not create any leading drops
795 if (leading) {
796 it = erase(it);
Mark Salyzyna69d5a42015-03-16 12:04:09 -0700797 } else {
Tom Cherry479b5032020-05-07 14:44:43 -0700798 stats_->Drop(element);
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700799 element->setDropped(1);
800 if (last.coalesce(element, 1)) {
Mark Salyzyn5c5189a2015-09-30 07:40:09 -0700801 it = erase(it, true);
Mark Salyzyn65ec8602015-05-22 10:03:31 -0700802 } else {
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700803 last.add(element);
Mark Salyzyn65059532017-03-10 14:31:54 -0800804 if (worstPid &&
805 (!gc || (mLastWorstPidOfSystem[id].find(worstPid) ==
806 mLastWorstPidOfSystem[id].end()))) {
Mark Salyzyn11178182016-10-21 09:46:42 -0700807 // element->getUid() may not be AID_SYSTEM, next best
Mark Salyzynab947712016-10-24 08:20:26 -0700808 // watermark if current one empty. id is not
809 // LOG_ID_EVENTS or LOG_ID_SECURITY because of worstPid.
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700810 mLastWorstPidOfSystem[id][worstPid] = it;
811 }
Mark Salyzyn6fa0d032016-07-14 15:34:30 -0700812 if ((!gc && !worstPid) ||
Mark Salyzyn65059532017-03-10 14:31:54 -0800813 (mLastWorst[id].find(worst) == mLastWorst[id].end())) {
Mark Salyzyn6fa0d032016-07-14 15:34:30 -0700814 mLastWorst[id][worst] = it;
Mark Salyzyne2827d52015-09-08 09:12:51 -0700815 }
Mark Salyzyn65ec8602015-05-22 10:03:31 -0700816 ++it;
817 }
Mark Salyzyna69d5a42015-03-16 12:04:09 -0700818 }
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700819 if (worst_sizes < second_worst_sizes) {
820 break;
821 }
822 worst_sizes -= len;
Mark Salyzyn5c06ca42014-02-06 18:11:13 -0800823 }
Mark Salyzynd84b27e2015-04-17 15:38:04 -0700824 last.clear();
Mark Salyzyn5c06ca42014-02-06 18:11:13 -0800825
Tom Cherry4bd63ef2020-05-01 17:03:20 -0700826 if (!kick || !prune_->worstUidEnabled()) {
Mark Salyzyn65059532017-03-10 14:31:54 -0800827 break; // the following loop will ask bad clients to skip/drop
Mark Salyzyn5c06ca42014-02-06 18:11:13 -0800828 }
829 }
830
Mark Salyzync89839a2014-02-11 12:29:31 -0800831 bool whitelist = false;
Tom Cherry4bd63ef2020-05-01 17:03:20 -0700832 bool hasWhitelist = (id != LOG_ID_SECURITY) && prune_->nice() && !clearAll;
Tom Cherry402364e2020-04-29 17:58:18 -0700833 it = GetOldest(id);
Mark Salyzyn65059532017-03-10 14:31:54 -0800834 while ((pruneRows > 0) && (it != mLogElements.end())) {
835 LogBufferElement* element = *it;
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700836
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700837 if (element->getLogId() != id) {
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700838 it++;
839 continue;
840 }
841
Tom Cherry7e3bc962020-05-04 17:10:16 -0700842 if (oldest && oldest->start() <= element->getSequence()) {
Tom Cherrybc02eff2020-04-08 10:47:26 -0700843 busy = true;
844 if (!whitelist) kickMe(oldest, id, pruneRows);
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700845 break;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800846 }
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700847
Tom Cherry4bd63ef2020-05-01 17:03:20 -0700848 if (hasWhitelist && !element->getDropped() && prune_->nice(element)) {
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700849 // WhiteListed
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700850 whitelist = true;
851 it++;
852 continue;
853 }
854
855 it = erase(it);
856 pruneRows--;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800857 }
858
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700859 // Do not save the whitelist if we are reader range limited
Mark Salyzync89839a2014-02-11 12:29:31 -0800860 if (whitelist && (pruneRows > 0)) {
Tom Cherry402364e2020-04-29 17:58:18 -0700861 it = GetOldest(id);
Mark Salyzyn65059532017-03-10 14:31:54 -0800862 while ((it != mLogElements.end()) && (pruneRows > 0)) {
863 LogBufferElement* element = *it;
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700864
Mark Salyzynedcbdfa2015-08-28 08:02:59 -0700865 if (element->getLogId() != id) {
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700866 ++it;
867 continue;
Mark Salyzync89839a2014-02-11 12:29:31 -0800868 }
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700869
Tom Cherry7e3bc962020-05-04 17:10:16 -0700870 if (oldest && oldest->start() <= element->getSequence()) {
Tom Cherrybc02eff2020-04-08 10:47:26 -0700871 busy = true;
872 kickMe(oldest, id, pruneRows);
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700873 break;
874 }
875
876 it = erase(it);
877 pruneRows--;
Mark Salyzync89839a2014-02-11 12:29:31 -0800878 }
879 }
Mark Salyzync89839a2014-02-11 12:29:31 -0800880
Mark Salyzyn8cf0d032015-09-16 15:34:00 -0700881 return (pruneRows > 0) && busy;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800882}
883
884// clear all rows of type "id" from the buffer.
Mark Salyzyn8cf0d032015-09-16 15:34:00 -0700885bool LogBuffer::clear(log_id_t id, uid_t uid) {
886 bool busy = true;
887 // If it takes more than 4 tries (seconds) to clear, then kill reader(s)
888 for (int retry = 4;;) {
Mark Salyzyn65059532017-03-10 14:31:54 -0800889 if (retry == 1) { // last pass
Mark Salyzyn8cf0d032015-09-16 15:34:00 -0700890 // Check if it is still busy after the sleep, we say prune
891 // one entry, not another clear run, so we are looking for
892 // the quick side effect of the return value to tell us if
893 // we have a _blocked_ reader.
Mark Salyzynd2712b12017-04-18 14:09:45 -0700894 wrlock();
Mark Salyzyn8cf0d032015-09-16 15:34:00 -0700895 busy = prune(id, 1, uid);
Mark Salyzynd2712b12017-04-18 14:09:45 -0700896 unlock();
Mark Salyzyn8cf0d032015-09-16 15:34:00 -0700897 // It is still busy, blocked reader(s), lets kill them all!
898 // otherwise, lets be a good citizen and preserve the slow
899 // readers and let the clear run (below) deal with determining
900 // if we are still blocked and return an error code to caller.
901 if (busy) {
Tom Cherry5ecfbf02020-05-11 16:29:29 -0700902 auto reader_threads_lock = std::lock_guard{reader_list_->reader_threads_lock()};
903 for (const auto& reader_thread : reader_list_->reader_threads()) {
904 if (reader_thread->IsWatching(id)) {
Tom Cherry59fc1192019-11-15 17:37:03 -0800905 android::prdebug(
906 "Kicking blocked reader, pid %d, from LogBuffer::clear()\n",
Tom Cherry5ecfbf02020-05-11 16:29:29 -0700907 reader_thread->client()->getPid());
908 reader_thread->release_Locked();
Mark Salyzyn8cf0d032015-09-16 15:34:00 -0700909 }
Mark Salyzyn8cf0d032015-09-16 15:34:00 -0700910 }
Mark Salyzyn8cf0d032015-09-16 15:34:00 -0700911 }
912 }
Mark Salyzynd2712b12017-04-18 14:09:45 -0700913 wrlock();
Mark Salyzyn8cf0d032015-09-16 15:34:00 -0700914 busy = prune(id, ULONG_MAX, uid);
Mark Salyzynd2712b12017-04-18 14:09:45 -0700915 unlock();
Mark Salyzyn8cf0d032015-09-16 15:34:00 -0700916 if (!busy || !--retry) {
917 break;
918 }
Mark Salyzyn65059532017-03-10 14:31:54 -0800919 sleep(1); // Let reader(s) catch up after notification
Mark Salyzyn8cf0d032015-09-16 15:34:00 -0700920 }
921 return busy;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800922}
923
Mark Salyzync89839a2014-02-11 12:29:31 -0800924// set the total space allocated to "id"
925int LogBuffer::setSize(log_id_t id, unsigned long size) {
926 // Reasonable limits ...
Mark Salyzynb0040832016-09-27 13:08:23 -0700927 if (!__android_logger_valid_buffer_size(size)) {
Mark Salyzync89839a2014-02-11 12:29:31 -0800928 return -1;
929 }
Mark Salyzynd2712b12017-04-18 14:09:45 -0700930 wrlock();
Mark Salyzync89839a2014-02-11 12:29:31 -0800931 log_buffer_size(id) = size;
Mark Salyzynd2712b12017-04-18 14:09:45 -0700932 unlock();
Mark Salyzync89839a2014-02-11 12:29:31 -0800933 return 0;
934}
935
936// get the total space allocated to "id"
937unsigned long LogBuffer::getSize(log_id_t id) {
Mark Salyzynd2712b12017-04-18 14:09:45 -0700938 rdlock();
Mark Salyzync89839a2014-02-11 12:29:31 -0800939 size_t retval = log_buffer_size(id);
Mark Salyzynd2712b12017-04-18 14:09:45 -0700940 unlock();
Mark Salyzync89839a2014-02-11 12:29:31 -0800941 return retval;
942}
943
Tom Cherry5ecfbf02020-05-11 16:29:29 -0700944uint64_t LogBuffer::flushTo(
945 SocketClient* reader, uint64_t start, pid_t* lastTid, bool privileged, bool security,
946 const std::function<FlushToResult(const LogBufferElement* element)>& filter) {
Mark Salyzyn12bac902014-02-26 09:50:16 -0800947 LogBufferElementCollection::iterator it;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800948 uid_t uid = reader->getUid();
949
Mark Salyzynd2712b12017-04-18 14:09:45 -0700950 rdlock();
Dragoslav Mitrinovic81624f22015-01-15 09:29:43 -0600951
Tom Cherryac228f12019-08-21 14:16:34 -0700952 if (start <= 1) {
Dragoslav Mitrinovic81624f22015-01-15 09:29:43 -0600953 // client wants to start from the beginning
954 it = mLogElements.begin();
955 } else {
956 // Client wants to start from some specified time. Chances are
957 // we are better off starting from the end of the time sorted list.
Tom Cherryac228f12019-08-21 14:16:34 -0700958 for (it = mLogElements.end(); it != mLogElements.begin();
Mark Salyzyn65059532017-03-10 14:31:54 -0800959 /* do nothing */) {
Dragoslav Mitrinovic81624f22015-01-15 09:29:43 -0600960 --it;
Mark Salyzyn65059532017-03-10 14:31:54 -0800961 LogBufferElement* element = *it;
Tom Cherryac228f12019-08-21 14:16:34 -0700962 if (element->getSequence() <= start) {
963 it++;
Dragoslav Mitrinovic81624f22015-01-15 09:29:43 -0600964 break;
965 }
966 }
967 }
968
Tom Cherryac228f12019-08-21 14:16:34 -0700969 uint64_t curr = start;
Mark Salyzyn1d7b0712017-01-23 14:20:31 -0800970
Dragoslav Mitrinovic81624f22015-01-15 09:29:43 -0600971 for (; it != mLogElements.end(); ++it) {
Mark Salyzyn65059532017-03-10 14:31:54 -0800972 LogBufferElement* element = *it;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800973
974 if (!privileged && (element->getUid() != uid)) {
975 continue;
976 }
977
Mark Salyzynb10f7372016-01-26 14:32:35 -0800978 if (!security && (element->getLogId() == LOG_ID_SECURITY)) {
979 continue;
980 }
981
Mark Salyzynd2712b12017-04-18 14:09:45 -0700982 // NB: calling out to another object with wrlock() held (safe)
Mark Salyzyn0aaf6cd2015-03-03 13:39:37 -0800983 if (filter) {
Tom Cherry5ecfbf02020-05-11 16:29:29 -0700984 FlushToResult ret = filter(element);
985 if (ret == FlushToResult::kSkip) {
Mark Salyzyn0aaf6cd2015-03-03 13:39:37 -0800986 continue;
987 }
Tom Cherry5ecfbf02020-05-11 16:29:29 -0700988 if (ret == FlushToResult::kStop) {
Mark Salyzyn0aaf6cd2015-03-03 13:39:37 -0800989 break;
990 }
Mark Salyzyn12bac902014-02-26 09:50:16 -0800991 }
992
Mark Salyzynbec7b2d2017-03-31 10:48:39 -0700993 bool sameTid = false;
994 if (lastTid) {
995 sameTid = lastTid[element->getLogId()] == element->getTid();
996 // Dropped (chatty) immediately following a valid log from the
997 // same source in the same log buffer indicates we have a
998 // multiple identical squash. chatty that differs source
999 // is due to spam filter. chatty to chatty of different
1000 // source is also due to spam filter.
1001 lastTid[element->getLogId()] =
1002 (element->getDropped() && !sameTid) ? 0 : element->getTid();
1003 }
Mark Salyzyn1d7b0712017-01-23 14:20:31 -08001004
Mark Salyzynd2712b12017-04-18 14:09:45 -07001005 unlock();
Mark Salyzyn12bac902014-02-26 09:50:16 -08001006
1007 // range locking in LastLogTimes looks after us
Tom Cherry479b5032020-05-07 14:44:43 -07001008 curr = element->flushTo(reader, stats_, sameTid);
Mark Salyzyn12bac902014-02-26 09:50:16 -08001009
Mark Salyzyncb722de2017-05-18 10:06:00 -07001010 if (curr == element->FLUSH_ERROR) {
1011 return curr;
Mark Salyzyne2c1ea42017-05-17 19:55:12 +00001012 }
Mark Salyzyn12bac902014-02-26 09:50:16 -08001013
Mark Salyzynd2712b12017-04-18 14:09:45 -07001014 rdlock();
Mark Salyzyn12bac902014-02-26 09:50:16 -08001015 }
Mark Salyzynd2712b12017-04-18 14:09:45 -07001016 unlock();
Mark Salyzyn12bac902014-02-26 09:50:16 -08001017
Mark Salyzyncb722de2017-05-18 10:06:00 -07001018 return curr;
Mark Salyzyn12bac902014-02-26 09:50:16 -08001019}