10175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn/*
20175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * Copyright (C) 2012-2014 The Android Open Source Project
30175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn *
40175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * Licensed under the Apache License, Version 2.0 (the "License");
50175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * you may not use this file except in compliance with the License.
60175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * You may obtain a copy of the License at
70175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn *
80175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn *      http://www.apache.org/licenses/LICENSE-2.0
90175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn *
100175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * Unless required by applicable law or agreed to in writing, software
110175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * distributed under the License is distributed on an "AS IS" BASIS,
120175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * See the License for the specific language governing permissions and
140175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn * limitations under the License.
150175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn */
160175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
17e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn#include <limits.h>
188daa9af02dc0e63ce220e3fa95bf5fe4d6b7a99aMark Salyzyn#include <sys/prctl.h>
190175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <sys/socket.h>
200175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <sys/types.h>
210175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <sys/un.h>
220175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <unistd.h>
230175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
240175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <cutils/sockets.h>
250175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include <log/logger.h>
26e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn#include <private/android_filesystem_config.h>
27b5f6e45d6bddd2f6262bf387c3314dc744896320Mark Salyzyn#include <private/android_logger.h>
280175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
290175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn#include "LogListener.h"
300175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
3166091f11f427587bf810d89b0f64be556e1cd168Mark SalyzynLogListener::LogListener(LogBuffer *buf, LogReader *reader) :
3266091f11f427587bf810d89b0f64be556e1cd168Mark Salyzyn        SocketListener(getLogSocket(), false),
3366091f11f427587bf810d89b0f64be556e1cd168Mark Salyzyn        logbuf(buf),
3466091f11f427587bf810d89b0f64be556e1cd168Mark Salyzyn        reader(reader) {
3566091f11f427587bf810d89b0f64be556e1cd168Mark Salyzyn}
360175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
370175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzynbool LogListener::onDataAvailable(SocketClient *cli) {
38e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn    static bool name_set;
39e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn    if (!name_set) {
40e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn        prctl(PR_SET_NAME, "logd.writer");
41e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn        name_set = true;
42e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn    }
438daa9af02dc0e63ce220e3fa95bf5fe4d6b7a99aMark Salyzyn
448444eb81b37991ce0fc4ae1d8d79b01688a02426Mark Salyzyn    char buffer[sizeof_log_id_t + sizeof(uint16_t) + sizeof(log_time)
45b059cf53c9185702e99345b7319bcb075ffc5beeMark Salyzyn        + LOGGER_ENTRY_MAX_PAYLOAD];
460175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    struct iovec iov = { buffer, sizeof(buffer) };
470175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    memset(buffer, 0, sizeof(buffer));
480175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
490175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    char control[CMSG_SPACE(sizeof(struct ucred))];
500175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    struct msghdr hdr = {
510175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        NULL,
520175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        0,
530175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        &iov,
540175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        1,
550175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        control,
560175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        sizeof(control),
570175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        0,
580175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    };
590175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
600175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    int socket = cli->getSocket();
610175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
620175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    ssize_t n = recvmsg(socket, &hdr, 0);
63b5f6e45d6bddd2f6262bf387c3314dc744896320Mark Salyzyn    if (n <= (ssize_t)(sizeof(android_log_header_t))) {
640175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        return false;
650175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    }
660175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
670175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    struct ucred *cred = NULL;
680175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
690175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    struct cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr);
700175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    while (cmsg != NULL) {
710175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        if (cmsg->cmsg_level == SOL_SOCKET
720175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn                && cmsg->cmsg_type  == SCM_CREDENTIALS) {
730175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn            cred = (struct ucred *)CMSG_DATA(cmsg);
740175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn            break;
750175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        }
760175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        cmsg = CMSG_NXTHDR(&hdr, cmsg);
770175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    }
780175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
790175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    if (cred == NULL) {
800175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        return false;
810175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    }
820175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
83e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn    if (cred->uid == AID_LOGD) {
840175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        // ignore log messages we send to ourself.
850175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        // Such log messages are often generated by libraries we depend on
860175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        // which use standard Android logging.
870175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        return false;
880175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    }
890175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
90b5f6e45d6bddd2f6262bf387c3314dc744896320Mark Salyzyn    android_log_header_t *header = reinterpret_cast<android_log_header_t *>(buffer);
91a1aacb71f387c91d5fe383b8aaa5b0be2ec9cd3cMark Salyzyn    if (/* header->id < LOG_ID_MIN || */ header->id >= LOG_ID_MAX || header->id == LOG_ID_KERNEL) {
920175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        return false;
930175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    }
940175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
95b5f6e45d6bddd2f6262bf387c3314dc744896320Mark Salyzyn    char *msg = ((char *)buffer) + sizeof(android_log_header_t);
96b5f6e45d6bddd2f6262bf387c3314dc744896320Mark Salyzyn    n -= sizeof(android_log_header_t);
970175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
9822e287df0dfbc6e10c02f570d2fc0c42a2a6b7aaMark Salyzyn    // NB: hdr.msg_flags & MSG_TRUNC is not tested, silently passing a
9922e287df0dfbc6e10c02f570d2fc0c42a2a6b7aaMark Salyzyn    // truncated message to the logs.
100e0fa291e898b451dc198ed52cebac3ffefac066eMark Salyzyn
101202e153f94a0957185ae4b4bed4c5356513e4322Mark Salyzyn    if (logbuf->log((log_id_t)header->id, header->realtime,
102202e153f94a0957185ae4b4bed4c5356513e4322Mark Salyzyn            cred->uid, cred->pid, header->tid, msg,
103202e153f94a0957185ae4b4bed4c5356513e4322Mark Salyzyn            ((size_t) n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX) >= 0) {
104202e153f94a0957185ae4b4bed4c5356513e4322Mark Salyzyn        reader->notifyNewLog();
105202e153f94a0957185ae4b4bed4c5356513e4322Mark Salyzyn    }
1060175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
1070175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    return true;
1080175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn}
1090175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn
1100175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzynint LogListener::getLogSocket() {
111dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn    static const char socketName[] = "logdw";
112dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn    int sock = android_get_control_socket(socketName);
113dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn
114dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn    if (sock < 0) {
115dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn        sock = socket_local_server(socketName,
116dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn                                   ANDROID_SOCKET_NAMESPACE_RESERVED,
117dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn                                   SOCK_DGRAM);
118dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn    }
119dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn
1200175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    int on = 1;
1210175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    if (setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
1220175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn        return -1;
1230175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    }
1240175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn    return sock;
1250175b0747a1f55329109e84c9a1322dcb95e2848Mark Salyzyn}
126