Home | History | Annotate | Download | only in logd
      1 /*
      2  * Copyright (C) 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 
     17 #include <ctype.h>
     18 #include <endian.h>
     19 #include <errno.h>
     20 #include <limits.h>
     21 #include <stdarg.h>
     22 #include <stdlib.h>
     23 #include <string.h>
     24 #include <sys/prctl.h>
     25 #include <sys/uio.h>
     26 #include <syslog.h>
     27 
     28 #include <log/logger.h>
     29 #include <private/android_filesystem_config.h>
     30 #include <private/android_logger.h>
     31 
     32 #include "libaudit.h"
     33 #include "LogAudit.h"
     34 #include "LogBuffer.h"
     35 #include "LogKlog.h"
     36 #include "LogReader.h"
     37 
     38 #define KMSG_PRIORITY(PRI)                          \
     39     '<',                                            \
     40     '0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) / 10, \
     41     '0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) % 10, \
     42     '>'
     43 
     44 LogAudit::LogAudit(LogBuffer *buf, LogReader *reader, int fdDmesg) :
     45         SocketListener(getLogSocket(), false),
     46         logbuf(buf),
     47         reader(reader),
     48         fdDmesg(fdDmesg),
     49         initialized(false) {
     50     static const char auditd_message[] = { KMSG_PRIORITY(LOG_INFO),
     51         'l', 'o', 'g', 'd', '.', 'a', 'u', 'd', 'i', 't', 'd', ':',
     52         ' ', 's', 't', 'a', 'r', 't', '\n' };
     53     write(fdDmesg, auditd_message, sizeof(auditd_message));
     54 }
     55 
     56 bool LogAudit::onDataAvailable(SocketClient *cli) {
     57     if (!initialized) {
     58         prctl(PR_SET_NAME, "logd.auditd");
     59         initialized = true;
     60     }
     61 
     62     struct audit_message rep;
     63 
     64     rep.nlh.nlmsg_type = 0;
     65     rep.nlh.nlmsg_len = 0;
     66     rep.data[0] = '\0';
     67 
     68     if (audit_get_reply(cli->getSocket(), &rep, GET_REPLY_BLOCKING, 0) < 0) {
     69         SLOGE("Failed on audit_get_reply with error: %s", strerror(errno));
     70         return false;
     71     }
     72 
     73     logPrint("type=%d %.*s",
     74         rep.nlh.nlmsg_type, rep.nlh.nlmsg_len, rep.data);
     75 
     76     return true;
     77 }
     78 
     79 int LogAudit::logPrint(const char *fmt, ...) {
     80     if (fmt == NULL) {
     81         return -EINVAL;
     82     }
     83 
     84     va_list args;
     85 
     86     char *str = NULL;
     87     va_start(args, fmt);
     88     int rc = vasprintf(&str, fmt, args);
     89     va_end(args);
     90 
     91     if (rc < 0) {
     92         return rc;
     93     }
     94 
     95     char *cp;
     96     while ((cp = strstr(str, "  "))) {
     97         memmove(cp, cp + 1, strlen(cp + 1) + 1);
     98     }
     99 
    100     bool info = strstr(str, " permissive=1") || strstr(str, " policy loaded ");
    101     if ((fdDmesg >= 0) && initialized) {
    102         struct iovec iov[3];
    103         static const char log_info[] = { KMSG_PRIORITY(LOG_INFO) };
    104         static const char log_warning[] = { KMSG_PRIORITY(LOG_WARNING) };
    105 
    106         iov[0].iov_base = info ? const_cast<char *>(log_info)
    107                                : const_cast<char *>(log_warning);
    108         iov[0].iov_len = info ? sizeof(log_info) : sizeof(log_warning);
    109         iov[1].iov_base = str;
    110         iov[1].iov_len = strlen(str);
    111         iov[2].iov_base = const_cast<char *>("\n");
    112         iov[2].iov_len = 1;
    113 
    114         writev(fdDmesg, iov, sizeof(iov) / sizeof(iov[0]));
    115     }
    116 
    117     pid_t pid = getpid();
    118     pid_t tid = gettid();
    119     uid_t uid = AID_LOGD;
    120     log_time now;
    121 
    122     static const char audit_str[] = " audit(";
    123     char *timeptr = strstr(str, audit_str);
    124     if (timeptr
    125             && ((cp = now.strptime(timeptr + sizeof(audit_str) - 1, "%s.%q")))
    126             && (*cp == ':')) {
    127         memcpy(timeptr + sizeof(audit_str) - 1, "0.0", 3);
    128         memmove(timeptr + sizeof(audit_str) - 1 + 3, cp, strlen(cp) + 1);
    129         if (!isMonotonic()) {
    130             if (android::isMonotonic(now)) {
    131                 LogKlog::convertMonotonicToReal(now);
    132             }
    133         } else {
    134             if (!android::isMonotonic(now)) {
    135                 LogKlog::convertRealToMonotonic(now);
    136             }
    137         }
    138     } else if (isMonotonic()) {
    139         now = log_time(CLOCK_MONOTONIC);
    140     } else {
    141         now = log_time(CLOCK_REALTIME);
    142     }
    143 
    144     static const char pid_str[] = " pid=";
    145     char *pidptr = strstr(str, pid_str);
    146     if (pidptr && isdigit(pidptr[sizeof(pid_str) - 1])) {
    147         cp = pidptr + sizeof(pid_str) - 1;
    148         pid = 0;
    149         while (isdigit(*cp)) {
    150             pid = (pid * 10) + (*cp - '0');
    151             ++cp;
    152         }
    153         tid = pid;
    154         logbuf->lock();
    155         uid = logbuf->pidToUid(pid);
    156         logbuf->unlock();
    157         memmove(pidptr, cp, strlen(cp) + 1);
    158     }
    159 
    160     // log to events
    161 
    162     size_t l = strnlen(str, LOGGER_ENTRY_MAX_PAYLOAD);
    163     size_t n = l + sizeof(android_log_event_string_t);
    164 
    165     bool notify = false;
    166 
    167     {   // begin scope for event buffer
    168         uint32_t buffer[(n + sizeof(uint32_t) - 1) / sizeof(uint32_t)];
    169 
    170         android_log_event_string_t *event
    171             = reinterpret_cast<android_log_event_string_t *>(buffer);
    172         event->header.tag = htole32(AUDITD_LOG_TAG);
    173         event->type = EVENT_TYPE_STRING;
    174         event->length = htole32(l);
    175         memcpy(event->data, str, l);
    176 
    177         rc = logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid,
    178                          reinterpret_cast<char *>(event),
    179                          (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
    180         if (rc >= 0) {
    181             notify = true;
    182         }
    183         // end scope for event buffer
    184     }
    185 
    186     // log to main
    187 
    188     static const char comm_str[] = " comm=\"";
    189     const char *comm = strstr(str, comm_str);
    190     const char *estr = str + strlen(str);
    191     const char *commfree = NULL;
    192     if (comm) {
    193         estr = comm;
    194         comm += sizeof(comm_str) - 1;
    195     } else if (pid == getpid()) {
    196         pid = tid;
    197         comm = "auditd";
    198     } else {
    199         logbuf->lock();
    200         comm = commfree = logbuf->pidToName(pid);
    201         logbuf->unlock();
    202         if (!comm) {
    203             comm = "unknown";
    204         }
    205     }
    206 
    207     const char *ecomm = strchr(comm, '"');
    208     if (ecomm) {
    209         ++ecomm;
    210         l = ecomm - comm;
    211     } else {
    212         l = strlen(comm) + 1;
    213         ecomm = "";
    214     }
    215     size_t b = estr - str;
    216     if (b > LOGGER_ENTRY_MAX_PAYLOAD) {
    217         b = LOGGER_ENTRY_MAX_PAYLOAD;
    218     }
    219     size_t e = strnlen(ecomm, LOGGER_ENTRY_MAX_PAYLOAD - b);
    220     n = b + e + l + 2;
    221 
    222     {   // begin scope for main buffer
    223         char newstr[n];
    224 
    225         *newstr = info ? ANDROID_LOG_INFO : ANDROID_LOG_WARN;
    226         strlcpy(newstr + 1, comm, l);
    227         strncpy(newstr + 1 + l, str, b);
    228         strncpy(newstr + 1 + l + b, ecomm, e);
    229 
    230         rc = logbuf->log(LOG_ID_MAIN, now, uid, pid, tid, newstr,
    231                          (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
    232 
    233         if (rc >= 0) {
    234             notify = true;
    235         }
    236         // end scope for main buffer
    237     }
    238 
    239     free(const_cast<char *>(commfree));
    240     free(str);
    241 
    242     if (notify) {
    243         reader->notifyNewLog();
    244         if (rc < 0) {
    245             rc = n;
    246         }
    247     }
    248 
    249     return rc;
    250 }
    251 
    252 int LogAudit::log(char *buf, size_t len) {
    253     char *audit = strstr(buf, " audit(");
    254     if (!audit || (audit >= &buf[len])) {
    255         return 0;
    256     }
    257 
    258     *audit = '\0';
    259 
    260     int rc;
    261     char *type = strstr(buf, "type=");
    262     if (type && (type < &buf[len])) {
    263         rc = logPrint("%s %s", type, audit + 1);
    264     } else {
    265         rc = logPrint("%s", audit + 1);
    266     }
    267     *audit = ' ';
    268     return rc;
    269 }
    270 
    271 int LogAudit::getLogSocket() {
    272     int fd = audit_open();
    273     if (fd < 0) {
    274         return fd;
    275     }
    276     if (audit_setup(fd, getpid()) < 0) {
    277         audit_close(fd);
    278         fd = -1;
    279     }
    280     return fd;
    281 }
    282