1/*
2 * Copyright (C) 2007-2014 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#if (FAKE_LOG_DEVICE == 0)
17#include <endian.h>
18#endif
19#include <errno.h>
20#include <fcntl.h>
21#if !defined(_WIN32)
22#include <pthread.h>
23#endif
24#include <stdarg.h>
25#include <stdatomic.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <sys/stat.h>
30#include <sys/types.h>
31#if (FAKE_LOG_DEVICE == 0)
32#include <sys/socket.h>
33#include <sys/un.h>
34#endif
35#include <time.h>
36#include <unistd.h>
37
38#ifdef __BIONIC__
39#include <android/set_abort_message.h>
40#endif
41
42#include <log/logd.h>
43#include <log/logger.h>
44#include <log/log_read.h>
45#include <private/android_filesystem_config.h>
46#include <private/android_logger.h>
47
48#define LOG_BUF_SIZE 1024
49
50#if FAKE_LOG_DEVICE
51/* This will be defined when building for the host. */
52#include "fake_log_device.h"
53#endif
54
55static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr);
56static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;
57#if !defined(_WIN32)
58static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
59#endif
60
61#ifndef __unused
62#define __unused  __attribute__((__unused__))
63#endif
64
65#if FAKE_LOG_DEVICE
66static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1 };
67#else
68static int logd_fd = -1;
69static int pstore_fd = -1;
70#endif
71
72/*
73 * This is used by the C++ code to decide if it should write logs through
74 * the C code.  Basically, if /dev/socket/logd is available, we're running in
75 * the simulator rather than a desktop tool and want to use the device.
76 */
77static enum {
78    kLogUninitialized, kLogNotAvailable, kLogAvailable
79} g_log_status = kLogUninitialized;
80
81int __android_log_dev_available(void)
82{
83    if (g_log_status == kLogUninitialized) {
84        if (access("/dev/socket/logdw", W_OK) == 0)
85            g_log_status = kLogAvailable;
86        else
87            g_log_status = kLogNotAvailable;
88    }
89
90    return (g_log_status == kLogAvailable);
91}
92
93/* log_init_lock assumed */
94static int __write_to_log_initialize()
95{
96    int i, ret = 0;
97
98#if FAKE_LOG_DEVICE
99    for (i = 0; i < LOG_ID_MAX; i++) {
100        char buf[sizeof("/dev/log_system")];
101        snprintf(buf, sizeof(buf), "/dev/log_%s", android_log_id_to_name(i));
102        log_fds[i] = fakeLogOpen(buf, O_WRONLY);
103    }
104#else
105    if (pstore_fd < 0) {
106        pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY));
107    }
108
109    if (logd_fd < 0) {
110        i = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0));
111        if (i < 0) {
112            ret = -errno;
113        } else if (TEMP_FAILURE_RETRY(fcntl(i, F_SETFL, O_NONBLOCK)) < 0) {
114            ret = -errno;
115            close(i);
116        } else {
117            struct sockaddr_un un;
118            memset(&un, 0, sizeof(struct sockaddr_un));
119            un.sun_family = AF_UNIX;
120            strcpy(un.sun_path, "/dev/socket/logdw");
121
122            if (TEMP_FAILURE_RETRY(connect(i, (struct sockaddr *)&un,
123                                           sizeof(struct sockaddr_un))) < 0) {
124                ret = -errno;
125                close(i);
126            } else {
127                logd_fd = i;
128            }
129        }
130    }
131#endif
132
133    return ret;
134}
135
136static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
137{
138    ssize_t ret;
139#if FAKE_LOG_DEVICE
140    int log_fd;
141
142    if (/*(int)log_id >= 0 &&*/ (int)log_id < (int)LOG_ID_MAX) {
143        log_fd = log_fds[(int)log_id];
144    } else {
145        return -EBADF;
146    }
147    do {
148        ret = fakeLogWritev(log_fd, vec, nr);
149        if (ret < 0) {
150            ret = -errno;
151        }
152    } while (ret == -EINTR);
153#else
154    static const unsigned header_length = 2;
155    struct iovec newVec[nr + header_length];
156    android_log_header_t header;
157    android_pmsg_log_header_t pmsg_header;
158    struct timespec ts;
159    size_t i, payload_size;
160    static uid_t last_uid = AID_ROOT; /* logd *always* starts up as AID_ROOT */
161    static pid_t last_pid = (pid_t) -1;
162    static atomic_int_fast32_t dropped;
163
164    if (!nr) {
165        return -EINVAL;
166    }
167
168    if (last_uid == AID_ROOT) { /* have we called to get the UID yet? */
169        last_uid = getuid();
170    }
171    if (last_pid == (pid_t) -1) {
172        last_pid = getpid();
173    }
174    /*
175     *  struct {
176     *      // what we provide to pstore
177     *      android_pmsg_log_header_t pmsg_header;
178     *      // what we provide to socket
179     *      android_log_header_t header;
180     *      // caller provides
181     *      union {
182     *          struct {
183     *              char     prio;
184     *              char     payload[];
185     *          } string;
186     *          struct {
187     *              uint32_t tag
188     *              char     payload[];
189     *          } binary;
190     *      };
191     *  };
192     */
193
194    clock_gettime(CLOCK_REALTIME, &ts);
195
196    pmsg_header.magic = LOGGER_MAGIC;
197    pmsg_header.len = sizeof(pmsg_header) + sizeof(header);
198    pmsg_header.uid = last_uid;
199    pmsg_header.pid = last_pid;
200
201    header.tid = gettid();
202    header.realtime.tv_sec = ts.tv_sec;
203    header.realtime.tv_nsec = ts.tv_nsec;
204
205    newVec[0].iov_base   = (unsigned char *) &pmsg_header;
206    newVec[0].iov_len    = sizeof(pmsg_header);
207    newVec[1].iov_base   = (unsigned char *) &header;
208    newVec[1].iov_len    = sizeof(header);
209
210    if (logd_fd > 0) {
211        int32_t snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
212        if (snapshot) {
213            android_log_event_int_t buffer;
214
215            header.id = LOG_ID_EVENTS;
216            buffer.header.tag = htole32(LIBLOG_LOG_TAG);
217            buffer.payload.type = EVENT_TYPE_INT;
218            buffer.payload.data = htole32(snapshot);
219
220            newVec[2].iov_base = &buffer;
221            newVec[2].iov_len  = sizeof(buffer);
222
223            ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, 2));
224            if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
225                atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed);
226            }
227        }
228    }
229
230    header.id = log_id;
231
232    for (payload_size = 0, i = header_length; i < nr + header_length; i++) {
233        newVec[i].iov_base = vec[i - header_length].iov_base;
234        payload_size += newVec[i].iov_len = vec[i - header_length].iov_len;
235
236        if (payload_size > LOGGER_ENTRY_MAX_PAYLOAD) {
237            newVec[i].iov_len -= payload_size - LOGGER_ENTRY_MAX_PAYLOAD;
238            if (newVec[i].iov_len) {
239                ++i;
240            }
241            payload_size = LOGGER_ENTRY_MAX_PAYLOAD;
242            break;
243        }
244    }
245    pmsg_header.len += payload_size;
246
247    if (pstore_fd >= 0) {
248        TEMP_FAILURE_RETRY(writev(pstore_fd, newVec, i));
249    }
250
251    if (last_uid == AID_LOGD) { /* logd, after initialization and priv drop */
252        /*
253         * ignore log messages we send to ourself (logd).
254         * Such log messages are often generated by libraries we depend on
255         * which use standard Android logging.
256         */
257        return 0;
258    }
259
260    if (logd_fd < 0) {
261        return -EBADF;
262    }
263
264    /*
265     * The write below could be lost, but will never block.
266     *
267     * To logd, we drop the pmsg_header
268     *
269     * ENOTCONN occurs if logd dies.
270     * EAGAIN occurs if logd is overloaded.
271     */
272    ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1));
273    if (ret < 0) {
274        ret = -errno;
275        if (ret == -ENOTCONN) {
276#if !defined(_WIN32)
277            pthread_mutex_lock(&log_init_lock);
278#endif
279            close(logd_fd);
280            logd_fd = -1;
281            ret = __write_to_log_initialize();
282#if !defined(_WIN32)
283            pthread_mutex_unlock(&log_init_lock);
284#endif
285
286            if (ret < 0) {
287                return ret;
288            }
289
290            ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1));
291            if (ret < 0) {
292                ret = -errno;
293            }
294        }
295    }
296
297    if (ret > (ssize_t)sizeof(header)) {
298        ret -= sizeof(header);
299    } else if (ret == -EAGAIN) {
300        atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
301    }
302#endif
303
304    return ret;
305}
306
307#if FAKE_LOG_DEVICE
308static const char *LOG_NAME[LOG_ID_MAX] = {
309    [LOG_ID_MAIN] = "main",
310    [LOG_ID_RADIO] = "radio",
311    [LOG_ID_EVENTS] = "events",
312    [LOG_ID_SYSTEM] = "system",
313    [LOG_ID_CRASH] = "crash",
314    [LOG_ID_KERNEL] = "kernel",
315};
316
317const char *android_log_id_to_name(log_id_t log_id)
318{
319    if (log_id >= LOG_ID_MAX) {
320        log_id = LOG_ID_MAIN;
321    }
322    return LOG_NAME[log_id];
323}
324#endif
325
326static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
327{
328#if !defined(_WIN32)
329    pthread_mutex_lock(&log_init_lock);
330#endif
331
332    if (write_to_log == __write_to_log_init) {
333        int ret;
334
335        ret = __write_to_log_initialize();
336        if (ret < 0) {
337#if !defined(_WIN32)
338            pthread_mutex_unlock(&log_init_lock);
339#endif
340#if (FAKE_LOG_DEVICE == 0)
341            if (pstore_fd >= 0) {
342                __write_to_log_daemon(log_id, vec, nr);
343            }
344#endif
345            return ret;
346        }
347
348        write_to_log = __write_to_log_daemon;
349    }
350
351#if !defined(_WIN32)
352    pthread_mutex_unlock(&log_init_lock);
353#endif
354
355    return write_to_log(log_id, vec, nr);
356}
357
358int __android_log_write(int prio, const char *tag, const char *msg)
359{
360    return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
361}
362
363int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg)
364{
365    struct iovec vec[3];
366    char tmp_tag[32];
367
368    if (!tag)
369        tag = "";
370
371    /* XXX: This needs to go! */
372    if ((bufID != LOG_ID_RADIO) &&
373         (!strcmp(tag, "HTC_RIL") ||
374        !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
375        !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
376        !strcmp(tag, "AT") ||
377        !strcmp(tag, "GSM") ||
378        !strcmp(tag, "STK") ||
379        !strcmp(tag, "CDMA") ||
380        !strcmp(tag, "PHONE") ||
381        !strcmp(tag, "SMS"))) {
382            bufID = LOG_ID_RADIO;
383            /* Inform third party apps/ril/radio.. to use Rlog or RLOG */
384            snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
385            tag = tmp_tag;
386    }
387
388#if __BIONIC__
389    if (prio == ANDROID_LOG_FATAL) {
390        android_set_abort_message(msg);
391    }
392#endif
393
394    vec[0].iov_base   = (unsigned char *) &prio;
395    vec[0].iov_len    = 1;
396    vec[1].iov_base   = (void *) tag;
397    vec[1].iov_len    = strlen(tag) + 1;
398    vec[2].iov_base   = (void *) msg;
399    vec[2].iov_len    = strlen(msg) + 1;
400
401    return write_to_log(bufID, vec, 3);
402}
403
404int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap)
405{
406    char buf[LOG_BUF_SIZE];
407
408    vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
409
410    return __android_log_write(prio, tag, buf);
411}
412
413int __android_log_print(int prio, const char *tag, const char *fmt, ...)
414{
415    va_list ap;
416    char buf[LOG_BUF_SIZE];
417
418    va_start(ap, fmt);
419    vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
420    va_end(ap);
421
422    return __android_log_write(prio, tag, buf);
423}
424
425int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...)
426{
427    va_list ap;
428    char buf[LOG_BUF_SIZE];
429
430    va_start(ap, fmt);
431    vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
432    va_end(ap);
433
434    return __android_log_buf_write(bufID, prio, tag, buf);
435}
436
437void __android_log_assert(const char *cond, const char *tag,
438                          const char *fmt, ...)
439{
440    char buf[LOG_BUF_SIZE];
441
442    if (fmt) {
443        va_list ap;
444        va_start(ap, fmt);
445        vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
446        va_end(ap);
447    } else {
448        /* Msg not provided, log condition.  N.B. Do not use cond directly as
449         * format string as it could contain spurious '%' syntax (e.g.
450         * "%d" in "blocks%devs == 0").
451         */
452        if (cond)
453            snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond);
454        else
455            strcpy(buf, "Unspecified assertion failed");
456    }
457
458    __android_log_write(ANDROID_LOG_FATAL, tag, buf);
459    abort(); /* abort so we have a chance to debug the situation */
460    /* NOTREACHED */
461}
462
463int __android_log_bwrite(int32_t tag, const void *payload, size_t len)
464{
465    struct iovec vec[2];
466
467    vec[0].iov_base = &tag;
468    vec[0].iov_len = sizeof(tag);
469    vec[1].iov_base = (void*)payload;
470    vec[1].iov_len = len;
471
472    return write_to_log(LOG_ID_EVENTS, vec, 2);
473}
474
475/*
476 * Like __android_log_bwrite, but takes the type as well.  Doesn't work
477 * for the general case where we're generating lists of stuff, but very
478 * handy if we just want to dump an integer into the log.
479 */
480int __android_log_btwrite(int32_t tag, char type, const void *payload,
481                          size_t len)
482{
483    struct iovec vec[3];
484
485    vec[0].iov_base = &tag;
486    vec[0].iov_len = sizeof(tag);
487    vec[1].iov_base = &type;
488    vec[1].iov_len = sizeof(type);
489    vec[2].iov_base = (void*)payload;
490    vec[2].iov_len = len;
491
492    return write_to_log(LOG_ID_EVENTS, vec, 3);
493}
494
495/*
496 * Like __android_log_bwrite, but used for writing strings to the
497 * event log.
498 */
499int __android_log_bswrite(int32_t tag, const char *payload)
500{
501    struct iovec vec[4];
502    char type = EVENT_TYPE_STRING;
503    uint32_t len = strlen(payload);
504
505    vec[0].iov_base = &tag;
506    vec[0].iov_len = sizeof(tag);
507    vec[1].iov_base = &type;
508    vec[1].iov_len = sizeof(type);
509    vec[2].iov_base = &len;
510    vec[2].iov_len = sizeof(len);
511    vec[3].iov_base = (void*)payload;
512    vec[3].iov_len = len;
513
514    return write_to_log(LOG_ID_EVENTS, vec, 4);
515}
516