blob: b802ed7b269c3ca96191a392a7d7bc6c8b1555a5 [file] [log] [blame]
Mark Salyzynfacf94c2016-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 Salyzyn5e635f72016-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 Salyzynfacf94c2016-03-01 13:45:42 -0800119LIBLOG_ABI_PUBLIC int __android_log_dev_available()
120{
121 struct android_log_transport_write *node;
Mark Salyzynfacf94c2016-03-01 13:45:42 -0800122
123 if (list_empty(&__android_log_transport_write)) {
124 return kLogUninitialized;
125 }
Mark Salyzyn5e635f72016-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 Salyzynfacf94c2016-03-01 13:45:42 -0800131 }
132 }
133 return kLogNotAvailable;
134}
135
136/* log_init_lock assumed */
137static int __write_to_log_initialize()
138{
139 struct android_log_transport_write *transport;
140 struct listnode *n;
141 int i = 0, ret = 0;
142
143 __android_log_config_write();
144 write_transport_for_each_safe(transport, n, &__android_log_transport_write) {
Mark Salyzyn5e635f72016-03-28 16:20:29 -0700145 __android_log_cache_available(transport);
146 if (!transport->logMask) {
147 list_remove(&transport->node);
148 continue;
149 }
Mark Salyzynfacf94c2016-03-01 13:45:42 -0800150 if (!transport->open || ((*transport->open)() < 0)) {
151 if (transport->close) {
152 (*transport->close)();
153 }
154 list_remove(&transport->node);
155 continue;
156 }
157 ++ret;
158 }
159 write_transport_for_each_safe(transport, n, &__android_log_persist_write) {
Mark Salyzyn5e635f72016-03-28 16:20:29 -0700160 __android_log_cache_available(transport);
161 if (!transport->logMask) {
162 list_remove(&transport->node);
163 continue;
164 }
Mark Salyzynfacf94c2016-03-01 13:45:42 -0800165 if (!transport->open || ((*transport->open)() < 0)) {
166 if (transport->close) {
167 (*transport->close)();
168 }
169 list_remove(&transport->node);
170 continue;
171 }
172 ++i;
173 }
174 if (!ret && !i) {
175 return -ENODEV;
176 }
177
178 return ret;
179}
180
181/*
182 * Extract a 4-byte value from a byte stream. le32toh open coded
183 */
184static inline uint32_t get4LE(const uint8_t* src)
185{
186 return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
187}
188
189static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
190{
191 struct android_log_transport_write *node;
192 int ret;
193 struct timespec ts;
194 size_t len, i;
195
196 for (len = i = 0; i < nr; ++i) {
197 len += vec[i].iov_len;
198 }
199 if (!len) {
200 return -EINVAL;
201 }
202
203#if defined(__BIONIC__)
204 if (log_id == LOG_ID_SECURITY) {
Mark Salyzynfacf94c2016-03-01 13:45:42 -0800205 if (vec[0].iov_len < 4) {
206 return -EINVAL;
207 }
208
Mark Salyzyn5e635f72016-03-28 16:20:29 -0700209 ret = check_log_uid_permissions();
210 if (ret < 0) {
211 return ret;
Mark Salyzynfacf94c2016-03-01 13:45:42 -0800212 }
213 if (!__android_log_security()) {
214 /* If only we could reset downstream logd counter */
215 return -EPERM;
216 }
217 } else if (log_id == LOG_ID_EVENTS) {
218 static atomic_uintptr_t map;
219 const char *tag;
220 EventTagMap *m, *f;
221
222 if (vec[0].iov_len < 4) {
223 return -EINVAL;
224 }
225
226 tag = NULL;
227 f = NULL;
228 m = (EventTagMap *)atomic_load(&map);
229
230 if (!m) {
231 ret = __android_log_trylock();
232 m = (EventTagMap *)atomic_load(&map); /* trylock flush cache */
233 if (!m) {
234 m = android_openEventTagMap(EVENT_TAG_MAP_FILE);
235 if (ret) { /* trylock failed, use local copy, mark for close */
236 f = m;
237 } else {
238 if (!m) { /* One chance to open map file */
239 m = (EventTagMap *)(uintptr_t)-1LL;
240 }
241 atomic_store(&map, (uintptr_t)m);
242 }
243 }
244 if (!ret) { /* trylock succeeded, unlock */
245 __android_log_unlock();
246 }
247 }
248 if (m && (m != (EventTagMap *)(uintptr_t)-1LL)) {
249 tag = android_lookupEventTag(m, get4LE(vec[0].iov_base));
250 }
251 ret = __android_log_is_loggable(ANDROID_LOG_INFO,
252 tag,
253 ANDROID_LOG_VERBOSE);
254 if (f) { /* local copy marked for close */
255 android_closeEventTagMap(f);
256 }
257 if (!ret) {
258 return -EPERM;
259 }
260 } else {
261 /* Validate the incoming tag, tag content can not split across iovec */
262 char prio = ANDROID_LOG_VERBOSE;
263 const char *tag = vec[0].iov_base;
264 size_t len = vec[0].iov_len;
265 if (!tag) {
266 len = 0;
267 }
268 if (len > 0) {
269 prio = *tag;
270 if (len > 1) {
271 --len;
272 ++tag;
273 } else {
274 len = vec[1].iov_len;
275 tag = ((const char *)vec[1].iov_base);
276 if (!tag) {
277 len = 0;
278 }
279 }
280 }
281 /* tag must be nul terminated */
282 if (strnlen(tag, len) >= len) {
283 tag = NULL;
284 }
285
286 if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
287 return -EPERM;
288 }
289 }
290
291 clock_gettime(android_log_clockid(), &ts);
292#else
293 /* simulate clock_gettime(CLOCK_REALTIME, &ts); */
294 {
295 struct timeval tv;
296 gettimeofday(&tv, NULL);
297 ts.tv_sec = tv.tv_sec;
298 ts.tv_nsec = tv.tv_usec * 1000;
299 }
300#endif
301
302 ret = 0;
Mark Salyzyn5e635f72016-03-28 16:20:29 -0700303 i = 1 << log_id;
Mark Salyzynfacf94c2016-03-01 13:45:42 -0800304 write_transport_for_each(node, &__android_log_transport_write) {
Mark Salyzyn5e635f72016-03-28 16:20:29 -0700305 if (node->logMask & i) {
Mark Salyzynfacf94c2016-03-01 13:45:42 -0800306 ssize_t retval;
307 retval = (*node->write)(log_id, &ts, vec, nr);
308 if (ret >= 0) {
309 ret = retval;
310 }
311 }
312 }
313
314 write_transport_for_each(node, &__android_log_persist_write) {
Mark Salyzyn5e635f72016-03-28 16:20:29 -0700315 if (node->logMask & i) {
Mark Salyzynfacf94c2016-03-01 13:45:42 -0800316 (void)(*node->write)(log_id, &ts, vec, nr);
317 }
318 }
319
320 return ret;
321}
322
323static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
324{
325 __android_log_lock();
326
327 if (write_to_log == __write_to_log_init) {
328 int ret;
329
330 ret = __write_to_log_initialize();
331 if (ret < 0) {
332 __android_log_unlock();
333 if (!list_empty(&__android_log_persist_write)) {
334 __write_to_log_daemon(log_id, vec, nr);
335 }
336 return ret;
337 }
338
339 write_to_log = __write_to_log_daemon;
340 }
341
342 __android_log_unlock();
343
344 return write_to_log(log_id, vec, nr);
345}
346
347LIBLOG_ABI_PUBLIC int __android_log_write(int prio, const char *tag,
348 const char *msg)
349{
350 return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
351}
352
353LIBLOG_ABI_PUBLIC int __android_log_buf_write(int bufID, int prio,
354 const char *tag, const char *msg)
355{
356 struct iovec vec[3];
357 char tmp_tag[32];
358
359 if (!tag)
360 tag = "";
361
362 /* XXX: This needs to go! */
363 if ((bufID != LOG_ID_RADIO) &&
364 (!strcmp(tag, "HTC_RIL") ||
365 !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
366 !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
367 !strcmp(tag, "AT") ||
368 !strcmp(tag, "GSM") ||
369 !strcmp(tag, "STK") ||
370 !strcmp(tag, "CDMA") ||
371 !strcmp(tag, "PHONE") ||
372 !strcmp(tag, "SMS"))) {
373 bufID = LOG_ID_RADIO;
374 /* Inform third party apps/ril/radio.. to use Rlog or RLOG */
375 snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
376 tag = tmp_tag;
377 }
378
379#if __BIONIC__
380 if (prio == ANDROID_LOG_FATAL) {
381 android_set_abort_message(msg);
382 }
383#endif
384
Mark Salyzyn5e635f72016-03-28 16:20:29 -0700385 vec[0].iov_base = (unsigned char *)&prio;
386 vec[0].iov_len = 1;
387 vec[1].iov_base = (void *)tag;
388 vec[1].iov_len = strlen(tag) + 1;
389 vec[2].iov_base = (void *)msg;
390 vec[2].iov_len = strlen(msg) + 1;
Mark Salyzynfacf94c2016-03-01 13:45:42 -0800391
392 return write_to_log(bufID, vec, 3);
393}
394
395LIBLOG_ABI_PUBLIC int __android_log_vprint(int prio, const char *tag,
396 const char *fmt, va_list ap)
397{
398 char buf[LOG_BUF_SIZE];
399
400 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
401
402 return __android_log_write(prio, tag, buf);
403}
404
405LIBLOG_ABI_PUBLIC int __android_log_print(int prio, const char *tag,
406 const char *fmt, ...)
407{
408 va_list ap;
409 char buf[LOG_BUF_SIZE];
410
411 va_start(ap, fmt);
412 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
413 va_end(ap);
414
415 return __android_log_write(prio, tag, buf);
416}
417
418LIBLOG_ABI_PUBLIC int __android_log_buf_print(int bufID, int prio,
419 const char *tag,
420 const char *fmt, ...)
421{
422 va_list ap;
423 char buf[LOG_BUF_SIZE];
424
425 va_start(ap, fmt);
426 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
427 va_end(ap);
428
429 return __android_log_buf_write(bufID, prio, tag, buf);
430}
431
432LIBLOG_ABI_PUBLIC void __android_log_assert(const char *cond, const char *tag,
433 const char *fmt, ...)
434{
435 char buf[LOG_BUF_SIZE];
436
437 if (fmt) {
438 va_list ap;
439 va_start(ap, fmt);
440 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
441 va_end(ap);
442 } else {
443 /* Msg not provided, log condition. N.B. Do not use cond directly as
444 * format string as it could contain spurious '%' syntax (e.g.
445 * "%d" in "blocks%devs == 0").
446 */
447 if (cond)
448 snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond);
449 else
450 strcpy(buf, "Unspecified assertion failed");
451 }
452
453 __android_log_write(ANDROID_LOG_FATAL, tag, buf);
454 abort(); /* abort so we have a chance to debug the situation */
455 /* NOTREACHED */
456}
457
458LIBLOG_ABI_PUBLIC int __android_log_bwrite(int32_t tag,
459 const void *payload, size_t len)
460{
461 struct iovec vec[2];
462
463 vec[0].iov_base = &tag;
464 vec[0].iov_len = sizeof(tag);
465 vec[1].iov_base = (void*)payload;
466 vec[1].iov_len = len;
467
468 return write_to_log(LOG_ID_EVENTS, vec, 2);
469}
470
471LIBLOG_ABI_PUBLIC int __android_log_security_bwrite(int32_t tag,
472 const void *payload,
473 size_t len)
474{
475 struct iovec vec[2];
476
477 vec[0].iov_base = &tag;
478 vec[0].iov_len = sizeof(tag);
479 vec[1].iov_base = (void*)payload;
480 vec[1].iov_len = len;
481
482 return write_to_log(LOG_ID_SECURITY, vec, 2);
483}
484
485/*
486 * Like __android_log_bwrite, but takes the type as well. Doesn't work
487 * for the general case where we're generating lists of stuff, but very
488 * handy if we just want to dump an integer into the log.
489 */
490LIBLOG_ABI_PUBLIC int __android_log_btwrite(int32_t tag, char type,
491 const void *payload, size_t len)
492{
493 struct iovec vec[3];
494
495 vec[0].iov_base = &tag;
496 vec[0].iov_len = sizeof(tag);
497 vec[1].iov_base = &type;
498 vec[1].iov_len = sizeof(type);
499 vec[2].iov_base = (void*)payload;
500 vec[2].iov_len = len;
501
502 return write_to_log(LOG_ID_EVENTS, vec, 3);
503}
504
505/*
506 * Like __android_log_bwrite, but used for writing strings to the
507 * event log.
508 */
509LIBLOG_ABI_PUBLIC int __android_log_bswrite(int32_t tag, const char *payload)
510{
511 struct iovec vec[4];
512 char type = EVENT_TYPE_STRING;
513 uint32_t len = strlen(payload);
514
515 vec[0].iov_base = &tag;
516 vec[0].iov_len = sizeof(tag);
517 vec[1].iov_base = &type;
518 vec[1].iov_len = sizeof(type);
519 vec[2].iov_base = &len;
520 vec[2].iov_len = sizeof(len);
521 vec[3].iov_base = (void*)payload;
522 vec[3].iov_len = len;
523
524 return write_to_log(LOG_ID_EVENTS, vec, 4);
525}
526
527/*
528 * Like __android_log_security_bwrite, but used for writing strings to the
529 * security log.
530 */
531LIBLOG_ABI_PUBLIC int __android_log_security_bswrite(int32_t tag,
532 const char *payload)
533{
534 struct iovec vec[4];
535 char type = EVENT_TYPE_STRING;
536 uint32_t len = strlen(payload);
537
538 vec[0].iov_base = &tag;
539 vec[0].iov_len = sizeof(tag);
540 vec[1].iov_base = &type;
541 vec[1].iov_len = sizeof(type);
542 vec[2].iov_base = &len;
543 vec[2].iov_len = sizeof(len);
544 vec[3].iov_base = (void*)payload;
545 vec[3].iov_len = len;
546
547 return write_to_log(LOG_ID_SECURITY, vec, 4);
548}