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