Exemple #1
0
void android::prdebug(const char* fmt, ...) {
    if (fdDmesg < 0) {
        return;
    }

    static const char message[] = {
        KMSG_PRIORITY(LOG_DEBUG), 'l', 'o', 'g', 'd', ':', ' '
    };
    char buffer[256];
    memcpy(buffer, message, sizeof(message));

    va_list ap;
    va_start(ap, fmt);
    int n = vsnprintf(buffer + sizeof(message),
                      sizeof(buffer) - sizeof(message), fmt, ap);
    va_end(ap);
    if (n > 0) {
        buffer[sizeof(buffer) - 1] = '\0';
        if (!strchr(buffer, '\n')) {
            buffer[sizeof(buffer) - 2] = '\0';
            strlcat(buffer, "\n", sizeof(buffer));
        }
        write(fdDmesg, buffer, strlen(buffer));
    }
}
LogAudit::LogAudit(LogBuffer* buf, LogReader* reader, int fdDmesg)
    : SocketListener(getLogSocket(), false),
      logbuf(buf),
      reader(reader),
      fdDmesg(fdDmesg),
      main(__android_logger_property_get_bool("ro.logd.auditd.main",
                                              BOOL_DEFAULT_TRUE)),
      events(__android_logger_property_get_bool("ro.logd.auditd.events",
                                                BOOL_DEFAULT_TRUE)),
      initialized(false) {
    static const char auditd_message[] = { KMSG_PRIORITY(LOG_INFO),
                                           'l',
                                           'o',
                                           'g',
                                           'd',
                                           '.',
                                           'a',
                                           'u',
                                           'd',
                                           'i',
                                           't',
                                           'd',
                                           ':',
                                           ' ',
                                           's',
                                           't',
                                           'a',
                                           'r',
                                           't',
                                           '\n' };
    write(fdDmesg, auditd_message, sizeof(auditd_message));
}
static void *reinit_thread_start(void * /*obj*/) {
    prctl(PR_SET_NAME, "logd.daemon");
    set_sched_policy(0, SP_BACKGROUND);
    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND);

    setgid(AID_SYSTEM);
    setuid(AID_SYSTEM);

    while (reinit_running && !sem_wait(&reinit) && reinit_running) {

        // uidToName Privileged Worker
        if (uid) {
            name = NULL;

            FILE *fp = fopen("/data/system/packages.list", "r");
            if (fp) {
                // This simple parser is sensitive to format changes in
                // frameworks/base/services/core/java/com/android/server/pm/Settings.java
                // A dependency note has been added to that file to correct
                // this parser.

                char *buffer = NULL;
                size_t len;
                while (getline(&buffer, &len, fp) > 0) {
                    char *userId = strchr(buffer, ' ');
                    if (!userId) {
                        continue;
                    }
                    *userId = '\0';
                    unsigned long value = strtoul(userId + 1, NULL, 10);
                    if (value != uid) {
                        continue;
                    }
                    name = strdup(buffer);
                    break;
                }
                free(buffer);
                fclose(fp);
            }
            uid = 0;
            sem_post(&uidName);
            continue;
        }

        if (fdDmesg >= 0) {
            static const char reinit_message[] = { KMSG_PRIORITY(LOG_INFO),
                'l', 'o', 'g', 'd', '.', 'd', 'a', 'e', 'm', 'o', 'n', ':',
                ' ', 'r', 'e', 'i', 'n', 'i', 't', '\n' };
            write(fdDmesg, reinit_message, sizeof(reinit_message));
        }

        // Anything that reads persist.<property>
        if (logBuf) {
            logBuf->init();
        }
    }

    return NULL;
}
void LogAudit::logToDmesg(const std::string& str)
{
    static const char prefix[] = { KMSG_PRIORITY(LOG_INFO),
        'l', 'o', 'g', 'd', '.', 'a', 'u', 'd', 'i', 't', 'd', ':',
        ' ', '\0' };
    std::string message = prefix + str + "\n";
    write(fdDmesg, message.c_str(), message.length());
}
static void *reinit_thread_start(void * /*obj*/) {
    prctl(PR_SET_NAME, "logd.daemon");
    set_sched_policy(0, SP_BACKGROUND);
    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND);

    setgid(AID_SYSTEM);
    setuid(AID_SYSTEM);

    while (reinit_running && !sem_wait(&reinit) && reinit_running) {

        // uidToName Privileged Worker
        if (uid) {
            name = NULL;

            packagelist_parse(package_list_parser_cb, NULL);

            uid = 0;
            sem_post(&uidName);
            continue;
        }

        if (fdDmesg >= 0) {
            static const char reinit_message[] = { KMSG_PRIORITY(LOG_INFO),
                'l', 'o', 'g', 'd', '.', 'd', 'a', 'e', 'm', 'o', 'n', ':',
                ' ', 'r', 'e', 'i', 'n', 'i', 't', '\n' };
            write(fdDmesg, reinit_message, sizeof(reinit_message));
        }

        // Anything that reads persist.<property>
        if (logBuf) {
            logBuf->init();
            logBuf->initPrune(NULL);
        }

        if (logAudit) {
            logAudit->allowSafeMode();
        }
    }

    return NULL;
}
#include <sys/uio.h>
#include <syslog.h>

