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;
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; }