diff options
-rw-r--r-- | logd/LogBuffer.cpp | 2 | ||||
-rw-r--r-- | logd/LogBuffer.h | 1 | ||||
-rw-r--r-- | logd/LogBufferElement.cpp | 104 | ||||
-rw-r--r-- | logd/LogBufferElement.h | 11 | ||||
-rw-r--r-- | logd/LogStatistics.cpp | 2 | ||||
-rw-r--r-- | logd/main.cpp | 13 |
6 files changed, 111 insertions, 22 deletions
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp index 62f29e7..b6b6124 100644 --- a/logd/LogBuffer.cpp +++ b/logd/LogBuffer.cpp @@ -631,7 +631,7 @@ uint64_t LogBuffer::flushTo( pthread_mutex_unlock(&mLogElementsLock); // range locking in LastLogTimes looks after us - max = element->flushTo(reader); + max = element->flushTo(reader, this); if (max == element->FLUSH_ERROR) { return max; diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h index 9ee243d..00b19b6 100644 --- a/logd/LogBuffer.h +++ b/logd/LogBuffer.h @@ -74,6 +74,7 @@ public: // helper char *pidToName(pid_t pid) { return stats.pidToName(pid); } uid_t pidToUid(pid_t pid) { return stats.pidToUid(pid); } + char *uidToName(uid_t uid) { return stats.uidToName(uid); } private: void maybePrune(log_id_t id); diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp index a173e63..6a05700 100644 --- a/logd/LogBufferElement.cpp +++ b/logd/LogBufferElement.cpp @@ -14,7 +14,9 @@ * limitations under the License. */ +#include <ctype.h> #include <endian.h> +#include <fcntl.h> #include <stdio.h> #include <string.h> #include <time.h> @@ -48,18 +50,88 @@ LogBufferElement::~LogBufferElement() { delete [] mMsg; } +// caller must own and free character string +static char *tidToName(pid_t tid) { + char *retval = NULL; + char buffer[256]; + snprintf(buffer, sizeof(buffer), "/proc/%u/comm", tid); + int fd = open(buffer, O_RDONLY); + if (fd >= 0) { + ssize_t ret = read(fd, buffer, sizeof(buffer)); + if (ret >= (ssize_t)sizeof(buffer)) { + ret = sizeof(buffer) - 1; + } + while ((ret > 0) && isspace(buffer[ret - 1])) { + --ret; + } + if (ret > 0) { + buffer[ret] = '\0'; + retval = strdup(buffer); + } + close(fd); + } + + // if nothing for comm, check out cmdline + char *name = android::pidToName(tid); + if (!retval) { + retval = name; + name = NULL; + } + + // check if comm is truncated, see if cmdline has full representation + if (name) { + // impossible for retval to be NULL if name not NULL + size_t retval_len = strlen(retval); + size_t name_len = strlen(name); + // KISS: ToDo: Only checks prefix truncated, not suffix, or both + if ((retval_len < name_len) && !strcmp(retval, name + name_len - retval_len)) { + free(retval); + retval = name; + } else { + free(name); + } + } + return retval; +} + // assumption: mMsg == NULL -size_t LogBufferElement::populateDroppedMessage(char *&buffer, bool privileged) { - static const char format_uid[] = "uid=%u dropped=%u"; - static const size_t unprivileged_offset = 7; +size_t LogBufferElement::populateDroppedMessage(char *&buffer, + LogBuffer *parent) { static const char tag[] = "logd"; + static const char format_uid[] = "uid=%u%s too chatty%s, expire %u line%s"; - size_t len; - if (privileged) { - len = snprintf(NULL, 0, format_uid, mUid, mDropped); - } else { - len = snprintf(NULL, 0, format_uid + unprivileged_offset, mDropped); + char *name = parent->uidToName(mUid); + char *commName = tidToName(mTid); + if (!commName && (mTid != mPid)) { + commName = tidToName(mPid); + } + if (!commName) { + commName = parent->pidToName(mPid); + } + if (name && commName && !strcmp(name, commName)) { + free(commName); + commName = NULL; + } + if (name) { + char *p = NULL; + asprintf(&p, "(%s)", name); + if (p) { + free(name); + name = p; + } + } + if (commName) { + char *p = NULL; + asprintf(&p, " comm=%s", commName); + if (p) { + free(commName); + commName = p; + } } + // identical to below to calculate the buffer size required + size_t len = snprintf(NULL, 0, format_uid, mUid, name ? name : "", + commName ? commName : "", + mDropped, (mDropped > 1) ? "s" : ""); size_t hdrLen; if (mLogId == LOG_ID_EVENTS) { @@ -70,6 +142,8 @@ size_t LogBufferElement::populateDroppedMessage(char *&buffer, bool privileged) buffer = static_cast<char *>(calloc(1, hdrLen + len + 1)); if (!buffer) { + free(name); + free(commName); return 0; } @@ -86,16 +160,16 @@ size_t LogBufferElement::populateDroppedMessage(char *&buffer, bool privileged) strcpy(buffer + 1, tag); } - if (privileged) { - snprintf(buffer + hdrLen, len + 1, format_uid, mUid, mDropped); - } else { - snprintf(buffer + hdrLen, len + 1, format_uid + unprivileged_offset, mDropped); - } + snprintf(buffer + hdrLen, len + 1, format_uid, mUid, name ? name : "", + commName ? commName : "", + mDropped, (mDropped > 1) ? "s" : ""); + free(name); + free(commName); return retval; } -uint64_t LogBufferElement::flushTo(SocketClient *reader) { +uint64_t LogBufferElement::flushTo(SocketClient *reader, LogBuffer *parent) { struct logger_entry_v3 entry; memset(&entry, 0, sizeof(struct logger_entry_v3)); @@ -114,7 +188,7 @@ uint64_t LogBufferElement::flushTo(SocketClient *reader) { char *buffer = NULL; if (!mMsg) { - entry.len = populateDroppedMessage(buffer, clientHasLogCredentials(reader)); + entry.len = populateDroppedMessage(buffer, parent); if (!entry.len) { return mSequence; } diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h index 7b6456d..059c031 100644 --- a/logd/LogBufferElement.h +++ b/logd/LogBufferElement.h @@ -28,15 +28,19 @@ namespace android { // Furnished in main.cpp. Caller must own and free returned value -// This function is designed for a single caller and is NOT thread-safe char *uidToName(uid_t uid); +// Furnished in LogStatistics.cpp. Caller must own and free returned value +char *pidToName(pid_t pid); + } static inline bool worstUidEnabledForLogid(log_id_t id) { return (id != LOG_ID_CRASH) && (id != LOG_ID_EVENTS); } +class LogBuffer; + class LogBufferElement { const log_id_t mLogId; const uid_t mUid; @@ -52,7 +56,8 @@ class LogBufferElement { static atomic_int_fast64_t sequence; // assumption: mMsg == NULL - size_t populateDroppedMessage(char *&buffer, bool privileged); + size_t populateDroppedMessage(char *&buffer, + LogBuffer *parent); public: LogBufferElement(log_id_t log_id, log_time realtime, @@ -78,7 +83,7 @@ public: log_time getRealTime(void) const { return mRealTime; } static const uint64_t FLUSH_ERROR; - uint64_t flushTo(SocketClient *writer); + uint64_t flushTo(SocketClient *writer, LogBuffer *parent); }; #endif diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp index eadc4dd..b063630 100644 --- a/logd/LogStatistics.cpp +++ b/logd/LogStatistics.cpp @@ -39,7 +39,7 @@ LogStatistics::LogStatistics() namespace android { // caller must own and free character string -static char *pidToName(pid_t pid) { +char *pidToName(pid_t pid) { char *retval = NULL; if (pid == 0) { // special case from auditd for kernel retval = strdup("logd.auditd"); diff --git a/logd/main.cpp b/logd/main.cpp index eb29596..237c7c1 100644 --- a/logd/main.cpp +++ b/logd/main.cpp @@ -210,18 +210,26 @@ static void *reinit_thread_start(void * /*obj*/) { return NULL; } +static sem_t sem_name; + char *android::uidToName(uid_t u) { if (!u || !reinit_running) { return NULL; } - // Not multi-thread safe, we know there is only one caller + sem_wait(&sem_name); + + // Not multi-thread safe, we use sem_name to protect uid = u; name = NULL; sem_post(&reinit); sem_wait(&uidName); - return name; + char *ret = name; + + sem_post(&sem_name); + + return ret; } // Serves as a global method to trigger reinitialization @@ -277,6 +285,7 @@ int main(int argc, char *argv[]) { // Reinit Thread sem_init(&reinit, 0, 0); sem_init(&uidName, 0, 0); + sem_init(&sem_name, 0, 1); pthread_attr_t attr; if (!pthread_attr_init(&attr)) { struct sched_param param; |