LogBuffer.cpp 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211
  1. /*
  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. */
  16. // for manual checking of stale entries during LogBuffer::erase()
  17. //#define DEBUG_CHECK_FOR_STALE_ENTRIES
  18. #include <ctype.h>
  19. #include <endian.h>
  20. #include <errno.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <sys/cdefs.h>
  24. #include <sys/user.h>
  25. #include <time.h>
  26. #include <unistd.h>
  27. #include <unordered_map>
  28. #include <cutils/properties.h>
  29. #include <private/android_logger.h>
  30. #include "LogBuffer.h"
  31. #include "LogKlog.h"
  32. #include "LogReader.h"
  33. #include "LogUtils.h"
  34. #ifndef __predict_false
  35. #define __predict_false(exp) __builtin_expect((exp) != 0, 0)
  36. #endif
  37. // Default
  38. #define log_buffer_size(id) mMaxSize[id]
  39. const log_time LogBuffer::pruneMargin(3, 0);
  40. void LogBuffer::init() {
  41. log_id_for_each(i) {
  42. mLastSet[i] = false;
  43. mLast[i] = mLogElements.begin();
  44. if (setSize(i, __android_logger_get_buffer_size(i))) {
  45. setSize(i, LOG_BUFFER_MIN_SIZE);
  46. }
  47. }
  48. bool lastMonotonic = monotonic;
  49. monotonic = android_log_clockid() == CLOCK_MONOTONIC;
  50. if (lastMonotonic != monotonic) {
  51. //
  52. // Fixup all timestamps, may not be 100% accurate, but better than
  53. // throwing what we have away when we get 'surprised' by a change.
  54. // In-place element fixup so no need to check reader-lock. Entries
  55. // should already be in timestamp order, but we could end up with a
  56. // few out-of-order entries if new monotonics come in before we
  57. // are notified of the reinit change in status. A Typical example would
  58. // be:
  59. // --------- beginning of system
  60. // 10.494082 184 201 D Cryptfs : Just triggered post_fs_data
  61. // --------- beginning of kernel
  62. // 0.000000 0 0 I : Initializing cgroup subsys
  63. // as the act of mounting /data would trigger persist.logd.timestamp to
  64. // be corrected. 1/30 corner case YMMV.
  65. //
  66. rdlock();
  67. LogBufferElementCollection::iterator it = mLogElements.begin();
  68. while ((it != mLogElements.end())) {
  69. LogBufferElement* e = *it;
  70. if (monotonic) {
  71. if (!android::isMonotonic(e->mRealTime)) {
  72. LogKlog::convertRealToMonotonic(e->mRealTime);
  73. if ((e->mRealTime.tv_nsec % 1000) == 0) {
  74. e->mRealTime.tv_nsec++;
  75. }
  76. }
  77. } else {
  78. if (android::isMonotonic(e->mRealTime)) {
  79. LogKlog::convertMonotonicToReal(e->mRealTime);
  80. if ((e->mRealTime.tv_nsec % 1000) == 0) {
  81. e->mRealTime.tv_nsec++;
  82. }
  83. }
  84. }
  85. ++it;
  86. }
  87. unlock();
  88. }
  89. // We may have been triggered by a SIGHUP. Release any sleeping reader
  90. // threads to dump their current content.
  91. //
  92. // NB: this is _not_ performed in the context of a SIGHUP, it is
  93. // performed during startup, and in context of reinit administrative thread
  94. LogTimeEntry::wrlock();
  95. LastLogTimes::iterator times = mTimes.begin();
  96. while (times != mTimes.end()) {
  97. LogTimeEntry* entry = times->get();
  98. entry->triggerReader_Locked();
  99. times++;
  100. }
  101. LogTimeEntry::unlock();
  102. }
  103. LogBuffer::LogBuffer(LastLogTimes* times)
  104. : monotonic(android_log_clockid() == CLOCK_MONOTONIC), mTimes(*times) {
  105. pthread_rwlock_init(&mLogElementsLock, nullptr);
  106. log_id_for_each(i) {
  107. lastLoggedElements[i] = nullptr;
  108. droppedElements[i] = nullptr;
  109. }
  110. init();
  111. }
  112. LogBuffer::~LogBuffer() {
  113. log_id_for_each(i) {
  114. delete lastLoggedElements[i];
  115. delete droppedElements[i];
  116. }
  117. }
  118. enum match_type { DIFFERENT, SAME, SAME_LIBLOG };
  119. static enum match_type identical(LogBufferElement* elem,
  120. LogBufferElement* last) {
  121. // is it mostly identical?
  122. // if (!elem) return DIFFERENT;
  123. ssize_t lenl = elem->getMsgLen();
  124. if (lenl <= 0) return DIFFERENT; // value if this represents a chatty elem
  125. // if (!last) return DIFFERENT;
  126. ssize_t lenr = last->getMsgLen();
  127. if (lenr <= 0) return DIFFERENT; // value if this represents a chatty elem
  128. // if (elem->getLogId() != last->getLogId()) return DIFFERENT;
  129. if (elem->getUid() != last->getUid()) return DIFFERENT;
  130. if (elem->getPid() != last->getPid()) return DIFFERENT;
  131. if (elem->getTid() != last->getTid()) return DIFFERENT;
  132. // last is more than a minute old, stop squashing identical messages
  133. if (elem->getRealTime().nsec() >
  134. (last->getRealTime().nsec() + 60 * NS_PER_SEC))
  135. return DIFFERENT;
  136. // Identical message
  137. const char* msgl = elem->getMsg();
  138. const char* msgr = last->getMsg();
  139. if (lenl == lenr) {
  140. if (!fastcmp<memcmp>(msgl, msgr, lenl)) return SAME;
  141. // liblog tagged messages (content gets summed)
  142. if ((elem->getLogId() == LOG_ID_EVENTS) &&
  143. (lenl == sizeof(android_log_event_int_t)) &&
  144. !fastcmp<memcmp>(msgl, msgr, sizeof(android_log_event_int_t) -
  145. sizeof(int32_t)) &&
  146. (elem->getTag() == LIBLOG_LOG_TAG)) {
  147. return SAME_LIBLOG;
  148. }
  149. }
  150. // audit message (except sequence number) identical?
  151. if (last->isBinary() &&
  152. (lenl > static_cast<ssize_t>(sizeof(android_log_event_string_t))) &&
  153. (lenr > static_cast<ssize_t>(sizeof(android_log_event_string_t)))) {
  154. if (fastcmp<memcmp>(msgl, msgr, sizeof(android_log_event_string_t) -
  155. sizeof(int32_t))) {
  156. return DIFFERENT;
  157. }
  158. msgl += sizeof(android_log_event_string_t);
  159. lenl -= sizeof(android_log_event_string_t);
  160. msgr += sizeof(android_log_event_string_t);
  161. lenr -= sizeof(android_log_event_string_t);
  162. }
  163. static const char avc[] = "): avc: ";
  164. const char* avcl = android::strnstr(msgl, lenl, avc);
  165. if (!avcl) return DIFFERENT;
  166. lenl -= avcl - msgl;
  167. const char* avcr = android::strnstr(msgr, lenr, avc);
  168. if (!avcr) return DIFFERENT;
  169. lenr -= avcr - msgr;
  170. if (lenl != lenr) return DIFFERENT;
  171. if (fastcmp<memcmp>(avcl + strlen(avc), avcr + strlen(avc),
  172. lenl - strlen(avc))) {
  173. return DIFFERENT;
  174. }
  175. return SAME;
  176. }
  177. int LogBuffer::log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
  178. pid_t tid, const char* msg, uint16_t len) {
  179. if (log_id >= LOG_ID_MAX) {
  180. return -EINVAL;
  181. }
  182. // Slip the time by 1 nsec if the incoming lands on xxxxxx000 ns.
  183. // This prevents any chance that an outside source can request an
  184. // exact entry with time specified in ms or us precision.
  185. if ((realtime.tv_nsec % 1000) == 0) ++realtime.tv_nsec;
  186. LogBufferElement* elem =
  187. new LogBufferElement(log_id, realtime, uid, pid, tid, msg, len);
  188. if (log_id != LOG_ID_SECURITY) {
  189. int prio = ANDROID_LOG_INFO;
  190. const char* tag = nullptr;
  191. size_t tag_len = 0;
  192. if (log_id == LOG_ID_EVENTS || log_id == LOG_ID_STATS) {
  193. tag = tagToName(elem->getTag());
  194. if (tag) {
  195. tag_len = strlen(tag);
  196. }
  197. } else {
  198. prio = *msg;
  199. tag = msg + 1;
  200. tag_len = strnlen(tag, len - 1);
  201. }
  202. if (!__android_log_is_loggable_len(prio, tag, tag_len,
  203. ANDROID_LOG_VERBOSE)) {
  204. // Log traffic received to total
  205. wrlock();
  206. stats.addTotal(elem);
  207. unlock();
  208. delete elem;
  209. return -EACCES;
  210. }
  211. }
  212. wrlock();
  213. LogBufferElement* currentLast = lastLoggedElements[log_id];
  214. if (currentLast) {
  215. LogBufferElement* dropped = droppedElements[log_id];
  216. uint16_t count = dropped ? dropped->getDropped() : 0;
  217. //
  218. // State Init
  219. // incoming:
  220. // dropped = nullptr
  221. // currentLast = nullptr;
  222. // elem = incoming message
  223. // outgoing:
  224. // dropped = nullptr -> State 0
  225. // currentLast = copy of elem
  226. // log elem
  227. // State 0
  228. // incoming:
  229. // count = 0
  230. // dropped = nullptr
  231. // currentLast = copy of last message
  232. // elem = incoming message
  233. // outgoing: if match != DIFFERENT
  234. // dropped = copy of first identical message -> State 1
  235. // currentLast = reference to elem
  236. // break: if match == DIFFERENT
  237. // dropped = nullptr -> State 0
  238. // delete copy of last message (incoming currentLast)
  239. // currentLast = copy of elem
  240. // log elem
  241. // State 1
  242. // incoming:
  243. // count = 0
  244. // dropped = copy of first identical message
  245. // currentLast = reference to last held-back incoming
  246. // message
  247. // elem = incoming message
  248. // outgoing: if match == SAME
  249. // delete copy of first identical message (dropped)
  250. // dropped = reference to last held-back incoming
  251. // message set to chatty count of 1 -> State 2
  252. // currentLast = reference to elem
  253. // outgoing: if match == SAME_LIBLOG
  254. // dropped = copy of first identical message -> State 1
  255. // take sum of currentLast and elem
  256. // if sum overflows:
  257. // log currentLast
  258. // currentLast = reference to elem
  259. // else
  260. // delete currentLast
  261. // currentLast = reference to elem, sum liblog.
  262. // break: if match == DIFFERENT
  263. // delete dropped
  264. // dropped = nullptr -> State 0
  265. // log reference to last held-back (currentLast)
  266. // currentLast = copy of elem
  267. // log elem
  268. // State 2
  269. // incoming:
  270. // count = chatty count
  271. // dropped = chatty message holding count
  272. // currentLast = reference to last held-back incoming
  273. // message.
  274. // dropped = chatty message holding count
  275. // elem = incoming message
  276. // outgoing: if match != DIFFERENT
  277. // delete chatty message holding count
  278. // dropped = reference to last held-back incoming
  279. // message, set to chatty count + 1
  280. // currentLast = reference to elem
  281. // break: if match == DIFFERENT
  282. // log dropped (chatty message)
  283. // dropped = nullptr -> State 0
  284. // log reference to last held-back (currentLast)
  285. // currentLast = copy of elem
  286. // log elem
  287. //
  288. enum match_type match = identical(elem, currentLast);
  289. if (match != DIFFERENT) {
  290. if (dropped) {
  291. // Sum up liblog tag messages?
  292. if ((count == 0) /* at Pass 1 */ && (match == SAME_LIBLOG)) {
  293. android_log_event_int_t* event =
  294. reinterpret_cast<android_log_event_int_t*>(
  295. const_cast<char*>(currentLast->getMsg()));
  296. //
  297. // To unit test, differentiate with something like:
  298. // event->header.tag = htole32(CHATTY_LOG_TAG);
  299. // here, then instead of delete currentLast below,
  300. // log(currentLast) to see the incremental sums form.
  301. //
  302. uint32_t swab = event->payload.data;
  303. unsigned long long total = htole32(swab);
  304. event = reinterpret_cast<android_log_event_int_t*>(
  305. const_cast<char*>(elem->getMsg()));
  306. swab = event->payload.data;
  307. lastLoggedElements[LOG_ID_EVENTS] = elem;
  308. total += htole32(swab);
  309. // check for overflow
  310. if (total >= UINT32_MAX) {
  311. log(currentLast);
  312. unlock();
  313. return len;
  314. }
  315. stats.addTotal(currentLast);
  316. delete currentLast;
  317. swab = total;
  318. event->payload.data = htole32(swab);
  319. unlock();
  320. return len;
  321. }
  322. if (count == USHRT_MAX) {
  323. log(dropped);
  324. count = 1;
  325. } else {
  326. delete dropped;
  327. ++count;
  328. }
  329. }
  330. if (count) {
  331. stats.addTotal(currentLast);
  332. currentLast->setDropped(count);
  333. }
  334. droppedElements[log_id] = currentLast;
  335. lastLoggedElements[log_id] = elem;
  336. unlock();
  337. return len;
  338. }
  339. if (dropped) { // State 1 or 2
  340. if (count) { // State 2
  341. log(dropped); // report chatty
  342. } else { // State 1
  343. delete dropped;
  344. }
  345. droppedElements[log_id] = nullptr;
  346. log(currentLast); // report last message in the series
  347. } else { // State 0
  348. delete currentLast;
  349. }
  350. }
  351. lastLoggedElements[log_id] = new LogBufferElement(*elem);
  352. log(elem);
  353. unlock();
  354. return len;
  355. }
  356. // assumes LogBuffer::wrlock() held, owns elem, look after garbage collection
  357. void LogBuffer::log(LogBufferElement* elem) {
  358. // cap on how far back we will sort in-place, otherwise append
  359. static uint32_t too_far_back = 5; // five seconds
  360. // Insert elements in time sorted order if possible
  361. // NB: if end is region locked, place element at end of list
  362. LogBufferElementCollection::iterator it = mLogElements.end();
  363. LogBufferElementCollection::iterator last = it;
  364. if (__predict_true(it != mLogElements.begin())) --it;
  365. if (__predict_false(it == mLogElements.begin()) ||
  366. __predict_true((*it)->getRealTime() <= elem->getRealTime()) ||
  367. __predict_false((((*it)->getRealTime().tv_sec - too_far_back) >
  368. elem->getRealTime().tv_sec) &&
  369. (elem->getLogId() != LOG_ID_KERNEL) &&
  370. ((*it)->getLogId() != LOG_ID_KERNEL))) {
  371. mLogElements.push_back(elem);
  372. } else {
  373. log_time end(log_time::EPOCH);
  374. bool end_set = false;
  375. bool end_always = false;
  376. LogTimeEntry::rdlock();
  377. LastLogTimes::iterator times = mTimes.begin();
  378. while (times != mTimes.end()) {
  379. LogTimeEntry* entry = times->get();
  380. if (!entry->mNonBlock) {
  381. end_always = true;
  382. break;
  383. }
  384. // it passing mEnd is blocked by the following checks.
  385. if (!end_set || (end <= entry->mEnd)) {
  386. end = entry->mEnd;
  387. end_set = true;
  388. }
  389. times++;
  390. }
  391. if (end_always || (end_set && (end > (*it)->getRealTime()))) {
  392. mLogElements.push_back(elem);
  393. } else {
  394. // should be short as timestamps are localized near end()
  395. do {
  396. last = it;
  397. if (__predict_false(it == mLogElements.begin())) {
  398. break;
  399. }
  400. --it;
  401. } while (((*it)->getRealTime() > elem->getRealTime()) &&
  402. (!end_set || (end <= (*it)->getRealTime())));
  403. mLogElements.insert(last, elem);
  404. }
  405. LogTimeEntry::unlock();
  406. }
  407. stats.add(elem);
  408. maybePrune(elem->getLogId());
  409. }
  410. // Prune at most 10% of the log entries or maxPrune, whichever is less.
  411. //
  412. // LogBuffer::wrlock() must be held when this function is called.
  413. void LogBuffer::maybePrune(log_id_t id) {
  414. size_t sizes = stats.sizes(id);
  415. unsigned long maxSize = log_buffer_size(id);
  416. if (sizes > maxSize) {
  417. size_t sizeOver = sizes - ((maxSize * 9) / 10);
  418. size_t elements = stats.realElements(id);
  419. size_t minElements = elements / 100;
  420. if (minElements < minPrune) {
  421. minElements = minPrune;
  422. }
  423. unsigned long pruneRows = elements * sizeOver / sizes;
  424. if (pruneRows < minElements) {
  425. pruneRows = minElements;
  426. }
  427. if (pruneRows > maxPrune) {
  428. pruneRows = maxPrune;
  429. }
  430. prune(id, pruneRows);
  431. }
  432. }
  433. LogBufferElementCollection::iterator LogBuffer::erase(
  434. LogBufferElementCollection::iterator it, bool coalesce) {
  435. LogBufferElement* element = *it;
  436. log_id_t id = element->getLogId();
  437. // Remove iterator references in the various lists that will become stale
  438. // after the element is erased from the main logging list.
  439. { // start of scope for found iterator
  440. int key = ((id == LOG_ID_EVENTS) || (id == LOG_ID_SECURITY))
  441. ? element->getTag()
  442. : element->getUid();
  443. LogBufferIteratorMap::iterator found = mLastWorst[id].find(key);
  444. if ((found != mLastWorst[id].end()) && (it == found->second)) {
  445. mLastWorst[id].erase(found);
  446. }
  447. }
  448. { // start of scope for pid found iterator
  449. // element->getUid() may not be AID_SYSTEM for next-best-watermark.
  450. // will not assume id != LOG_ID_EVENTS or LOG_ID_SECURITY for KISS and
  451. // long term code stability, find() check should be fast for those ids.
  452. LogBufferPidIteratorMap::iterator found =
  453. mLastWorstPidOfSystem[id].find(element->getPid());
  454. if ((found != mLastWorstPidOfSystem[id].end()) &&
  455. (it == found->second)) {
  456. mLastWorstPidOfSystem[id].erase(found);
  457. }
  458. }
  459. bool setLast[LOG_ID_MAX];
  460. bool doSetLast = false;
  461. log_id_for_each(i) {
  462. doSetLast |= setLast[i] = mLastSet[i] && (it == mLast[i]);
  463. }
  464. #ifdef DEBUG_CHECK_FOR_STALE_ENTRIES
  465. LogBufferElementCollection::iterator bad = it;
  466. int key = ((id == LOG_ID_EVENTS) || (id == LOG_ID_SECURITY))
  467. ? element->getTag()
  468. : element->getUid();
  469. #endif
  470. it = mLogElements.erase(it);
  471. if (doSetLast) {
  472. log_id_for_each(i) {
  473. if (setLast[i]) {
  474. if (__predict_false(it == mLogElements.end())) { // impossible
  475. mLastSet[i] = false;
  476. mLast[i] = mLogElements.begin();
  477. } else {
  478. mLast[i] = it; // push down the road as next-best-watermark
  479. }
  480. }
  481. }
  482. }
  483. #ifdef DEBUG_CHECK_FOR_STALE_ENTRIES
  484. log_id_for_each(i) {
  485. for (auto b : mLastWorst[i]) {
  486. if (bad == b.second) {
  487. android::prdebug("stale mLastWorst[%d] key=%d mykey=%d\n", i,
  488. b.first, key);
  489. }
  490. }
  491. for (auto b : mLastWorstPidOfSystem[i]) {
  492. if (bad == b.second) {
  493. android::prdebug("stale mLastWorstPidOfSystem[%d] pid=%d\n", i,
  494. b.first);
  495. }
  496. }
  497. if (mLastSet[i] && (bad == mLast[i])) {
  498. android::prdebug("stale mLast[%d]\n", i);
  499. mLastSet[i] = false;
  500. mLast[i] = mLogElements.begin();
  501. }
  502. }
  503. #endif
  504. if (coalesce) {
  505. stats.erase(element);
  506. } else {
  507. stats.subtract(element);
  508. }
  509. delete element;
  510. return it;
  511. }
  512. // Define a temporary mechanism to report the last LogBufferElement pointer
  513. // for the specified uid, pid and tid. Used below to help merge-sort when
  514. // pruning for worst UID.
  515. class LogBufferElementKey {
  516. const union {
  517. struct {
  518. uint32_t uid;
  519. uint16_t pid;
  520. uint16_t tid;
  521. } __packed;
  522. uint64_t value;
  523. } __packed;
  524. public:
  525. LogBufferElementKey(uid_t uid, pid_t pid, pid_t tid)
  526. : uid(uid), pid(pid), tid(tid) {
  527. }
  528. explicit LogBufferElementKey(uint64_t key) : value(key) {
  529. }
  530. uint64_t getKey() {
  531. return value;
  532. }
  533. };
  534. class LogBufferElementLast {
  535. typedef std::unordered_map<uint64_t, LogBufferElement*> LogBufferElementMap;
  536. LogBufferElementMap map;
  537. public:
  538. bool coalesce(LogBufferElement* element, uint16_t dropped) {
  539. LogBufferElementKey key(element->getUid(), element->getPid(),
  540. element->getTid());
  541. LogBufferElementMap::iterator it = map.find(key.getKey());
  542. if (it != map.end()) {
  543. LogBufferElement* found = it->second;
  544. uint16_t moreDropped = found->getDropped();
  545. if ((dropped + moreDropped) > USHRT_MAX) {
  546. map.erase(it);
  547. } else {
  548. found->setDropped(dropped + moreDropped);
  549. return true;
  550. }
  551. }
  552. return false;
  553. }
  554. void add(LogBufferElement* element) {
  555. LogBufferElementKey key(element->getUid(), element->getPid(),
  556. element->getTid());
  557. map[key.getKey()] = element;
  558. }
  559. inline void clear() {
  560. map.clear();
  561. }
  562. void clear(LogBufferElement* element) {
  563. log_time current =
  564. element->getRealTime() - log_time(EXPIRE_RATELIMIT, 0);
  565. for (LogBufferElementMap::iterator it = map.begin(); it != map.end();) {
  566. LogBufferElement* mapElement = it->second;
  567. if ((mapElement->getDropped() >= EXPIRE_THRESHOLD) &&
  568. (current > mapElement->getRealTime())) {
  569. it = map.erase(it);
  570. } else {
  571. ++it;
  572. }
  573. }
  574. }
  575. };
  576. // Determine if watermark is within pruneMargin + 1s from the end of the list,
  577. // the caller will use this result to set an internal busy flag indicating
  578. // the prune operation could not be completed because a reader is blocking
  579. // the request.
  580. bool LogBuffer::isBusy(log_time watermark) {
  581. LogBufferElementCollection::iterator ei = mLogElements.end();
  582. --ei;
  583. return watermark < ((*ei)->getRealTime() - pruneMargin - log_time(1, 0));
  584. }
  585. // If the selected reader is blocking our pruning progress, decide on
  586. // what kind of mitigation is necessary to unblock the situation.
  587. void LogBuffer::kickMe(LogTimeEntry* me, log_id_t id, unsigned long pruneRows) {
  588. if (stats.sizes(id) > (2 * log_buffer_size(id))) { // +100%
  589. // A misbehaving or slow reader has its connection
  590. // dropped if we hit too much memory pressure.
  591. me->release_Locked();
  592. } else if (me->mTimeout.tv_sec || me->mTimeout.tv_nsec) {
  593. // Allow a blocked WRAP timeout reader to
  594. // trigger and start reporting the log data.
  595. me->triggerReader_Locked();
  596. } else {
  597. // tell slow reader to skip entries to catch up
  598. me->triggerSkip_Locked(id, pruneRows);
  599. }
  600. }
  601. // prune "pruneRows" of type "id" from the buffer.
  602. //
  603. // This garbage collection task is used to expire log entries. It is called to
  604. // remove all logs (clear), all UID logs (unprivileged clear), or every
  605. // 256 or 10% of the total logs (whichever is less) to prune the logs.
  606. //
  607. // First there is a prep phase where we discover the reader region lock that
  608. // acts as a backstop to any pruning activity to stop there and go no further.
  609. //
  610. // There are three major pruning loops that follow. All expire from the oldest
  611. // entries. Since there are multiple log buffers, the Android logging facility
  612. // will appear to drop entries 'in the middle' when looking at multiple log
  613. // sources and buffers. This effect is slightly more prominent when we prune
  614. // the worst offender by logging source. Thus the logs slowly loose content
  615. // and value as you move back in time. This is preferred since chatty sources
  616. // invariably move the logs value down faster as less chatty sources would be
  617. // expired in the noise.
  618. //
  619. // The first loop performs blacklisting and worst offender pruning. Falling
  620. // through when there are no notable worst offenders and have not hit the
  621. // region lock preventing further worst offender pruning. This loop also looks
  622. // after managing the chatty log entries and merging to help provide
  623. // statistical basis for blame. The chatty entries are not a notification of
  624. // how much logs you may have, but instead represent how much logs you would
  625. // have had in a virtual log buffer that is extended to cover all the in-memory
  626. // logs without loss. They last much longer than the represented pruned logs
  627. // since they get multiplied by the gains in the non-chatty log sources.
  628. //
  629. // The second loop get complicated because an algorithm of watermarks and
  630. // history is maintained to reduce the order and keep processing time
  631. // down to a minimum at scale. These algorithms can be costly in the face
  632. // of larger log buffers, or severly limited processing time granted to a
  633. // background task at lowest priority.
  634. //
  635. // This second loop does straight-up expiration from the end of the logs
  636. // (again, remember for the specified log buffer id) but does some whitelist
  637. // preservation. Thus whitelist is a Hail Mary low priority, blacklists and
  638. // spam filtration all take priority. This second loop also checks if a region
  639. // lock is causing us to buffer too much in the logs to help the reader(s),
  640. // and will tell the slowest reader thread to skip log entries, and if
  641. // persistent and hits a further threshold, kill the reader thread.
  642. //
  643. // The third thread is optional, and only gets hit if there was a whitelist
  644. // and more needs to be pruned against the backstop of the region lock.
  645. //
  646. // LogBuffer::wrlock() must be held when this function is called.
  647. //
  648. bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
  649. LogTimeEntry* oldest = nullptr;
  650. bool busy = false;
  651. bool clearAll = pruneRows == ULONG_MAX;
  652. LogTimeEntry::rdlock();
  653. // Region locked?
  654. LastLogTimes::iterator times = mTimes.begin();
  655. while (times != mTimes.end()) {
  656. LogTimeEntry* entry = times->get();
  657. if (entry->isWatching(id) &&
  658. (!oldest || (oldest->mStart > entry->mStart) ||
  659. ((oldest->mStart == entry->mStart) &&
  660. (entry->mTimeout.tv_sec || entry->mTimeout.tv_nsec)))) {
  661. oldest = entry;
  662. }
  663. times++;
  664. }
  665. log_time watermark(log_time::tv_sec_max, log_time::tv_nsec_max);
  666. if (oldest) watermark = oldest->mStart - pruneMargin;
  667. LogBufferElementCollection::iterator it;
  668. if (__predict_false(caller_uid != AID_ROOT)) { // unlikely
  669. // Only here if clear all request from non system source, so chatty
  670. // filter logistics is not required.
  671. it = mLastSet[id] ? mLast[id] : mLogElements.begin();
  672. while (it != mLogElements.end()) {
  673. LogBufferElement* element = *it;
  674. if ((element->getLogId() != id) ||
  675. (element->getUid() != caller_uid)) {
  676. ++it;
  677. continue;
  678. }
  679. if (!mLastSet[id] || ((*mLast[id])->getLogId() != id)) {
  680. mLast[id] = it;
  681. mLastSet[id] = true;
  682. }
  683. if (oldest && (watermark <= element->getRealTime())) {
  684. busy = isBusy(watermark);
  685. if (busy) kickMe(oldest, id, pruneRows);
  686. break;
  687. }
  688. it = erase(it);
  689. if (--pruneRows == 0) {
  690. break;
  691. }
  692. }
  693. LogTimeEntry::unlock();
  694. return busy;
  695. }
  696. // prune by worst offenders; by blacklist, UID, and by PID of system UID
  697. bool hasBlacklist = (id != LOG_ID_SECURITY) && mPrune.naughty();
  698. while (!clearAll && (pruneRows > 0)) {
  699. // recalculate the worst offender on every batched pass
  700. int worst = -1; // not valid for getUid() or getKey()
  701. size_t worst_sizes = 0;
  702. size_t second_worst_sizes = 0;
  703. pid_t worstPid = 0; // POSIX guarantees PID != 0
  704. if (worstUidEnabledForLogid(id) && mPrune.worstUidEnabled()) {
  705. // Calculate threshold as 12.5% of available storage
  706. size_t threshold = log_buffer_size(id) / 8;
  707. if ((id == LOG_ID_EVENTS) || (id == LOG_ID_SECURITY)) {
  708. stats.sortTags(AID_ROOT, (pid_t)0, 2, id)
  709. .findWorst(worst, worst_sizes, second_worst_sizes,
  710. threshold);
  711. // per-pid filter for AID_SYSTEM sources is too complex
  712. } else {
  713. stats.sort(AID_ROOT, (pid_t)0, 2, id)
  714. .findWorst(worst, worst_sizes, second_worst_sizes,
  715. threshold);
  716. if ((worst == AID_SYSTEM) && mPrune.worstPidOfSystemEnabled()) {
  717. stats.sortPids(worst, (pid_t)0, 2, id)
  718. .findWorst(worstPid, worst_sizes, second_worst_sizes);
  719. }
  720. }
  721. }
  722. // skip if we have neither worst nor naughty filters
  723. if ((worst == -1) && !hasBlacklist) {
  724. break;
  725. }
  726. bool kick = false;
  727. bool leading = true;
  728. it = mLastSet[id] ? mLast[id] : mLogElements.begin();
  729. // Perform at least one mandatory garbage collection cycle in following
  730. // - clear leading chatty tags
  731. // - coalesce chatty tags
  732. // - check age-out of preserved logs
  733. bool gc = pruneRows <= 1;
  734. if (!gc && (worst != -1)) {
  735. { // begin scope for worst found iterator
  736. LogBufferIteratorMap::iterator found =
  737. mLastWorst[id].find(worst);
  738. if ((found != mLastWorst[id].end()) &&
  739. (found->second != mLogElements.end())) {
  740. leading = false;
  741. it = found->second;
  742. }
  743. }
  744. if (worstPid) { // begin scope for pid worst found iterator
  745. // FYI: worstPid only set if !LOG_ID_EVENTS and
  746. // !LOG_ID_SECURITY, not going to make that assumption ...
  747. LogBufferPidIteratorMap::iterator found =
  748. mLastWorstPidOfSystem[id].find(worstPid);
  749. if ((found != mLastWorstPidOfSystem[id].end()) &&
  750. (found->second != mLogElements.end())) {
  751. leading = false;
  752. it = found->second;
  753. }
  754. }
  755. }
  756. static const timespec too_old = { EXPIRE_HOUR_THRESHOLD * 60 * 60, 0 };
  757. LogBufferElementCollection::iterator lastt;
  758. lastt = mLogElements.end();
  759. --lastt;
  760. LogBufferElementLast last;
  761. while (it != mLogElements.end()) {
  762. LogBufferElement* element = *it;
  763. if (oldest && (watermark <= element->getRealTime())) {
  764. busy = isBusy(watermark);
  765. // Do not let chatty eliding trigger any reader mitigation
  766. break;
  767. }
  768. if (element->getLogId() != id) {
  769. ++it;
  770. continue;
  771. }
  772. // below this point element->getLogId() == id
  773. if (leading && (!mLastSet[id] || ((*mLast[id])->getLogId() != id))) {
  774. mLast[id] = it;
  775. mLastSet[id] = true;
  776. }
  777. uint16_t dropped = element->getDropped();
  778. // remove any leading drops
  779. if (leading && dropped) {
  780. it = erase(it);
  781. continue;
  782. }
  783. if (dropped && last.coalesce(element, dropped)) {
  784. it = erase(it, true);
  785. continue;
  786. }
  787. int key = ((id == LOG_ID_EVENTS) || (id == LOG_ID_SECURITY))
  788. ? element->getTag()
  789. : element->getUid();
  790. if (hasBlacklist && mPrune.naughty(element)) {
  791. last.clear(element);
  792. it = erase(it);
  793. if (dropped) {
  794. continue;
  795. }
  796. pruneRows--;
  797. if (pruneRows == 0) {
  798. break;
  799. }
  800. if (key == worst) {
  801. kick = true;
  802. if (worst_sizes < second_worst_sizes) {
  803. break;
  804. }
  805. worst_sizes -= element->getMsgLen();
  806. }
  807. continue;
  808. }
  809. if ((element->getRealTime() < ((*lastt)->getRealTime() - too_old)) ||
  810. (element->getRealTime() > (*lastt)->getRealTime())) {
  811. break;
  812. }
  813. if (dropped) {
  814. last.add(element);
  815. if (worstPid &&
  816. ((!gc && (element->getPid() == worstPid)) ||
  817. (mLastWorstPidOfSystem[id].find(element->getPid()) ==
  818. mLastWorstPidOfSystem[id].end()))) {
  819. // element->getUid() may not be AID_SYSTEM, next best
  820. // watermark if current one empty. id is not LOG_ID_EVENTS
  821. // or LOG_ID_SECURITY because of worstPid check.
  822. mLastWorstPidOfSystem[id][element->getPid()] = it;
  823. }
  824. if ((!gc && !worstPid && (key == worst)) ||
  825. (mLastWorst[id].find(key) == mLastWorst[id].end())) {
  826. mLastWorst[id][key] = it;
  827. }
  828. ++it;
  829. continue;
  830. }
  831. if ((key != worst) ||
  832. (worstPid && (element->getPid() != worstPid))) {
  833. leading = false;
  834. last.clear(element);
  835. ++it;
  836. continue;
  837. }
  838. // key == worst below here
  839. // If worstPid set, then element->getPid() == worstPid below here
  840. pruneRows--;
  841. if (pruneRows == 0) {
  842. break;
  843. }
  844. kick = true;
  845. uint16_t len = element->getMsgLen();
  846. // do not create any leading drops
  847. if (leading) {
  848. it = erase(it);
  849. } else {
  850. stats.drop(element);
  851. element->setDropped(1);
  852. if (last.coalesce(element, 1)) {
  853. it = erase(it, true);
  854. } else {
  855. last.add(element);
  856. if (worstPid &&
  857. (!gc || (mLastWorstPidOfSystem[id].find(worstPid) ==
  858. mLastWorstPidOfSystem[id].end()))) {
  859. // element->getUid() may not be AID_SYSTEM, next best
  860. // watermark if current one empty. id is not
  861. // LOG_ID_EVENTS or LOG_ID_SECURITY because of worstPid.
  862. mLastWorstPidOfSystem[id][worstPid] = it;
  863. }
  864. if ((!gc && !worstPid) ||
  865. (mLastWorst[id].find(worst) == mLastWorst[id].end())) {
  866. mLastWorst[id][worst] = it;
  867. }
  868. ++it;
  869. }
  870. }
  871. if (worst_sizes < second_worst_sizes) {
  872. break;
  873. }
  874. worst_sizes -= len;
  875. }
  876. last.clear();
  877. if (!kick || !mPrune.worstUidEnabled()) {
  878. break; // the following loop will ask bad clients to skip/drop
  879. }
  880. }
  881. bool whitelist = false;
  882. bool hasWhitelist = (id != LOG_ID_SECURITY) && mPrune.nice() && !clearAll;
  883. it = mLastSet[id] ? mLast[id] : mLogElements.begin();
  884. while ((pruneRows > 0) && (it != mLogElements.end())) {
  885. LogBufferElement* element = *it;
  886. if (element->getLogId() != id) {
  887. it++;
  888. continue;
  889. }
  890. if (!mLastSet[id] || ((*mLast[id])->getLogId() != id)) {
  891. mLast[id] = it;
  892. mLastSet[id] = true;
  893. }
  894. if (oldest && (watermark <= element->getRealTime())) {
  895. busy = isBusy(watermark);
  896. if (!whitelist && busy) kickMe(oldest, id, pruneRows);
  897. break;
  898. }
  899. if (hasWhitelist && !element->getDropped() && mPrune.nice(element)) {
  900. // WhiteListed
  901. whitelist = true;
  902. it++;
  903. continue;
  904. }
  905. it = erase(it);
  906. pruneRows--;
  907. }
  908. // Do not save the whitelist if we are reader range limited
  909. if (whitelist && (pruneRows > 0)) {
  910. it = mLastSet[id] ? mLast[id] : mLogElements.begin();
  911. while ((it != mLogElements.end()) && (pruneRows > 0)) {
  912. LogBufferElement* element = *it;
  913. if (element->getLogId() != id) {
  914. ++it;
  915. continue;
  916. }
  917. if (!mLastSet[id] || ((*mLast[id])->getLogId() != id)) {
  918. mLast[id] = it;
  919. mLastSet[id] = true;
  920. }
  921. if (oldest && (watermark <= element->getRealTime())) {
  922. busy = isBusy(watermark);
  923. if (busy) kickMe(oldest, id, pruneRows);
  924. break;
  925. }
  926. it = erase(it);
  927. pruneRows--;
  928. }
  929. }
  930. LogTimeEntry::unlock();
  931. return (pruneRows > 0) && busy;
  932. }
  933. // clear all rows of type "id" from the buffer.
  934. bool LogBuffer::clear(log_id_t id, uid_t uid) {
  935. bool busy = true;
  936. // If it takes more than 4 tries (seconds) to clear, then kill reader(s)
  937. for (int retry = 4;;) {
  938. if (retry == 1) { // last pass
  939. // Check if it is still busy after the sleep, we say prune
  940. // one entry, not another clear run, so we are looking for
  941. // the quick side effect of the return value to tell us if
  942. // we have a _blocked_ reader.
  943. wrlock();
  944. busy = prune(id, 1, uid);
  945. unlock();
  946. // It is still busy, blocked reader(s), lets kill them all!
  947. // otherwise, lets be a good citizen and preserve the slow
  948. // readers and let the clear run (below) deal with determining
  949. // if we are still blocked and return an error code to caller.
  950. if (busy) {
  951. LogTimeEntry::wrlock();
  952. LastLogTimes::iterator times = mTimes.begin();
  953. while (times != mTimes.end()) {
  954. LogTimeEntry* entry = times->get();
  955. // Killer punch
  956. if (entry->isWatching(id)) {
  957. entry->release_Locked();
  958. }
  959. times++;
  960. }
  961. LogTimeEntry::unlock();
  962. }
  963. }
  964. wrlock();
  965. busy = prune(id, ULONG_MAX, uid);
  966. unlock();
  967. if (!busy || !--retry) {
  968. break;
  969. }
  970. sleep(1); // Let reader(s) catch up after notification
  971. }
  972. return busy;
  973. }
  974. // get the used space associated with "id".
  975. unsigned long LogBuffer::getSizeUsed(log_id_t id) {
  976. rdlock();
  977. size_t retval = stats.sizes(id);
  978. unlock();
  979. return retval;
  980. }
  981. // set the total space allocated to "id"
  982. int LogBuffer::setSize(log_id_t id, unsigned long size) {
  983. // Reasonable limits ...
  984. if (!__android_logger_valid_buffer_size(size)) {
  985. return -1;
  986. }
  987. wrlock();
  988. log_buffer_size(id) = size;
  989. unlock();
  990. return 0;
  991. }
  992. // get the total space allocated to "id"
  993. unsigned long LogBuffer::getSize(log_id_t id) {
  994. rdlock();
  995. size_t retval = log_buffer_size(id);
  996. unlock();
  997. return retval;
  998. }
  999. log_time LogBuffer::flushTo(SocketClient* reader, const log_time& start,
  1000. pid_t* lastTid, bool privileged, bool security,
  1001. int (*filter)(const LogBufferElement* element,
  1002. void* arg),
  1003. void* arg) {
  1004. LogBufferElementCollection::iterator it;
  1005. uid_t uid = reader->getUid();
  1006. rdlock();
  1007. if (start == log_time::EPOCH) {
  1008. // client wants to start from the beginning
  1009. it = mLogElements.begin();
  1010. } else {
  1011. // Cap to 300 iterations we look back for out-of-order entries.
  1012. size_t count = 300;
  1013. // Client wants to start from some specified time. Chances are
  1014. // we are better off starting from the end of the time sorted list.
  1015. LogBufferElementCollection::iterator last;
  1016. for (last = it = mLogElements.end(); it != mLogElements.begin();
  1017. /* do nothing */) {
  1018. --it;
  1019. LogBufferElement* element = *it;
  1020. if (element->getRealTime() > start) {
  1021. last = it;
  1022. } else if (element->getRealTime() == start) {
  1023. last = ++it;
  1024. break;
  1025. } else if (!--count) {
  1026. break;
  1027. }
  1028. }
  1029. it = last;
  1030. }
  1031. log_time curr = start;
  1032. LogBufferElement* lastElement = nullptr; // iterator corruption paranoia
  1033. static const size_t maxSkip = 4194304; // maximum entries to skip
  1034. size_t skip = maxSkip;
  1035. for (; it != mLogElements.end(); ++it) {
  1036. LogBufferElement* element = *it;
  1037. if (!--skip) {
  1038. android::prdebug("reader.per: too many elements skipped");
  1039. break;
  1040. }
  1041. if (element == lastElement) {
  1042. android::prdebug("reader.per: identical elements");
  1043. break;
  1044. }
  1045. lastElement = element;
  1046. if (!privileged && (element->getUid() != uid)) {
  1047. continue;
  1048. }
  1049. if (!security && (element->getLogId() == LOG_ID_SECURITY)) {
  1050. continue;
  1051. }
  1052. // NB: calling out to another object with wrlock() held (safe)
  1053. if (filter) {
  1054. int ret = (*filter)(element, arg);
  1055. if (ret == false) {
  1056. continue;
  1057. }
  1058. if (ret != true) {
  1059. break;
  1060. }
  1061. }
  1062. bool sameTid = false;
  1063. if (lastTid) {
  1064. sameTid = lastTid[element->getLogId()] == element->getTid();
  1065. // Dropped (chatty) immediately following a valid log from the
  1066. // same source in the same log buffer indicates we have a
  1067. // multiple identical squash. chatty that differs source
  1068. // is due to spam filter. chatty to chatty of different
  1069. // source is also due to spam filter.
  1070. lastTid[element->getLogId()] =
  1071. (element->getDropped() && !sameTid) ? 0 : element->getTid();
  1072. }
  1073. unlock();
  1074. // range locking in LastLogTimes looks after us
  1075. curr = element->flushTo(reader, this, privileged, sameTid);
  1076. if (curr == element->FLUSH_ERROR) {
  1077. return curr;
  1078. }
  1079. skip = maxSkip;
  1080. rdlock();
  1081. }
  1082. unlock();
  1083. return curr;
  1084. }
  1085. std::string LogBuffer::formatStatistics(uid_t uid, pid_t pid,
  1086. unsigned int logMask) {
  1087. wrlock();
  1088. std::string ret = stats.format(uid, pid, logMask);
  1089. unlock();
  1090. return ret;
  1091. }