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