#include <log/logger.h>

#include "LogBuffer.h"
#include "LogKlog.h"
#include "LogReader.h"

#define KMSG_PRIORITY(PRI)           \
    '<',                             \
    '0' + (LOG_SYSLOG | (PRI)) / 10, \
    '0' + (LOG_SYSLOG | (PRI)) % 10, \
    '>'

static const char priority_message[] = { KMSG_PRIORITY(LOG_INFO), '\0' };

// Parsing is hard

// called if we see a '<', s is the next character, returns pointer after '>'
static char *is_prio(char *s, size_t len) {
    if (!len || !isdigit(*s++)) {
        return NULL;
    }
    --len;
    static const size_t max_prio_len = (len < 4) ? len : 4;
    size_t priolen = 0;
    char c;
    while (((c = *s++)) && (++priolen <= max_prio_len)) {
        if (!isdigit(c)) {
            return ((c == '>') && (*s == '[')) ? s : NULL;
Exemple #7
0
static void* reinit_thread_start(void* /*obj*/) {
    prctl(PR_SET_NAME, "logd.daemon");
    set_sched_policy(0, SP_BACKGROUND);
    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND);

    // We should drop to AID_LOGD, if we are anything else, we have
    // even lesser privileges and accept our fate.
    gid_t groups[] = {
        AID_SYSTEM,        // search access to /data/system path
        AID_PACKAGE_INFO,  // readonly access to /data/system/packages.list
    };
    if (setgroups(arraysize(groups), groups) == -1) {
        android::prdebug(
            "logd.daemon: failed to set AID_SYSTEM AID_PACKAGE_INFO groups");
    }
    if (setgid(AID_LOGD) != 0) {
        android::prdebug("logd.daemon: failed to set AID_LOGD gid");
    }
    if (setuid(AID_LOGD) != 0) {
        android::prdebug("logd.daemon: failed to set AID_LOGD uid");
    }

    cap_t caps = cap_init();
    (void)cap_clear(caps);
    (void)cap_set_proc(caps);
    (void)cap_free(caps);

    while (reinit_running && !sem_wait(&reinit) && reinit_running) {
        // uidToName Privileged Worker
        if (uid) {
            name = nullptr;

            // if we got the perms wrong above, this would spam if we reported
            // problems with acquisition of an uid name from the packages.
            (void)packagelist_parse(package_list_parser_cb, nullptr);

            uid = 0;
            sem_post(&uidName);
            continue;
        }

        if (fdDmesg >= 0) {
            static const char reinit_message[] = { KMSG_PRIORITY(LOG_INFO),
                                                   'l',
                                                   'o',
                                                   'g',
                                                   'd',
                                                   '.',
                                                   'd',
                                                   'a',
                                                   'e',
                                                   'm',
                                                   'o',
                                                   'n',
                                                   ':',
                                                   ' ',
                                                   'r',
                                                   'e',
                                                   'i',
                                                   'n',
                                                   'i',
                                                   't',
                                                   '\n' };
            write(fdDmesg, reinit_message, sizeof(reinit_message));
        }

        // Anything that reads persist.<property>
        if (logBuf) {
            logBuf->init();
            logBuf->initPrune(nullptr);
        }
        android::ReReadEventLogTags();
    }

    return nullptr;
}
int LogAudit::logPrint(const char *fmt, ...) {
    if (fmt == NULL) {
        return -EINVAL;
    }

    va_list args;

    char *str = NULL;
    va_start(args, fmt);
    int rc = vasprintf(&str, fmt, args);
    va_end(args);

    if (rc < 0) {
        return rc;
    }

    char *cp;
    while ((cp = strstr(str, "  "))) {
        memmove(cp, cp + 1, strlen(cp + 1) + 1);
    }

    bool loaded = strstr(str, " policy loaded ");

    if (loaded) {
        if (policyLoaded) {
            // SELinux policy changes are not allowed
            enforceIntegrity();
        } else {
            logToDmesg("policy loaded");
            policyLoaded = true;
        }
    }

    bool permissive = strstr(str, " enforcing=0") ||
                      strstr(str, " permissive=1");

    if (permissive) {
        // SELinux in permissive mode is not allowed
        enforceIntegrity();
    }

    bool info = loaded || permissive;
    if ((fdDmesg >= 0) && initialized) {
        struct iovec iov[3];
        static const char log_info[] = { KMSG_PRIORITY(LOG_INFO) };
        static const char log_warning[] = { KMSG_PRIORITY(LOG_WARNING) };

        iov[0].iov_base = info ? const_cast<char *>(log_info)
                               : const_cast<char *>(log_warning);
        iov[0].iov_len = info ? sizeof(log_info) : sizeof(log_warning);
        iov[1].iov_base = str;
        iov[1].iov_len = strlen(str);
        iov[2].iov_base = const_cast<char *>("\n");
        iov[2].iov_len = 1;

        writev(fdDmesg, iov, sizeof(iov) / sizeof(iov[0]));
    }

    pid_t pid = getpid();
    pid_t tid = gettid();
    uid_t uid = AID_LOGD;
    log_time now;

    static const char audit_str[] = " audit(";
    char *timeptr = strstr(str, audit_str);
    if (timeptr
            && ((cp = now.strptime(timeptr + sizeof(audit_str) - 1, "%s.%q")))
            && (*cp == ':')) {
        memcpy(timeptr + sizeof(audit_str) - 1, "0.0", 3);
        memmove(timeptr + sizeof(audit_str) - 1 + 3, cp, strlen(cp) + 1);
        if (!isMonotonic()) {
            if (android::isMonotonic(now)) {
                LogKlog::convertMonotonicToReal(now);
            }
        } else {
            if (!android::isMonotonic(now)) {
                LogKlog::convertRealToMonotonic(now);
            }
        }
    } else if (isMonotonic()) {
        now = log_time(CLOCK_MONOTONIC);
    } else {
        now = log_time(CLOCK_REALTIME);
    }

    static const char pid_str[] = " pid=";
    char *pidptr = strstr(str, pid_str);
    if (pidptr && isdigit(pidptr[sizeof(pid_str) - 1])) {
        cp = pidptr + sizeof(pid_str) - 1;
        pid = 0;
        while (isdigit(*cp)) {
            pid = (pid * 10) + (*cp - '0');
            ++cp;
        }
        tid = pid;
        logbuf->lock();
        uid = logbuf->pidToUid(pid);
        logbuf->unlock();
        memmove(pidptr, cp, strlen(cp) + 1);
    }

    // log to events

    size_t l = strnlen(str, LOGGER_ENTRY_MAX_PAYLOAD);
    size_t n = l + sizeof(android_log_event_string_t);

    bool notify = false;

    {   // begin scope for event buffer
        uint32_t buffer[(n + sizeof(uint32_t) - 1) / sizeof(uint32_t)];

        android_log_event_string_t *event
            = reinterpret_cast<android_log_event_string_t *>(buffer);
        event->header.tag = htole32(AUDITD_LOG_TAG);
        event->type = EVENT_TYPE_STRING;
        event->length = htole32(l);
        memcpy(event->data, str, l);

        rc = logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid,
                         reinterpret_cast<char *>(event),
                         (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
        if (rc >= 0) {
            notify = true;
        }
        // end scope for event buffer
    }

    // log to main

    static const char comm_str[] = " comm=\"";
    const char *comm = strstr(str, comm_str);
    const char *estr = str + strlen(str);
    const char *commfree = NULL;
    if (comm) {
        estr = comm;
        comm += sizeof(comm_str) - 1;
    } else if (pid == getpid()) {
        pid = tid;
        comm = "auditd";
    } else {
        logbuf->lock();
        comm = commfree = logbuf->pidToName(pid);
        logbuf->unlock();
        if (!comm) {
            comm = "unknown";
        }
    }

    const char *ecomm = strchr(comm, '"');
    if (ecomm) {
        ++ecomm;
        l = ecomm - comm;
    } else {
        l = strlen(comm) + 1;
        ecomm = "";
    }
    size_t b = estr - str;
    if (b > LOGGER_ENTRY_MAX_PAYLOAD) {
        b = LOGGER_ENTRY_MAX_PAYLOAD;
    }
    size_t e = strnlen(ecomm, LOGGER_ENTRY_MAX_PAYLOAD - b);
    n = b + e + l + 2;

    {   // begin scope for main buffer
        char newstr[n];

        *newstr = info ? ANDROID_LOG_INFO : ANDROID_LOG_WARN;
        strlcpy(newstr + 1, comm, l);
        strncpy(newstr + 1 + l, str, b);
        strncpy(newstr + 1 + l + b, ecomm, e);

        rc = logbuf->log(LOG_ID_MAIN, now, uid, pid, tid, newstr,
                         (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);

        if (rc >= 0) {
            notify = true;
        }
        // end scope for main buffer
    }

    free(const_cast<char *>(commfree));
    free(str);

    if (notify) {
        reader->notifyNewLog();
        if (rc < 0) {
            rc = n;
        }
    }

    return rc;
}