bool LogListener::onDataAvailable(SocketClient *cli) { static bool name_set; if (!name_set) { prctl(PR_SET_NAME, "logd.writer"); name_set = true; } char buffer[sizeof_log_id_t + sizeof(uint16_t) + sizeof(log_time) + LOGGER_ENTRY_MAX_PAYLOAD]; struct iovec iov = { buffer, sizeof(buffer) }; char control[CMSG_SPACE(sizeof(struct ucred))] __aligned(4); struct msghdr hdr = { NULL, 0, &iov, 1, control, sizeof(control), 0, }; int socket = cli->getSocket(); // To clear the entire buffer is secure/safe, but this contributes to 1.68% // overhead under logging load. We are safe because we check counts. // memset(buffer, 0, sizeof(buffer)); ssize_t n = recvmsg(socket, &hdr, 0); if (n <= (ssize_t)(sizeof(android_log_header_t))) { return false; } struct ucred *cred = NULL; struct cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr); while (cmsg != NULL) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) { cred = (struct ucred *)CMSG_DATA(cmsg); break; } cmsg = CMSG_NXTHDR(&hdr, cmsg); } if (cred == NULL) { return false; } if (cred->uid == AID_LOGD) { // ignore log messages we send to ourself. // Such log messages are often generated by libraries we depend on // which use standard Android logging. return false; } android_log_header_t *header = reinterpret_cast<android_log_header_t *>(buffer); if (/* header->id < LOG_ID_MIN || */ header->id >= LOG_ID_MAX || header->id == LOG_ID_KERNEL) { return false; } if ((header->id == LOG_ID_SECURITY) && (!__android_log_security() || !clientHasLogCredentials(cred->uid, cred->gid, cred->pid))) { return false; } char *msg = ((char *)buffer) + sizeof(android_log_header_t); n -= sizeof(android_log_header_t); // NB: hdr.msg_flags & MSG_TRUNC is not tested, silently passing a // truncated message to the logs. if (logbuf->log((log_id_t)header->id, header->realtime, cred->uid, cred->pid, header->tid, msg, ((size_t) n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX) >= 0) { reader->notifyNewLog(); } return true; }
/* * Measure the time it takes for __android_log_security. */ static void BM_security(benchmark::State& state) { while (state.KeepRunning()) { __android_log_security(); } }