blob: fc51dcf08d4ce724269d3d4a28e308eb6792e1e1 [file] [log] [blame]
Mark Salyzyn0175b072014-02-26 09:50:16 -08001/*
2 * Copyright (C) 2012-2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Mark Salyzync4e48232017-05-04 13:54:46 -070017#include <ctype.h>
Mark Salyzyne0fa2912014-04-28 16:39:04 -070018#include <limits.h>
Mark Salyzync4e48232017-05-04 13:54:46 -070019#include <stdio.h>
Mark Salyzyn46906402016-01-12 10:08:03 -080020#include <sys/cdefs.h>
Mark Salyzyn8daa9af2014-04-28 14:07:23 -070021#include <sys/prctl.h>
Mark Salyzyn0175b072014-02-26 09:50:16 -080022#include <sys/socket.h>
23#include <sys/types.h>
24#include <sys/un.h>
25#include <unistd.h>
26
27#include <cutils/sockets.h>
Mark Salyzyne3aeeee2015-03-17 07:56:32 -070028#include <private/android_filesystem_config.h>
Mark Salyzynb5f6e452015-01-16 13:38:07 -080029#include <private/android_logger.h>
Mark Salyzyn0175b072014-02-26 09:50:16 -080030
Mark Salyzyn2ad0bd02016-02-23 08:55:43 -080031#include "LogBuffer.h"
Mark Salyzyn0175b072014-02-26 09:50:16 -080032#include "LogListener.h"
Mark Salyzyn083b0372015-12-04 10:59:45 -080033#include "LogUtils.h"
Mark Salyzyn0175b072014-02-26 09:50:16 -080034
Chenjie Luofafea322017-04-27 16:49:09 -070035LogListener::LogListener(LogBufferInterface* buf, LogReader* reader)
Mark Salyzyn501c3732017-03-10 14:31:54 -080036 : SocketListener(getLogSocket(), false), logbuf(buf), reader(reader) {
Mark Salyzyn77187782015-05-12 15:21:31 -070037}
Mark Salyzyn0175b072014-02-26 09:50:16 -080038
Mark Salyzyn501c3732017-03-10 14:31:54 -080039bool LogListener::onDataAvailable(SocketClient* cli) {
Mark Salyzyne3aeeee2015-03-17 07:56:32 -070040 static bool name_set;
41 if (!name_set) {
42 prctl(PR_SET_NAME, "logd.writer");
43 name_set = true;
44 }
Mark Salyzyn8daa9af2014-04-28 14:07:23 -070045
Paul Elliottc6ed8f32017-11-07 11:11:41 +000046 // + 1 to ensure null terminator if MAX_PAYLOAD buffer is received
Mark Salyzyn501c3732017-03-10 14:31:54 -080047 char buffer[sizeof_log_id_t + sizeof(uint16_t) + sizeof(log_time) +
Paul Elliottc6ed8f32017-11-07 11:11:41 +000048 LOGGER_ENTRY_MAX_PAYLOAD + 1];
49 struct iovec iov = { buffer, sizeof(buffer) - 1 };
Mark Salyzyn0175b072014-02-26 09:50:16 -080050
Elliott Hughes5f4a9462016-06-06 19:56:24 -070051 alignas(4) char control[CMSG_SPACE(sizeof(struct ucred))];
Mark Salyzyn0175b072014-02-26 09:50:16 -080052 struct msghdr hdr = {
Mark Salyzyn501c3732017-03-10 14:31:54 -080053 NULL, 0, &iov, 1, control, sizeof(control), 0,
Mark Salyzyn0175b072014-02-26 09:50:16 -080054 };
55
56 int socket = cli->getSocket();
57
Mark Salyzyn1d9c7e72015-12-15 12:30:46 -080058 // To clear the entire buffer is secure/safe, but this contributes to 1.68%
Paul Elliottc6ed8f32017-11-07 11:11:41 +000059 // overhead under logging load. We are safe because we check counts, but
60 // still need to clear null terminator
Mark Salyzyn1d9c7e72015-12-15 12:30:46 -080061 // memset(buffer, 0, sizeof(buffer));
Mark Salyzyn0175b072014-02-26 09:50:16 -080062 ssize_t n = recvmsg(socket, &hdr, 0);
Mark Salyzynb5f6e452015-01-16 13:38:07 -080063 if (n <= (ssize_t)(sizeof(android_log_header_t))) {
Mark Salyzyn0175b072014-02-26 09:50:16 -080064 return false;
65 }
66
Paul Elliottc6ed8f32017-11-07 11:11:41 +000067 buffer[n] = 0;
68
Mark Salyzyn501c3732017-03-10 14:31:54 -080069 struct ucred* cred = NULL;
Mark Salyzyn0175b072014-02-26 09:50:16 -080070
Mark Salyzyn501c3732017-03-10 14:31:54 -080071 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr);
Mark Salyzyn0175b072014-02-26 09:50:16 -080072 while (cmsg != NULL) {
Mark Salyzyn501c3732017-03-10 14:31:54 -080073 if (cmsg->cmsg_level == SOL_SOCKET &&
74 cmsg->cmsg_type == SCM_CREDENTIALS) {
75 cred = (struct ucred*)CMSG_DATA(cmsg);
Mark Salyzyn0175b072014-02-26 09:50:16 -080076 break;
77 }
78 cmsg = CMSG_NXTHDR(&hdr, cmsg);
79 }
80
Mark Salyzync4e48232017-05-04 13:54:46 -070081 struct ucred fake_cred;
Mark Salyzyn0175b072014-02-26 09:50:16 -080082 if (cred == NULL) {
Mark Salyzync4e48232017-05-04 13:54:46 -070083 cred = &fake_cred;
84 cred->pid = 0;
85 cred->uid = DEFAULT_OVERFLOWUID;
Mark Salyzyn0175b072014-02-26 09:50:16 -080086 }
87
Mark Salyzyne3aeeee2015-03-17 07:56:32 -070088 if (cred->uid == AID_LOGD) {
Mark Salyzyn0175b072014-02-26 09:50:16 -080089 // ignore log messages we send to ourself.
90 // Such log messages are often generated by libraries we depend on
91 // which use standard Android logging.
92 return false;
93 }
94
Mark Salyzyn501c3732017-03-10 14:31:54 -080095 android_log_header_t* header =
96 reinterpret_cast<android_log_header_t*>(buffer);
Hao Wangf6e22962017-12-04 14:10:40 +080097 log_id_t logId = static_cast<log_id_t>(header->id);
98 if (/* logId < LOG_ID_MIN || */ logId >= LOG_ID_MAX ||
99 logId == LOG_ID_KERNEL) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800100 return false;
101 }
Mark Salyzyn0175b072014-02-26 09:50:16 -0800102
Hao Wangf6e22962017-12-04 14:10:40 +0800103 if ((logId == LOG_ID_SECURITY) &&
Mark Salyzyn501c3732017-03-10 14:31:54 -0800104 (!__android_log_security() ||
105 !clientHasLogCredentials(cred->uid, cred->gid, cred->pid))) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800106 return false;
107 }
108
Mark Salyzync4e48232017-05-04 13:54:46 -0700109 // Check credential validity, acquire corrected details if not supplied.
110 if (cred->pid == 0) {
111 cred->pid = logbuf ? logbuf->tidToPid(header->tid)
112 : android::tidToPid(header->tid);
113 if (cred->pid == getpid()) {
114 // We expect that /proc/<tid>/ is accessible to self even without
115 // readproc group, so that we will always drop messages that come
116 // from any of our logd threads and their library calls.
117 return false; // ignore self
118 }
119 }
120 if (cred->uid == DEFAULT_OVERFLOWUID) {
121 uid_t uid =
122 logbuf ? logbuf->pidToUid(cred->pid) : android::pidToUid(cred->pid);
123 if (uid == AID_LOGD) {
124 uid = logbuf ? logbuf->pidToUid(header->tid)
125 : android::pidToUid(cred->pid);
126 }
127 if (uid != AID_LOGD) cred->uid = uid;
128 }
129
Mark Salyzyn501c3732017-03-10 14:31:54 -0800130 char* msg = ((char*)buffer) + sizeof(android_log_header_t);
Mark Salyzynb5f6e452015-01-16 13:38:07 -0800131 n -= sizeof(android_log_header_t);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800132
Mark Salyzyn22e287d2014-03-21 13:12:16 -0700133 // NB: hdr.msg_flags & MSG_TRUNC is not tested, silently passing a
134 // truncated message to the logs.
Mark Salyzyne0fa2912014-04-28 16:39:04 -0700135
Chenjie Luofafea322017-04-27 16:49:09 -0700136 if (logbuf != nullptr) {
137 int res = logbuf->log(
Hao Wangf6e22962017-12-04 14:10:40 +0800138 logId, header->realtime, cred->uid, cred->pid, header->tid, msg,
Chenjie Luofafea322017-04-27 16:49:09 -0700139 ((size_t)n <= USHRT_MAX) ? (unsigned short)n : USHRT_MAX);
140 if (res > 0 && reader != nullptr) {
Hao Wangf6e22962017-12-04 14:10:40 +0800141 reader->notifyNewLog(static_cast<log_mask_t>(1 << logId));
Chenjie Luofafea322017-04-27 16:49:09 -0700142 }
Mark Salyzyn202e1532015-02-09 08:21:05 -0800143 }
Mark Salyzyn0175b072014-02-26 09:50:16 -0800144
145 return true;
146}
147
148int LogListener::getLogSocket() {
Mark Salyzyndfc47e82014-03-24 10:26:47 -0700149 static const char socketName[] = "logdw";
150 int sock = android_get_control_socket(socketName);
151
Mark Salyzyn54d8ff12017-05-05 15:32:10 -0700152 if (sock < 0) { // logd started up in init.sh
Mark Salyzyn501c3732017-03-10 14:31:54 -0800153 sock = socket_local_server(
154 socketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_DGRAM);
Mark Salyzyndfc47e82014-03-24 10:26:47 -0700155
Mark Salyzyn54d8ff12017-05-05 15:32:10 -0700156 int on = 1;
157 if (setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) {
158 return -1;
159 }
Mark Salyzyn0175b072014-02-26 09:50:16 -0800160 }
161 return sock;
162}