Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 95108f18 authored by Mark Salyzyn's avatar Mark Salyzyn
Browse files

logd: improve details on chatty records

(Cherry pick from commit 21fb7e0b)

- Report applications UID, TID/PID by name.
- change wording to have an accurate connotation
- drop privilege check since filtered upstream

Bug: 19608965
Bug: 20334069
Bug: 20370119
Change-Id: I2b1c26580b4c2de293874214ff5ae745546f3cca
parent 5a9d33ee
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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);
+89 −15
Original line number Diff line number Diff line
@@ -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;
        }
+8 −3
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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");
Loading