blob: c7b5a841500ea70879dde3b0fb3eac5a62333950 [file] [log] [blame]
Mark Salyzyn018a96d2016-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>
28#include <log/logd.h>
29#include <log/logger.h>
30#include <log/log_read.h>
31#include <private/android_filesystem_config.h>
32#include <private/android_logger.h>
33
34#include "config_write.h"
35#include "log_portability.h"
36#include "logger.h"
37
38#define LOG_BUF_SIZE 1024
39
40static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr);
41static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;
42
43/*
44 * This is used by the C++ code to decide if it should write logs through
45 * the C code. Basically, if /dev/socket/logd is available, we're running in
46 * the simulator rather than a desktop tool and want to use the device.
47 */
48static enum {
49 kLogUninitialized, kLogNotAvailable, kLogAvailable
50} g_log_status = kLogUninitialized;
51
Mark Salyzync33103c2016-03-28 16:20:29 -070052static int check_log_uid_permissions()
53{
54#if defined(__BIONIC__)
55 uid_t uid = __android_log_uid();
56
57 /* Matches clientHasLogCredentials() in logd */
58 if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) {
59 uid = geteuid();
60 if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) {
61 gid_t gid = getgid();
62 if ((gid != AID_SYSTEM) &&
63 (gid != AID_ROOT) &&
64 (gid != AID_LOG)) {
65 gid = getegid();
66 if ((gid != AID_SYSTEM) &&
67 (gid != AID_ROOT) &&
68 (gid != AID_LOG)) {
69 int num_groups;
70 gid_t *groups;
71
72 num_groups = getgroups(0, NULL);
73 if (num_groups <= 0) {
74 return -EPERM;
75 }
76 groups = calloc(num_groups, sizeof(gid_t));
77 if (!groups) {
78 return -ENOMEM;
79 }
80 num_groups = getgroups(num_groups, groups);
81 while (num_groups > 0) {
82 if (groups[num_groups - 1] == AID_LOG) {
83 break;
84 }
85 --num_groups;
86 }
87 free(groups);
88 if (num_groups <= 0) {
89 return -EPERM;
90 }
91 }
92 }
93 }
94 }
95#endif
96 return 0;
97}
98
99static void __android_log_cache_available(
100 struct android_log_transport_write *node)
101{
102 size_t i;
103
104 if (node->logMask) {
105 return;
106 }
107
108 for (i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
109 if (node->write &&
110 (i != LOG_ID_KERNEL) &&
111 ((i != LOG_ID_SECURITY) ||
112 (check_log_uid_permissions() == 0)) &&
113 (!node->available || ((*node->available)(i) >= 0))) {
114 node->logMask |= 1 << i;
115 }
116 }
117}
118
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800119LIBLOG_ABI_PUBLIC int __android_log_dev_available()
120{
121 struct android_log_transport_write *node;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800122
123 if (list_empty(&__android_log_transport_write)) {
124 return kLogUninitialized;
125 }
Mark Salyzync33103c2016-03-28 16:20:29 -0700126
127 write_transport_for_each(node, &__android_log_transport_write) {
128 __android_log_cache_available(node);
129 if (node->logMask) {
130 return kLogAvailable;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800131 }
132 }
133 return kLogNotAvailable;
134}
Mark Salyzyndf7a4c62016-08-23 10:23:36 -0700135/*
136 * Release any logger resources. A new log write will immediately re-acquire.
137 */
138LIBLOG_ABI_PUBLIC void __android_log_close()
139{
140 struct android_log_transport_write *transport;
141
142 __android_log_lock();
143
144 write_to_log = __write_to_log_init;
145
146 /*
147 * Threads that are actively writing at this point are not held back
148 * by a lock and are at risk of dropping the messages with a return code
149 * -EBADF. Prefer to return error code than add the overhead of a lock to
150 * each log writing call to guarantee delivery. In addition, anyone
151 * calling this is doing so to release the logging resources and shut down,
152 * for them to do so with outstanding log requests in other threads is a
153 * disengenuous use of this function.
154 */
155
156 write_transport_for_each(transport, &__android_log_persist_write) {
157 if (transport->close) {
158 (*transport->close)();
159 }
160 }
161
162 write_transport_for_each(transport, &__android_log_transport_write) {
163 if (transport->close) {
164 (*transport->close)();
165 }
166 }
167
168 __android_log_unlock();
169}
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800170
171/* log_init_lock assumed */
172static int __write_to_log_initialize()
173{
174 struct android_log_transport_write *transport;
175 struct listnode *n;
176 int i = 0, ret = 0;
177
178 __android_log_config_write();
179 write_transport_for_each_safe(transport, n, &__android_log_transport_write) {
Mark Salyzync33103c2016-03-28 16:20:29 -0700180 __android_log_cache_available(transport);
181 if (!transport->logMask) {
182 list_remove(&transport->node);
183 continue;
184 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800185 if (!transport->open || ((*transport->open)() < 0)) {
186 if (transport->close) {
187 (*transport->close)();
188 }
189 list_remove(&transport->node);
190 continue;
191 }
192 ++ret;
193 }
194 write_transport_for_each_safe(transport, n, &__android_log_persist_write) {
Mark Salyzync33103c2016-03-28 16:20:29 -0700195 __android_log_cache_available(transport);
196 if (!transport->logMask) {
197 list_remove(&transport->node);
198 continue;
199 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800200 if (!transport->open || ((*transport->open)() < 0)) {
201 if (transport->close) {
202 (*transport->close)();
203 }
204 list_remove(&transport->node);
205 continue;
206 }
207 ++i;
208 }
209 if (!ret && !i) {
210 return -ENODEV;
211 }
212
213 return ret;
214}
215
216/*
217 * Extract a 4-byte value from a byte stream. le32toh open coded
218 */
219static inline uint32_t get4LE(const uint8_t* src)
220{
221 return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
222}
223
224static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
225{
226 struct android_log_transport_write *node;
227 int ret;
228 struct timespec ts;
229 size_t len, i;
230
231 for (len = i = 0; i < nr; ++i) {
232 len += vec[i].iov_len;
233 }
234 if (!len) {
235 return -EINVAL;
236 }
237
238#if defined(__BIONIC__)
239 if (log_id == LOG_ID_SECURITY) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800240 if (vec[0].iov_len < 4) {
241 return -EINVAL;
242 }
243
Mark Salyzync33103c2016-03-28 16:20:29 -0700244 ret = check_log_uid_permissions();
245 if (ret < 0) {
246 return ret;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800247 }
248 if (!__android_log_security()) {
249 /* If only we could reset downstream logd counter */
250 return -EPERM;
251 }
252 } else if (log_id == LOG_ID_EVENTS) {
253 static atomic_uintptr_t map;
254 const char *tag;
255 EventTagMap *m, *f;
256
257 if (vec[0].iov_len < 4) {
258 return -EINVAL;
259 }
260
261 tag = NULL;
262 f = NULL;
263 m = (EventTagMap *)atomic_load(&map);
264
265 if (!m) {
266 ret = __android_log_trylock();
267 m = (EventTagMap *)atomic_load(&map); /* trylock flush cache */
268 if (!m) {
269 m = android_openEventTagMap(EVENT_TAG_MAP_FILE);
270 if (ret) { /* trylock failed, use local copy, mark for close */
271 f = m;
272 } else {
273 if (!m) { /* One chance to open map file */
274 m = (EventTagMap *)(uintptr_t)-1LL;
275 }
276 atomic_store(&map, (uintptr_t)m);
277 }
278 }
279 if (!ret) { /* trylock succeeded, unlock */
280 __android_log_unlock();
281 }
282 }
283 if (m && (m != (EventTagMap *)(uintptr_t)-1LL)) {
284 tag = android_lookupEventTag(m, get4LE(vec[0].iov_base));
285 }
286 ret = __android_log_is_loggable(ANDROID_LOG_INFO,
287 tag,
288 ANDROID_LOG_VERBOSE);
289 if (f) { /* local copy marked for close */
290 android_closeEventTagMap(f);
291 }
292 if (!ret) {
293 return -EPERM;
294 }
295 } else {
296 /* Validate the incoming tag, tag content can not split across iovec */
297 char prio = ANDROID_LOG_VERBOSE;
298 const char *tag = vec[0].iov_base;
299 size_t len = vec[0].iov_len;
300 if (!tag) {
301 len = 0;
302 }
303 if (len > 0) {
304 prio = *tag;
305 if (len > 1) {
306 --len;
307 ++tag;
308 } else {
309 len = vec[1].iov_len;
310 tag = ((const char *)vec[1].iov_base);
311 if (!tag) {
312 len = 0;
313 }
314 }
315 }
316 /* tag must be nul terminated */
317 if (strnlen(tag, len) >= len) {
318 tag = NULL;
319 }
320
321 if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
322 return -EPERM;
323 }
324 }
325
326 clock_gettime(android_log_clockid(), &ts);
327#else
328 /* simulate clock_gettime(CLOCK_REALTIME, &ts); */
329 {
330 struct timeval tv;
331 gettimeofday(&tv, NULL);
332 ts.tv_sec = tv.tv_sec;
333 ts.tv_nsec = tv.tv_usec * 1000;
334 }
335#endif
336
337 ret = 0;
Mark Salyzync33103c2016-03-28 16:20:29 -0700338 i = 1 << log_id;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800339 write_transport_for_each(node, &__android_log_transport_write) {
Mark Salyzync33103c2016-03-28 16:20:29 -0700340 if (node->logMask & i) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800341 ssize_t retval;
342 retval = (*node->write)(log_id, &ts, vec, nr);
343 if (ret >= 0) {
344 ret = retval;
345 }
346 }
347 }
348
349 write_transport_for_each(node, &__android_log_persist_write) {
Mark Salyzync33103c2016-03-28 16:20:29 -0700350 if (node->logMask & i) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800351 (void)(*node->write)(log_id, &ts, vec, nr);
352 }
353 }
354
355 return ret;
356}
357
358static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
359{
360 __android_log_lock();
361
362 if (write_to_log == __write_to_log_init) {
363 int ret;
364
365 ret = __write_to_log_initialize();
366 if (ret < 0) {
367 __android_log_unlock();
368 if (!list_empty(&__android_log_persist_write)) {
369 __write_to_log_daemon(log_id, vec, nr);
370 }
371 return ret;
372 }
373
374 write_to_log = __write_to_log_daemon;
375 }
376
377 __android_log_unlock();
378
379 return write_to_log(log_id, vec, nr);
380}
381
382LIBLOG_ABI_PUBLIC int __android_log_write(int prio, const char *tag,
383 const char *msg)
384{
385 return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
386}
387
388LIBLOG_ABI_PUBLIC int __android_log_buf_write(int bufID, int prio,
389 const char *tag, const char *msg)
390{
391 struct iovec vec[3];
392 char tmp_tag[32];
393
394 if (!tag)
395 tag = "";
396
397 /* XXX: This needs to go! */
398 if ((bufID != LOG_ID_RADIO) &&
399 (!strcmp(tag, "HTC_RIL") ||
400 !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
401 !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
402 !strcmp(tag, "AT") ||
403 !strcmp(tag, "GSM") ||
404 !strcmp(tag, "STK") ||
405 !strcmp(tag, "CDMA") ||
406 !strcmp(tag, "PHONE") ||
407 !strcmp(tag, "SMS"))) {
408 bufID = LOG_ID_RADIO;
409 /* Inform third party apps/ril/radio.. to use Rlog or RLOG */
410 snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
411 tag = tmp_tag;
412 }
413
414#if __BIONIC__
415 if (prio == ANDROID_LOG_FATAL) {
416 android_set_abort_message(msg);
417 }
418#endif
419
Mark Salyzync33103c2016-03-28 16:20:29 -0700420 vec[0].iov_base = (unsigned char *)&prio;
421 vec[0].iov_len = 1;
422 vec[1].iov_base = (void *)tag;
423 vec[1].iov_len = strlen(tag) + 1;
424 vec[2].iov_base = (void *)msg;
425 vec[2].iov_len = strlen(msg) + 1;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800426
427 return write_to_log(bufID, vec, 3);
428}
429
430LIBLOG_ABI_PUBLIC int __android_log_vprint(int prio, const char *tag,
431 const char *fmt, va_list ap)
432{
433 char buf[LOG_BUF_SIZE];
434
435 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
436
437 return __android_log_write(prio, tag, buf);
438}
439
440LIBLOG_ABI_PUBLIC int __android_log_print(int prio, const char *tag,
441 const char *fmt, ...)
442{
443 va_list ap;
444 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 return __android_log_write(prio, tag, buf);
451}
452
453LIBLOG_ABI_PUBLIC int __android_log_buf_print(int bufID, int prio,
454 const char *tag,
455 const char *fmt, ...)
456{
457 va_list ap;
458 char buf[LOG_BUF_SIZE];
459
460 va_start(ap, fmt);
461 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
462 va_end(ap);
463
464 return __android_log_buf_write(bufID, prio, tag, buf);
465}
466
467LIBLOG_ABI_PUBLIC void __android_log_assert(const char *cond, const char *tag,
468 const char *fmt, ...)
469{
470 char buf[LOG_BUF_SIZE];
471
472 if (fmt) {
473 va_list ap;
474 va_start(ap, fmt);
475 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
476 va_end(ap);
477 } else {
478 /* Msg not provided, log condition. N.B. Do not use cond directly as
479 * format string as it could contain spurious '%' syntax (e.g.
480 * "%d" in "blocks%devs == 0").
481 */
482 if (cond)
483 snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond);
484 else
485 strcpy(buf, "Unspecified assertion failed");
486 }
487
488 __android_log_write(ANDROID_LOG_FATAL, tag, buf);
489 abort(); /* abort so we have a chance to debug the situation */
490 /* NOTREACHED */
491}
492
493LIBLOG_ABI_PUBLIC int __android_log_bwrite(int32_t tag,
494 const void *payload, size_t len)
495{
496 struct iovec vec[2];
497
498 vec[0].iov_base = &tag;
499 vec[0].iov_len = sizeof(tag);
500 vec[1].iov_base = (void*)payload;
501 vec[1].iov_len = len;
502
503 return write_to_log(LOG_ID_EVENTS, vec, 2);
504}
505
506LIBLOG_ABI_PUBLIC int __android_log_security_bwrite(int32_t tag,
507 const void *payload,
508 size_t len)
509{
510 struct iovec vec[2];
511
512 vec[0].iov_base = &tag;
513 vec[0].iov_len = sizeof(tag);
514 vec[1].iov_base = (void*)payload;
515 vec[1].iov_len = len;
516
517 return write_to_log(LOG_ID_SECURITY, vec, 2);
518}
519
520/*
521 * Like __android_log_bwrite, but takes the type as well. Doesn't work
522 * for the general case where we're generating lists of stuff, but very
523 * handy if we just want to dump an integer into the log.
524 */
525LIBLOG_ABI_PUBLIC int __android_log_btwrite(int32_t tag, char type,
526 const void *payload, size_t len)
527{
528 struct iovec vec[3];
529
530 vec[0].iov_base = &tag;
531 vec[0].iov_len = sizeof(tag);
532 vec[1].iov_base = &type;
533 vec[1].iov_len = sizeof(type);
534 vec[2].iov_base = (void*)payload;
535 vec[2].iov_len = len;
536
537 return write_to_log(LOG_ID_EVENTS, vec, 3);
538}
539
540/*
541 * Like __android_log_bwrite, but used for writing strings to the
542 * event log.
543 */
544LIBLOG_ABI_PUBLIC int __android_log_bswrite(int32_t tag, const char *payload)
545{
546 struct iovec vec[4];
547 char type = EVENT_TYPE_STRING;
548 uint32_t len = strlen(payload);
549
550 vec[0].iov_base = &tag;
551 vec[0].iov_len = sizeof(tag);
552 vec[1].iov_base = &type;
553 vec[1].iov_len = sizeof(type);
554 vec[2].iov_base = &len;
555 vec[2].iov_len = sizeof(len);
556 vec[3].iov_base = (void*)payload;
557 vec[3].iov_len = len;
558
559 return write_to_log(LOG_ID_EVENTS, vec, 4);
560}
561
562/*
563 * Like __android_log_security_bwrite, but used for writing strings to the
564 * security log.
565 */
566LIBLOG_ABI_PUBLIC int __android_log_security_bswrite(int32_t tag,
567 const char *payload)
568{
569 struct iovec vec[4];
570 char type = EVENT_TYPE_STRING;
571 uint32_t len = strlen(payload);
572
573 vec[0].iov_base = &tag;
574 vec[0].iov_len = sizeof(tag);
575 vec[1].iov_base = &type;
576 vec[1].iov_len = sizeof(type);
577 vec[2].iov_base = &len;
578 vec[2].iov_len = sizeof(len);
579 vec[3].iov_base = (void*)payload;
580 vec[3].iov_len = len;
581
582 return write_to_log(LOG_ID_SECURITY, vec, 4);
583}