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 <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
52static 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
119LIBLOG_ABI_PUBLIC int __android_log_dev_available()
120{
121    struct android_log_transport_write *node;
122
123    if (list_empty(&__android_log_transport_write)) {
124        return kLogUninitialized;
125    }
126
127    write_transport_for_each(node, &__android_log_transport_write) {
128        __android_log_cache_available(node);
129        if (node->logMask) {
130            return kLogAvailable;
131        }
132    }
133    return kLogNotAvailable;
134}
135/*
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}
170
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) {
180        __android_log_cache_available(transport);
181        if (!transport->logMask) {
182            list_remove(&transport->node);
183            continue;
184        }
185        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) {
195        __android_log_cache_available(transport);
196        if (!transport->logMask) {
197            list_remove(&transport->node);
198            continue;
199        }
200        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) {
240        if (vec[0].iov_len < 4) {
241            return -EINVAL;
242        }
243
244        ret = check_log_uid_permissions();
245        if (ret < 0) {
246            return ret;
247        }
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;
338    i = 1 << log_id;
339    write_transport_for_each(node, &__android_log_transport_write) {
340        if (node->logMask & i) {
341            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) {
350        if (node->logMask & i) {
351            (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
420    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;
426
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}
584