blob: ff7e7625829d7c25f09b93f903b7718a96f18f9e [file] [log] [blame]
Mark Salyzyn61e9ce62016-09-12 14:51:54 -07001/*
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/macros.h>
33#include <android-base/stringprintf.h>
34#include <log/log_event_list.h>
Steven Moreland1f83aa42017-04-13 23:48:57 -070035#include <log/log_properties.h>
Mark Salyzyn61e9ce62016-09-12 14:51:54 -070036#include <private/android_filesystem_config.h>
Mark Salyzyn61e9ce62016-09-12 14:51:54 -070037
38#include "LogTags.h"
39#include "LogUtils.h"
40
41static LogTags* logtags;
42
43const char LogTags::system_event_log_tags[] = "/system/etc/event-log-tags";
44const char LogTags::dynamic_event_log_tags[] = "/dev/event-log-tags";
45// Only for debug
46const char LogTags::debug_event_log_tags[] = "/data/misc/logd/event-log-tags";
47
48// Sniff for first uid=%d in utf8z comment string
49static uid_t sniffUid(const char* comment, const char* endp) {
50 if (!comment) return AID_ROOT;
51
52 if (*comment == '#') ++comment;
Mark Salyzyn501c3732017-03-10 14:31:54 -080053 while ((comment < endp) && (*comment != '\n') && isspace(*comment))
54 ++comment;
Mark Salyzyn61e9ce62016-09-12 14:51:54 -070055 static const char uid_str[] = "uid=";
56 if (((comment + strlen(uid_str)) >= endp) ||
Mark Salyzyn501c3732017-03-10 14:31:54 -080057 fastcmp<strncmp>(comment, uid_str, strlen(uid_str)) ||
58 !isdigit(comment[strlen(uid_str)]))
59 return AID_ROOT;
Mark Salyzyn61e9ce62016-09-12 14:51:54 -070060 char* cp;
61 unsigned long Uid = strtoul(comment + 4, &cp, 10);
62 if ((cp > endp) || (Uid >= INT_MAX)) return AID_ROOT;
63
64 return Uid;
65}
66
67// Checks for file corruption, and report false if there was no need
68// to rebuild the referenced file. Failure to rebuild is only logged,
69// does not cause a return value of false.
70bool LogTags::RebuildFileEventLogTags(const char* filename, bool warn) {
71 int fd;
72
73 {
74 android::RWLock::AutoRLock readLock(rwlock);
75
76 if (tag2total.begin() == tag2total.end()) {
77 return false;
78 }
79
80 file2watermark_const_iterator iwater = file2watermark.find(filename);
81 if (iwater == file2watermark.end()) {
82 return false;
83 }
84
85 struct stat sb;
86 if (!stat(filename, &sb) && ((size_t)sb.st_size >= iwater->second)) {
87 return false;
88 }
89
90 // dump what we already know back into the file?
Mark Salyzyn501c3732017-03-10 14:31:54 -080091 fd = TEMP_FAILURE_RETRY(open(
92 filename, O_WRONLY | O_TRUNC | O_CLOEXEC | O_NOFOLLOW | O_BINARY));
Mark Salyzyn61e9ce62016-09-12 14:51:54 -070093 if (fd >= 0) {
94 time_t now = time(NULL);
95 struct tm tm;
96 localtime_r(&now, &tm);
97 char timebuf[20];
Mark Salyzyn501c3732017-03-10 14:31:54 -080098 size_t len =
99 strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", &tm);
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700100 android::base::WriteStringToFd(
101 android::base::StringPrintf(
102 "# Rebuilt %.20s, content owned by logd\n", timebuf),
103 fd);
104 for (const auto& it : tag2total) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800105 android::base::WriteStringToFd(
106 formatEntry_locked(it.first, AID_ROOT), fd);
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700107 }
Nick Kralevich3d118e72017-10-24 10:45:48 -0700108 close(fd);
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700109 }
110 }
111
112 if (warn) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800113 android::prdebug(
114 ((fd < 0) ? "%s failed to rebuild"
115 : "%s missing, damaged or truncated; rebuilt"),
116 filename);
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700117 }
118
119 if (fd >= 0) {
120 android::RWLock::AutoWLock writeLock(rwlock);
121
122 struct stat sb;
123 if (!stat(filename, &sb)) file2watermark[filename] = sb.st_size;
124 }
125
126 return true;
127}
128
Mark Salyzyn501c3732017-03-10 14:31:54 -0800129void LogTags::AddEventLogTags(uint32_t tag, uid_t uid, const std::string& Name,
130 const std::string& Format, const char* source,
131 bool warn) {
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700132 std::string Key = Name;
133 if (Format.length()) Key += "+" + Format;
134
135 bool update = !source || !!strcmp(source, system_event_log_tags);
136 bool newOne;
137
138 {
139 android::RWLock::AutoWLock writeLock(rwlock);
140
141 tag2total_const_iterator itot = tag2total.find(tag);
142
143 // unlikely except for dupes, or updates to uid list (more later)
144 if (itot != tag2total.end()) update = false;
145
146 newOne = tag2name.find(tag) == tag2name.end();
147 key2tag[Key] = tag;
148
149 if (Format.length()) {
150 if (key2tag.find(Name) == key2tag.end()) {
151 key2tag[Name] = tag;
152 }
153 tag2format[tag] = Format;
154 }
155 tag2name[tag] = Name;
156
157 tag2uid_const_iterator ut = tag2uid.find(tag);
158 if (ut != tag2uid.end()) {
159 if (uid == AID_ROOT) {
160 tag2uid.erase(ut);
161 update = true;
162 } else if (ut->second.find(uid) == ut->second.end()) {
163 const_cast<uid_list&>(ut->second).emplace(uid);
164 update = true;
165 }
166 } else if (newOne && (uid != AID_ROOT)) {
167 tag2uid[tag].emplace(uid);
168 update = true;
169 }
170
171 // updatePersist -> trigger output on modified
172 // content, reset tag2total if available
173 if (update && (itot != tag2total.end())) tag2total[tag] = 0;
174 }
175
176 if (update) {
177 WritePersistEventLogTags(tag, uid, source);
178 } else if (warn && !newOne && source) {
179 // For the files, we want to report dupes.
Mark Salyzyn501c3732017-03-10 14:31:54 -0800180 android::prdebug("Multiple tag %" PRIu32 " %s %s %s", tag, Name.c_str(),
181 Format.c_str(), source);
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700182 }
183}
184
185// Read the event log tags file, and build up our internal database
186void LogTags::ReadFileEventLogTags(const char* filename, bool warn) {
187 bool etc = !strcmp(filename, system_event_log_tags);
188 bool debug = !etc && !strcmp(filename, debug_event_log_tags);
189
190 if (!etc) {
191 RebuildFileEventLogTags(filename, warn);
192 }
193 std::string content;
194 if (android::base::ReadFileToString(filename, &content)) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800195 char* cp = (char*)content.c_str();
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700196 char* endp = cp + content.length();
197
198 {
199 android::RWLock::AutoRLock writeLock(rwlock);
200
201 file2watermark[filename] = content.length();
202 }
203
204 char* lineStart = cp;
205 while (cp < endp) {
206 if (*cp == '\n') {
207 lineStart = cp;
208 } else if (lineStart) {
209 if (*cp == '#') {
210 /* comment; just scan to end */
211 lineStart = NULL;
212 } else if (isdigit(*cp)) {
213 unsigned long Tag = strtoul(cp, &cp, 10);
214 if (warn && (Tag > emptyTag)) {
215 android::prdebug("tag too large %lu", Tag);
216 }
217 while ((cp < endp) && (*cp != '\n') && isspace(*cp)) ++cp;
218 if (cp >= endp) break;
219 if (*cp == '\n') continue;
220 const char* name = cp;
221 /* Determine whether it is a valid tag name [a-zA-Z0-9_] */
222 bool hasAlpha = false;
223 while ((cp < endp) && (isalnum(*cp) || (*cp == '_'))) {
224 if (!isdigit(*cp)) hasAlpha = true;
225 ++cp;
226 }
227 std::string Name(name, cp - name);
228#ifdef ALLOW_NOISY_LOGGING_OF_PROBLEM_WITH_LOTS_OF_TECHNICAL_DEBT
229 static const size_t maximum_official_tag_name_size = 24;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800230 if (warn &&
231 (Name.length() > maximum_official_tag_name_size)) {
232 android::prdebug("tag name too long %s", Name.c_str());
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700233 }
234#endif
Mark Salyzyn501c3732017-03-10 14:31:54 -0800235 if (hasAlpha &&
236 ((cp >= endp) || (*cp == '#') || isspace(*cp))) {
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700237 if (Tag > emptyTag) {
238 if (*cp != '\n') lineStart = NULL;
239 continue;
240 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800241 while ((cp < endp) && (*cp != '\n') && isspace(*cp))
242 ++cp;
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700243 const char* format = cp;
244 uid_t uid = AID_ROOT;
245 while ((cp < endp) && (*cp != '\n')) {
246 if (*cp == '#') {
247 uid = sniffUid(cp, endp);
248 lineStart = NULL;
249 break;
250 }
251 ++cp;
252 }
253 while ((cp > format) && isspace(cp[-1])) {
254 --cp;
255 lineStart = NULL;
256 }
257 std::string Format(format, cp - format);
258
259 AddEventLogTags((uint32_t)Tag, uid, Name, Format,
260 filename, warn);
261 } else {
262 if (warn) {
263 android::prdebug("tag name invalid %.*s",
264 (int)(cp - name + 1), name);
265 }
266 lineStart = NULL;
267 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800268 } else if (!isspace(*cp)) {
269 break;
270 }
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700271 }
272 cp++;
273 }
274 } else if (warn) {
275 android::prdebug("Cannot read %s", filename);
276 }
277}
278
279// Extract a 4-byte value from a byte stream.
Mark Salyzyn501c3732017-03-10 14:31:54 -0800280static inline uint32_t get4LE(const char* msg) {
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700281 const uint8_t* src = reinterpret_cast<const uint8_t*>(msg);
282 return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
283}
284
285// Additional persistent sources for invented log tags. Read the
286// special pmsg event for log tags, and build up our internal
287// database with any found.
288void LogTags::ReadPersistEventLogTags() {
289 struct logger_list* logger_list = android_logger_list_alloc(
Mark Salyzyn501c3732017-03-10 14:31:54 -0800290 ANDROID_LOG_RDONLY | ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK, 0,
291 (pid_t)0);
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700292 if (!logger_list) return;
293
294 struct logger* e = android_logger_open(logger_list, LOG_ID_EVENTS);
295 struct logger* s = android_logger_open(logger_list, LOG_ID_SECURITY);
296 if (!e && !s) {
297 android_logger_list_free(logger_list);
298 return;
299 }
300
301 for (;;) {
302 struct log_msg log_msg;
303 int ret = android_logger_list_read(logger_list, &log_msg);
304 if (ret <= 0) break;
305
306 const char* msg = log_msg.msg();
307 if (!msg) continue;
308 if (log_msg.entry.len <= sizeof(uint32_t)) continue;
309 uint32_t Tag = get4LE(msg);
310 if (Tag != TAG_DEF_LOG_TAG) continue;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800311 uid_t uid = (log_msg.entry.hdr_size >= sizeof(logger_entry_v4))
312 ? log_msg.entry.uid
313 : AID_ROOT;
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700314
315 std::string Name;
316 std::string Format;
317 android_log_list_element elem;
318 {
319 android_log_event_list ctx(log_msg);
320 elem = ctx.read();
321 if (elem.type != EVENT_TYPE_LIST) {
322 continue;
323 }
324 elem = ctx.read();
325 if (elem.type != EVENT_TYPE_INT) {
326 continue;
327 }
328 Tag = elem.data.int32;
329 elem = ctx.read();
330 if (elem.type != EVENT_TYPE_STRING) {
331 continue;
332 }
333 Name = std::string(elem.data.string, elem.len);
334 elem = ctx.read();
335 if (elem.type != EVENT_TYPE_STRING) {
336 continue;
337 }
338 Format = std::string(elem.data.string, elem.len);
339 elem = ctx.read();
340 }
341 if ((elem.type != EVENT_TYPE_LIST_STOP) || !elem.complete) continue;
342
343 AddEventLogTags(Tag, uid, Name, Format);
344 }
345 android_logger_list_free(logger_list);
346}
347
348LogTags::LogTags() {
349 ReadFileEventLogTags(system_event_log_tags);
350 // Following will likely fail on boot, but is required if logd restarts
351 ReadFileEventLogTags(dynamic_event_log_tags, false);
352 if (__android_log_is_debuggable()) {
353 ReadFileEventLogTags(debug_event_log_tags, false);
354 }
355 ReadPersistEventLogTags();
356
357 logtags = this;
358}
359
360// Converts an event tag into a name
361const char* LogTags::tagToName(uint32_t tag) const {
362 tag2name_const_iterator it;
363
364 android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock));
365
366 it = tag2name.find(tag);
367 if ((it == tag2name.end()) || (it->second.length() == 0)) return NULL;
368
369 return it->second.c_str();
370}
371
372// Prototype in LogUtils.h allowing external access to our database.
373//
374// This must be a pure reader to our database, as everything else is
375// guaranteed single-threaded except this access point which is
376// asynchonous and can be multithreaded and thus rentrant. The
377// object's rwlock is only used to guarantee atomic access to the
378// unordered_map to prevent corruption, with a requirement to be a
379// low chance of contention for this call. If we end up changing
380// this algorithm resulting in write, then we should use a different
381// lock than the object's rwlock to protect groups of associated
382// actions.
383const char* android::tagToName(uint32_t tag) {
384 LogTags* me = logtags;
385
386 if (!me) return NULL;
387 me->WritePmsgEventLogTags(tag);
388 return me->tagToName(tag);
389}
390
391// Prototype in LogUtils.h allowing external access to our database.
392//
393// This only works on userdebug and eng devices to re-read the
394// /data/misc/logd/event-log-tags file right after /data is mounted.
395// The operation is near to boot and should only happen once. There
396// are races associated with its use since it can trigger a Rebuild
397// of the file, but that is a can-not-happen since the file was not
398// read yet. More dangerous if called later, but if all is well it
399// should just skip over everything and not write any new entries.
400void android::ReReadEventLogTags() {
401 LogTags* me = logtags;
402
403 if (me && __android_log_is_debuggable()) {
404 me->ReadFileEventLogTags(me->debug_event_log_tags);
405 }
406}
407
408// converts an event tag into a format
409const char* LogTags::tagToFormat(uint32_t tag) const {
410 tag2format_const_iterator iform;
411
412 android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock));
413
414 iform = tag2format.find(tag);
415 if (iform == tag2format.end()) return NULL;
416
417 return iform->second.c_str();
418}
419
420// converts a name into an event tag
421uint32_t LogTags::nameToTag(const char* name) const {
422 uint32_t ret = emptyTag;
423
424 // Bug: Only works for a single entry, we can have multiple entries,
425 // one for each format, so we find first entry recorded, or entry with
426 // no format associated with it.
427
428 android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock));
429
430 key2tag_const_iterator ik = key2tag.find(std::string(name));
431 if (ik != key2tag.end()) ret = ik->second;
432
433 return ret;
434}
435
436// Caller must perform locks, can be under reader (for pre-check) or
437// writer lock. We use this call to invent a new deterministically
438// random tag, unique is cleared if no conflicts. If format is NULL,
439// we are in readonly mode.
Mark Salyzyn501c3732017-03-10 14:31:54 -0800440uint32_t LogTags::nameToTag_locked(const std::string& name, const char* format,
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700441 bool& unique) {
442 key2tag_const_iterator ik;
443
444 bool write = format != NULL;
445 unique = write;
446
447 if (!write) {
448 // Bug: Only works for a single entry, we can have multiple entries,
449 // one for each format, so we find first entry recorded, or entry with
450 // no format associated with it.
451 ik = key2tag.find(name);
452 if (ik == key2tag.end()) return emptyTag;
453 return ik->second;
454 }
455
456 std::string Key(name);
457 if (*format) Key += std::string("+") + format;
458
459 ik = key2tag.find(Key);
460 if (ik != key2tag.end()) {
461 unique = false;
462 return ik->second;
463 }
464
465 size_t Hash = key2tag.hash_function()(Key);
466 uint32_t Tag = Hash;
467 // This sets an upper limit on the conflics we are allowed to deal with.
Mark Salyzyn501c3732017-03-10 14:31:54 -0800468 for (unsigned i = 0; i < 256;) {
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700469 tag2name_const_iterator it = tag2name.find(Tag);
470 if (it == tag2name.end()) return Tag;
471 std::string localKey(it->second);
472 tag2format_const_iterator iform = tag2format.find(Tag);
473 if ((iform == tag2format.end()) && iform->second.length()) {
474 localKey += "+" + iform->second;
475 }
476 unique = !!it->second.compare(localKey);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800477 if (!unique) return Tag; // unlikely except in a race
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700478
479 ++i;
480 // Algorithm to convert hash to next tag
481 if (i < 32) {
482 Tag = (Hash >> i);
483 // size_t is 32 bits, or upper word zero, rotate
Mark Salyzyn501c3732017-03-10 14:31:54 -0800484 if ((sizeof(Hash) <= 4) || ((Hash & (uint64_t(-1LL) << 32)) == 0)) {
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700485 Tag |= Hash << (32 - i);
486 }
487 } else {
488 Tag = Hash + i - 31;
489 }
490 }
491 return emptyTag;
492}
493
494static int openFile(const char* name, int mode, bool warning) {
495 int fd = TEMP_FAILURE_RETRY(open(name, mode));
496 if ((fd < 0) && warning) {
497 android::prdebug("Failed open %s (%d)", name, errno);
498 }
499 return fd;
500}
501
502void LogTags::WritePmsgEventLogTags(uint32_t tag, uid_t uid) {
503 android::RWLock::AutoRLock readLock(rwlock);
504
505 tag2total_const_iterator itot = tag2total.find(tag);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800506 if (itot == tag2total.end()) return; // source is a static entry
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700507
508 size_t lastTotal = itot->second;
509
510 // Every 16K (half the smallest configurable pmsg buffer size) record
511 static const size_t rate_to_pmsg = 16 * 1024;
512 if (lastTotal && ((android::sizesTotal() - lastTotal) < rate_to_pmsg)) {
513 return;
514 }
515
516 static int pmsg_fd = -1;
517 if (pmsg_fd < 0) {
518 pmsg_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
519 // unlikely, but deal with partners with borken pmsg
520 if (pmsg_fd < 0) return;
521 }
522
523 std::string Name = tag2name[tag];
524 tag2format_const_iterator iform = tag2format.find(tag);
525 std::string Format = (iform != tag2format.end()) ? iform->second : "";
526
527 __android_log_event_list ctx(TAG_DEF_LOG_TAG);
528 ctx << tag << Name << Format;
529 std::string buffer(ctx);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800530 if (buffer.length() <= 0) return; // unlikely
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700531
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(android_log_clockid(), &ts);
554
555 android_log_header_t header = {
556 .id = LOG_ID_EVENTS,
557 .tid = (uint16_t)gettid(),
558 .realtime.tv_sec = (uint32_t)ts.tv_sec,
559 .realtime.tv_nsec = (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,
Mark Salyzyn501c3732017-03-10 14:31:54 -0800567 .len = (uint16_t)(sizeof(pmsgHeader) + sizeof(header) + sizeof(outTag) +
568 buffer.length()),
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700569 .uid = (uint16_t)AID_ROOT,
570 .pid = (uint16_t)getpid(),
571 };
572
Mark Salyzyn501c3732017-03-10 14:31:54 -0800573 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() } };
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700578
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 {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800586 for (auto& it : ut->second) {
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700587 pmsgHeader.uid = (uint16_t)it;
588 TEMP_FAILURE_RETRY(writev(pmsg_fd, Vec, arraysize(Vec)));
589 }
590 }
591}
592
593void LogTags::WriteDynamicEventLogTags(uint32_t tag, uid_t uid) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800594 static const int mode =
595 O_WRONLY | O_APPEND | O_CLOEXEC | O_NOFOLLOW | O_BINARY;
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700596
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);
Nick Kralevich3d118e72017-10-24 10:45:48 -0700604 close(fd);
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700605
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
615void LogTags::WriteDebugEventLogTags(uint32_t tag, uid_t uid) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800616 static const int mode =
617 O_WRONLY | O_APPEND | O_CLOEXEC | O_NOFOLLOW | O_BINARY;
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700618
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);
Nick Kralevich3d118e72017-10-24 10:45:48 -0700628 close(fd);
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700629
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
Mark Salyzyn501c3732017-03-10 14:31:54 -0800640void LogTags::WritePersistEventLogTags(uint32_t tag, uid_t uid,
641 const char* source) {
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700642 // 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);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800647 bool debug = (!dynamic && source && !strcmp(source, debug_event_log_tags)) ||
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700648 !__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
Mark Salyzyn501c3732017-03-10 14:31:54 -0800660 if (lastTotal == 0) { // denotes first time for this one
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700661 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 = android::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.
680uint32_t LogTags::nameToTag(uid_t uid, const char* name, const char* format) {
681 std::string Name = std::string(name);
682 bool write = format != NULL;
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()) &&
Mark Salyzyn501c3732017-03-10 14:31:54 -0800696 (ut->second.find(uid) == ut->second.end())) {
697 unique = write; // write passthrough to update uid counts
698 if (!write) Tag = emptyTag; // deny read access
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700699 }
700 } else {
701 unique = write && (ut != tag2uid.end());
702 }
703 }
704 }
705
706 if (Tag == emptyTag) return Tag;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800707 WritePmsgEventLogTags(Tag, uid); // record references periodically
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700708 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()) ||
Mark Salyzyn501c3732017-03-10 14:31:54 -0800730 (ut->second.find(uid) != ut->second.end())) {
731 return Tag;
732 }
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700733 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
Mark Salyzyn501c3732017-03-10 14:31:54 -0800795std::string LogTags::formatEntry(uint32_t tag, uid_t uid, const char* name,
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700796 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);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800805 return android::base::StringPrintf("%" PRIu32 "\t%s%s\t%s%s\n", tag, name,
806 &tabs[len], format, Uid.c_str());
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700807}
808
809std::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;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800832 for (auto& it : ut->second) {
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700833 ret += formatEntry(tag, it, name, format);
834 }
835 return ret;
836}
837
Mark Salyzyn407537f2017-02-21 16:19:08 -0800838std::string LogTags::formatEntry(uint32_t tag, uid_t uid) {
839 android::RWLock::AutoRLock readLock(rwlock);
840 return formatEntry_locked(tag, uid);
841}
842
Mark Salyzyn501c3732017-03-10 14:31:54 -0800843std::string LogTags::formatGetEventTag(uid_t uid, const char* name,
844 const char* format) {
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700845 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 = NULL;
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()) &&
Mark Salyzyn501c3732017-03-10 14:31:54 -0800866 (ut->second.begin() != ut->second.end())) {
Mark Salyzyn61e9ce62016-09-12 14:51:54 -0700867 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}