blob: 157bd88a17308dbcda0c80e7dd729fddf74b8414 [file] [log] [blame]
Mark Salyzync5ae20f2016-03-01 13:45:42 -08001/*
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 <errno.h>
18#include <stdatomic.h>
19#include <stdlib.h>
20#include <string.h>
21#include <sys/time.h>
22
23#ifdef __BIONIC__
24#include <android/set_abort_message.h>
25#endif
26
27#include <log/event_tag_map.h>
Mark Salyzync5ae20f2016-03-01 13:45:42 -080028#include <private/android_filesystem_config.h>
29#include <private/android_logger.h>
30
31#include "config_write.h"
32#include "log_portability.h"
33#include "logger.h"
34
35#define LOG_BUF_SIZE 1024
36
37static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr);
38static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;
39
40/*
41 * This is used by the C++ code to decide if it should write logs through
42 * the C code. Basically, if /dev/socket/logd is available, we're running in
43 * the simulator rather than a desktop tool and want to use the device.
44 */
45static enum {
46 kLogUninitialized, kLogNotAvailable, kLogAvailable
47} g_log_status = kLogUninitialized;
48
Mark Salyzynef5a14e2016-03-28 16:20:29 -070049static int check_log_uid_permissions()
50{
51#if defined(__BIONIC__)
52 uid_t uid = __android_log_uid();
53
54 /* Matches clientHasLogCredentials() in logd */
55 if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) {
56 uid = geteuid();
57 if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) {
58 gid_t gid = getgid();
59 if ((gid != AID_SYSTEM) &&
60 (gid != AID_ROOT) &&
61 (gid != AID_LOG)) {
62 gid = getegid();
63 if ((gid != AID_SYSTEM) &&
64 (gid != AID_ROOT) &&
65 (gid != AID_LOG)) {
66 int num_groups;
67 gid_t *groups;
68
69 num_groups = getgroups(0, NULL);
70 if (num_groups <= 0) {
71 return -EPERM;
72 }
73 groups = calloc(num_groups, sizeof(gid_t));
74 if (!groups) {
75 return -ENOMEM;
76 }
77 num_groups = getgroups(num_groups, groups);
78 while (num_groups > 0) {
79 if (groups[num_groups - 1] == AID_LOG) {
80 break;
81 }
82 --num_groups;
83 }
84 free(groups);
85 if (num_groups <= 0) {
86 return -EPERM;
87 }
88 }
89 }
90 }
91 }
92#endif
93 return 0;
94}
95
96static void __android_log_cache_available(
97 struct android_log_transport_write *node)
98{
99 size_t i;
100
101 if (node->logMask) {
102 return;
103 }
104
105 for (i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
106 if (node->write &&
107 (i != LOG_ID_KERNEL) &&
108 ((i != LOG_ID_SECURITY) ||
109 (check_log_uid_permissions() == 0)) &&
110 (!node->available || ((*node->available)(i) >= 0))) {
111 node->logMask |= 1 << i;
112 }
113 }
114}
115
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800116LIBLOG_ABI_PUBLIC int __android_log_dev_available()
117{
118 struct android_log_transport_write *node;
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800119
120 if (list_empty(&__android_log_transport_write)) {
121 return kLogUninitialized;
122 }
Mark Salyzynef5a14e2016-03-28 16:20:29 -0700123
124 write_transport_for_each(node, &__android_log_transport_write) {
125 __android_log_cache_available(node);
126 if (node->logMask) {
127 return kLogAvailable;
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800128 }
129 }
130 return kLogNotAvailable;
131}
Mark Salyzyn0a9c0b92016-09-13 07:28:21 -0700132
133#if defined(__BIONIC__)
134static atomic_uintptr_t tagMap;
135#endif
136
Mark Salyzyn67dc7482016-08-23 10:23:36 -0700137/*
138 * Release any logger resources. A new log write will immediately re-acquire.
139 */
140LIBLOG_ABI_PUBLIC void __android_log_close()
141{
142 struct android_log_transport_write *transport;
Mark Salyzyn0a9c0b92016-09-13 07:28:21 -0700143#if defined(__BIONIC__)
144 EventTagMap *m;
145#endif
Mark Salyzyn67dc7482016-08-23 10:23:36 -0700146
147 __android_log_lock();
148
149 write_to_log = __write_to_log_init;
150
151 /*
152 * Threads that are actively writing at this point are not held back
153 * by a lock and are at risk of dropping the messages with a return code
154 * -EBADF. Prefer to return error code than add the overhead of a lock to
155 * each log writing call to guarantee delivery. In addition, anyone
156 * calling this is doing so to release the logging resources and shut down,
157 * for them to do so with outstanding log requests in other threads is a
158 * disengenuous use of this function.
159 */
160
161 write_transport_for_each(transport, &__android_log_persist_write) {
162 if (transport->close) {
163 (*transport->close)();
164 }
165 }
166
167 write_transport_for_each(transport, &__android_log_transport_write) {
168 if (transport->close) {
169 (*transport->close)();
170 }
171 }
172
Mark Salyzyn0a9c0b92016-09-13 07:28:21 -0700173#if defined(__BIONIC__)
174 /*
175 * Additional risk here somewhat mitigated by immediately unlock flushing
176 * the processor cache. The multi-threaded race that we choose to accept,
177 * to minimize locking, is an atomic_load in a writer picking up a value
178 * just prior to entering this routine. There will be an use after free.
179 *
180 * Again, anyone calling this is doing so to release the logging resources
181 * is most probably going to quiesce then shut down; or to restart after
182 * a fork so the risk should be non-existent. For this reason we
183 * choose a mitigation stance for efficiency instead of incuring the cost
184 * of a lock for every log write.
185 */
186 m = (EventTagMap *)atomic_exchange(&tagMap, (uintptr_t)0);
187#endif
188
Mark Salyzyn67dc7482016-08-23 10:23:36 -0700189 __android_log_unlock();
Mark Salyzyn0a9c0b92016-09-13 07:28:21 -0700190
191#if defined(__BIONIC__)
Mark Salyzyn75da0c52016-11-09 10:14:35 -0800192 if (m != (EventTagMap *)(uintptr_t)-1LL) android_closeEventTagMap(m);
Mark Salyzyn0a9c0b92016-09-13 07:28:21 -0700193#endif
194
Mark Salyzyn67dc7482016-08-23 10:23:36 -0700195}
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800196
197/* log_init_lock assumed */
198static int __write_to_log_initialize()
199{
200 struct android_log_transport_write *transport;
201 struct listnode *n;
202 int i = 0, ret = 0;
203
204 __android_log_config_write();
205 write_transport_for_each_safe(transport, n, &__android_log_transport_write) {
Mark Salyzynef5a14e2016-03-28 16:20:29 -0700206 __android_log_cache_available(transport);
207 if (!transport->logMask) {
208 list_remove(&transport->node);
209 continue;
210 }
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800211 if (!transport->open || ((*transport->open)() < 0)) {
212 if (transport->close) {
213 (*transport->close)();
214 }
215 list_remove(&transport->node);
216 continue;
217 }
218 ++ret;
219 }
220 write_transport_for_each_safe(transport, n, &__android_log_persist_write) {
Mark Salyzynef5a14e2016-03-28 16:20:29 -0700221 __android_log_cache_available(transport);
222 if (!transport->logMask) {
223 list_remove(&transport->node);
224 continue;
225 }
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800226 if (!transport->open || ((*transport->open)() < 0)) {
227 if (transport->close) {
228 (*transport->close)();
229 }
230 list_remove(&transport->node);
231 continue;
232 }
233 ++i;
234 }
235 if (!ret && !i) {
236 return -ENODEV;
237 }
238
239 return ret;
240}
241
242/*
243 * Extract a 4-byte value from a byte stream. le32toh open coded
244 */
245static inline uint32_t get4LE(const uint8_t* src)
246{
247 return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
248}
249
250static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
251{
252 struct android_log_transport_write *node;
253 int ret;
254 struct timespec ts;
255 size_t len, i;
256
257 for (len = i = 0; i < nr; ++i) {
258 len += vec[i].iov_len;
259 }
260 if (!len) {
261 return -EINVAL;
262 }
263
264#if defined(__BIONIC__)
265 if (log_id == LOG_ID_SECURITY) {
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800266 if (vec[0].iov_len < 4) {
267 return -EINVAL;
268 }
269
Mark Salyzynef5a14e2016-03-28 16:20:29 -0700270 ret = check_log_uid_permissions();
271 if (ret < 0) {
272 return ret;
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800273 }
274 if (!__android_log_security()) {
275 /* If only we could reset downstream logd counter */
276 return -EPERM;
277 }
278 } else if (log_id == LOG_ID_EVENTS) {
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800279 const char *tag;
Mark Salyzyn0da1b472016-09-22 09:56:51 -0700280 size_t len;
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800281 EventTagMap *m, *f;
282
283 if (vec[0].iov_len < 4) {
284 return -EINVAL;
285 }
286
287 tag = NULL;
Mark Salyzyn0da1b472016-09-22 09:56:51 -0700288 len = 0;
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800289 f = NULL;
Mark Salyzyn0a9c0b92016-09-13 07:28:21 -0700290 m = (EventTagMap *)atomic_load(&tagMap);
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800291
292 if (!m) {
293 ret = __android_log_trylock();
Mark Salyzyn0a9c0b92016-09-13 07:28:21 -0700294 m = (EventTagMap *)atomic_load(&tagMap); /* trylock flush cache */
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800295 if (!m) {
296 m = android_openEventTagMap(EVENT_TAG_MAP_FILE);
297 if (ret) { /* trylock failed, use local copy, mark for close */
298 f = m;
299 } else {
300 if (!m) { /* One chance to open map file */
301 m = (EventTagMap *)(uintptr_t)-1LL;
302 }
Mark Salyzyn0a9c0b92016-09-13 07:28:21 -0700303 atomic_store(&tagMap, (uintptr_t)m);
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800304 }
305 }
306 if (!ret) { /* trylock succeeded, unlock */
307 __android_log_unlock();
308 }
309 }
310 if (m && (m != (EventTagMap *)(uintptr_t)-1LL)) {
Mark Salyzyn0da1b472016-09-22 09:56:51 -0700311 tag = android_lookupEventTag_len(m, &len, get4LE(vec[0].iov_base));
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800312 }
Mark Salyzyn0da1b472016-09-22 09:56:51 -0700313 ret = __android_log_is_loggable_len(ANDROID_LOG_INFO,
314 tag, len,
315 ANDROID_LOG_VERBOSE);
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800316 if (f) { /* local copy marked for close */
317 android_closeEventTagMap(f);
318 }
319 if (!ret) {
320 return -EPERM;
321 }
322 } else {
323 /* Validate the incoming tag, tag content can not split across iovec */
324 char prio = ANDROID_LOG_VERBOSE;
325 const char *tag = vec[0].iov_base;
326 size_t len = vec[0].iov_len;
327 if (!tag) {
328 len = 0;
329 }
330 if (len > 0) {
331 prio = *tag;
332 if (len > 1) {
333 --len;
334 ++tag;
335 } else {
336 len = vec[1].iov_len;
337 tag = ((const char *)vec[1].iov_base);
338 if (!tag) {
339 len = 0;
340 }
341 }
342 }
343 /* tag must be nul terminated */
344 if (strnlen(tag, len) >= len) {
345 tag = NULL;
346 }
347
Mark Salyzyn0da1b472016-09-22 09:56:51 -0700348 if (!__android_log_is_loggable_len(prio,
349 tag, len - 1,
350 ANDROID_LOG_VERBOSE)) {
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800351 return -EPERM;
352 }
353 }
354
355 clock_gettime(android_log_clockid(), &ts);
356#else
357 /* simulate clock_gettime(CLOCK_REALTIME, &ts); */
358 {
359 struct timeval tv;
360 gettimeofday(&tv, NULL);
361 ts.tv_sec = tv.tv_sec;
362 ts.tv_nsec = tv.tv_usec * 1000;
363 }
364#endif
365
366 ret = 0;
Mark Salyzynef5a14e2016-03-28 16:20:29 -0700367 i = 1 << log_id;
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800368 write_transport_for_each(node, &__android_log_transport_write) {
Mark Salyzynef5a14e2016-03-28 16:20:29 -0700369 if (node->logMask & i) {
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800370 ssize_t retval;
371 retval = (*node->write)(log_id, &ts, vec, nr);
372 if (ret >= 0) {
373 ret = retval;
374 }
375 }
376 }
377
378 write_transport_for_each(node, &__android_log_persist_write) {
Mark Salyzynef5a14e2016-03-28 16:20:29 -0700379 if (node->logMask & i) {
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800380 (void)(*node->write)(log_id, &ts, vec, nr);
381 }
382 }
383
384 return ret;
385}
386
387static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
388{
389 __android_log_lock();
390
391 if (write_to_log == __write_to_log_init) {
392 int ret;
393
394 ret = __write_to_log_initialize();
395 if (ret < 0) {
396 __android_log_unlock();
397 if (!list_empty(&__android_log_persist_write)) {
398 __write_to_log_daemon(log_id, vec, nr);
399 }
400 return ret;
401 }
402
403 write_to_log = __write_to_log_daemon;
404 }
405
406 __android_log_unlock();
407
408 return write_to_log(log_id, vec, nr);
409}
410
411LIBLOG_ABI_PUBLIC int __android_log_write(int prio, const char *tag,
412 const char *msg)
413{
414 return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
415}
416
417LIBLOG_ABI_PUBLIC int __android_log_buf_write(int bufID, int prio,
418 const char *tag, const char *msg)
419{
420 struct iovec vec[3];
421 char tmp_tag[32];
422
423 if (!tag)
424 tag = "";
425
426 /* XXX: This needs to go! */
427 if ((bufID != LOG_ID_RADIO) &&
428 (!strcmp(tag, "HTC_RIL") ||
429 !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
430 !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
431 !strcmp(tag, "AT") ||
432 !strcmp(tag, "GSM") ||
433 !strcmp(tag, "STK") ||
434 !strcmp(tag, "CDMA") ||
435 !strcmp(tag, "PHONE") ||
436 !strcmp(tag, "SMS"))) {
437 bufID = LOG_ID_RADIO;
438 /* Inform third party apps/ril/radio.. to use Rlog or RLOG */
439 snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
440 tag = tmp_tag;
441 }
442
443#if __BIONIC__
444 if (prio == ANDROID_LOG_FATAL) {
445 android_set_abort_message(msg);
446 }
447#endif
448
Mark Salyzynef5a14e2016-03-28 16:20:29 -0700449 vec[0].iov_base = (unsigned char *)&prio;
450 vec[0].iov_len = 1;
451 vec[1].iov_base = (void *)tag;
452 vec[1].iov_len = strlen(tag) + 1;
453 vec[2].iov_base = (void *)msg;
454 vec[2].iov_len = strlen(msg) + 1;
Mark Salyzync5ae20f2016-03-01 13:45:42 -0800455
456 return write_to_log(bufID, vec, 3);
457}
458
459LIBLOG_ABI_PUBLIC int __android_log_vprint(int prio, const char *tag,
460 const char *fmt, va_list ap)
461{
462 char buf[LOG_BUF_SIZE];
463
464 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
465
466 return __android_log_write(prio, tag, buf);
467}
468
469LIBLOG_ABI_PUBLIC int __android_log_print(int prio, const char *tag,
470 const char *fmt, ...)
471{
472 va_list ap;
473 char buf[LOG_BUF_SIZE];
474
475 va_start(ap, fmt);
476 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
477 va_end(ap);
478
479 return __android_log_write(prio, tag, buf);
480}
481
482LIBLOG_ABI_PUBLIC int __android_log_buf_print(int bufID, int prio,
483 const char *tag,
484 const char *fmt, ...)
485{
486 va_list ap;
487 char buf[LOG_BUF_SIZE];
488
489 va_start(ap, fmt);
490 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
491 va_end(ap);
492
493 return __android_log_buf_write(bufID, prio, tag, buf);
494}
495
496LIBLOG_ABI_PUBLIC void __android_log_assert(const char *cond, const char *tag,
497 const char *fmt, ...)
498{
499 char buf[LOG_BUF_SIZE];
500
501 if (fmt) {
502 va_list ap;
503 va_start(ap, fmt);
504 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
505 va_end(ap);
506 } else {
507 /* Msg not provided, log condition. N.B. Do not use cond directly as
508 * format string as it could contain spurious '%' syntax (e.g.
509 * "%d" in "blocks%devs == 0").
510 */
511 if (cond)
512 snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond);
513 else
514 strcpy(buf, "Unspecified assertion failed");
515 }
516
517 __android_log_write(ANDROID_LOG_FATAL, tag, buf);
518 abort(); /* abort so we have a chance to debug the situation */
519 /* NOTREACHED */
520}
521
522LIBLOG_ABI_PUBLIC int __android_log_bwrite(int32_t tag,
523 const void *payload, size_t len)
524{
525 struct iovec vec[2];
526
527 vec[0].iov_base = &tag;
528 vec[0].iov_len = sizeof(tag);
529 vec[1].iov_base = (void*)payload;
530 vec[1].iov_len = len;
531
532 return write_to_log(LOG_ID_EVENTS, vec, 2);
533}
534
535LIBLOG_ABI_PUBLIC int __android_log_security_bwrite(int32_t tag,
536 const void *payload,
537 size_t len)
538{
539 struct iovec vec[2];
540
541 vec[0].iov_base = &tag;
542 vec[0].iov_len = sizeof(tag);
543 vec[1].iov_base = (void*)payload;
544 vec[1].iov_len = len;
545
546 return write_to_log(LOG_ID_SECURITY, vec, 2);
547}
548
549/*
550 * Like __android_log_bwrite, but takes the type as well. Doesn't work
551 * for the general case where we're generating lists of stuff, but very
552 * handy if we just want to dump an integer into the log.
553 */
554LIBLOG_ABI_PUBLIC int __android_log_btwrite(int32_t tag, char type,
555 const void *payload, size_t len)
556{
557 struct iovec vec[3];
558
559 vec[0].iov_base = &tag;
560 vec[0].iov_len = sizeof(tag);
561 vec[1].iov_base = &type;
562 vec[1].iov_len = sizeof(type);
563 vec[2].iov_base = (void*)payload;
564 vec[2].iov_len = len;
565
566 return write_to_log(LOG_ID_EVENTS, vec, 3);
567}
568
569/*
570 * Like __android_log_bwrite, but used for writing strings to the
571 * event log.
572 */
573LIBLOG_ABI_PUBLIC int __android_log_bswrite(int32_t tag, const char *payload)
574{
575 struct iovec vec[4];
576 char type = EVENT_TYPE_STRING;
577 uint32_t len = strlen(payload);
578
579 vec[0].iov_base = &tag;
580 vec[0].iov_len = sizeof(tag);
581 vec[1].iov_base = &type;
582 vec[1].iov_len = sizeof(type);
583 vec[2].iov_base = &len;
584 vec[2].iov_len = sizeof(len);
585 vec[3].iov_base = (void*)payload;
586 vec[3].iov_len = len;
587
588 return write_to_log(LOG_ID_EVENTS, vec, 4);
589}
590
591/*
592 * Like __android_log_security_bwrite, but used for writing strings to the
593 * security log.
594 */
595LIBLOG_ABI_PUBLIC int __android_log_security_bswrite(int32_t tag,
596 const char *payload)
597{
598 struct iovec vec[4];
599 char type = EVENT_TYPE_STRING;
600 uint32_t len = strlen(payload);
601
602 vec[0].iov_base = &tag;
603 vec[0].iov_len = sizeof(tag);
604 vec[1].iov_base = &type;
605 vec[1].iov_len = sizeof(type);
606 vec[2].iov_base = &len;
607 vec[2].iov_len = sizeof(len);
608 vec[3].iov_base = (void*)payload;
609 vec[3].iov_len = len;
610
611 return write_to_log(LOG_ID_SECURITY, vec, 4);
612}