1 /*
2 * Copyright (C) 2017 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
17 #include <ctype.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <inttypes.h>
21 #include <pthread.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/mman.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/uio.h>
28 #include <unistd.h>
29
30 #include <string>
31
32 #include <android-base/file.h>
33 #include <android-base/logging.h>
34 #include <android-base/macros.h>
35 #include <android-base/scopeguard.h>
36 #include <android-base/stringprintf.h>
37 #include <android-base/threads.h>
38 #include <log/log_event_list.h>
39 #include <log/log_properties.h>
40 #include <log/log_read.h>
41 #include <private/android_filesystem_config.h>
42
43 #include "LogStatistics.h"
44 #include "LogTags.h"
45 #include "LogUtils.h"
46
47 using android::base::make_scope_guard;
48
49 static LogTags* logtags;
50
51 const char LogTags::system_event_log_tags[] = "/system/etc/event-log-tags";
52 const char LogTags::dynamic_event_log_tags[] = "/dev/event-log-tags";
53 // Only for debug
54 const char LogTags::debug_event_log_tags[] = "/data/misc/logd/event-log-tags";
55
56 // Sniff for first uid=%d in utf8z comment string
sniffUid(const char * comment,const char * endp)57 static uid_t sniffUid(const char* comment, const char* endp) {
58 if (!comment) return AID_ROOT;
59
60 if (*comment == '#') ++comment;
61 while ((comment < endp) && (*comment != '\n') && isspace(*comment))
62 ++comment;
63 static const char uid_str[] = "uid=";
64 if (((comment + strlen(uid_str)) >= endp) ||
65 fastcmp<strncmp>(comment, uid_str, strlen(uid_str)) ||
66 !isdigit(comment[strlen(uid_str)]))
67 return AID_ROOT;
68 char* cp;
69 unsigned long Uid = strtoul(comment + 4, &cp, 10);
70 if ((cp > endp) || (Uid >= INT_MAX)) return AID_ROOT;
71
72 return Uid;
73 }
74
75 // Checks for file corruption, and report false if there was no need
76 // to rebuild the referenced file. Failure to rebuild is only logged,
77 // does not cause a return value of false.
RebuildFileEventLogTags(const char * filename,bool warn)78 bool LogTags::RebuildFileEventLogTags(const char* filename, bool warn) {
79 int fd;
80
81 {
82 android::RWLock::AutoRLock readLock(rwlock);
83
84 if (tag2total.begin() == tag2total.end()) {
85 return false;
86 }
87
88 file2watermark_const_iterator iwater = file2watermark.find(filename);
89 if (iwater == file2watermark.end()) {
90 return false;
91 }
92
93 struct stat sb;
94 if (!stat(filename, &sb) && ((size_t)sb.st_size >= iwater->second)) {
95 return false;
96 }
97
98 // dump what we already know back into the file?
99 fd = TEMP_FAILURE_RETRY(open(
100 filename, O_WRONLY | O_TRUNC | O_CLOEXEC | O_NOFOLLOW | O_BINARY));
101 if (fd >= 0) {
102 time_t now = time(nullptr);
103 struct tm tm;
104 localtime_r(&now, &tm);
105 char timebuf[20];
106 strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", &tm);
107 android::base::WriteStringToFd(
108 android::base::StringPrintf(
109 "# Rebuilt %.20s, content owned by logd\n", timebuf),
110 fd);
111 for (const auto& it : tag2total) {
112 android::base::WriteStringToFd(
113 formatEntry_locked(it.first, AID_ROOT), fd);
114 }
115 close(fd);
116 }
117 }
118
119 if (warn) {
120 if (fd < 0) {
121 LOG(ERROR) << filename << " failed to rebuild";
122 } else {
123 LOG(ERROR) << filename << " missing, damaged or truncated; rebuilt";
124 }
125 }
126
127 if (fd >= 0) {
128 android::RWLock::AutoWLock writeLock(rwlock);
129
130 struct stat sb;
131 if (!stat(filename, &sb)) file2watermark[filename] = sb.st_size;
132 }
133
134 return true;
135 }
136
AddEventLogTags(uint32_t tag,uid_t uid,const std::string & Name,const std::string & Format,const char * source,bool warn)137 void LogTags::AddEventLogTags(uint32_t tag, uid_t uid, const std::string& Name,
138 const std::string& Format, const char* source,
139 bool warn) {
140 std::string Key = Name;
141 if (Format.length()) Key += "+" + Format;
142
143 bool update = !source || !!strcmp(source, system_event_log_tags);
144 bool newOne;
145
146 {
147 android::RWLock::AutoWLock writeLock(rwlock);
148
149 tag2total_const_iterator itot = tag2total.find(tag);
150
151 // unlikely except for dupes, or updates to uid list (more later)
152 if (itot != tag2total.end()) update = false;
153
154 newOne = tag2name.find(tag) == tag2name.end();
155 key2tag[Key] = tag;
156
157 if (Format.length()) {
158 if (key2tag.find(Name) == key2tag.end()) {
159 key2tag[Name] = tag;
160 }
161 tag2format[tag] = Format;
162 }
163 tag2name[tag] = Name;
164
165 tag2uid_const_iterator ut = tag2uid.find(tag);
166 if (ut != tag2uid.end()) {
167 if (uid == AID_ROOT) {
168 tag2uid.erase(ut);
169 update = true;
170 } else if (ut->second.find(uid) == ut->second.end()) {
171 const_cast<uid_list&>(ut->second).emplace(uid);
172 update = true;
173 }
174 } else if (newOne && (uid != AID_ROOT)) {
175 tag2uid[tag].emplace(uid);
176 update = true;
177 }
178
179 // updatePersist -> trigger output on modified
180 // content, reset tag2total if available
181 if (update && (itot != tag2total.end())) tag2total[tag] = 0;
182 }
183
184 if (update) {
185 WritePersistEventLogTags(tag, uid, source);
186 } else if (warn && !newOne && source) {
187 // For the files, we want to report dupes.
188 LOG(DEBUG) << "Multiple tag " << tag << " " << Name << " " << Format << " " << source;
189 }
190 }
191
192 // Read the event log tags file, and build up our internal database
ReadFileEventLogTags(const char * filename,bool warn)193 void LogTags::ReadFileEventLogTags(const char* filename, bool warn) {
194 bool etc = !strcmp(filename, system_event_log_tags);
195
196 if (!etc) {
197 RebuildFileEventLogTags(filename, warn);
198 }
199 std::string content;
200 if (android::base::ReadFileToString(filename, &content)) {
201 char* cp = (char*)content.c_str();
202 char* endp = cp + content.length();
203
204 {
205 android::RWLock::AutoRLock writeLock(rwlock);
206
207 file2watermark[filename] = content.length();
208 }
209
210 char* lineStart = cp;
211 while (cp < endp) {
212 if (*cp == '\n') {
213 lineStart = cp;
214 } else if (lineStart) {
215 if (*cp == '#') {
216 /* comment; just scan to end */
217 lineStart = nullptr;
218 } else if (isdigit(*cp)) {
219 unsigned long Tag = strtoul(cp, &cp, 10);
220 if (warn && (Tag > emptyTag)) {
221 LOG(WARNING) << "tag too large " << Tag;
222 }
223 while ((cp < endp) && (*cp != '\n') && isspace(*cp)) ++cp;
224 if (cp >= endp) break;
225 if (*cp == '\n') continue;
226 const char* name = cp;
227 /* Determine whether it is a valid tag name [a-zA-Z0-9_] */
228 bool hasAlpha = false;
229 while ((cp < endp) && (isalnum(*cp) || (*cp == '_'))) {
230 if (!isdigit(*cp)) hasAlpha = true;
231 ++cp;
232 }
233 std::string Name(name, cp - name);
234 #ifdef ALLOW_NOISY_LOGGING_OF_PROBLEM_WITH_LOTS_OF_TECHNICAL_DEBT
235 static const size_t maximum_official_tag_name_size = 24;
236 if (warn && (Name.length() > maximum_official_tag_name_size)) {
237 LOG(WARNING) << "tag name too long " << Name;
238 }
239 #endif
240 if (hasAlpha &&
241 ((cp >= endp) || (*cp == '#') || isspace(*cp))) {
242 if (Tag > emptyTag) {
243 if (*cp != '\n') lineStart = nullptr;
244 continue;
245 }
246 while ((cp < endp) && (*cp != '\n') && isspace(*cp))
247 ++cp;
248 const char* format = cp;
249 uid_t uid = AID_ROOT;
250 while ((cp < endp) && (*cp != '\n')) {
251 if (*cp == '#') {
252 uid = sniffUid(cp, endp);
253 lineStart = nullptr;
254 break;
255 }
256 ++cp;
257 }
258 while ((cp > format) && isspace(cp[-1])) {
259 --cp;
260 lineStart = nullptr;
261 }
262 std::string Format(format, cp - format);
263
264 AddEventLogTags((uint32_t)Tag, uid, Name, Format,
265 filename, warn);
266 } else {
267 if (warn) {
268 LOG(ERROR) << android::base::StringPrintf("tag name invalid %.*s",
269 (int)(cp - name + 1), name);
270 }
271 lineStart = nullptr;
272 }
273 } else if (!isspace(*cp)) {
274 break;
275 }
276 }
277 cp++;
278 }
279 } else if (warn) {
280 #ifdef __ANDROID__
281 LOG(ERROR) << "Cannot read " << filename;
282 #endif
283 }
284 }
285
286 // Extract a 4-byte value from a byte stream.
get4LE(const char * msg)287 static inline uint32_t get4LE(const char* msg) {
288 const uint8_t* src = reinterpret_cast<const uint8_t*>(msg);
289 return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
290 }
291
292 // Additional persistent sources for invented log tags. Read the
293 // special pmsg event for log tags, and build up our internal
294 // database with any found.
ReadPersistEventLogTags()295 void LogTags::ReadPersistEventLogTags() {
296 struct logger_list* logger_list =
297 android_logger_list_alloc(ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK, 0, (pid_t)0);
298 if (!logger_list) return;
299
300 struct logger* e = android_logger_open(logger_list, LOG_ID_EVENTS);
301 struct logger* s = android_logger_open(logger_list, LOG_ID_SECURITY);
302 if (!e && !s) {
303 android_logger_list_free(logger_list);
304 return;
305 }
306
307 for (;;) {
308 struct log_msg log_msg;
309 int ret = android_logger_list_read(logger_list, &log_msg);
310 if (ret <= 0) break;
311
312 const char* msg = log_msg.msg();
313 if (!msg) continue;
314 if (log_msg.entry.len <= sizeof(uint32_t)) continue;
315 uint32_t Tag = get4LE(msg);
316 if (Tag != TAG_DEF_LOG_TAG) continue;
317 uid_t uid = log_msg.entry.uid;
318
319 std::string Name;
320 std::string Format;
321 android_log_list_element elem;
322 {
323 auto ctx = create_android_log_parser(log_msg.msg() + sizeof(uint32_t),
324 log_msg.entry.len - sizeof(uint32_t));
325 auto guard = make_scope_guard([&ctx]() { android_log_destroy(&ctx); });
326 elem = android_log_read_next(ctx);
327 if (elem.type != EVENT_TYPE_LIST) {
328 continue;
329 }
330 elem = android_log_read_next(ctx);
331 if (elem.type != EVENT_TYPE_INT) {
332 continue;
333 }
334 Tag = elem.data.int32;
335 elem = android_log_read_next(ctx);
336 if (elem.type != EVENT_TYPE_STRING) {
337 continue;
338 }
339 Name = std::string(elem.data.string, elem.len);
340 elem = android_log_read_next(ctx);
341 if (elem.type != EVENT_TYPE_STRING) {
342 continue;
343 }
344 Format = std::string(elem.data.string, elem.len);
345 elem = android_log_read_next(ctx);
346 }
347 if ((elem.type != EVENT_TYPE_LIST_STOP) || !elem.complete) continue;
348
349 AddEventLogTags(Tag, uid, Name, Format);
350 }
351 android_logger_list_free(logger_list);
352 }
353
LogTags()354 LogTags::LogTags() {
355 ReadFileEventLogTags(system_event_log_tags);
356 // Following will likely fail on boot, but is required if logd restarts
357 ReadFileEventLogTags(dynamic_event_log_tags, false);
358 if (__android_log_is_debuggable()) {
359 ReadFileEventLogTags(debug_event_log_tags, false);
360 }
361 ReadPersistEventLogTags();
362
363 logtags = this;
364 }
365
366 // Converts an event tag into a name
tagToName(uint32_t tag) const367 const char* LogTags::tagToName(uint32_t tag) const {
368 tag2name_const_iterator it;
369
370 android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock));
371
372 it = tag2name.find(tag);
373 if ((it == tag2name.end()) || (it->second.length() == 0)) return nullptr;
374
375 return it->second.c_str();
376 }
377
378 // Prototype in LogUtils.h allowing external access to our database.
379 //
380 // This must be a pure reader to our database, as everything else is
381 // guaranteed single-threaded except this access point which is
382 // asynchonous and can be multithreaded and thus rentrant. The
383 // object's rwlock is only used to guarantee atomic access to the
384 // unordered_map to prevent corruption, with a requirement to be a
385 // low chance of contention for this call. If we end up changing
386 // this algorithm resulting in write, then we should use a different
387 // lock than the object's rwlock to protect groups of associated
388 // actions.
tagToName(uint32_t tag)389 const char* android::tagToName(uint32_t tag) {
390 LogTags* me = logtags;
391
392 if (!me) return nullptr;
393 me->WritePmsgEventLogTags(tag);
394 return me->tagToName(tag);
395 }
396
397 // converts an event tag into a format
tagToFormat(uint32_t tag) const398 const char* LogTags::tagToFormat(uint32_t tag) const {
399 tag2format_const_iterator iform;
400
401 android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock));
402
403 iform = tag2format.find(tag);
404 if (iform == tag2format.end()) return nullptr;
405
406 return iform->second.c_str();
407 }
408
409 // converts a name into an event tag
nameToTag(const char * name) const410 uint32_t LogTags::nameToTag(const char* name) const {
411 uint32_t ret = emptyTag;
412
413 // Bug: Only works for a single entry, we can have multiple entries,
414 // one for each format, so we find first entry recorded, or entry with
415 // no format associated with it.
416
417 android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock));
418
419 key2tag_const_iterator ik = key2tag.find(std::string(name));
420 if (ik != key2tag.end()) ret = ik->second;
421
422 return ret;
423 }
424
425 // Caller must perform locks, can be under reader (for pre-check) or
426 // writer lock. We use this call to invent a new deterministically
427 // random tag, unique is cleared if no conflicts. If format is NULL,
428 // we are in readonly mode.
nameToTag_locked(const std::string & name,const char * format,bool & unique)429 uint32_t LogTags::nameToTag_locked(const std::string& name, const char* format,
430 bool& unique) {
431 key2tag_const_iterator ik;
432
433 bool write = format != nullptr;
434 unique = write;
435
436 if (!write) {
437 // Bug: Only works for a single entry, we can have multiple entries,
438 // one for each format, so we find first entry recorded, or entry with
439 // no format associated with it.
440 ik = key2tag.find(name);
441 if (ik == key2tag.end()) return emptyTag;
442 return ik->second;
443 }
444
445 std::string Key(name);
446 if (*format) Key += std::string("+") + format;
447
448 ik = key2tag.find(Key);
449 if (ik != key2tag.end()) {
450 unique = false;
451 return ik->second;
452 }
453
454 size_t Hash = key2tag.hash_function()(Key);
455 uint32_t Tag = Hash;
456 // This sets an upper limit on the conflics we are allowed to deal with.
457 for (unsigned i = 0; i < 256;) {
458 tag2name_const_iterator it = tag2name.find(Tag);
459 if (it == tag2name.end()) return Tag;
460 std::string localKey(it->second);
461 tag2format_const_iterator iform = tag2format.find(Tag);
462 if ((iform == tag2format.end()) && iform->second.length()) {
463 localKey += "+" + iform->second;
464 }
465 unique = !!it->second.compare(localKey);
466 if (!unique) return Tag; // unlikely except in a race
467
468 ++i;
469 // Algorithm to convert hash to next tag
470 if (i < 32) {
471 Tag = (Hash >> i);
472 // size_t is 32 bits, or upper word zero, rotate
473 if ((sizeof(Hash) <= 4) || ((Hash & (uint64_t(-1LL) << 32)) == 0)) {
474 Tag |= Hash << (32 - i);
475 }
476 } else {
477 Tag = Hash + i - 31;
478 }
479 }
480 return emptyTag;
481 }
482
openFile(const char * name,int mode,bool warning)483 static int openFile(const char* name, int mode, bool warning) {
484 int fd = TEMP_FAILURE_RETRY(open(name, mode));
485 if (fd < 0 && warning) {
486 PLOG(ERROR) << "Failed to open " << name;
487 }
488 return fd;
489 }
490
WritePmsgEventLogTags(uint32_t tag,uid_t uid)491 void LogTags::WritePmsgEventLogTags(uint32_t tag, uid_t uid) {
492 android::RWLock::AutoRLock readLock(rwlock);
493
494 tag2total_const_iterator itot = tag2total.find(tag);
495 if (itot == tag2total.end()) return; // source is a static entry
496
497 size_t lastTotal = itot->second;
498
499 // Every 16K (half the smallest configurable pmsg buffer size) record
500 static const size_t rate_to_pmsg = 16 * 1024;
501 if (lastTotal && (LogStatistics::sizesTotal() - lastTotal) < rate_to_pmsg) {
502 return;
503 }
504
505 static int pmsg_fd = -1;
506 if (pmsg_fd < 0) {
507 pmsg_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
508 // unlikely, but deal with partners with borken pmsg
509 if (pmsg_fd < 0) return;
510 }
511
512 std::string Name = tag2name[tag];
513 tag2format_const_iterator iform = tag2format.find(tag);
514 std::string Format = (iform != tag2format.end()) ? iform->second : "";
515
516 auto ctx = create_android_logger(TAG_DEF_LOG_TAG);
517 auto guard = make_scope_guard([&ctx]() { android_log_destroy(&ctx); });
518 if (android_log_write_int32(ctx, static_cast<int32_t>(tag) < 0) ||
519 android_log_write_string8_len(ctx, Name.c_str(), Name.size()) < 0 ||
520 android_log_write_string8_len(ctx, Format.c_str(), Format.size()) < 0) {
521 return;
522 }
523
524 const char* cp = nullptr;
525 ssize_t len = android_log_write_list_buffer(ctx, &cp);
526
527 if (len <= 0 || cp == nullptr) {
528 return;
529 }
530
531 std::string buffer(cp, len);
532
533 /*
534 * struct {
535 * // what we provide to pstore
536 * android_pmsg_log_header_t pmsgHeader;
537 * // what we provide to file
538 * android_log_header_t header;
539 * // caller provides
540 * union {
541 * struct {
542 * char prio;
543 * char payload[];
544 * } string;
545 * struct {
546 * uint32_t tag
547 * char payload[];
548 * } binary;
549 * };
550 * };
551 */
552
553 struct timespec ts;
554 clock_gettime(CLOCK_REALTIME, &ts);
555
556 android_log_header_t header = {
557 .id = LOG_ID_EVENTS,
558 .tid = static_cast<uint16_t>(android::base::GetThreadId()),
559 .realtime.tv_sec = static_cast<uint32_t>(ts.tv_sec),
560 .realtime.tv_nsec = static_cast<uint32_t>(ts.tv_nsec),
561 };
562
563 uint32_t outTag = TAG_DEF_LOG_TAG;
564 outTag = get4LE((const char*)&outTag);
565
566 android_pmsg_log_header_t pmsgHeader = {
567 .magic = LOGGER_MAGIC,
568 .len = (uint16_t)(sizeof(pmsgHeader) + sizeof(header) + sizeof(outTag) +
569 buffer.length()),
570 .uid = (uint16_t)AID_ROOT,
571 .pid = (uint16_t)getpid(),
572 };
573
574 struct iovec Vec[] = { { (unsigned char*)&pmsgHeader, sizeof(pmsgHeader) },
575 { (unsigned char*)&header, sizeof(header) },
576 { (unsigned char*)&outTag, sizeof(outTag) },
577 { (unsigned char*)const_cast<char*>(buffer.data()),
578 buffer.length() } };
579
580 tag2uid_const_iterator ut = tag2uid.find(tag);
581 if (ut == tag2uid.end()) {
582 TEMP_FAILURE_RETRY(writev(pmsg_fd, Vec, arraysize(Vec)));
583 } else if (uid != AID_ROOT) {
584 pmsgHeader.uid = (uint16_t)uid;
585 TEMP_FAILURE_RETRY(writev(pmsg_fd, Vec, arraysize(Vec)));
586 } else {
587 for (auto& it : ut->second) {
588 pmsgHeader.uid = (uint16_t)it;
589 TEMP_FAILURE_RETRY(writev(pmsg_fd, Vec, arraysize(Vec)));
590 }
591 }
592 }
593
WriteDynamicEventLogTags(uint32_t tag,uid_t uid)594 void LogTags::WriteDynamicEventLogTags(uint32_t tag, uid_t uid) {
595 static const int mode =
596 O_WRONLY | O_APPEND | O_CLOEXEC | O_NOFOLLOW | O_BINARY;
597
598 int fd = openFile(dynamic_event_log_tags, mode, true);
599 if (fd < 0) return;
600
601 android::RWLock::AutoWLock writeLock(rwlock);
602
603 std::string ret = formatEntry_locked(tag, uid, false);
604 android::base::WriteStringToFd(ret, fd);
605 close(fd);
606
607 size_t size = 0;
608 file2watermark_const_iterator iwater;
609
610 iwater = file2watermark.find(dynamic_event_log_tags);
611 if (iwater != file2watermark.end()) size = iwater->second;
612
613 file2watermark[dynamic_event_log_tags] = size + ret.length();
614 }
615
WriteDebugEventLogTags(uint32_t tag,uid_t uid)616 void LogTags::WriteDebugEventLogTags(uint32_t tag, uid_t uid) {
617 static const int mode =
618 O_WRONLY | O_APPEND | O_CLOEXEC | O_NOFOLLOW | O_BINARY;
619
620 static bool one = true;
621 int fd = openFile(debug_event_log_tags, mode, one);
622 one = fd >= 0;
623 if (!one) return;
624
625 android::RWLock::AutoWLock writeLock(rwlock);
626
627 std::string ret = formatEntry_locked(tag, uid, false);
628 android::base::WriteStringToFd(ret, fd);
629 close(fd);
630
631 size_t size = 0;
632 file2watermark_const_iterator iwater;
633
634 iwater = file2watermark.find(debug_event_log_tags);
635 if (iwater != file2watermark.end()) size = iwater->second;
636
637 file2watermark[debug_event_log_tags] = size + ret.length();
638 }
639
640 // How we maintain some runtime or reboot stickiness
WritePersistEventLogTags(uint32_t tag,uid_t uid,const char * source)641 void LogTags::WritePersistEventLogTags(uint32_t tag, uid_t uid,
642 const char* source) {
643 // very unlikely
644 bool etc = source && !strcmp(source, system_event_log_tags);
645 if (etc) return;
646
647 bool dynamic = source && !strcmp(source, dynamic_event_log_tags);
648 bool debug = (!dynamic && source && !strcmp(source, debug_event_log_tags)) ||
649 !__android_log_is_debuggable();
650
651 WritePmsgEventLogTags(tag, uid);
652
653 size_t lastTotal = 0;
654 {
655 android::RWLock::AutoRLock readLock(rwlock);
656
657 tag2total_const_iterator itot = tag2total.find(tag);
658 if (itot != tag2total.end()) lastTotal = itot->second;
659 }
660
661 if (lastTotal == 0) { // denotes first time for this one
662 if (!dynamic || !RebuildFileEventLogTags(dynamic_event_log_tags)) {
663 WriteDynamicEventLogTags(tag, uid);
664 }
665
666 if (!debug && !RebuildFileEventLogTags(debug_event_log_tags)) {
667 WriteDebugEventLogTags(tag, uid);
668 }
669 }
670
671 lastTotal = LogStatistics::sizesTotal();
672 if (!lastTotal) ++lastTotal;
673
674 // record totals for next watermark.
675 android::RWLock::AutoWLock writeLock(rwlock);
676 tag2total[tag] = lastTotal;
677 }
678
679 // nameToTag converts a name into an event tag. If format is NULL, then we
680 // are in readonly mode.
nameToTag(uid_t uid,const char * name,const char * format)681 uint32_t LogTags::nameToTag(uid_t uid, const char* name, const char* format) {
682 std::string Name = std::string(name);
683 bool write = format != nullptr;
684 bool updateUid = uid != AID_ROOT;
685 bool updateFormat = format && *format;
686 bool unique;
687 uint32_t Tag;
688
689 {
690 android::RWLock::AutoRLock readLock(rwlock);
691
692 Tag = nameToTag_locked(Name, format, unique);
693 if (updateUid && (Tag != emptyTag) && !unique) {
694 tag2uid_const_iterator ut = tag2uid.find(Tag);
695 if ((ut != tag2uid.end()) &&
696 (ut->second.find(uid) == ut->second.end())) {
697 unique = write; // write passthrough to update uid counts
698 if (!write) Tag = emptyTag; // deny read access
699 }
700 }
701 }
702
703 if (Tag == emptyTag) return Tag;
704 WritePmsgEventLogTags(Tag, uid); // record references periodically
705 if (!unique) return Tag;
706
707 bool updateWrite = false;
708 bool updateTag;
709
710 // Special case of AddEventLogTags, checks per-uid counter which makes
711 // no sense there, and is also optimized somewhat to reduce write times.
712 {
713 android::RWLock::AutoWLock writeLock(rwlock);
714
715 // double check after switch from read lock to write lock for Tag
716 updateTag = tag2name.find(Tag) == tag2name.end();
717 // unlikely, either update, race inviting conflict or multiple uids
718 if (!updateTag) {
719 Tag = nameToTag_locked(Name, format, unique);
720 if (Tag == emptyTag) return Tag;
721 // is it multiple uid's setting this value
722 if (!unique) {
723 tag2uid_const_iterator ut = tag2uid.find(Tag);
724 if (updateUid) {
725 // Add it to the uid list
726 if ((ut == tag2uid.end()) ||
727 (ut->second.find(uid) != ut->second.end())) {
728 return Tag;
729 }
730 const_cast<uid_list&>(ut->second).emplace(uid);
731 updateWrite = true;
732 } else {
733 if (ut == tag2uid.end()) return Tag;
734 // (system) adding a global one, erase the uid list
735 tag2uid.erase(ut);
736 updateWrite = true;
737 }
738 }
739 }
740
741 // Update section
742 size_t count;
743 if (updateUid) {
744 count = 0;
745 uid2count_const_iterator ci = uid2count.find(uid);
746 if (ci != uid2count.end()) {
747 count = ci->second;
748 if (count >= max_per_uid) {
749 if (!updateWrite) return emptyTag;
750 // If we are added to the per-Uid perms, leak the Tag
751 // if it already exists.
752 updateUid = false;
753 updateTag = false;
754 updateFormat = false;
755 }
756 }
757 }
758
759 // updateWrite -> trigger output on modified content, reset tag2total
760 // also sets static to dynamic entries if they are alterred,
761 // only occurs if they have a uid, and runtime adds another uid.
762 if (updateWrite) tag2total[Tag] = 0;
763
764 if (updateTag) {
765 // mark as a dynamic entry, but do not upset current total counter
766 tag2total_const_iterator itot = tag2total.find(Tag);
767 if (itot == tag2total.end()) tag2total[Tag] = 0;
768
769 if (*format) {
770 key2tag[Name + "+" + format] = Tag;
771 if (key2tag.find(Name) == key2tag.end()) key2tag[Name] = Tag;
772 } else {
773 key2tag[Name] = Tag;
774 }
775 tag2name[Tag] = Name;
776 }
777 if (updateFormat) tag2format[Tag] = format;
778
779 if (updateUid) {
780 tag2uid[Tag].emplace(uid);
781 uid2count[uid] = count + 1;
782 }
783 }
784
785 if (updateTag || updateFormat || updateWrite) {
786 WritePersistEventLogTags(Tag, uid);
787 }
788
789 return Tag;
790 }
791
formatEntry(uint32_t tag,uid_t uid,const char * name,const char * format)792 std::string LogTags::formatEntry(uint32_t tag, uid_t uid, const char* name,
793 const char* format) {
794 if (!format || !format[0]) {
795 return android::base::StringPrintf("%" PRIu32 "\t%s\n", tag, name);
796 }
797 size_t len = (strlen(name) + 7) / 8;
798 static const char tabs[] = "\t\t\t";
799 if (len > strlen(tabs)) len = strlen(tabs);
800 std::string Uid;
801 if (uid != AID_ROOT) Uid = android::base::StringPrintf(" # uid=%u", uid);
802 return android::base::StringPrintf("%" PRIu32 "\t%s%s\t%s%s\n", tag, name,
803 &tabs[len], format, Uid.c_str());
804 }
805
formatEntry_locked(uint32_t tag,uid_t uid,bool authenticate)806 std::string LogTags::formatEntry_locked(uint32_t tag, uid_t uid,
807 bool authenticate) {
808 const char* name = tag2name[tag].c_str();
809
810 const char* format = "";
811 tag2format_const_iterator iform = tag2format.find(tag);
812 if (iform != tag2format.end()) format = iform->second.c_str();
813
814 // Access permission test, do not report dynamic entries
815 // that do not belong to us.
816 tag2uid_const_iterator ut = tag2uid.find(tag);
817 if (ut == tag2uid.end()) {
818 return formatEntry(tag, AID_ROOT, name, format);
819 }
820 if (uid != AID_ROOT) {
821 if (authenticate && (ut->second.find(uid) == ut->second.end())) {
822 return std::string("");
823 }
824 return formatEntry(tag, uid, name, format);
825 }
826
827 // Show all, one for each registered uid (we are group root)
828 std::string ret;
829 for (auto& it : ut->second) {
830 ret += formatEntry(tag, it, name, format);
831 }
832 return ret;
833 }
834
formatEntry(uint32_t tag,uid_t uid)835 std::string LogTags::formatEntry(uint32_t tag, uid_t uid) {
836 android::RWLock::AutoRLock readLock(rwlock);
837 return formatEntry_locked(tag, uid);
838 }
839
formatGetEventTag(uid_t uid,const char * name,const char * format)840 std::string LogTags::formatGetEventTag(uid_t uid, const char* name,
841 const char* format) {
842 bool all = name && (name[0] == '*') && !name[1];
843 bool list = !name || all;
844 std::string ret;
845
846 if (!list) {
847 // switch to read entry only if format == "*"
848 if (format && (format[0] == '*') && !format[1]) format = nullptr;
849
850 // WAI: for null format, only works for a single entry, we can have
851 // multiple entries, one for each format, so we find first entry
852 // recorded, or entry with no format associated with it.
853 // We may desire to print all that match the name, but we did not
854 // add a mapping table for that and the cost is too high.
855 uint32_t tag = nameToTag(uid, name, format);
856 if (tag == emptyTag) return std::string("-1 ESRCH");
857 if (uid == AID_ROOT) {
858 android::RWLock::AutoRLock readLock(rwlock);
859
860 // first uid in list so as to manufacture an accurate reference
861 tag2uid_const_iterator ut = tag2uid.find(tag);
862 if ((ut != tag2uid.end()) &&
863 (ut->second.begin() != ut->second.end())) {
864 uid = *(ut->second.begin());
865 }
866 }
867 ret = formatEntry(tag, uid, name, format ?: tagToFormat(tag));
868 if (!ret.length()) return std::string("-1 ESRCH");
869 return ret;
870 }
871
872 android::RWLock::AutoRLock readLock(rwlock);
873 if (all) {
874 // everything under the sun
875 for (const auto& it : tag2name) {
876 ret += formatEntry_locked(it.first, uid);
877 }
878 } else {
879 // set entries are dynamic
880 for (const auto& it : tag2total) {
881 ret += formatEntry_locked(it.first, uid);
882 }
883 }
884 return ret;
885 }
886