blob: 494607359a65fcd9bae925d584e104fd7710660c [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
Mark Salyzyne9c41962014-01-02 13:52:29 -08002 * Copyright (C) 2007-2014 The Android Open Source Project
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08003 *
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 */
Mark Salyzyn31dd00f2015-03-04 17:01:30 -080016#if (FAKE_LOG_DEVICE == 0)
Mark Salyzynd45d36e2015-02-12 15:14:26 -080017#include <endian.h>
Mark Salyzyn31dd00f2015-03-04 17:01:30 -080018#endif
Mark Salyzyn154f4602014-02-20 14:59:07 -080019#include <errno.h>
20#include <fcntl.h>
Yabin Cui4a6e5a32015-01-26 19:48:54 -080021#if !defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080022#include <pthread.h>
23#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080024#include <stdarg.h>
Mark Salyzynd45d36e2015-02-12 15:14:26 -080025#include <stdatomic.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080026#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
Nick Kralevicha1703222013-03-15 09:45:12 -070029#include <sys/stat.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080030#include <sys/types.h>
31#if (FAKE_LOG_DEVICE == 0)
32#include <sys/socket.h>
33#include <sys/un.h>
34#endif
35#include <time.h>
36#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080037
Dan Albertc68fedc2014-08-18 17:29:34 -070038#ifdef __BIONIC__
39#include <android/set_abort_message.h>
40#endif
41
Mark Salyzyna0140042015-03-13 06:50:32 -070042#include <log/event_tag_map.h>
Colin Cross9227bd32013-07-23 16:59:20 -070043#include <log/logd.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080044#include <log/logger.h>
45#include <log/log_read.h>
46#include <private/android_filesystem_config.h>
Mark Salyzyn7a809402015-01-16 13:38:07 -080047#include <private/android_logger.h>
Mark Salyzyne9c41962014-01-02 13:52:29 -080048
Mark Salyzyncf4aa032013-11-22 07:54:30 -080049#define LOG_BUF_SIZE 1024
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080050
51#if FAKE_LOG_DEVICE
Mark Salyzyn154f4602014-02-20 14:59:07 -080052/* This will be defined when building for the host. */
Kristian Monsenb5a98902014-01-28 11:26:56 -080053#include "fake_log_device.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080054#endif
55
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080056static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr);
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -080057static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080058
Mark Salyzyna04464a2014-04-30 08:50:53 -070059#ifndef __unused
60#define __unused __attribute__((__unused__))
61#endif
Kristian Monsenb5a98902014-01-28 11:26:56 -080062
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080063#if !defined(_WIN32)
64static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
65
66static void lock()
67{
68 /*
69 * If we trigger a signal handler in the middle of locked activity and the
70 * signal handler logs a message, we could get into a deadlock state.
71 */
72 pthread_mutex_lock(&log_init_lock);
73}
74
Mark Salyzyna0140042015-03-13 06:50:32 -070075static int trylock()
76{
77 return pthread_mutex_trylock(&log_init_lock);
78}
79
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080080static void unlock()
81{
82 pthread_mutex_unlock(&log_init_lock);
83}
84
85#else /* !defined(_WIN32) */
86
87#define lock() ((void)0)
Mark Salyzyna0140042015-03-13 06:50:32 -070088#define trylock() (0) /* success */
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080089#define unlock() ((void)0)
90
91#endif /* !defined(_WIN32) */
92
Mark Salyzyn154f4602014-02-20 14:59:07 -080093#if FAKE_LOG_DEVICE
Mark Salyzyn083b0372015-12-04 10:59:45 -080094static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1, -1 };
Mark Salyzyna04464a2014-04-30 08:50:53 -070095#else
96static int logd_fd = -1;
Mark Salyzynd91ab582014-12-15 10:52:12 -080097static int pstore_fd = -1;
Mark Salyzyn154f4602014-02-20 14:59:07 -080098#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080099
100/*
101 * This is used by the C++ code to decide if it should write logs through
Mark Salyzyn154f4602014-02-20 14:59:07 -0800102 * the C code. Basically, if /dev/socket/logd is available, we're running in
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800103 * the simulator rather than a desktop tool and want to use the device.
104 */
105static enum {
Chris Pearson19299902010-06-02 16:25:35 -0700106 kLogUninitialized, kLogNotAvailable, kLogAvailable
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800107} g_log_status = kLogUninitialized;
Mark Salyzyn53016d82015-02-04 12:28:47 -0800108
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800109int __android_log_dev_available(void)
110{
111 if (g_log_status == kLogUninitialized) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800112 if (access("/dev/socket/logdw", W_OK) == 0)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800113 g_log_status = kLogAvailable;
114 else
115 g_log_status = kLogNotAvailable;
116 }
117
118 return (g_log_status == kLogAvailable);
119}
120
Mark Salyzyn8245af12014-03-25 13:45:33 -0700121/* log_init_lock assumed */
122static int __write_to_log_initialize()
123{
124 int i, ret = 0;
125
126#if FAKE_LOG_DEVICE
127 for (i = 0; i < LOG_ID_MAX; i++) {
128 char buf[sizeof("/dev/log_system")];
129 snprintf(buf, sizeof(buf), "/dev/log_%s", android_log_id_to_name(i));
130 log_fds[i] = fakeLogOpen(buf, O_WRONLY);
131 }
132#else
Mark Salyzyn0d00a442015-03-13 12:15:57 -0700133 if (pstore_fd < 0) {
134 pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY));
Mark Salyzyn8245af12014-03-25 13:45:33 -0700135 }
136
Mark Salyzyn0d00a442015-03-13 12:15:57 -0700137 if (logd_fd < 0) {
138 i = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0));
139 if (i < 0) {
140 ret = -errno;
141 } else if (TEMP_FAILURE_RETRY(fcntl(i, F_SETFL, O_NONBLOCK)) < 0) {
Mark Salyzyn8245af12014-03-25 13:45:33 -0700142 ret = -errno;
143 close(i);
Mark Salyzyn0d00a442015-03-13 12:15:57 -0700144 } else {
145 struct sockaddr_un un;
146 memset(&un, 0, sizeof(struct sockaddr_un));
147 un.sun_family = AF_UNIX;
148 strcpy(un.sun_path, "/dev/socket/logdw");
149
150 if (TEMP_FAILURE_RETRY(connect(i, (struct sockaddr *)&un,
151 sizeof(struct sockaddr_un))) < 0) {
152 ret = -errno;
153 close(i);
154 } else {
155 logd_fd = i;
156 }
Mark Salyzyn8245af12014-03-25 13:45:33 -0700157 }
158 }
Mark Salyzyn8245af12014-03-25 13:45:33 -0700159#endif
160
161 return ret;
162}
163
Mark Salyzyn53016d82015-02-04 12:28:47 -0800164static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800165{
166 ssize_t ret;
Mark Salyzyn8245af12014-03-25 13:45:33 -0700167#if FAKE_LOG_DEVICE
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800168 int log_fd;
169
170 if (/*(int)log_id >= 0 &&*/ (int)log_id < (int)LOG_ID_MAX) {
171 log_fd = log_fds[(int)log_id];
172 } else {
Mark Salyzyn8245af12014-03-25 13:45:33 -0700173 return -EBADF;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800174 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800175 do {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800176 ret = fakeLogWritev(log_fd, vec, nr);
Mark Salyzyn8245af12014-03-25 13:45:33 -0700177 if (ret < 0) {
178 ret = -errno;
179 }
180 } while (ret == -EINTR);
Mark Salyzyn154f4602014-02-20 14:59:07 -0800181#else
Mark Salyzynd91ab582014-12-15 10:52:12 -0800182 static const unsigned header_length = 2;
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700183 struct iovec newVec[nr + header_length];
Mark Salyzynd91ab582014-12-15 10:52:12 -0800184 android_log_header_t header;
185 android_pmsg_log_header_t pmsg_header;
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700186 struct timespec ts;
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700187 size_t i, payload_size;
Mark Salyzyn076ba812014-05-29 17:53:41 -0700188 static uid_t last_uid = AID_ROOT; /* logd *always* starts up as AID_ROOT */
Mark Salyzynd91ab582014-12-15 10:52:12 -0800189 static pid_t last_pid = (pid_t) -1;
Mark Salyzynd45d36e2015-02-12 15:14:26 -0800190 static atomic_int_fast32_t dropped;
Mark Salyzyn083b0372015-12-04 10:59:45 -0800191 static atomic_int_fast32_t dropped_security;
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700192
Mark Salyzyn31f7df52015-03-13 15:57:11 -0700193 if (!nr) {
194 return -EINVAL;
195 }
196
Mark Salyzyn076ba812014-05-29 17:53:41 -0700197 if (last_uid == AID_ROOT) { /* have we called to get the UID yet? */
198 last_uid = getuid();
199 }
Mark Salyzynd91ab582014-12-15 10:52:12 -0800200 if (last_pid == (pid_t) -1) {
201 last_pid = getpid();
Mark Salyzyn154f4602014-02-20 14:59:07 -0800202 }
Mark Salyzyn083b0372015-12-04 10:59:45 -0800203 if (log_id == LOG_ID_SECURITY) {
Mark Salyzyna0140042015-03-13 06:50:32 -0700204 if (vec[0].iov_len < 4) {
205 return -EINVAL;
206 }
Mark Salyzyn9107c462016-01-26 13:02:20 -0800207 /* Matches clientHasLogCredentials() in logd */
208 if ((last_uid != AID_SYSTEM) && (last_uid != AID_ROOT) && (last_uid != AID_LOG)) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800209 uid_t uid = geteuid();
Mark Salyzyn9107c462016-01-26 13:02:20 -0800210 if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800211 gid_t gid = getgid();
Mark Salyzyn9107c462016-01-26 13:02:20 -0800212 if ((gid != AID_SYSTEM) && (gid != AID_ROOT) && (gid != AID_LOG)) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800213 gid = getegid();
Mark Salyzyn9107c462016-01-26 13:02:20 -0800214 if ((gid != AID_SYSTEM) && (gid != AID_ROOT) && (gid != AID_LOG)) {
215 int num_groups;
216 gid_t *groups;
217
218 num_groups = getgroups(0, NULL);
219 if (num_groups <= 0) {
220 return -EPERM;
221 }
222 groups = calloc(num_groups, sizeof(gid_t));
223 if (!groups) {
224 return -ENOMEM;
225 }
226 num_groups = getgroups(num_groups, groups);
227 while (num_groups > 0) {
228 if (groups[num_groups - 1] == AID_LOG) {
229 break;
230 }
231 --num_groups;
232 }
233 free(groups);
234 if (num_groups <= 0) {
235 return -EPERM;
236 }
Mark Salyzyn083b0372015-12-04 10:59:45 -0800237 }
238 }
239 }
240 }
241 if (!__android_log_security()) {
Mark Salyzyna0140042015-03-13 06:50:32 -0700242 atomic_store(&dropped_security, 0);
243 return -EPERM;
244 }
245 } else if (log_id == LOG_ID_EVENTS) {
Mark Salyzyn0ee8de32016-01-06 21:17:43 +0000246 static atomic_uintptr_t map;
247 int ret;
248 const char *tag;
249 EventTagMap *m, *f;
250
Mark Salyzyna0140042015-03-13 06:50:32 -0700251 if (vec[0].iov_len < 4) {
252 return -EINVAL;
253 }
254
Mark Salyzyn0ee8de32016-01-06 21:17:43 +0000255 tag = NULL;
256 f = NULL;
257 m = (EventTagMap *)atomic_load(&map);
258
259 if (!m) {
260 ret = trylock();
261 m = (EventTagMap *)atomic_load(&map); /* trylock flush cache */
Mark Salyzyna0140042015-03-13 06:50:32 -0700262 if (!m) {
Mark Salyzyn0ee8de32016-01-06 21:17:43 +0000263 m = android_openEventTagMap(EVENT_TAG_MAP_FILE);
264 if (ret) { /* trylock failed, use local copy, mark for close */
265 f = m;
266 } else {
267 if (!m) { /* One chance to open map file */
268 m = (EventTagMap *)(uintptr_t)-1LL;
Mark Salyzyna0140042015-03-13 06:50:32 -0700269 }
Mark Salyzyn0ee8de32016-01-06 21:17:43 +0000270 atomic_store(&map, (uintptr_t)m);
Mark Salyzyna0140042015-03-13 06:50:32 -0700271 }
272 }
Mark Salyzyn0ee8de32016-01-06 21:17:43 +0000273 if (!ret) { /* trylock succeeded, unlock */
274 unlock();
275 }
276 }
277 if (m && (m != (EventTagMap *)(uintptr_t)-1LL)) {
278 tag = android_lookupEventTag(
Mark Salyzyna0140042015-03-13 06:50:32 -0700279 m,
280 htole32(((uint32_t *)vec[0].iov_base)[0]));
Mark Salyzyn0ee8de32016-01-06 21:17:43 +0000281 }
282 ret = __android_log_is_loggable(ANDROID_LOG_INFO,
283 tag,
284 ANDROID_LOG_VERBOSE);
285 if (f) { /* local copy marked for close */
286 android_closeEventTagMap(f);
287 }
288 if (!ret) {
289 return -EPERM;
Mark Salyzyna0140042015-03-13 06:50:32 -0700290 }
291 } else {
292 /* Validate the incoming tag, tag content can not split across iovec */
293 char prio = ANDROID_LOG_VERBOSE;
294 const char *tag = vec[0].iov_base;
295 size_t len = vec[0].iov_len;
296 if (!tag) {
297 len = 0;
298 }
299 if (len > 0) {
300 prio = *tag;
301 if (len > 1) {
302 --len;
303 ++tag;
304 } else {
305 len = vec[1].iov_len;
306 tag = ((const char *)vec[1].iov_base);
307 if (!tag) {
308 len = 0;
309 }
310 }
311 }
312 /* tag must be nul terminated */
313 if (strnlen(tag, len) >= len) {
314 tag = NULL;
315 }
316
317 if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800318 return -EPERM;
319 }
320 }
Mark Salyzyna0140042015-03-13 06:50:32 -0700321
Mark Salyzynb992d0d2014-03-20 16:09:38 -0700322 /*
323 * struct {
Mark Salyzyn53016d82015-02-04 12:28:47 -0800324 * // what we provide to pstore
Mark Salyzynd91ab582014-12-15 10:52:12 -0800325 * android_pmsg_log_header_t pmsg_header;
326 * // what we provide to socket
Mark Salyzyn7a809402015-01-16 13:38:07 -0800327 * android_log_header_t header;
Mark Salyzynb992d0d2014-03-20 16:09:38 -0700328 * // caller provides
329 * union {
330 * struct {
331 * char prio;
332 * char payload[];
333 * } string;
334 * struct {
335 * uint32_t tag
336 * char payload[];
337 * } binary;
338 * };
339 * };
340 */
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700341
Mark Salyzynba7a9a02015-12-01 15:57:25 -0800342 clock_gettime(android_log_clockid(), &ts);
Mark Salyzyn076ba812014-05-29 17:53:41 -0700343
Mark Salyzynd91ab582014-12-15 10:52:12 -0800344 pmsg_header.magic = LOGGER_MAGIC;
345 pmsg_header.len = sizeof(pmsg_header) + sizeof(header);
346 pmsg_header.uid = last_uid;
347 pmsg_header.pid = last_pid;
348
Mark Salyzyn7a809402015-01-16 13:38:07 -0800349 header.tid = gettid();
350 header.realtime.tv_sec = ts.tv_sec;
351 header.realtime.tv_nsec = ts.tv_nsec;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800352
Mark Salyzynd91ab582014-12-15 10:52:12 -0800353 newVec[0].iov_base = (unsigned char *) &pmsg_header;
354 newVec[0].iov_len = sizeof(pmsg_header);
355 newVec[1].iov_base = (unsigned char *) &header;
356 newVec[1].iov_len = sizeof(header);
Mark Salyzyn154f4602014-02-20 14:59:07 -0800357
Mark Salyzynd45d36e2015-02-12 15:14:26 -0800358 if (logd_fd > 0) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800359 int32_t snapshot = atomic_exchange_explicit(&dropped_security, 0,
360 memory_order_relaxed);
361 if (snapshot) {
362 android_log_event_int_t buffer;
363
364 header.id = LOG_ID_SECURITY;
365 buffer.header.tag = htole32(LIBLOG_LOG_TAG);
366 buffer.payload.type = EVENT_TYPE_INT;
367 buffer.payload.data = htole32(snapshot);
368
369 newVec[2].iov_base = &buffer;
370 newVec[2].iov_len = sizeof(buffer);
371
372 ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, 2));
373 if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
374 atomic_fetch_add_explicit(&dropped_security, snapshot,
375 memory_order_relaxed);
376 }
377 }
378 snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
Mark Salyzyna0140042015-03-13 06:50:32 -0700379 if (snapshot && __android_log_is_loggable(ANDROID_LOG_INFO,
380 "liblog",
381 ANDROID_LOG_VERBOSE)) {
Mark Salyzynd45d36e2015-02-12 15:14:26 -0800382 android_log_event_int_t buffer;
383
384 header.id = LOG_ID_EVENTS;
385 buffer.header.tag = htole32(LIBLOG_LOG_TAG);
386 buffer.payload.type = EVENT_TYPE_INT;
387 buffer.payload.data = htole32(snapshot);
388
389 newVec[2].iov_base = &buffer;
390 newVec[2].iov_len = sizeof(buffer);
391
392 ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, 2));
393 if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800394 atomic_fetch_add_explicit(&dropped, snapshot,
395 memory_order_relaxed);
Mark Salyzynd45d36e2015-02-12 15:14:26 -0800396 }
397 }
398 }
399
400 header.id = log_id;
401
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700402 for (payload_size = 0, i = header_length; i < nr + header_length; i++) {
403 newVec[i].iov_base = vec[i - header_length].iov_base;
404 payload_size += newVec[i].iov_len = vec[i - header_length].iov_len;
405
406 if (payload_size > LOGGER_ENTRY_MAX_PAYLOAD) {
407 newVec[i].iov_len -= payload_size - LOGGER_ENTRY_MAX_PAYLOAD;
408 if (newVec[i].iov_len) {
409 ++i;
410 }
Mark Salyzynd91ab582014-12-15 10:52:12 -0800411 payload_size = LOGGER_ENTRY_MAX_PAYLOAD;
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700412 break;
413 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800414 }
Mark Salyzynd91ab582014-12-15 10:52:12 -0800415 pmsg_header.len += payload_size;
416
417 if (pstore_fd >= 0) {
418 TEMP_FAILURE_RETRY(writev(pstore_fd, newVec, i));
419 }
420
421 if (last_uid == AID_LOGD) { /* logd, after initialization and priv drop */
422 /*
423 * ignore log messages we send to ourself (logd).
424 * Such log messages are often generated by libraries we depend on
425 * which use standard Android logging.
426 */
427 return 0;
428 }
429
430 if (logd_fd < 0) {
431 return -EBADF;
432 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800433
Mark Salyzyn8245af12014-03-25 13:45:33 -0700434 /*
435 * The write below could be lost, but will never block.
436 *
Mark Salyzynd91ab582014-12-15 10:52:12 -0800437 * To logd, we drop the pmsg_header
438 *
Mark Salyzyn8245af12014-03-25 13:45:33 -0700439 * ENOTCONN occurs if logd dies.
440 * EAGAIN occurs if logd is overloaded.
441 */
Mark Salyzynd91ab582014-12-15 10:52:12 -0800442 ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1));
Mark Salyzyn8245af12014-03-25 13:45:33 -0700443 if (ret < 0) {
444 ret = -errno;
445 if (ret == -ENOTCONN) {
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800446 lock();
Mark Salyzyn0d00a442015-03-13 12:15:57 -0700447 close(logd_fd);
448 logd_fd = -1;
Mark Salyzyn8245af12014-03-25 13:45:33 -0700449 ret = __write_to_log_initialize();
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800450 unlock();
Mark Salyzyn8245af12014-03-25 13:45:33 -0700451
452 if (ret < 0) {
453 return ret;
454 }
455
Mark Salyzynd91ab582014-12-15 10:52:12 -0800456 ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1));
Mark Salyzyn8245af12014-03-25 13:45:33 -0700457 if (ret < 0) {
458 ret = -errno;
459 }
460 }
461 }
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700462
Mark Salyzyn7a809402015-01-16 13:38:07 -0800463 if (ret > (ssize_t)sizeof(header)) {
464 ret -= sizeof(header);
Mark Salyzynd45d36e2015-02-12 15:14:26 -0800465 } else if (ret == -EAGAIN) {
466 atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800467 if (log_id == LOG_ID_SECURITY) {
468 atomic_fetch_add_explicit(&dropped_security, 1,
469 memory_order_relaxed);
470 }
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700471 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800472#endif
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700473
474 return ret;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800475}
476
Mark Salyzyn154f4602014-02-20 14:59:07 -0800477#if FAKE_LOG_DEVICE
478static const char *LOG_NAME[LOG_ID_MAX] = {
479 [LOG_ID_MAIN] = "main",
480 [LOG_ID_RADIO] = "radio",
481 [LOG_ID_EVENTS] = "events",
Mark Salyzyn99f47a92014-04-07 14:58:08 -0700482 [LOG_ID_SYSTEM] = "system",
Mark Salyzyn440e1092014-10-10 15:13:15 -0700483 [LOG_ID_CRASH] = "crash",
Mark Salyzyn083b0372015-12-04 10:59:45 -0800484 [LOG_ID_SECURITY] = "security",
Mark Salyzyn440e1092014-10-10 15:13:15 -0700485 [LOG_ID_KERNEL] = "kernel",
Mark Salyzyn154f4602014-02-20 14:59:07 -0800486};
487
Adam Lesinskia1ac84c2014-10-20 12:31:30 -0700488const char *android_log_id_to_name(log_id_t log_id)
Mark Salyzyn154f4602014-02-20 14:59:07 -0800489{
490 if (log_id >= LOG_ID_MAX) {
491 log_id = LOG_ID_MAIN;
492 }
493 return LOG_NAME[log_id];
494}
495#endif
496
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800497static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
498{
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800499 lock();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800500
501 if (write_to_log == __write_to_log_init) {
Mark Salyzyn8245af12014-03-25 13:45:33 -0700502 int ret;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800503
Mark Salyzyn8245af12014-03-25 13:45:33 -0700504 ret = __write_to_log_initialize();
505 if (ret < 0) {
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800506 unlock();
Mark Salyzyn0d00a442015-03-13 12:15:57 -0700507#if (FAKE_LOG_DEVICE == 0)
508 if (pstore_fd >= 0) {
509 __write_to_log_daemon(log_id, vec, nr);
510 }
511#endif
Mark Salyzyn8245af12014-03-25 13:45:33 -0700512 return ret;
513 }
514
Mark Salyzyn53016d82015-02-04 12:28:47 -0800515 write_to_log = __write_to_log_daemon;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800516 }
517
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800518 unlock();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800519
520 return write_to_log(log_id, vec, nr);
521}
522
523int __android_log_write(int prio, const char *tag, const char *msg)
524{
Dan Albertc7aadc42015-04-02 10:32:44 -0700525 return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800526}
527
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800528int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg)
529{
530 struct iovec vec[3];
Wink Saville3761e962012-11-28 12:20:19 -0800531 char tmp_tag[32];
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800532
533 if (!tag)
534 tag = "";
535
536 /* XXX: This needs to go! */
Wink Saville3761e962012-11-28 12:20:19 -0800537 if ((bufID != LOG_ID_RADIO) &&
538 (!strcmp(tag, "HTC_RIL") ||
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800539 !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
Jeff Sharkey84dcf092012-08-13 11:27:30 -0700540 !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800541 !strcmp(tag, "AT") ||
542 !strcmp(tag, "GSM") ||
543 !strcmp(tag, "STK") ||
544 !strcmp(tag, "CDMA") ||
545 !strcmp(tag, "PHONE") ||
Wink Saville3761e962012-11-28 12:20:19 -0800546 !strcmp(tag, "SMS"))) {
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800547 bufID = LOG_ID_RADIO;
Mark Salyzyn8245af12014-03-25 13:45:33 -0700548 /* Inform third party apps/ril/radio.. to use Rlog or RLOG */
Wink Saville3761e962012-11-28 12:20:19 -0800549 snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
550 tag = tmp_tag;
551 }
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800552
Dan Albertc7aadc42015-04-02 10:32:44 -0700553#if __BIONIC__
554 if (prio == ANDROID_LOG_FATAL) {
555 android_set_abort_message(msg);
556 }
557#endif
558
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800559 vec[0].iov_base = (unsigned char *) &prio;
560 vec[0].iov_len = 1;
561 vec[1].iov_base = (void *) tag;
562 vec[1].iov_len = strlen(tag) + 1;
563 vec[2].iov_base = (void *) msg;
564 vec[2].iov_len = strlen(msg) + 1;
565
566 return write_to_log(bufID, vec, 3);
567}
568
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800569int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap)
570{
Chris Pearson19299902010-06-02 16:25:35 -0700571 char buf[LOG_BUF_SIZE];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800572
573 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
574
575 return __android_log_write(prio, tag, buf);
576}
577
578int __android_log_print(int prio, const char *tag, const char *fmt, ...)
579{
580 va_list ap;
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800581 char buf[LOG_BUF_SIZE];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800582
583 va_start(ap, fmt);
584 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
585 va_end(ap);
586
587 return __android_log_write(prio, tag, buf);
588}
589
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800590int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...)
591{
592 va_list ap;
593 char buf[LOG_BUF_SIZE];
594
595 va_start(ap, fmt);
596 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
597 va_end(ap);
598
599 return __android_log_buf_write(bufID, prio, tag, buf);
600}
601
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800602void __android_log_assert(const char *cond, const char *tag,
Mark Salyzyncf4aa032013-11-22 07:54:30 -0800603 const char *fmt, ...)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800604{
Chris Pearson19299902010-06-02 16:25:35 -0700605 char buf[LOG_BUF_SIZE];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800606
Chris Pearson19299902010-06-02 16:25:35 -0700607 if (fmt) {
608 va_list ap;
609 va_start(ap, fmt);
610 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
611 va_end(ap);
612 } else {
613 /* Msg not provided, log condition. N.B. Do not use cond directly as
614 * format string as it could contain spurious '%' syntax (e.g.
615 * "%d" in "blocks%devs == 0").
616 */
617 if (cond)
618 snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond);
619 else
620 strcpy(buf, "Unspecified assertion failed");
621 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800622
623 __android_log_write(ANDROID_LOG_FATAL, tag, buf);
Elliott Hughes02ff4b82015-03-07 11:21:37 -0800624 abort(); /* abort so we have a chance to debug the situation */
Elliott Hughesda6b2e22014-04-23 14:57:32 -0700625 /* NOTREACHED */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800626}
627
628int __android_log_bwrite(int32_t tag, const void *payload, size_t len)
629{
630 struct iovec vec[2];
631
632 vec[0].iov_base = &tag;
633 vec[0].iov_len = sizeof(tag);
634 vec[1].iov_base = (void*)payload;
635 vec[1].iov_len = len;
636
637 return write_to_log(LOG_ID_EVENTS, vec, 2);
638}
639
Mark Salyzyn083b0372015-12-04 10:59:45 -0800640int __android_log_security_bwrite(int32_t tag, const void *payload, size_t len)
641{
642 struct iovec vec[2];
643
644 vec[0].iov_base = &tag;
645 vec[0].iov_len = sizeof(tag);
646 vec[1].iov_base = (void*)payload;
647 vec[1].iov_len = len;
648
649 return write_to_log(LOG_ID_SECURITY, vec, 2);
650}
651
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800652/*
653 * Like __android_log_bwrite, but takes the type as well. Doesn't work
654 * for the general case where we're generating lists of stuff, but very
655 * handy if we just want to dump an integer into the log.
656 */
657int __android_log_btwrite(int32_t tag, char type, const void *payload,
Mark Salyzyn154f4602014-02-20 14:59:07 -0800658 size_t len)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800659{
660 struct iovec vec[3];
661
662 vec[0].iov_base = &tag;
663 vec[0].iov_len = sizeof(tag);
664 vec[1].iov_base = &type;
665 vec[1].iov_len = sizeof(type);
666 vec[2].iov_base = (void*)payload;
667 vec[2].iov_len = len;
668
669 return write_to_log(LOG_ID_EVENTS, vec, 3);
670}
Nick Kralevich2a4d05a2014-07-01 10:57:16 -0700671
672/*
673 * Like __android_log_bwrite, but used for writing strings to the
674 * event log.
675 */
676int __android_log_bswrite(int32_t tag, const char *payload)
677{
678 struct iovec vec[4];
679 char type = EVENT_TYPE_STRING;
680 uint32_t len = strlen(payload);
681
682 vec[0].iov_base = &tag;
683 vec[0].iov_len = sizeof(tag);
684 vec[1].iov_base = &type;
685 vec[1].iov_len = sizeof(type);
686 vec[2].iov_base = &len;
687 vec[2].iov_len = sizeof(len);
688 vec[3].iov_base = (void*)payload;
689 vec[3].iov_len = len;
690
691 return write_to_log(LOG_ID_EVENTS, vec, 4);
692}
Rubin Xud545d292016-01-10 22:31:19 +0000693
694/*
695 * Like __android_log_security_bwrite, but used for writing strings to the
696 * security log.
697 */
698int __android_log_security_bswrite(int32_t tag, const char *payload)
699{
700 struct iovec vec[4];
701 char type = EVENT_TYPE_STRING;
702 uint32_t len = strlen(payload);
703
704 vec[0].iov_base = &tag;
705 vec[0].iov_len = sizeof(tag);
706 vec[1].iov_base = &type;
707 vec[1].iov_len = sizeof(type);
708 vec[2].iov_base = &len;
709 vec[2].iov_len = sizeof(len);
710 vec[3].iov_base = (void*)payload;
711 vec[3].iov_len = len;
712
713 return write_to_log(LOG_ID_SECURITY, vec, 4);
714}