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 // The preferred way to access system properties is using android::base::GetProperty in libbase.
56 // However, adding dependency to libbase requires that if liblog was statically linked to a client,
57 // that client now has additional dependency to libbase as well because static dependencies of
58 // static library is not exported. (users of liblog.so however is fine).
59 #ifdef __ANDROID__
60 #include <sys/system_properties.h>
61 #endif
62
63 using android::base::ErrnoRestorer;
64
65 #define LOG_BUF_SIZE 1024
66
67 #if defined(__ANDROID__)
check_log_uid_permissions()68 static int check_log_uid_permissions() {
69 uid_t uid = getuid();
70
71 /* Matches clientCanWriteSecurityLog() in logd */
72 if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) {
73 uid = geteuid();
74 if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) {
75 gid_t gid = getgid();
76 if ((gid != AID_SYSTEM) && (gid != AID_ROOT) && (gid != AID_LOG)) {
77 gid = getegid();
78 if ((gid != AID_SYSTEM) && (gid != AID_ROOT) && (gid != AID_LOG)) {
79 int num_groups;
80 gid_t* groups;
81
82 num_groups = getgroups(0, NULL);
83 if (num_groups <= 0) {
84 return -EPERM;
85 }
86 groups = static_cast<gid_t*>(calloc(num_groups, sizeof(gid_t)));
87 if (!groups) {
88 return -ENOMEM;
89 }
90 num_groups = getgroups(num_groups, groups);
91 while (num_groups > 0) {
92 if (groups[num_groups - 1] == AID_LOG ||
93 groups[num_groups - 1] == AID_SECURITY_LOG_WRITER) {
94 break;
95 }
96 --num_groups;
97 }
98 free(groups);
99 if (num_groups <= 0) {
100 return -EPERM;
101 }
102 }
103 }
104 }
105 }
106 return 0;
107 }
108 #endif
109
110 /*
111 * Release any logger resources. A new log write will immediately re-acquire.
112 */
__android_log_close()113 void __android_log_close() {
114 #ifdef __ANDROID__
115 LogdClose();
116 PmsgClose();
117 #endif
118 }
119
120 // BSD-based systems like Android/macOS have getprogname(). Others need us to provide one.
121 #if !defined(__APPLE__) && !defined(__BIONIC__)
getprogname()122 static const char* getprogname() {
123 #ifdef _WIN32
124 static bool first = true;
125 static char progname[MAX_PATH] = {};
126
127 if (first) {
128 char path[PATH_MAX + 1];
129 DWORD result = GetModuleFileName(nullptr, path, sizeof(path) - 1);
130 if (result == 0 || result == sizeof(path) - 1) return "";
131 path[PATH_MAX - 1] = 0;
132
133 char* path_basename = basename(path);
134
135 snprintf(progname, sizeof(progname), "%s", path_basename);
136 first = false;
137 }
138
139 return progname;
140 #else
141 return program_invocation_short_name;
142 #endif
143 }
144 #endif
145
146 // It's possible for logging to happen during static initialization before our globals are
147 // initialized, so we place this std::string in a function such that it is initialized on the first
148 // call. We use a pointer to avoid exit time destructors.
GetDefaultTag()149 std::string& GetDefaultTag() {
150 static std::string* default_tag = new std::string(getprogname());
151 return *default_tag;
152 }
153
__android_log_set_default_tag(const char * tag)154 void __android_log_set_default_tag(const char* tag) {
155 GetDefaultTag().assign(tag, 0, LOGGER_ENTRY_MAX_PAYLOAD);
156 }
157
158 static std::atomic_int32_t minimum_log_priority = ANDROID_LOG_DEFAULT;
__android_log_set_minimum_priority(int32_t priority)159 int32_t __android_log_set_minimum_priority(int32_t priority) {
160 return minimum_log_priority.exchange(priority, std::memory_order_relaxed);
161 }
162
__android_log_get_minimum_priority()163 int32_t __android_log_get_minimum_priority() {
164 return minimum_log_priority;
165 }
166
167 #ifdef __ANDROID__
get_file_logger_path()168 static const char* get_file_logger_path() {
169 static const char* file_logger_path = []() {
170 static char path[PROP_VALUE_MAX] = {};
171 if (__system_property_get("ro.log.file_logger.path", path) > 0) {
172 return path;
173 }
174 return (char*)nullptr; // means file_logger should not be used
175 }();
176 return file_logger_path;
177 }
178 #endif
179
180 static void file_logger(const struct __android_log_message* log_message);
181
182 static __android_logger_function user_set_logger_function = nullptr;
183
get_logger_function()184 static __android_logger_function get_logger_function() {
185 if (user_set_logger_function != nullptr) {
186 return user_set_logger_function;
187 }
188 static __android_logger_function default_logger_function = []() {
189 #if __ANDROID__
190 if (get_file_logger_path() != nullptr) {
191 return file_logger;
192 } else {
193 return __android_log_logd_logger;
194 }
195 #else
196 return file_logger;
197 #endif
198 }();
199 return default_logger_function;
200 }
201
__android_log_set_logger(__android_logger_function logger)202 void __android_log_set_logger(__android_logger_function logger) {
203 user_set_logger_function = logger;
204 }
205
__android_log_default_aborter(const char * abort_message)206 void __android_log_default_aborter(const char* abort_message) {
207 #ifdef __ANDROID__
208 android_set_abort_message(abort_message);
209 #else
210 UNUSED(abort_message);
211 #endif
212 abort();
213 }
214
215 static __android_aborter_function aborter_function = __android_log_default_aborter;
216
__android_log_set_aborter(__android_aborter_function aborter)217 void __android_log_set_aborter(__android_aborter_function aborter) {
218 aborter_function = aborter;
219 }
220
__android_log_call_aborter(const char * abort_message)221 void __android_log_call_aborter(const char* abort_message) {
222 aborter_function(abort_message);
223 }
224
225 #ifdef __ANDROID__
write_to_log(log_id_t log_id,struct iovec * vec,size_t nr)226 static int write_to_log(log_id_t log_id, struct iovec* vec, size_t nr) {
227 int ret;
228 struct timespec ts;
229
230 if (log_id == LOG_ID_KERNEL) {
231 return -EINVAL;
232 }
233
234 clock_gettime(CLOCK_REALTIME, &ts);
235
236 if (log_id == LOG_ID_SECURITY) {
237 if (vec[0].iov_len < 4) {
238 return -EINVAL;
239 }
240
241 ret = check_log_uid_permissions();
242 if (ret < 0) {
243 return ret;
244 }
245 if (!__android_log_security()) {
246 /* If only we could reset downstream logd counter */
247 return -EPERM;
248 }
249 } else if (log_id == LOG_ID_EVENTS || log_id == LOG_ID_STATS) {
250 if (vec[0].iov_len < 4) {
251 return -EINVAL;
252 }
253 }
254
255 ret = LogdWrite(log_id, &ts, vec, nr);
256 PmsgWrite(log_id, &ts, vec, nr);
257
258 return ret;
259 }
260 #else
write_to_log(log_id_t,struct iovec *,size_t)261 static int write_to_log(log_id_t, struct iovec*, size_t) {
262 // Non-Android text logs should go to __android_log_stderr_logger, not here.
263 // Non-Android binary logs are always dropped.
264 return 1;
265 }
266 #endif
267
268 // Copied from base/threads.cpp
GetThreadId()269 static uint64_t GetThreadId() {
270 #if defined(__BIONIC__)
271 return gettid();
272 #elif defined(__APPLE__)
273 uint64_t tid;
274 pthread_threadid_np(NULL, &tid);
275 return tid;
276 #elif defined(__linux__)
277 return syscall(__NR_gettid);
278 #elif defined(_WIN32)
279 return GetCurrentThreadId();
280 #endif
281 }
282
filestream_logger(const struct __android_log_message * log_message,FILE * stream)283 static void filestream_logger(const struct __android_log_message* log_message, FILE* stream) {
284 struct tm now;
285 time_t t = time(nullptr);
286
287 #if defined(_WIN32)
288 localtime_s(&now, &t);
289 #else
290 localtime_r(&t, &now);
291 #endif
292
293 char timestamp[32];
294 strftime(timestamp, sizeof(timestamp), "%m-%d %H:%M:%S", &now);
295
296 static const char log_characters[] = "XXVDIWEF";
297 static_assert(arraysize(log_characters) - 1 == ANDROID_LOG_SILENT,
298 "Mismatch in size of log_characters and values in android_LogPriority");
299 int32_t priority =
300 log_message->priority > ANDROID_LOG_SILENT ? ANDROID_LOG_FATAL : log_message->priority;
301 char priority_char = log_characters[priority];
302 uint64_t tid = GetThreadId();
303
304 if (log_message->file != nullptr) {
305 fprintf(stream, "%s %c %s %5d %5" PRIu64 " %s:%u] %s\n",
306 log_message->tag ? log_message->tag : "nullptr", priority_char, timestamp, getpid(),
307 tid, log_message->file, log_message->line, log_message->message);
308 } else {
309 fprintf(stream, "%s %c %s %5d %5" PRIu64 "] %s\n",
310 log_message->tag ? log_message->tag : "nullptr", priority_char, timestamp, getpid(),
311 tid, log_message->message);
312 }
313 }
314
file_logger(const struct __android_log_message * log_message)315 static void file_logger(const struct __android_log_message* log_message) {
316 static FILE* stream = []() {
317 #ifdef __ANDROID__
318 const char* file_logger_path = get_file_logger_path();
319 if (file_logger_path != nullptr) {
320 FILE* f = fopen(file_logger_path, "ae");
321 if (f != nullptr) return f;
322 using namespace std::string_literals;
323 std::string err_msg = "Cannot open "s + file_logger_path + " for logging: (" + strerror(errno) +
324 "). Falling back to stderr";
325 __android_log_message m = {sizeof(__android_log_message),
326 LOG_ID_DEFAULT,
327 ANDROID_LOG_WARN,
328 "liblog",
329 __FILE__,
330 __LINE__,
331 err_msg.c_str()};
332 filestream_logger(&m, stderr);
333 }
334 #endif
335 // defaults to stderr if the sysprop is not set or the file is not available
336 return stderr;
337 }();
338 filestream_logger(log_message, stream);
339 }
340
__android_log_stderr_logger(const struct __android_log_message * log_message)341 void __android_log_stderr_logger(const struct __android_log_message* log_message) {
342 filestream_logger(log_message, stderr);
343 }
344
__android_log_logd_logger(const struct __android_log_message * log_message)345 void __android_log_logd_logger(const struct __android_log_message* log_message) {
346 int buffer_id = log_message->buffer_id == LOG_ID_DEFAULT ? LOG_ID_MAIN : log_message->buffer_id;
347
348 struct iovec vec[3];
349 vec[0].iov_base =
350 const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(&log_message->priority));
351 vec[0].iov_len = 1;
352 vec[1].iov_base = const_cast<void*>(static_cast<const void*>(log_message->tag));
353 vec[1].iov_len = strlen(log_message->tag) + 1;
354 vec[2].iov_base = const_cast<void*>(static_cast<const void*>(log_message->message));
355 vec[2].iov_len = strlen(log_message->message) + 1;
356
357 write_to_log(static_cast<log_id_t>(buffer_id), vec, 3);
358 }
359
__android_log_write(int prio,const char * tag,const char * msg)360 int __android_log_write(int prio, const char* tag, const char* msg) {
361 return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
362 }
363
__android_log_write_log_message(__android_log_message * log_message)364 void __android_log_write_log_message(__android_log_message* log_message) {
365 ErrnoRestorer errno_restorer;
366
367 if (log_message->buffer_id != LOG_ID_DEFAULT && log_message->buffer_id != LOG_ID_MAIN &&
368 log_message->buffer_id != LOG_ID_SYSTEM && log_message->buffer_id != LOG_ID_RADIO &&
369 log_message->buffer_id != LOG_ID_CRASH) {
370 return;
371 }
372
373 if (log_message->tag == nullptr) {
374 log_message->tag = GetDefaultTag().c_str();
375 }
376
377 #if __BIONIC__
378 if (log_message->priority == ANDROID_LOG_FATAL) {
379 android_set_abort_message(log_message->message);
380 }
381 #endif
382
383 get_logger_function()(log_message);
384 }
385
__android_log_buf_write(int bufID,int prio,const char * tag,const char * msg)386 int __android_log_buf_write(int bufID, int prio, const char* tag, const char* msg) {
387 ErrnoRestorer errno_restorer;
388
389 if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
390 return -EPERM;
391 }
392
393 __android_log_message log_message = {
394 sizeof(__android_log_message), bufID, prio, tag, nullptr, 0, msg};
395 __android_log_write_log_message(&log_message);
396 return 1;
397 }
398
__android_log_vprint(int prio,const char * tag,const char * fmt,va_list ap)399 int __android_log_vprint(int prio, const char* tag, const char* fmt, va_list ap) {
400 ErrnoRestorer errno_restorer;
401
402 if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
403 return -EPERM;
404 }
405
406 __attribute__((uninitialized)) char buf[LOG_BUF_SIZE];
407
408 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
409
410 __android_log_message log_message = {
411 sizeof(__android_log_message), LOG_ID_MAIN, prio, tag, nullptr, 0, buf};
412 __android_log_write_log_message(&log_message);
413 return 1;
414 }
415
__android_log_print(int prio,const char * tag,const char * fmt,...)416 int __android_log_print(int prio, const char* tag, const char* fmt, ...) {
417 ErrnoRestorer errno_restorer;
418
419 if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
420 return -EPERM;
421 }
422
423 va_list ap;
424 __attribute__((uninitialized)) char buf[LOG_BUF_SIZE];
425
426 va_start(ap, fmt);
427 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
428 va_end(ap);
429
430 __android_log_message log_message = {
431 sizeof(__android_log_message), LOG_ID_MAIN, prio, tag, nullptr, 0, buf};
432 __android_log_write_log_message(&log_message);
433 return 1;
434 }
435
__android_log_buf_print(int bufID,int prio,const char * tag,const char * fmt,...)436 int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt, ...) {
437 ErrnoRestorer errno_restorer;
438
439 if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
440 return -EPERM;
441 }
442
443 va_list ap;
444 __attribute__((uninitialized)) char buf[LOG_BUF_SIZE];
445
446 va_start(ap, fmt);
447 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
448 va_end(ap);
449
450 __android_log_message log_message = {
451 sizeof(__android_log_message), bufID, prio, tag, nullptr, 0, buf};
452 __android_log_write_log_message(&log_message);
453 return 1;
454 }
455
__android_log_assert(const char * cond,const char * tag,const char * fmt,...)456 void __android_log_assert(const char* cond, const char* tag, const char* fmt, ...) {
457 __attribute__((uninitialized)) char buf[LOG_BUF_SIZE];
458
459 if (fmt) {
460 va_list ap;
461 va_start(ap, fmt);
462 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
463 va_end(ap);
464 } else {
465 /* Msg not provided, log condition. N.B. Do not use cond directly as
466 * format string as it could contain spurious '%' syntax (e.g.
467 * "%d" in "blocks%devs == 0").
468 */
469 if (cond)
470 snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond);
471 else
472 strcpy(buf, "Unspecified assertion failed");
473 }
474
475 // Log assertion failures to stderr for the benefit of "adb shell" users
476 // and gtests (http://b/23675822).
477 TEMP_FAILURE_RETRY(write(2, buf, strlen(buf)));
478 TEMP_FAILURE_RETRY(write(2, "\n", 1));
479
480 __android_log_write(ANDROID_LOG_FATAL, tag, buf);
481 __android_log_call_aborter(buf);
482 abort();
483 }
484
__android_log_bwrite(int32_t tag,const void * payload,size_t len)485 int __android_log_bwrite(int32_t tag, const void* payload, size_t len) {
486 ErrnoRestorer errno_restorer;
487
488 struct iovec vec[2];
489
490 vec[0].iov_base = &tag;
491 vec[0].iov_len = sizeof(tag);
492 vec[1].iov_base = (void*)payload;
493 vec[1].iov_len = len;
494
495 return write_to_log(LOG_ID_EVENTS, vec, 2);
496 }
497
__android_log_stats_bwrite(int32_t tag,const void * payload,size_t len)498 int __android_log_stats_bwrite(int32_t tag, const void* payload, size_t len) {
499 ErrnoRestorer errno_restorer;
500
501 struct iovec vec[2];
502
503 vec[0].iov_base = &tag;
504 vec[0].iov_len = sizeof(tag);
505 vec[1].iov_base = (void*)payload;
506 vec[1].iov_len = len;
507
508 return write_to_log(LOG_ID_STATS, vec, 2);
509 }
510
__android_log_security_bwrite(int32_t tag,const void * payload,size_t len)511 int __android_log_security_bwrite(int32_t tag, const void* payload, size_t len) {
512 ErrnoRestorer errno_restorer;
513
514 struct iovec vec[2];
515
516 vec[0].iov_base = &tag;
517 vec[0].iov_len = sizeof(tag);
518 vec[1].iov_base = (void*)payload;
519 vec[1].iov_len = len;
520
521 return write_to_log(LOG_ID_SECURITY, vec, 2);
522 }
523
524 /*
525 * Like __android_log_bwrite, but takes the type as well. Doesn't work
526 * for the general case where we're generating lists of stuff, but very
527 * handy if we just want to dump an integer into the log.
528 */
__android_log_btwrite(int32_t tag,char type,const void * payload,size_t len)529 int __android_log_btwrite(int32_t tag, char type, const void* payload, size_t len) {
530 ErrnoRestorer errno_restorer;
531
532 struct iovec vec[3];
533
534 vec[0].iov_base = &tag;
535 vec[0].iov_len = sizeof(tag);
536 vec[1].iov_base = &type;
537 vec[1].iov_len = sizeof(type);
538 vec[2].iov_base = (void*)payload;
539 vec[2].iov_len = len;
540
541 return write_to_log(LOG_ID_EVENTS, vec, 3);
542 }
543
544 /*
545 * Like __android_log_bwrite, but used for writing strings to the
546 * event log.
547 */
__android_log_bswrite(int32_t tag,const char * payload)548 int __android_log_bswrite(int32_t tag, const char* payload) {
549 ErrnoRestorer errno_restorer;
550
551 struct iovec vec[4];
552 char type = EVENT_TYPE_STRING;
553 uint32_t len = strlen(payload);
554
555 vec[0].iov_base = &tag;
556 vec[0].iov_len = sizeof(tag);
557 vec[1].iov_base = &type;
558 vec[1].iov_len = sizeof(type);
559 vec[2].iov_base = &len;
560 vec[2].iov_len = sizeof(len);
561 vec[3].iov_base = (void*)payload;
562 vec[3].iov_len = len;
563
564 return write_to_log(LOG_ID_EVENTS, vec, 4);
565 }
566
567 /*
568 * Like __android_log_security_bwrite, but used for writing strings to the
569 * security log.
570 */
__android_log_security_bswrite(int32_t tag,const char * payload)571 int __android_log_security_bswrite(int32_t tag, const char* payload) {
572 ErrnoRestorer errno_restorer;
573
574 struct iovec vec[4];
575 char type = EVENT_TYPE_STRING;
576 uint32_t len = strlen(payload);
577
578 vec[0].iov_base = &tag;
579 vec[0].iov_len = sizeof(tag);
580 vec[1].iov_base = &type;
581 vec[1].iov_len = sizeof(type);
582 vec[2].iov_base = &len;
583 vec[2].iov_len = sizeof(len);
584 vec[3].iov_base = (void*)payload;
585 vec[3].iov_len = len;
586
587 return write_to_log(LOG_ID_SECURITY, vec, 4);
588 }
589