logd: improve details on chatty records
(Cherry pick from commit 21fb7e0b75
)
- 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
This commit is contained in:
parent
5a9d33ee1c
commit
95108f1844
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,19 +50,89 @@ LogBufferElement::~LogBufferElement() {
|
|||
delete [] mMsg;
|
||||
}
|
||||
|
||||
// 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;
|
||||
static const char tag[] = "logd";
|
||||
|
||||
size_t len;
|
||||
if (privileged) {
|
||||
len = snprintf(NULL, 0, format_uid, mUid, mDropped);
|
||||
} else {
|
||||
len = snprintf(NULL, 0, format_uid + unprivileged_offset, mDropped);
|
||||
// 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,
|
||||
LogBuffer *parent) {
|
||||
static const char tag[] = "logd";
|
||||
static const char format_uid[] = "uid=%u%s too chatty%s, expire %u line%s";
|
||||
|
||||
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) {
|
||||
hdrLen = sizeof(android_log_event_string_t);
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue