diff --git a/include/private/android_logger.h b/include/private/android_logger.h index 54aa86b41..cc7ba3042 100644 --- a/include/private/android_logger.h +++ b/include/private/android_logger.h @@ -24,7 +24,17 @@ #include #include -/* Header Structure to logd */ +#define LOGGER_MAGIC 'l' + +/* Header Structure to pstore */ +typedef struct __attribute__((__packed__)) { + uint8_t magic; + uint16_t len; + uint16_t uid; + uint16_t pid; +} android_pmsg_log_header_t; + +/* Header Structure to logd, and second header for pstore */ typedef struct __attribute__((__packed__)) { typeof_log_id_t id; uint16_t tid; diff --git a/liblog/logd_write.c b/liblog/logd_write.c index 3d847f148..1e9b59147 100644 --- a/liblog/logd_write.c +++ b/liblog/logd_write.c @@ -62,6 +62,7 @@ static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER; static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1 }; #else static int logd_fd = -1; +static int pstore_fd = -1; #endif /* @@ -110,6 +111,12 @@ static int __write_to_log_initialize() logd_fd = -1; close(i); } + if (pstore_fd >= 0) { + i = pstore_fd; + pstore_fd = -1; + close(i); + } + pstore_fd = open("/dev/pmsg0", O_WRONLY); i = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (i < 0) { @@ -156,32 +163,26 @@ static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr) } } while (ret == -EINTR); #else - static const unsigned header_length = 1; + static const unsigned header_length = 2; struct iovec newVec[nr + header_length]; - struct android_log_header_t header; + android_log_header_t header; + android_pmsg_log_header_t pmsg_header; struct timespec ts; size_t i, payload_size; static uid_t last_uid = AID_ROOT; /* logd *always* starts up as AID_ROOT */ + static pid_t last_pid = (pid_t) -1; if (last_uid == AID_ROOT) { /* have we called to get the UID yet? */ last_uid = getuid(); } - if (last_uid == AID_LOGD) { /* logd, after initialization and priv drop */ - /* - * ignore log messages we send to ourself (logd). - * Such log messages are often generated by libraries we depend on - * which use standard Android logging. - */ - return 0; + if (last_pid == (pid_t) -1) { + last_pid = getpid(); } - - if (logd_fd < 0) { - return -EBADF; - } - /* * struct { - * // what we provide + * // whate we provire to pstore + * android_pmsg_log_header_t pmsg_header; + * // what we provide to socket * android_log_header_t header; * // caller provides * union { @@ -199,13 +200,20 @@ static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr) clock_gettime(CLOCK_REALTIME, &ts); + pmsg_header.magic = LOGGER_MAGIC; + pmsg_header.len = sizeof(pmsg_header) + sizeof(header); + pmsg_header.uid = last_uid; + pmsg_header.pid = last_pid; + header.id = log_id; header.tid = gettid(); header.realtime.tv_sec = ts.tv_sec; header.realtime.tv_nsec = ts.tv_nsec; - newVec[0].iov_base = (unsigned char *) &header; - newVec[0].iov_len = sizeof(header); + newVec[0].iov_base = (unsigned char *) &pmsg_header; + newVec[0].iov_len = sizeof(pmsg_header); + newVec[1].iov_base = (unsigned char *) &header; + newVec[1].iov_len = sizeof(header); for (payload_size = 0, i = header_length; i < nr + header_length; i++) { newVec[i].iov_base = vec[i - header_length].iov_base; @@ -216,17 +224,38 @@ static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr) if (newVec[i].iov_len) { ++i; } + payload_size = LOGGER_ENTRY_MAX_PAYLOAD; break; } } + pmsg_header.len += payload_size; + + if (pstore_fd >= 0) { + TEMP_FAILURE_RETRY(writev(pstore_fd, newVec, i)); + } + + if (last_uid == AID_LOGD) { /* logd, after initialization and priv drop */ + /* + * ignore log messages we send to ourself (logd). + * Such log messages are often generated by libraries we depend on + * which use standard Android logging. + */ + return 0; + } + + if (logd_fd < 0) { + return -EBADF; + } /* * The write below could be lost, but will never block. * + * To logd, we drop the pmsg_header + * * ENOTCONN occurs if logd dies. * EAGAIN occurs if logd is overloaded. */ - ret = writev(logd_fd, newVec, i); + ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1)); if (ret < 0) { ret = -errno; if (ret == -ENOTCONN) { @@ -242,7 +271,7 @@ static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr) return ret; } - ret = writev(logd_fd, newVec, i); + ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1)); if (ret < 0) { ret = -errno; }