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 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 */
__android_log_close()104 void __android_log_close() {
105 #ifdef __ANDROID__
106 LogdClose();
107 PmsgClose();
108 #endif
109 }
110
111 #if defined(__GLIBC__) || defined(_WIN32)
getprogname()112 static const char* getprogname() {
113 #if defined(__GLIBC__)
114 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 }
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.
GetDefaultTag()139 std::string& GetDefaultTag() {
140 static std::string default_tag = getprogname();
141 return default_tag;
142 }
143
__android_log_set_default_tag(const char * tag)144 void __android_log_set_default_tag(const char* tag) {
145 GetDefaultTag().assign(tag, 0, LOGGER_ENTRY_MAX_PAYLOAD);
146 }
147
148 static std::atomic_int32_t minimum_log_priority = ANDROID_LOG_DEFAULT;
__android_log_set_minimum_priority(int32_t priority)149 int32_t __android_log_set_minimum_priority(int32_t priority) {
150 return minimum_log_priority.exchange(priority, std::memory_order_relaxed);
151 }
152
__android_log_get_minimum_priority()153 int32_t __android_log_get_minimum_priority() {
154 return minimum_log_priority;
155 }
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
__android_log_set_logger(__android_logger_function logger)163 void __android_log_set_logger(__android_logger_function logger) {
164 logger_function = logger;
165 }
166
__android_log_default_aborter(const char * abort_message)167 void __android_log_default_aborter(const char* abort_message) {
168 #ifdef __ANDROID__
169 android_set_abort_message(abort_message);
170 #else
171 UNUSED(abort_message);
172 #endif
173 abort();
174 }
175
176 static __android_aborter_function aborter_function = __android_log_default_aborter;
177
__android_log_set_aborter(__android_aborter_function aborter)178 void __android_log_set_aborter(__android_aborter_function aborter) {
179 aborter_function = aborter;
180 }
181
__android_log_call_aborter(const char * abort_message)182 void __android_log_call_aborter(const char* abort_message) {
183 aborter_function(abort_message);
184 }
185
186 #ifdef __ANDROID__
write_to_log(log_id_t log_id,struct iovec * vec,size_t nr)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
write_to_log(log_id_t,struct iovec *,size_t)222 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 return 1;
226 }
227 #endif
228
229 // Copied from base/threads.cpp
GetThreadId()230 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 }
243
__android_log_stderr_logger(const struct __android_log_message * log_message)244 void __android_log_stderr_logger(const struct __android_log_message* log_message) {
245 struct tm now;
246 time_t t = time(nullptr);
247
248 #if defined(_WIN32)
249 localtime_s(&now, &t);
250 #else
251 localtime_r(&t, &now);
252 #endif
253
254 char timestamp[32];
255 strftime(timestamp, sizeof(timestamp), "%m-%d %H:%M:%S", &now);
256
257 static const char log_characters[] = "XXVDIWEF";
258 static_assert(arraysize(log_characters) - 1 == ANDROID_LOG_SILENT,
259 "Mismatch in size of log_characters and values in android_LogPriority");
260 int32_t priority =
261 log_message->priority > ANDROID_LOG_SILENT ? ANDROID_LOG_FATAL : log_message->priority;
262 char priority_char = log_characters[priority];
263 uint64_t tid = GetThreadId();
264
265 if (log_message->file != nullptr) {
266 fprintf(stderr, "%s %c %s %5d %5" PRIu64 " %s:%u] %s\n",
267 log_message->tag ? log_message->tag : "nullptr", priority_char, timestamp, getpid(),
268 tid, log_message->file, log_message->line, log_message->message);
269 } else {
270 fprintf(stderr, "%s %c %s %5d %5" PRIu64 " %s\n",
271 log_message->tag ? log_message->tag : "nullptr", priority_char, timestamp, getpid(),
272 tid, log_message->message);
273 }
274 }
275
__android_log_logd_logger(const struct __android_log_message * log_message)276 void __android_log_logd_logger(const struct __android_log_message* log_message) {
277 int buffer_id = log_message->buffer_id == LOG_ID_DEFAULT ? LOG_ID_MAIN : log_message->buffer_id;
278
279 struct iovec vec[3];
280 vec[0].iov_base =
281 const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(&log_message->priority));
282 vec[0].iov_len = 1;
283 vec[1].iov_base = const_cast<void*>(static_cast<const void*>(log_message->tag));
284 vec[1].iov_len = strlen(log_message->tag) + 1;
285 vec[2].iov_base = const_cast<void*>(static_cast<const void*>(log_message->message));
286 vec[2].iov_len = strlen(log_message->message) + 1;
287
288 write_to_log(static_cast<log_id_t>(buffer_id), vec, 3);
289 }
290
__android_log_write(int prio,const char * tag,const char * msg)291 int __android_log_write(int prio, const char* tag, const char* msg) {
292 return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
293 }
294
__android_log_write_log_message(__android_log_message * log_message)295 void __android_log_write_log_message(__android_log_message* log_message) {
296 ErrnoRestorer errno_restorer;
297
298 if (log_message->buffer_id != LOG_ID_DEFAULT && log_message->buffer_id != LOG_ID_MAIN &&
299 log_message->buffer_id != LOG_ID_SYSTEM && log_message->buffer_id != LOG_ID_RADIO &&
300 log_message->buffer_id != LOG_ID_CRASH) {
301 return;
302 }
303
304 if (log_message->tag == nullptr) {
305 log_message->tag = GetDefaultTag().c_str();
306 }
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 logger_function(log_message);
315 }
316
__android_log_buf_write(int bufID,int prio,const char * tag,const char * msg)317 int __android_log_buf_write(int bufID, int prio, const char* tag, const char* msg) {
318 ErrnoRestorer errno_restorer;
319
320 if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
321 return -EPERM;
322 }
323
324 __android_log_message log_message = {
325 sizeof(__android_log_message), bufID, prio, tag, nullptr, 0, msg};
326 __android_log_write_log_message(&log_message);
327 return 1;
328 }
329
__android_log_vprint(int prio,const char * tag,const char * fmt,va_list ap)330 int __android_log_vprint(int prio, const char* tag, const char* fmt, va_list ap) {
331 ErrnoRestorer errno_restorer;
332
333 if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
334 return -EPERM;
335 }
336
337 __attribute__((uninitialized)) char buf[LOG_BUF_SIZE];
338
339 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
340
341 __android_log_message log_message = {
342 sizeof(__android_log_message), LOG_ID_MAIN, prio, tag, nullptr, 0, buf};
343 __android_log_write_log_message(&log_message);
344 return 1;
345 }
346
__android_log_print(int prio,const char * tag,const char * fmt,...)347 int __android_log_print(int prio, const char* tag, const char* fmt, ...) {
348 ErrnoRestorer errno_restorer;
349
350 if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
351 return -EPERM;
352 }
353
354 va_list ap;
355 __attribute__((uninitialized)) char buf[LOG_BUF_SIZE];
356
357 va_start(ap, fmt);
358 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
359 va_end(ap);
360
361 __android_log_message log_message = {
362 sizeof(__android_log_message), LOG_ID_MAIN, prio, tag, nullptr, 0, buf};
363 __android_log_write_log_message(&log_message);
364 return 1;
365 }
366
__android_log_buf_print(int bufID,int prio,const char * tag,const char * fmt,...)367 int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt, ...) {
368 ErrnoRestorer errno_restorer;
369
370 if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
371 return -EPERM;
372 }
373
374 va_list ap;
375 __attribute__((uninitialized)) char buf[LOG_BUF_SIZE];
376
377 va_start(ap, fmt);
378 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
379 va_end(ap);
380
381 __android_log_message log_message = {
382 sizeof(__android_log_message), bufID, prio, tag, nullptr, 0, buf};
383 __android_log_write_log_message(&log_message);
384 return 1;
385 }
386
__android_log_assert(const char * cond,const char * tag,const char * fmt,...)387 void __android_log_assert(const char* cond, const char* tag, const char* fmt, ...) {
388 __attribute__((uninitialized)) char buf[LOG_BUF_SIZE];
389
390 if (fmt) {
391 va_list ap;
392 va_start(ap, fmt);
393 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
394 va_end(ap);
395 } 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 if (cond)
401 snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond);
402 else
403 strcpy(buf, "Unspecified assertion failed");
404 }
405
406 // Log assertion failures to stderr for the benefit of "adb shell" users
407 // and gtests (http://b/23675822).
408 TEMP_FAILURE_RETRY(write(2, buf, strlen(buf)));
409 TEMP_FAILURE_RETRY(write(2, "\n", 1));
410
411 __android_log_write(ANDROID_LOG_FATAL, tag, buf);
412 __android_log_call_aborter(buf);
413 abort();
414 }
415
__android_log_bwrite(int32_t tag,const void * payload,size_t len)416 int __android_log_bwrite(int32_t tag, const void* payload, size_t len) {
417 ErrnoRestorer errno_restorer;
418
419 struct iovec vec[2];
420
421 vec[0].iov_base = &tag;
422 vec[0].iov_len = sizeof(tag);
423 vec[1].iov_base = (void*)payload;
424 vec[1].iov_len = len;
425
426 return write_to_log(LOG_ID_EVENTS, vec, 2);
427 }
428
__android_log_stats_bwrite(int32_t tag,const void * payload,size_t len)429 int __android_log_stats_bwrite(int32_t tag, const void* payload, size_t len) {
430 ErrnoRestorer errno_restorer;
431
432 struct iovec vec[2];
433
434 vec[0].iov_base = &tag;
435 vec[0].iov_len = sizeof(tag);
436 vec[1].iov_base = (void*)payload;
437 vec[1].iov_len = len;
438
439 return write_to_log(LOG_ID_STATS, vec, 2);
440 }
441
__android_log_security_bwrite(int32_t tag,const void * payload,size_t len)442 int __android_log_security_bwrite(int32_t tag, const void* payload, size_t len) {
443 ErrnoRestorer errno_restorer;
444
445 struct iovec vec[2];
446
447 vec[0].iov_base = &tag;
448 vec[0].iov_len = sizeof(tag);
449 vec[1].iov_base = (void*)payload;
450 vec[1].iov_len = len;
451
452 return write_to_log(LOG_ID_SECURITY, vec, 2);
453 }
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 */
__android_log_btwrite(int32_t tag,char type,const void * payload,size_t len)460 int __android_log_btwrite(int32_t tag, char type, const void* payload, size_t len) {
461 ErrnoRestorer errno_restorer;
462
463 struct iovec vec[3];
464
465 vec[0].iov_base = &tag;
466 vec[0].iov_len = sizeof(tag);
467 vec[1].iov_base = &type;
468 vec[1].iov_len = sizeof(type);
469 vec[2].iov_base = (void*)payload;
470 vec[2].iov_len = len;
471
472 return write_to_log(LOG_ID_EVENTS, vec, 3);
473 }
474
475 /*
476 * Like __android_log_bwrite, but used for writing strings to the
477 * event log.
478 */
__android_log_bswrite(int32_t tag,const char * payload)479 int __android_log_bswrite(int32_t tag, const char* payload) {
480 ErrnoRestorer errno_restorer;
481
482 struct iovec vec[4];
483 char type = EVENT_TYPE_STRING;
484 uint32_t len = strlen(payload);
485
486 vec[0].iov_base = &tag;
487 vec[0].iov_len = sizeof(tag);
488 vec[1].iov_base = &type;
489 vec[1].iov_len = sizeof(type);
490 vec[2].iov_base = &len;
491 vec[2].iov_len = sizeof(len);
492 vec[3].iov_base = (void*)payload;
493 vec[3].iov_len = len;
494
495 return write_to_log(LOG_ID_EVENTS, vec, 4);
496 }
497
498 /*
499 * Like __android_log_security_bwrite, but used for writing strings to the
500 * security log.
501 */
__android_log_security_bswrite(int32_t tag,const char * payload)502 int __android_log_security_bswrite(int32_t tag, const char* payload) {
503 ErrnoRestorer errno_restorer;
504
505 struct iovec vec[4];
506 char type = EVENT_TYPE_STRING;
507 uint32_t len = strlen(payload);
508
509 vec[0].iov_base = &tag;
510 vec[0].iov_len = sizeof(tag);
511 vec[1].iov_base = &type;
512 vec[1].iov_len = sizeof(type);
513 vec[2].iov_base = &len;
514 vec[2].iov_len = sizeof(len);
515 vec[3].iov_base = (void*)payload;
516 vec[3].iov_len = len;
517
518 return write_to_log(LOG_ID_SECURITY, vec, 4);
519 }
520