/src/perfetto/buildtools/android-logging/liblog/logger_write.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2007-2016 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 "logger_write.h" |
18 | | |
19 | | #include <errno.h> |
20 | | #include <inttypes.h> |
21 | | #include <libgen.h> |
22 | | #include <stdlib.h> |
23 | | #include <string.h> |
24 | | #include <sys/time.h> |
25 | | |
26 | | #ifdef __BIONIC__ |
27 | | #include <android/set_abort_message.h> |
28 | | #endif |
29 | | |
30 | | #include <atomic> |
31 | | |
32 | | #include <android-base/errno_restorer.h> |
33 | | #include <android-base/macros.h> |
34 | | #include <private/android_filesystem_config.h> |
35 | | #include <private/android_logger.h> |
36 | | |
37 | | #include "android/log.h" |
38 | | #include "log/log_read.h" |
39 | | #include "logger.h" |
40 | | #include "uio.h" |
41 | | |
42 | | #ifdef __ANDROID__ |
43 | | #include "logd_writer.h" |
44 | | #include "pmsg_writer.h" |
45 | | #endif |
46 | | |
47 | | #if defined(__APPLE__) |
48 | | #include <pthread.h> |
49 | | #elif defined(__linux__) && !defined(__ANDROID__) |
50 | | #include <syscall.h> |
51 | | #elif defined(_WIN32) |
52 | | #include <windows.h> |
53 | | #endif |
54 | | |
55 | | using android::base::ErrnoRestorer; |
56 | | |
57 | 0 | #define LOG_BUF_SIZE 1024 |
58 | | |
59 | | #if defined(__ANDROID__) |
60 | | static int check_log_uid_permissions() { |
61 | | uid_t uid = getuid(); |
62 | | |
63 | | /* Matches clientHasLogCredentials() in logd */ |
64 | | if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) { |
65 | | uid = geteuid(); |
66 | | if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) { |
67 | | gid_t gid = getgid(); |
68 | | if ((gid != AID_SYSTEM) && (gid != AID_ROOT) && (gid != AID_LOG)) { |
69 | | gid = getegid(); |
70 | | if ((gid != AID_SYSTEM) && (gid != AID_ROOT) && (gid != AID_LOG)) { |
71 | | int num_groups; |
72 | | gid_t* groups; |
73 | | |
74 | | num_groups = getgroups(0, NULL); |
75 | | if (num_groups <= 0) { |
76 | | return -EPERM; |
77 | | } |
78 | | groups = static_cast<gid_t*>(calloc(num_groups, sizeof(gid_t))); |
79 | | if (!groups) { |
80 | | return -ENOMEM; |
81 | | } |
82 | | num_groups = getgroups(num_groups, groups); |
83 | | while (num_groups > 0) { |
84 | | if (groups[num_groups - 1] == AID_LOG) { |
85 | | break; |
86 | | } |
87 | | --num_groups; |
88 | | } |
89 | | free(groups); |
90 | | if (num_groups <= 0) { |
91 | | return -EPERM; |
92 | | } |
93 | | } |
94 | | } |
95 | | } |
96 | | } |
97 | | return 0; |
98 | | } |
99 | | #endif |
100 | | |
101 | | /* |
102 | | * Release any logger resources. A new log write will immediately re-acquire. |
103 | | */ |
104 | 0 | void __android_log_close() { |
105 | | #ifdef __ANDROID__ |
106 | | LogdClose(); |
107 | | PmsgClose(); |
108 | | #endif |
109 | 0 | } |
110 | | |
111 | | #if defined(__GLIBC__) || defined(_WIN32) |
112 | 0 | static const char* getprogname() { |
113 | 0 | #if defined(__GLIBC__) |
114 | 0 | return program_invocation_short_name; |
115 | | #elif defined(_WIN32) |
116 | | static bool first = true; |
117 | | static char progname[MAX_PATH] = {}; |
118 | | |
119 | | if (first) { |
120 | | char path[PATH_MAX + 1]; |
121 | | DWORD result = GetModuleFileName(nullptr, path, sizeof(path) - 1); |
122 | | if (result == 0 || result == sizeof(path) - 1) return ""; |
123 | | path[PATH_MAX - 1] = 0; |
124 | | |
125 | | char* path_basename = basename(path); |
126 | | |
127 | | snprintf(progname, sizeof(progname), "%s", path_basename); |
128 | | first = false; |
129 | | } |
130 | | |
131 | | return progname; |
132 | | #endif |
133 | 0 | } |
134 | | #endif |
135 | | |
136 | | // It's possible for logging to happen during static initialization before our globals are |
137 | | // initialized, so we place this std::string in a function such that it is initialized on the first |
138 | | // call. |
139 | 0 | std::string& GetDefaultTag() { |
140 | 0 | static std::string default_tag = getprogname(); |
141 | 0 | return default_tag; |
142 | 0 | } |
143 | | |
144 | 0 | void __android_log_set_default_tag(const char* tag) { |
145 | 0 | GetDefaultTag().assign(tag, 0, LOGGER_ENTRY_MAX_PAYLOAD); |
146 | 0 | } |
147 | | |
148 | | static std::atomic_int32_t minimum_log_priority = ANDROID_LOG_DEFAULT; |
149 | 0 | int32_t __android_log_set_minimum_priority(int32_t priority) { |
150 | 0 | return minimum_log_priority.exchange(priority, std::memory_order_relaxed); |
151 | 0 | } |
152 | | |
153 | 0 | int32_t __android_log_get_minimum_priority() { |
154 | 0 | return minimum_log_priority; |
155 | 0 | } |
156 | | |
157 | | #ifdef __ANDROID__ |
158 | | static __android_logger_function logger_function = __android_log_logd_logger; |
159 | | #else |
160 | | static __android_logger_function logger_function = __android_log_stderr_logger; |
161 | | #endif |
162 | | |
163 | 0 | void __android_log_set_logger(__android_logger_function logger) { |
164 | 0 | logger_function = logger; |
165 | 0 | } |
166 | | |
167 | 0 | void __android_log_default_aborter(const char* abort_message) { |
168 | | #ifdef __ANDROID__ |
169 | | android_set_abort_message(abort_message); |
170 | | #else |
171 | 0 | UNUSED(abort_message); |
172 | 0 | #endif |
173 | 0 | abort(); |
174 | 0 | } |
175 | | |
176 | | static __android_aborter_function aborter_function = __android_log_default_aborter; |
177 | | |
178 | 0 | void __android_log_set_aborter(__android_aborter_function aborter) { |
179 | 0 | aborter_function = aborter; |
180 | 0 | } |
181 | | |
182 | 0 | void __android_log_call_aborter(const char* abort_message) { |
183 | 0 | aborter_function(abort_message); |
184 | 0 | } |
185 | | |
186 | | #ifdef __ANDROID__ |
187 | | static int write_to_log(log_id_t log_id, struct iovec* vec, size_t nr) { |
188 | | int ret; |
189 | | struct timespec ts; |
190 | | |
191 | | if (log_id == LOG_ID_KERNEL) { |
192 | | return -EINVAL; |
193 | | } |
194 | | |
195 | | clock_gettime(CLOCK_REALTIME, &ts); |
196 | | |
197 | | if (log_id == LOG_ID_SECURITY) { |
198 | | if (vec[0].iov_len < 4) { |
199 | | return -EINVAL; |
200 | | } |
201 | | |
202 | | ret = check_log_uid_permissions(); |
203 | | if (ret < 0) { |
204 | | return ret; |
205 | | } |
206 | | if (!__android_log_security()) { |
207 | | /* If only we could reset downstream logd counter */ |
208 | | return -EPERM; |
209 | | } |
210 | | } else if (log_id == LOG_ID_EVENTS || log_id == LOG_ID_STATS) { |
211 | | if (vec[0].iov_len < 4) { |
212 | | return -EINVAL; |
213 | | } |
214 | | } |
215 | | |
216 | | ret = LogdWrite(log_id, &ts, vec, nr); |
217 | | PmsgWrite(log_id, &ts, vec, nr); |
218 | | |
219 | | return ret; |
220 | | } |
221 | | #else |
222 | 0 | static int write_to_log(log_id_t, struct iovec*, size_t) { |
223 | | // Non-Android text logs should go to __android_log_stderr_logger, not here. |
224 | | // Non-Android binary logs are always dropped. |
225 | 0 | return 1; |
226 | 0 | } |
227 | | #endif |
228 | | |
229 | | // Copied from base/threads.cpp |
230 | 0 | static uint64_t GetThreadId() { |
231 | | #if defined(__BIONIC__) |
232 | | return gettid(); |
233 | | #elif defined(__APPLE__) |
234 | | uint64_t tid; |
235 | | pthread_threadid_np(NULL, &tid); |
236 | | return tid; |
237 | | #elif defined(__linux__) |
238 | | return syscall(__NR_gettid); |
239 | | #elif defined(_WIN32) |
240 | | return GetCurrentThreadId(); |
241 | | #endif |
242 | 0 | } |
243 | | |
244 | 0 | void __android_log_stderr_logger(const struct __android_log_message* log_message) { |
245 | 0 | struct tm now; |
246 | 0 | time_t t = time(nullptr); |
247 | |
|
248 | | #if defined(_WIN32) |
249 | | localtime_s(&now, &t); |
250 | | #else |
251 | 0 | localtime_r(&t, &now); |
252 | 0 | #endif |
253 | |
|
254 | 0 | char timestamp[32]; |
255 | 0 | strftime(timestamp, sizeof(timestamp), "%m-%d %H:%M:%S", &now); |
256 | |
|
257 | 0 | static const char log_characters[] = "XXVDIWEF"; |
258 | 0 | static_assert(arraysize(log_characters) - 1 == ANDROID_LOG_SILENT, |
259 | 0 | "Mismatch in size of log_characters and values in android_LogPriority"); |
260 | 0 | int32_t priority = |
261 | 0 | log_message->priority > ANDROID_LOG_SILENT ? ANDROID_LOG_FATAL : log_message->priority; |
262 | 0 | char priority_char = log_characters[priority]; |
263 | 0 | uint64_t tid = GetThreadId(); |
264 | |
|
265 | 0 | if (log_message->file != nullptr) { |
266 | 0 | fprintf(stderr, "%s %c %s %5d %5" PRIu64 " %s:%u] %s\n", |
267 | 0 | log_message->tag ? log_message->tag : "nullptr", priority_char, timestamp, getpid(), |
268 | 0 | tid, log_message->file, log_message->line, log_message->message); |
269 | 0 | } else { |
270 | 0 | fprintf(stderr, "%s %c %s %5d %5" PRIu64 " %s\n", |
271 | 0 | log_message->tag ? log_message->tag : "nullptr", priority_char, timestamp, getpid(), |
272 | 0 | tid, log_message->message); |
273 | 0 | } |
274 | 0 | } |
275 | | |
276 | 0 | void __android_log_logd_logger(const struct __android_log_message* log_message) { |
277 | 0 | int buffer_id = log_message->buffer_id == LOG_ID_DEFAULT ? LOG_ID_MAIN : log_message->buffer_id; |
278 | |
|
279 | 0 | struct iovec vec[3]; |
280 | 0 | vec[0].iov_base = |
281 | 0 | const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(&log_message->priority)); |
282 | 0 | vec[0].iov_len = 1; |
283 | 0 | vec[1].iov_base = const_cast<void*>(static_cast<const void*>(log_message->tag)); |
284 | 0 | vec[1].iov_len = strlen(log_message->tag) + 1; |
285 | 0 | vec[2].iov_base = const_cast<void*>(static_cast<const void*>(log_message->message)); |
286 | 0 | vec[2].iov_len = strlen(log_message->message) + 1; |
287 | |
|
288 | 0 | write_to_log(static_cast<log_id_t>(buffer_id), vec, 3); |
289 | 0 | } |
290 | | |
291 | 0 | int __android_log_write(int prio, const char* tag, const char* msg) { |
292 | 0 | return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg); |
293 | 0 | } |
294 | | |
295 | 0 | void __android_log_write_log_message(__android_log_message* log_message) { |
296 | 0 | ErrnoRestorer errno_restorer; |
297 | |
|
298 | 0 | if (log_message->buffer_id != LOG_ID_DEFAULT && log_message->buffer_id != LOG_ID_MAIN && |
299 | 0 | log_message->buffer_id != LOG_ID_SYSTEM && log_message->buffer_id != LOG_ID_RADIO && |
300 | 0 | log_message->buffer_id != LOG_ID_CRASH) { |
301 | 0 | return; |
302 | 0 | } |
303 | | |
304 | 0 | if (log_message->tag == nullptr) { |
305 | 0 | log_message->tag = GetDefaultTag().c_str(); |
306 | 0 | } |
307 | |
|
308 | | #if __BIONIC__ |
309 | | if (log_message->priority == ANDROID_LOG_FATAL) { |
310 | | android_set_abort_message(log_message->message); |
311 | | } |
312 | | #endif |
313 | |
|
314 | 0 | logger_function(log_message); |
315 | 0 | } |
316 | | |
317 | 0 | int __android_log_buf_write(int bufID, int prio, const char* tag, const char* msg) { |
318 | 0 | ErrnoRestorer errno_restorer; |
319 | |
|
320 | 0 | if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) { |
321 | 0 | return -EPERM; |
322 | 0 | } |
323 | | |
324 | 0 | __android_log_message log_message = { |
325 | 0 | sizeof(__android_log_message), bufID, prio, tag, nullptr, 0, msg}; |
326 | 0 | __android_log_write_log_message(&log_message); |
327 | 0 | return 1; |
328 | 0 | } |
329 | | |
330 | 0 | int __android_log_vprint(int prio, const char* tag, const char* fmt, va_list ap) { |
331 | 0 | ErrnoRestorer errno_restorer; |
332 | |
|
333 | 0 | if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) { |
334 | 0 | return -EPERM; |
335 | 0 | } |
336 | | |
337 | 0 | __attribute__((uninitialized)) char buf[LOG_BUF_SIZE]; |
338 | |
|
339 | 0 | vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); |
340 | |
|
341 | 0 | __android_log_message log_message = { |
342 | 0 | sizeof(__android_log_message), LOG_ID_MAIN, prio, tag, nullptr, 0, buf}; |
343 | 0 | __android_log_write_log_message(&log_message); |
344 | 0 | return 1; |
345 | 0 | } |
346 | | |
347 | 0 | int __android_log_print(int prio, const char* tag, const char* fmt, ...) { |
348 | 0 | ErrnoRestorer errno_restorer; |
349 | |
|
350 | 0 | if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) { |
351 | 0 | return -EPERM; |
352 | 0 | } |
353 | | |
354 | 0 | va_list ap; |
355 | 0 | __attribute__((uninitialized)) char buf[LOG_BUF_SIZE]; |
356 | |
|
357 | 0 | va_start(ap, fmt); |
358 | 0 | vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); |
359 | 0 | va_end(ap); |
360 | |
|
361 | 0 | __android_log_message log_message = { |
362 | 0 | sizeof(__android_log_message), LOG_ID_MAIN, prio, tag, nullptr, 0, buf}; |
363 | 0 | __android_log_write_log_message(&log_message); |
364 | 0 | return 1; |
365 | 0 | } |
366 | | |
367 | 0 | int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt, ...) { |
368 | 0 | ErrnoRestorer errno_restorer; |
369 | |
|
370 | 0 | if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) { |
371 | 0 | return -EPERM; |
372 | 0 | } |
373 | | |
374 | 0 | va_list ap; |
375 | 0 | __attribute__((uninitialized)) char buf[LOG_BUF_SIZE]; |
376 | |
|
377 | 0 | va_start(ap, fmt); |
378 | 0 | vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); |
379 | 0 | va_end(ap); |
380 | |
|
381 | 0 | __android_log_message log_message = { |
382 | 0 | sizeof(__android_log_message), bufID, prio, tag, nullptr, 0, buf}; |
383 | 0 | __android_log_write_log_message(&log_message); |
384 | 0 | return 1; |
385 | 0 | } |
386 | | |
387 | 0 | void __android_log_assert(const char* cond, const char* tag, const char* fmt, ...) { |
388 | 0 | __attribute__((uninitialized)) char buf[LOG_BUF_SIZE]; |
389 | |
|
390 | 0 | if (fmt) { |
391 | 0 | va_list ap; |
392 | 0 | va_start(ap, fmt); |
393 | 0 | vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); |
394 | 0 | va_end(ap); |
395 | 0 | } else { |
396 | | /* Msg not provided, log condition. N.B. Do not use cond directly as |
397 | | * format string as it could contain spurious '%' syntax (e.g. |
398 | | * "%d" in "blocks%devs == 0"). |
399 | | */ |
400 | 0 | if (cond) |
401 | 0 | snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond); |
402 | 0 | else |
403 | 0 | strcpy(buf, "Unspecified assertion failed"); |
404 | 0 | } |
405 | | |
406 | | // Log assertion failures to stderr for the benefit of "adb shell" users |
407 | | // and gtests (http://b/23675822). |
408 | 0 | TEMP_FAILURE_RETRY(write(2, buf, strlen(buf))); |
409 | 0 | TEMP_FAILURE_RETRY(write(2, "\n", 1)); |
410 | |
|
411 | 0 | __android_log_write(ANDROID_LOG_FATAL, tag, buf); |
412 | 0 | __android_log_call_aborter(buf); |
413 | 0 | abort(); |
414 | 0 | } |
415 | | |
416 | 0 | int __android_log_bwrite(int32_t tag, const void* payload, size_t len) { |
417 | 0 | ErrnoRestorer errno_restorer; |
418 | |
|
419 | 0 | struct iovec vec[2]; |
420 | |
|
421 | 0 | vec[0].iov_base = &tag; |
422 | 0 | vec[0].iov_len = sizeof(tag); |
423 | 0 | vec[1].iov_base = (void*)payload; |
424 | 0 | vec[1].iov_len = len; |
425 | |
|
426 | 0 | return write_to_log(LOG_ID_EVENTS, vec, 2); |
427 | 0 | } |
428 | | |
429 | 0 | int __android_log_stats_bwrite(int32_t tag, const void* payload, size_t len) { |
430 | 0 | ErrnoRestorer errno_restorer; |
431 | |
|
432 | 0 | struct iovec vec[2]; |
433 | |
|
434 | 0 | vec[0].iov_base = &tag; |
435 | 0 | vec[0].iov_len = sizeof(tag); |
436 | 0 | vec[1].iov_base = (void*)payload; |
437 | 0 | vec[1].iov_len = len; |
438 | |
|
439 | 0 | return write_to_log(LOG_ID_STATS, vec, 2); |
440 | 0 | } |
441 | | |
442 | 0 | int __android_log_security_bwrite(int32_t tag, const void* payload, size_t len) { |
443 | 0 | ErrnoRestorer errno_restorer; |
444 | |
|
445 | 0 | struct iovec vec[2]; |
446 | |
|
447 | 0 | vec[0].iov_base = &tag; |
448 | 0 | vec[0].iov_len = sizeof(tag); |
449 | 0 | vec[1].iov_base = (void*)payload; |
450 | 0 | vec[1].iov_len = len; |
451 | |
|
452 | 0 | return write_to_log(LOG_ID_SECURITY, vec, 2); |
453 | 0 | } |
454 | | |
455 | | /* |
456 | | * Like __android_log_bwrite, but takes the type as well. Doesn't work |
457 | | * for the general case where we're generating lists of stuff, but very |
458 | | * handy if we just want to dump an integer into the log. |
459 | | */ |
460 | 0 | int __android_log_btwrite(int32_t tag, char type, const void* payload, size_t len) { |
461 | 0 | ErrnoRestorer errno_restorer; |
462 | |
|
463 | 0 | struct iovec vec[3]; |
464 | |
|
465 | 0 | vec[0].iov_base = &tag; |
466 | 0 | vec[0].iov_len = sizeof(tag); |
467 | 0 | vec[1].iov_base = &type; |
468 | 0 | vec[1].iov_len = sizeof(type); |
469 | 0 | vec[2].iov_base = (void*)payload; |
470 | 0 | vec[2].iov_len = len; |
471 | |
|
472 | 0 | return write_to_log(LOG_ID_EVENTS, vec, 3); |
473 | 0 | } |
474 | | |
475 | | /* |
476 | | * Like __android_log_bwrite, but used for writing strings to the |
477 | | * event log. |
478 | | */ |
479 | 0 | int __android_log_bswrite(int32_t tag, const char* payload) { |
480 | 0 | ErrnoRestorer errno_restorer; |
481 | |
|
482 | 0 | struct iovec vec[4]; |
483 | 0 | char type = EVENT_TYPE_STRING; |
484 | 0 | uint32_t len = strlen(payload); |
485 | |
|
486 | 0 | vec[0].iov_base = &tag; |
487 | 0 | vec[0].iov_len = sizeof(tag); |
488 | 0 | vec[1].iov_base = &type; |
489 | 0 | vec[1].iov_len = sizeof(type); |
490 | 0 | vec[2].iov_base = &len; |
491 | 0 | vec[2].iov_len = sizeof(len); |
492 | 0 | vec[3].iov_base = (void*)payload; |
493 | 0 | vec[3].iov_len = len; |
494 | |
|
495 | 0 | return write_to_log(LOG_ID_EVENTS, vec, 4); |
496 | 0 | } |
497 | | |
498 | | /* |
499 | | * Like __android_log_security_bwrite, but used for writing strings to the |
500 | | * security log. |
501 | | */ |
502 | 0 | int __android_log_security_bswrite(int32_t tag, const char* payload) { |
503 | 0 | ErrnoRestorer errno_restorer; |
504 | |
|
505 | 0 | struct iovec vec[4]; |
506 | 0 | char type = EVENT_TYPE_STRING; |
507 | 0 | uint32_t len = strlen(payload); |
508 | |
|
509 | 0 | vec[0].iov_base = &tag; |
510 | 0 | vec[0].iov_len = sizeof(tag); |
511 | 0 | vec[1].iov_base = &type; |
512 | 0 | vec[1].iov_len = sizeof(type); |
513 | 0 | vec[2].iov_base = &len; |
514 | 0 | vec[2].iov_len = sizeof(len); |
515 | 0 | vec[3].iov_base = (void*)payload; |
516 | 0 | vec[3].iov_len = len; |
517 | |
|
518 | 0 | return write_to_log(LOG_ID_SECURITY, vec, 4); |
519 | 0 | } |