blob: 9a085ec6d1f04375013fdb825c0addec0e9da173 [file] [log] [blame]
Mark Salyzyn018a96d2016-03-01 13:45:42 -08001/*
2 * Copyright (C) 2007-2016 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
Tom Cherry21bb36c2020-01-08 15:18:26 -080017#include "logd_writer.h"
18
Mark Salyzyn018a96d2016-03-01 13:45:42 -080019#include <errno.h>
20#include <fcntl.h>
21#include <inttypes.h>
22#include <poll.h>
23#include <stdarg.h>
24#include <stdatomic.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080028#include <sys/socket.h>
Mark Salyzyn018a96d2016-03-01 13:45:42 -080029#include <sys/stat.h>
30#include <sys/types.h>
Mark Salyzyn018a96d2016-03-01 13:45:42 -080031#include <sys/un.h>
32#include <time.h>
33#include <unistd.h>
34
Tom Cherry2a6811b2019-12-11 12:56:01 -080035#include <shared_mutex>
36
Mark Salyzyn018a96d2016-03-01 13:45:42 -080037#include <cutils/sockets.h>
Mark Salyzyn018a96d2016-03-01 13:45:42 -080038#include <private/android_filesystem_config.h>
39#include <private/android_logger.h>
40
Mark Salyzyn018a96d2016-03-01 13:45:42 -080041#include "log_portability.h"
42#include "logger.h"
Tom Cherry2a6811b2019-12-11 12:56:01 -080043#include "rwlock.h"
Tom Cherry6f6ef392019-01-16 14:17:08 -080044#include "uio.h"
Mark Salyzyn018a96d2016-03-01 13:45:42 -080045
Tom Cherry2a6811b2019-12-11 12:56:01 -080046static int logd_socket;
47static RwLock logd_socket_lock;
Mark Salyzyn018a96d2016-03-01 13:45:42 -080048
Tom Cherry2a6811b2019-12-11 12:56:01 -080049static void OpenSocketLocked() {
50 logd_socket = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
51 if (logd_socket <= 0) {
52 return;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080053 }
54
Tom Cherry2a6811b2019-12-11 12:56:01 -080055 sockaddr_un un = {};
56 un.sun_family = AF_UNIX;
57 strcpy(un.sun_path, "/dev/socket/logdw");
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080058
Tom Cherry2a6811b2019-12-11 12:56:01 -080059 if (TEMP_FAILURE_RETRY(
60 connect(logd_socket, reinterpret_cast<sockaddr*>(&un), sizeof(sockaddr_un))) < 0) {
61 close(logd_socket);
62 logd_socket = 0;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080063 }
64}
65
Tom Cherry2a6811b2019-12-11 12:56:01 -080066static void OpenSocket() {
67 auto lock = std::unique_lock{logd_socket_lock};
68 if (logd_socket > 0) {
69 // Someone raced us and opened the socket already.
70 return;
71 }
72
73 OpenSocketLocked();
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080074}
75
Tom Cherry2a6811b2019-12-11 12:56:01 -080076static void ResetSocket(int old_socket) {
77 auto lock = std::unique_lock{logd_socket_lock};
78 if (old_socket != logd_socket) {
79 // Someone raced us and reset the socket already.
80 return;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080081 }
Tom Cherry2a6811b2019-12-11 12:56:01 -080082 close(logd_socket);
83 logd_socket = 0;
84 OpenSocketLocked();
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080085}
86
Tom Cherry21bb36c2020-01-08 15:18:26 -080087void LogdClose() {
Tom Cherry2a6811b2019-12-11 12:56:01 -080088 auto lock = std::unique_lock{logd_socket_lock};
89 if (logd_socket > 0) {
90 close(logd_socket);
91 }
92 logd_socket = 0;
93}
94
Tom Cherry21bb36c2020-01-08 15:18:26 -080095int LogdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080096 ssize_t ret;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080097 static const unsigned headerLength = 1;
98 struct iovec newVec[nr + headerLength];
99 android_log_header_t header;
100 size_t i, payloadSize;
Tom Cherry71ba1642019-01-10 10:37:36 -0800101 static atomic_int dropped;
102 static atomic_int droppedSecurity;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800103
Tom Cherry2a6811b2019-12-11 12:56:01 -0800104 auto lock = std::shared_lock{logd_socket_lock};
105 if (logd_socket <= 0) {
106 lock.unlock();
107 OpenSocket();
108 lock.lock();
109 }
110
111 if (logd_socket <= 0) {
112 return -EBADF;
113 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800114
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800115 /* logd, after initialization and priv drop */
116 if (__android_log_uid() == AID_LOGD) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800117 /*
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800118 * ignore log messages we send to ourself (logd).
119 * Such log messages are often generated by libraries we depend on
120 * which use standard Android logging.
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800121 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800122 return 0;
123 }
124
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800125 header.tid = gettid();
126 header.realtime.tv_sec = ts->tv_sec;
127 header.realtime.tv_nsec = ts->tv_nsec;
128
129 newVec[0].iov_base = (unsigned char*)&header;
130 newVec[0].iov_len = sizeof(header);
131
Tom Cherry2a6811b2019-12-11 12:56:01 -0800132 int32_t snapshot = atomic_exchange_explicit(&droppedSecurity, 0, memory_order_relaxed);
133 if (snapshot) {
134 android_log_event_int_t buffer;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800135
Tom Cherry2a6811b2019-12-11 12:56:01 -0800136 header.id = LOG_ID_SECURITY;
137 buffer.header.tag = LIBLOG_LOG_TAG;
138 buffer.payload.type = EVENT_TYPE_INT;
139 buffer.payload.data = snapshot;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800140
Tom Cherry2a6811b2019-12-11 12:56:01 -0800141 newVec[headerLength].iov_base = &buffer;
142 newVec[headerLength].iov_len = sizeof(buffer);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800143
Tom Cherry2a6811b2019-12-11 12:56:01 -0800144 ret = TEMP_FAILURE_RETRY(writev(logd_socket, newVec, 2));
145 if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
146 atomic_fetch_add_explicit(&droppedSecurity, snapshot, memory_order_relaxed);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800147 }
Tom Cherry2a6811b2019-12-11 12:56:01 -0800148 }
149 snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
150 if (snapshot && __android_log_is_loggable_len(ANDROID_LOG_INFO, "liblog", strlen("liblog"),
151 ANDROID_LOG_VERBOSE)) {
152 android_log_event_int_t buffer;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800153
Tom Cherry2a6811b2019-12-11 12:56:01 -0800154 header.id = LOG_ID_EVENTS;
155 buffer.header.tag = LIBLOG_LOG_TAG;
156 buffer.payload.type = EVENT_TYPE_INT;
157 buffer.payload.data = snapshot;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800158
Tom Cherry2a6811b2019-12-11 12:56:01 -0800159 newVec[headerLength].iov_base = &buffer;
160 newVec[headerLength].iov_len = sizeof(buffer);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800161
Tom Cherry2a6811b2019-12-11 12:56:01 -0800162 ret = TEMP_FAILURE_RETRY(writev(logd_socket, newVec, 2));
163 if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
164 atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800165 }
166 }
167
168 header.id = logId;
169
170 for (payloadSize = 0, i = headerLength; i < nr + headerLength; i++) {
171 newVec[i].iov_base = vec[i - headerLength].iov_base;
172 payloadSize += newVec[i].iov_len = vec[i - headerLength].iov_len;
173
174 if (payloadSize > LOGGER_ENTRY_MAX_PAYLOAD) {
175 newVec[i].iov_len -= payloadSize - LOGGER_ENTRY_MAX_PAYLOAD;
176 if (newVec[i].iov_len) {
177 ++i;
178 }
179 break;
180 }
181 }
182
Tom Cherry2a6811b2019-12-11 12:56:01 -0800183 // The write below could be lost, but will never block.
184 // EAGAIN occurs if logd is overloaded, other errors indicate that something went wrong with
185 // the connection, so we reset it and try again.
186 ret = TEMP_FAILURE_RETRY(writev(logd_socket, newVec, i));
187 if (ret < 0 && errno != EAGAIN) {
188 int old_socket = logd_socket;
189 lock.unlock();
190 ResetSocket(old_socket);
191 lock.lock();
192
193 ret = TEMP_FAILURE_RETRY(writev(logd_socket, newVec, i));
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800194 }
Mark Salyzyn65e1e622017-01-03 13:28:18 -0800195
Tom Cherry2a6811b2019-12-11 12:56:01 -0800196 if (ret < 0) {
197 ret = -errno;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800198 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800199
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800200 if (ret > (ssize_t)sizeof(header)) {
201 ret -= sizeof(header);
Tom Cherry2a6811b2019-12-11 12:56:01 -0800202 } else if (ret < 0) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800203 atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
204 if (logId == LOG_ID_SECURITY) {
205 atomic_fetch_add_explicit(&droppedSecurity, 1, memory_order_relaxed);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800206 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800207 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800208
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800209 return ret;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800210}