blob: 4731487b6862ccd5a3bb10e279cb391e28048dcd [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
17#include <endian.h>
18#include <errno.h>
19#include <fcntl.h>
20#include <inttypes.h>
21#include <poll.h>
22#include <stdarg.h>
23#include <stdatomic.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080027#include <sys/socket.h>
Mark Salyzyn018a96d2016-03-01 13:45:42 -080028#include <sys/stat.h>
29#include <sys/types.h>
Mark Salyzyn018a96d2016-03-01 13:45:42 -080030#include <sys/un.h>
31#include <time.h>
32#include <unistd.h>
33
34#include <cutils/sockets.h>
Mark Salyzyn018a96d2016-03-01 13:45:42 -080035#include <private/android_filesystem_config.h>
36#include <private/android_logger.h>
37
38#include "config_write.h"
39#include "log_portability.h"
40#include "logger.h"
41
42/* branchless on many architectures. */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080043#define min(x, y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
Mark Salyzyn018a96d2016-03-01 13:45:42 -080044
45static int logdAvailable(log_id_t LogId);
46static int logdOpen();
47static void logdClose();
Tom Cherry71ba1642019-01-10 10:37:36 -080048static int logdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr);
Mark Salyzyn018a96d2016-03-01 13:45:42 -080049
50LIBLOG_HIDDEN struct android_log_transport_write logdLoggerWrite = {
Tom Cherry71ba1642019-01-10 10:37:36 -080051 .node = {&logdLoggerWrite.node, &logdLoggerWrite.node},
52 .context.sock = -EBADF,
53 .name = "logd",
54 .available = logdAvailable,
55 .open = logdOpen,
56 .close = logdClose,
57 .write = logdWrite,
Mark Salyzyn018a96d2016-03-01 13:45:42 -080058};
59
60/* log_init_lock assumed */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080061static int logdOpen() {
62 int i, ret = 0;
Mark Salyzyn018a96d2016-03-01 13:45:42 -080063
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080064 i = atomic_load(&logdLoggerWrite.context.sock);
65 if (i < 0) {
Tom Cherry71ba1642019-01-10 10:37:36 -080066 int sock = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080067 if (sock < 0) {
68 ret = -errno;
69 } else {
70 struct sockaddr_un un;
71 memset(&un, 0, sizeof(struct sockaddr_un));
72 un.sun_family = AF_UNIX;
73 strcpy(un.sun_path, "/dev/socket/logdw");
Mark Salyzyn018a96d2016-03-01 13:45:42 -080074
Tom Cherry71ba1642019-01-10 10:37:36 -080075 if (TEMP_FAILURE_RETRY(connect(sock, (struct sockaddr*)&un, sizeof(struct sockaddr_un))) <
76 0) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080077 ret = -errno;
78 switch (ret) {
79 case -ENOTCONN:
80 case -ECONNREFUSED:
81 case -ENOENT:
82 i = atomic_exchange(&logdLoggerWrite.context.sock, ret);
Tom Cherry71ba1642019-01-10 10:37:36 -080083 [[fallthrough]];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080084 default:
Mark Salyzyn018a96d2016-03-01 13:45:42 -080085 break;
86 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080087 close(sock);
88 } else {
89 ret = atomic_exchange(&logdLoggerWrite.context.sock, sock);
90 if ((ret >= 0) && (ret != sock)) {
91 close(ret);
92 }
93 ret = 0;
94 }
95 }
96 }
97
98 return ret;
99}
100
101static void __logdClose(int negative_errno) {
102 int sock = atomic_exchange(&logdLoggerWrite.context.sock, negative_errno);
103 if (sock >= 0) {
104 close(sock);
105 }
106}
107
108static void logdClose() {
109 __logdClose(-EBADF);
110}
111
112static int logdAvailable(log_id_t logId) {
113 if (logId >= LOG_ID_MAX || logId == LOG_ID_KERNEL) {
114 return -EINVAL;
115 }
116 if (atomic_load(&logdLoggerWrite.context.sock) < 0) {
117 if (access("/dev/socket/logdw", W_OK) == 0) {
118 return 0;
119 }
120 return -EBADF;
121 }
122 return 1;
123}
124
Tom Cherry71ba1642019-01-10 10:37:36 -0800125static int logdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800126 ssize_t ret;
127 int sock;
128 static const unsigned headerLength = 1;
129 struct iovec newVec[nr + headerLength];
130 android_log_header_t header;
131 size_t i, payloadSize;
Tom Cherry71ba1642019-01-10 10:37:36 -0800132 static atomic_int dropped;
133 static atomic_int droppedSecurity;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800134
135 sock = atomic_load(&logdLoggerWrite.context.sock);
136 if (sock < 0) switch (sock) {
137 case -ENOTCONN:
138 case -ECONNREFUSED:
139 case -ENOENT:
140 break;
141 default:
142 return -EBADF;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800143 }
144
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800145 /* logd, after initialization and priv drop */
146 if (__android_log_uid() == AID_LOGD) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800147 /*
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800148 * ignore log messages we send to ourself (logd).
149 * Such log messages are often generated by libraries we depend on
150 * which use standard Android logging.
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800151 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800152 return 0;
153 }
154
155 /*
156 * struct {
157 * // what we provide to socket
158 * android_log_header_t header;
159 * // caller provides
160 * union {
161 * struct {
162 * char prio;
163 * char payload[];
164 * } string;
165 * struct {
166 * uint32_t tag
167 * char payload[];
168 * } binary;
169 * };
170 * };
171 */
172
173 header.tid = gettid();
174 header.realtime.tv_sec = ts->tv_sec;
175 header.realtime.tv_nsec = ts->tv_nsec;
176
177 newVec[0].iov_base = (unsigned char*)&header;
178 newVec[0].iov_len = sizeof(header);
179
180 if (sock >= 0) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800181 int32_t snapshot = atomic_exchange_explicit(&droppedSecurity, 0, memory_order_relaxed);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800182 if (snapshot) {
183 android_log_event_int_t buffer;
184
185 header.id = LOG_ID_SECURITY;
186 buffer.header.tag = htole32(LIBLOG_LOG_TAG);
187 buffer.payload.type = EVENT_TYPE_INT;
188 buffer.payload.data = htole32(snapshot);
189
190 newVec[headerLength].iov_base = &buffer;
191 newVec[headerLength].iov_len = sizeof(buffer);
192
193 ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2));
194 if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800195 atomic_fetch_add_explicit(&droppedSecurity, snapshot, memory_order_relaxed);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800196 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800197 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800198 snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
Tom Cherry71ba1642019-01-10 10:37:36 -0800199 if (snapshot && __android_log_is_loggable_len(ANDROID_LOG_INFO, "liblog", strlen("liblog"),
200 ANDROID_LOG_VERBOSE)) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800201 android_log_event_int_t buffer;
202
203 header.id = LOG_ID_EVENTS;
204 buffer.header.tag = htole32(LIBLOG_LOG_TAG);
205 buffer.payload.type = EVENT_TYPE_INT;
206 buffer.payload.data = htole32(snapshot);
207
208 newVec[headerLength].iov_base = &buffer;
209 newVec[headerLength].iov_len = sizeof(buffer);
210
211 ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2));
212 if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
213 atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed);
214 }
215 }
216 }
217
218 header.id = logId;
219
220 for (payloadSize = 0, i = headerLength; i < nr + headerLength; i++) {
221 newVec[i].iov_base = vec[i - headerLength].iov_base;
222 payloadSize += newVec[i].iov_len = vec[i - headerLength].iov_len;
223
224 if (payloadSize > LOGGER_ENTRY_MAX_PAYLOAD) {
225 newVec[i].iov_len -= payloadSize - LOGGER_ENTRY_MAX_PAYLOAD;
226 if (newVec[i].iov_len) {
227 ++i;
228 }
229 break;
230 }
231 }
232
233 /*
234 * The write below could be lost, but will never block.
235 *
236 * ENOTCONN occurs if logd has died.
237 * ENOENT occurs if logd is not running and socket is missing.
238 * ECONNREFUSED occurs if we can not reconnect to logd.
239 * EAGAIN occurs if logd is overloaded.
240 */
241 if (sock < 0) {
242 ret = sock;
243 } else {
244 ret = TEMP_FAILURE_RETRY(writev(sock, newVec, i));
245 if (ret < 0) {
246 ret = -errno;
247 }
248 }
249 switch (ret) {
Mark Salyzyn65e1e622017-01-03 13:28:18 -0800250 case -ENOTCONN:
251 case -ECONNREFUSED:
252 case -ENOENT:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800253 if (__android_log_trylock()) {
254 return ret; /* in a signal handler? try again when less stressed */
255 }
256 __logdClose(ret);
257 ret = logdOpen();
258 __android_log_unlock();
Mark Salyzyn65e1e622017-01-03 13:28:18 -0800259
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800260 if (ret < 0) {
261 return ret;
262 }
Mark Salyzyn65e1e622017-01-03 13:28:18 -0800263
Tom Cherry71ba1642019-01-10 10:37:36 -0800264 ret = TEMP_FAILURE_RETRY(writev(atomic_load(&logdLoggerWrite.context.sock), newVec, i));
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800265 if (ret < 0) {
266 ret = -errno;
267 }
Tom Cherry71ba1642019-01-10 10:37:36 -0800268 [[fallthrough]];
Mark Salyzyn65e1e622017-01-03 13:28:18 -0800269 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800270 break;
271 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800272
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800273 if (ret > (ssize_t)sizeof(header)) {
274 ret -= sizeof(header);
275 } else if (ret == -EAGAIN) {
276 atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
277 if (logId == LOG_ID_SECURITY) {
278 atomic_fetch_add_explicit(&droppedSecurity, 1, memory_order_relaxed);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800279 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800280 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800281
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800282 return ret;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800283}