blob: a4155e92733bcefe778942128414b0bb317b8eb0 [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
52LIBLOG_ABI_PUBLIC int __android_log_dev_available()
53{
54 struct android_log_transport_write *node;
55 size_t i;
56
57 if (list_empty(&__android_log_transport_write)) {
58 return kLogUninitialized;
59 }
60 for (i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
61 write_transport_for_each(node, &__android_log_transport_write) {
62 if (node->write &&
63 (!node->available || ((*node->available)(i) >= 0))) {
64 return kLogAvailable;
65 }
66 }
67 }
68 return kLogNotAvailable;
69}
70
71/* log_init_lock assumed */
72static int __write_to_log_initialize()
73{
74 struct android_log_transport_write *transport;
75 struct listnode *n;
76 int i = 0, ret = 0;
77
78 __android_log_config_write();
79 write_transport_for_each_safe(transport, n, &__android_log_transport_write) {
80 if (!transport->open || ((*transport->open)() < 0)) {
81 if (transport->close) {
82 (*transport->close)();
83 }
84 list_remove(&transport->node);
85 continue;
86 }
87 ++ret;
88 }
89 write_transport_for_each_safe(transport, n, &__android_log_persist_write) {
90 if (!transport->open || ((*transport->open)() < 0)) {
91 if (transport->close) {
92 (*transport->close)();
93 }
94 list_remove(&transport->node);
95 continue;
96 }
97 ++i;
98 }
99 if (!ret && !i) {
100 return -ENODEV;
101 }
102
103 return ret;
104}
105
106/*
107 * Extract a 4-byte value from a byte stream. le32toh open coded
108 */
109static inline uint32_t get4LE(const uint8_t* src)
110{
111 return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
112}
113
114static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
115{
116 struct android_log_transport_write *node;
117 int ret;
118 struct timespec ts;
119 size_t len, i;
120
121 for (len = i = 0; i < nr; ++i) {
122 len += vec[i].iov_len;
123 }
124 if (!len) {
125 return -EINVAL;
126 }
127
128#if defined(__BIONIC__)
129 if (log_id == LOG_ID_SECURITY) {
130 uid_t uid;
131
132 if (vec[0].iov_len < 4) {
133 return -EINVAL;
134 }
135
136 uid = __android_log_uid();
137 /* Matches clientHasLogCredentials() in logd */
138 if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) {
139 uid = geteuid();
140 if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) {
141 gid_t gid = getgid();
142 if ((gid != AID_SYSTEM) &&
143 (gid != AID_ROOT) &&
144 (gid != AID_LOG)) {
145 gid = getegid();
146 if ((gid != AID_SYSTEM) &&
147 (gid != AID_ROOT) &&
148 (gid != AID_LOG)) {
149 int num_groups;
150 gid_t *groups;
151
152 num_groups = getgroups(0, NULL);
153 if (num_groups <= 0) {
154 return -EPERM;
155 }
156 groups = calloc(num_groups, sizeof(gid_t));
157 if (!groups) {
158 return -ENOMEM;
159 }
160 num_groups = getgroups(num_groups, groups);
161 while (num_groups > 0) {
162 if (groups[num_groups - 1] == AID_LOG) {
163 break;
164 }
165 --num_groups;
166 }
167 free(groups);
168 if (num_groups <= 0) {
169 return -EPERM;
170 }
171 }
172 }
173 }
174 }
175 if (!__android_log_security()) {
176 /* If only we could reset downstream logd counter */
177 return -EPERM;
178 }
179 } else if (log_id == LOG_ID_EVENTS) {
180 static atomic_uintptr_t map;
181 const char *tag;
182 EventTagMap *m, *f;
183
184 if (vec[0].iov_len < 4) {
185 return -EINVAL;
186 }
187
188 tag = NULL;
189 f = NULL;
190 m = (EventTagMap *)atomic_load(&map);
191
192 if (!m) {
193 ret = __android_log_trylock();
194 m = (EventTagMap *)atomic_load(&map); /* trylock flush cache */
195 if (!m) {
196 m = android_openEventTagMap(EVENT_TAG_MAP_FILE);
197 if (ret) { /* trylock failed, use local copy, mark for close */
198 f = m;
199 } else {
200 if (!m) { /* One chance to open map file */
201 m = (EventTagMap *)(uintptr_t)-1LL;
202 }
203 atomic_store(&map, (uintptr_t)m);
204 }
205 }
206 if (!ret) { /* trylock succeeded, unlock */
207 __android_log_unlock();
208 }
209 }
210 if (m && (m != (EventTagMap *)(uintptr_t)-1LL)) {
211 tag = android_lookupEventTag(m, get4LE(vec[0].iov_base));
212 }
213 ret = __android_log_is_loggable(ANDROID_LOG_INFO,
214 tag,
215 ANDROID_LOG_VERBOSE);
216 if (f) { /* local copy marked for close */
217 android_closeEventTagMap(f);
218 }
219 if (!ret) {
220 return -EPERM;
221 }
222 } else {
223 /* Validate the incoming tag, tag content can not split across iovec */
224 char prio = ANDROID_LOG_VERBOSE;
225 const char *tag = vec[0].iov_base;
226 size_t len = vec[0].iov_len;
227 if (!tag) {
228 len = 0;
229 }
230 if (len > 0) {
231 prio = *tag;
232 if (len > 1) {
233 --len;
234 ++tag;
235 } else {
236 len = vec[1].iov_len;
237 tag = ((const char *)vec[1].iov_base);
238 if (!tag) {
239 len = 0;
240 }
241 }
242 }
243 /* tag must be nul terminated */
244 if (strnlen(tag, len) >= len) {
245 tag = NULL;
246 }
247
248 if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
249 return -EPERM;
250 }
251 }
252
253 clock_gettime(android_log_clockid(), &ts);
254#else
255 /* simulate clock_gettime(CLOCK_REALTIME, &ts); */
256 {
257 struct timeval tv;
258 gettimeofday(&tv, NULL);
259 ts.tv_sec = tv.tv_sec;
260 ts.tv_nsec = tv.tv_usec * 1000;
261 }
262#endif
263
264 ret = 0;
265 write_transport_for_each(node, &__android_log_transport_write) {
266 if (node->write) {
267 ssize_t retval;
268 retval = (*node->write)(log_id, &ts, vec, nr);
269 if (ret >= 0) {
270 ret = retval;
271 }
272 }
273 }
274
275 write_transport_for_each(node, &__android_log_persist_write) {
276 if (node->write) {
277 (void)(*node->write)(log_id, &ts, vec, nr);
278 }
279 }
280
281 return ret;
282}
283
284static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
285{
286 __android_log_lock();
287
288 if (write_to_log == __write_to_log_init) {
289 int ret;
290
291 ret = __write_to_log_initialize();
292 if (ret < 0) {
293 __android_log_unlock();
294 if (!list_empty(&__android_log_persist_write)) {
295 __write_to_log_daemon(log_id, vec, nr);
296 }
297 return ret;
298 }
299
300 write_to_log = __write_to_log_daemon;
301 }
302
303 __android_log_unlock();
304
305 return write_to_log(log_id, vec, nr);
306}
307
308LIBLOG_ABI_PUBLIC int __android_log_write(int prio, const char *tag,
309 const char *msg)
310{
311 return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
312}
313
314LIBLOG_ABI_PUBLIC int __android_log_buf_write(int bufID, int prio,
315 const char *tag, const char *msg)
316{
317 struct iovec vec[3];
318 char tmp_tag[32];
319
320 if (!tag)
321 tag = "";
322
323 /* XXX: This needs to go! */
324 if ((bufID != LOG_ID_RADIO) &&
325 (!strcmp(tag, "HTC_RIL") ||
326 !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
327 !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
328 !strcmp(tag, "AT") ||
329 !strcmp(tag, "GSM") ||
330 !strcmp(tag, "STK") ||
331 !strcmp(tag, "CDMA") ||
332 !strcmp(tag, "PHONE") ||
333 !strcmp(tag, "SMS"))) {
334 bufID = LOG_ID_RADIO;
335 /* Inform third party apps/ril/radio.. to use Rlog or RLOG */
336 snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
337 tag = tmp_tag;
338 }
339
340#if __BIONIC__
341 if (prio == ANDROID_LOG_FATAL) {
342 android_set_abort_message(msg);
343 }
344#endif
345
346 vec[0].iov_base = (unsigned char *) &prio;
347 vec[0].iov_len = 1;
348 vec[1].iov_base = (void *) tag;
349 vec[1].iov_len = strlen(tag) + 1;
350 vec[2].iov_base = (void *) msg;
351 vec[2].iov_len = strlen(msg) + 1;
352
353 return write_to_log(bufID, vec, 3);
354}
355
356LIBLOG_ABI_PUBLIC int __android_log_vprint(int prio, const char *tag,
357 const char *fmt, va_list ap)
358{
359 char buf[LOG_BUF_SIZE];
360
361 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
362
363 return __android_log_write(prio, tag, buf);
364}
365
366LIBLOG_ABI_PUBLIC int __android_log_print(int prio, const char *tag,
367 const char *fmt, ...)
368{
369 va_list ap;
370 char buf[LOG_BUF_SIZE];
371
372 va_start(ap, fmt);
373 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
374 va_end(ap);
375
376 return __android_log_write(prio, tag, buf);
377}
378
379LIBLOG_ABI_PUBLIC int __android_log_buf_print(int bufID, int prio,
380 const char *tag,
381 const char *fmt, ...)
382{
383 va_list ap;
384 char buf[LOG_BUF_SIZE];
385
386 va_start(ap, fmt);
387 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
388 va_end(ap);
389
390 return __android_log_buf_write(bufID, prio, tag, buf);
391}
392
393LIBLOG_ABI_PUBLIC void __android_log_assert(const char *cond, const char *tag,
394 const char *fmt, ...)
395{
396 char buf[LOG_BUF_SIZE];
397
398 if (fmt) {
399 va_list ap;
400 va_start(ap, fmt);
401 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
402 va_end(ap);
403 } else {
404 /* Msg not provided, log condition. N.B. Do not use cond directly as
405 * format string as it could contain spurious '%' syntax (e.g.
406 * "%d" in "blocks%devs == 0").
407 */
408 if (cond)
409 snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond);
410 else
411 strcpy(buf, "Unspecified assertion failed");
412 }
413
414 __android_log_write(ANDROID_LOG_FATAL, tag, buf);
415 abort(); /* abort so we have a chance to debug the situation */
416 /* NOTREACHED */
417}
418
419LIBLOG_ABI_PUBLIC int __android_log_bwrite(int32_t tag,
420 const void *payload, size_t len)
421{
422 struct iovec vec[2];
423
424 vec[0].iov_base = &tag;
425 vec[0].iov_len = sizeof(tag);
426 vec[1].iov_base = (void*)payload;
427 vec[1].iov_len = len;
428
429 return write_to_log(LOG_ID_EVENTS, vec, 2);
430}
431
432LIBLOG_ABI_PUBLIC int __android_log_security_bwrite(int32_t tag,
433 const void *payload,
434 size_t len)
435{
436 struct iovec vec[2];
437
438 vec[0].iov_base = &tag;
439 vec[0].iov_len = sizeof(tag);
440 vec[1].iov_base = (void*)payload;
441 vec[1].iov_len = len;
442
443 return write_to_log(LOG_ID_SECURITY, vec, 2);
444}
445
446/*
447 * Like __android_log_bwrite, but takes the type as well. Doesn't work
448 * for the general case where we're generating lists of stuff, but very
449 * handy if we just want to dump an integer into the log.
450 */
451LIBLOG_ABI_PUBLIC int __android_log_btwrite(int32_t tag, char type,
452 const void *payload, size_t len)
453{
454 struct iovec vec[3];
455
456 vec[0].iov_base = &tag;
457 vec[0].iov_len = sizeof(tag);
458 vec[1].iov_base = &type;
459 vec[1].iov_len = sizeof(type);
460 vec[2].iov_base = (void*)payload;
461 vec[2].iov_len = len;
462
463 return write_to_log(LOG_ID_EVENTS, vec, 3);
464}
465
466/*
467 * Like __android_log_bwrite, but used for writing strings to the
468 * event log.
469 */
470LIBLOG_ABI_PUBLIC int __android_log_bswrite(int32_t tag, const char *payload)
471{
472 struct iovec vec[4];
473 char type = EVENT_TYPE_STRING;
474 uint32_t len = strlen(payload);
475
476 vec[0].iov_base = &tag;
477 vec[0].iov_len = sizeof(tag);
478 vec[1].iov_base = &type;
479 vec[1].iov_len = sizeof(type);
480 vec[2].iov_base = &len;
481 vec[2].iov_len = sizeof(len);
482 vec[3].iov_base = (void*)payload;
483 vec[3].iov_len = len;
484
485 return write_to_log(LOG_ID_EVENTS, vec, 4);
486}
487
488/*
489 * Like __android_log_security_bwrite, but used for writing strings to the
490 * security log.
491 */
492LIBLOG_ABI_PUBLIC int __android_log_security_bswrite(int32_t tag,
493 const char *payload)
494{
495 struct iovec vec[4];
496 char type = EVENT_TYPE_STRING;
497 uint32_t len = strlen(payload);
498
499 vec[0].iov_base = &tag;
500 vec[0].iov_len = sizeof(tag);
501 vec[1].iov_base = &type;
502 vec[1].iov_len = sizeof(type);
503 vec[2].iov_base = &len;
504 vec[2].iov_len = sizeof(len);
505 vec[3].iov_base = (void*)payload;
506 vec[3].iov_len = len;
507
508 return write_to_log(LOG_ID_SECURITY, vec, 4);
509}