logger_write.c revision facf94c74a2cc44f294c4789d36d5c7281c7bc3f
1/* 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 <errno.h> 18#include <stdatomic.h> 19#include <stdlib.h> 20#include <string.h> 21#include <sys/time.h> 22 23#ifdef __BIONIC__ 24#include <android/set_abort_message.h> 25#endif 26 27#include <log/event_tag_map.h> 28#include <log/logd.h> 29#include <log/logger.h> 30#include <log/log_read.h> 31#include <private/android_filesystem_config.h> 32#include <private/android_logger.h> 33 34#include "config_write.h" 35#include "log_portability.h" 36#include "logger.h" 37 38#define LOG_BUF_SIZE 1024 39 40static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr); 41static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init; 42 43/* 44 * This is used by the C++ code to decide if it should write logs through 45 * the C code. Basically, if /dev/socket/logd is available, we're running in 46 * the simulator rather than a desktop tool and want to use the device. 47 */ 48static enum { 49 kLogUninitialized, kLogNotAvailable, kLogAvailable 50} g_log_status = kLogUninitialized; 51 52LIBLOG_ABI_PUBLIC int __android_log_dev_available() 53{ 54 struct android_log_transport_write *node; 55 size_t i; 56 57 if (list_empty(&__android_log_transport_write)) { 58 return kLogUninitialized; 59 } 60 for (i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) { 61 write_transport_for_each(node, &__android_log_transport_write) { 62 if (node->write && 63 (!node->available || ((*node->available)(i) >= 0))) { 64 return kLogAvailable; 65 } 66 } 67 } 68 return kLogNotAvailable; 69} 70 71/* log_init_lock assumed */ 72static int __write_to_log_initialize() 73{ 74 struct android_log_transport_write *transport; 75 struct listnode *n; 76 int i = 0, ret = 0; 77 78 __android_log_config_write(); 79 write_transport_for_each_safe(transport, n, &__android_log_transport_write) { 80 if (!transport->open || ((*transport->open)() < 0)) { 81 if (transport->close) { 82 (*transport->close)(); 83 } 84 list_remove(&transport->node); 85 continue; 86 } 87 ++ret; 88 } 89 write_transport_for_each_safe(transport, n, &__android_log_persist_write) { 90 if (!transport->open || ((*transport->open)() < 0)) { 91 if (transport->close) { 92 (*transport->close)(); 93 } 94 list_remove(&transport->node); 95 continue; 96 } 97 ++i; 98 } 99 if (!ret && !i) { 100 return -ENODEV; 101 } 102 103 return ret; 104} 105 106/* 107 * Extract a 4-byte value from a byte stream. le32toh open coded 108 */ 109static inline uint32_t get4LE(const uint8_t* src) 110{ 111 return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); 112} 113 114static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr) 115{ 116 struct android_log_transport_write *node; 117 int ret; 118 struct timespec ts; 119 size_t len, i; 120 121 for (len = i = 0; i < nr; ++i) { 122 len += vec[i].iov_len; 123 } 124 if (!len) { 125 return -EINVAL; 126 } 127 128#if defined(__BIONIC__) 129 if (log_id == LOG_ID_SECURITY) { 130 uid_t uid; 131 132 if (vec[0].iov_len < 4) { 133 return -EINVAL; 134 } 135 136 uid = __android_log_uid(); 137 /* Matches clientHasLogCredentials() in logd */ 138 if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) { 139 uid = geteuid(); 140 if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) { 141 gid_t gid = getgid(); 142 if ((gid != AID_SYSTEM) && 143 (gid != AID_ROOT) && 144 (gid != AID_LOG)) { 145 gid = getegid(); 146 if ((gid != AID_SYSTEM) && 147 (gid != AID_ROOT) && 148 (gid != AID_LOG)) { 149 int num_groups; 150 gid_t *groups; 151 152 num_groups = getgroups(0, NULL); 153 if (num_groups <= 0) { 154 return -EPERM; 155 } 156 groups = calloc(num_groups, sizeof(gid_t)); 157 if (!groups) { 158 return -ENOMEM; 159 } 160 num_groups = getgroups(num_groups, groups); 161 while (num_groups > 0) { 162 if (groups[num_groups - 1] == AID_LOG) { 163 break; 164 } 165 --num_groups; 166 } 167 free(groups); 168 if (num_groups <= 0) { 169 return -EPERM; 170 } 171 } 172 } 173 } 174 } 175 if (!__android_log_security()) { 176 /* If only we could reset downstream logd counter */ 177 return -EPERM; 178 } 179 } else if (log_id == LOG_ID_EVENTS) { 180 static atomic_uintptr_t map; 181 const char *tag; 182 EventTagMap *m, *f; 183 184 if (vec[0].iov_len < 4) { 185 return -EINVAL; 186 } 187 188 tag = NULL; 189 f = NULL; 190 m = (EventTagMap *)atomic_load(&map); 191 192 if (!m) { 193 ret = __android_log_trylock(); 194 m = (EventTagMap *)atomic_load(&map); /* trylock flush cache */ 195 if (!m) { 196 m = android_openEventTagMap(EVENT_TAG_MAP_FILE); 197 if (ret) { /* trylock failed, use local copy, mark for close */ 198 f = m; 199 } else { 200 if (!m) { /* One chance to open map file */ 201 m = (EventTagMap *)(uintptr_t)-1LL; 202 } 203 atomic_store(&map, (uintptr_t)m); 204 } 205 } 206 if (!ret) { /* trylock succeeded, unlock */ 207 __android_log_unlock(); 208 } 209 } 210 if (m && (m != (EventTagMap *)(uintptr_t)-1LL)) { 211 tag = android_lookupEventTag(m, get4LE(vec[0].iov_base)); 212 } 213 ret = __android_log_is_loggable(ANDROID_LOG_INFO, 214 tag, 215 ANDROID_LOG_VERBOSE); 216 if (f) { /* local copy marked for close */ 217 android_closeEventTagMap(f); 218 } 219 if (!ret) { 220 return -EPERM; 221 } 222 } else { 223 /* Validate the incoming tag, tag content can not split across iovec */ 224 char prio = ANDROID_LOG_VERBOSE; 225 const char *tag = vec[0].iov_base; 226 size_t len = vec[0].iov_len; 227 if (!tag) { 228 len = 0; 229 } 230 if (len > 0) { 231 prio = *tag; 232 if (len > 1) { 233 --len; 234 ++tag; 235 } else { 236 len = vec[1].iov_len; 237 tag = ((const char *)vec[1].iov_base); 238 if (!tag) { 239 len = 0; 240 } 241 } 242 } 243 /* tag must be nul terminated */ 244 if (strnlen(tag, len) >= len) { 245 tag = NULL; 246 } 247 248 if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) { 249 return -EPERM; 250 } 251 } 252 253 clock_gettime(android_log_clockid(), &ts); 254#else 255 /* simulate clock_gettime(CLOCK_REALTIME, &ts); */ 256 { 257 struct timeval tv; 258 gettimeofday(&tv, NULL); 259 ts.tv_sec = tv.tv_sec; 260 ts.tv_nsec = tv.tv_usec * 1000; 261 } 262#endif 263 264 ret = 0; 265 write_transport_for_each(node, &__android_log_transport_write) { 266 if (node->write) { 267 ssize_t retval; 268 retval = (*node->write)(log_id, &ts, vec, nr); 269 if (ret >= 0) { 270 ret = retval; 271 } 272 } 273 } 274 275 write_transport_for_each(node, &__android_log_persist_write) { 276 if (node->write) { 277 (void)(*node->write)(log_id, &ts, vec, nr); 278 } 279 } 280 281 return ret; 282} 283 284static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr) 285{ 286 __android_log_lock(); 287 288 if (write_to_log == __write_to_log_init) { 289 int ret; 290 291 ret = __write_to_log_initialize(); 292 if (ret < 0) { 293 __android_log_unlock(); 294 if (!list_empty(&__android_log_persist_write)) { 295 __write_to_log_daemon(log_id, vec, nr); 296 } 297 return ret; 298 } 299 300 write_to_log = __write_to_log_daemon; 301 } 302 303 __android_log_unlock(); 304 305 return write_to_log(log_id, vec, nr); 306} 307 308LIBLOG_ABI_PUBLIC int __android_log_write(int prio, const char *tag, 309 const char *msg) 310{ 311 return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg); 312} 313 314LIBLOG_ABI_PUBLIC int __android_log_buf_write(int bufID, int prio, 315 const char *tag, const char *msg) 316{ 317 struct iovec vec[3]; 318 char tmp_tag[32]; 319 320 if (!tag) 321 tag = ""; 322 323 /* XXX: This needs to go! */ 324 if ((bufID != LOG_ID_RADIO) && 325 (!strcmp(tag, "HTC_RIL") || 326 !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */ 327 !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */ 328 !strcmp(tag, "AT") || 329 !strcmp(tag, "GSM") || 330 !strcmp(tag, "STK") || 331 !strcmp(tag, "CDMA") || 332 !strcmp(tag, "PHONE") || 333 !strcmp(tag, "SMS"))) { 334 bufID = LOG_ID_RADIO; 335 /* Inform third party apps/ril/radio.. to use Rlog or RLOG */ 336 snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag); 337 tag = tmp_tag; 338 } 339 340#if __BIONIC__ 341 if (prio == ANDROID_LOG_FATAL) { 342 android_set_abort_message(msg); 343 } 344#endif 345 346 vec[0].iov_base = (unsigned char *) &prio; 347 vec[0].iov_len = 1; 348 vec[1].iov_base = (void *) tag; 349 vec[1].iov_len = strlen(tag) + 1; 350 vec[2].iov_base = (void *) msg; 351 vec[2].iov_len = strlen(msg) + 1; 352 353 return write_to_log(bufID, vec, 3); 354} 355 356LIBLOG_ABI_PUBLIC int __android_log_vprint(int prio, const char *tag, 357 const char *fmt, va_list ap) 358{ 359 char buf[LOG_BUF_SIZE]; 360 361 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); 362 363 return __android_log_write(prio, tag, buf); 364} 365 366LIBLOG_ABI_PUBLIC int __android_log_print(int prio, const char *tag, 367 const char *fmt, ...) 368{ 369 va_list ap; 370 char buf[LOG_BUF_SIZE]; 371 372 va_start(ap, fmt); 373 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); 374 va_end(ap); 375 376 return __android_log_write(prio, tag, buf); 377} 378 379LIBLOG_ABI_PUBLIC int __android_log_buf_print(int bufID, int prio, 380 const char *tag, 381 const char *fmt, ...) 382{ 383 va_list ap; 384 char buf[LOG_BUF_SIZE]; 385 386 va_start(ap, fmt); 387 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); 388 va_end(ap); 389 390 return __android_log_buf_write(bufID, prio, tag, buf); 391} 392 393LIBLOG_ABI_PUBLIC void __android_log_assert(const char *cond, const char *tag, 394 const char *fmt, ...) 395{ 396 char buf[LOG_BUF_SIZE]; 397 398 if (fmt) { 399 va_list ap; 400 va_start(ap, fmt); 401 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); 402 va_end(ap); 403 } else { 404 /* Msg not provided, log condition. N.B. Do not use cond directly as 405 * format string as it could contain spurious '%' syntax (e.g. 406 * "%d" in "blocks%devs == 0"). 407 */ 408 if (cond) 409 snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond); 410 else 411 strcpy(buf, "Unspecified assertion failed"); 412 } 413 414 __android_log_write(ANDROID_LOG_FATAL, tag, buf); 415 abort(); /* abort so we have a chance to debug the situation */ 416 /* NOTREACHED */ 417} 418 419LIBLOG_ABI_PUBLIC int __android_log_bwrite(int32_t tag, 420 const void *payload, size_t len) 421{ 422 struct iovec vec[2]; 423 424 vec[0].iov_base = &tag; 425 vec[0].iov_len = sizeof(tag); 426 vec[1].iov_base = (void*)payload; 427 vec[1].iov_len = len; 428 429 return write_to_log(LOG_ID_EVENTS, vec, 2); 430} 431 432LIBLOG_ABI_PUBLIC int __android_log_security_bwrite(int32_t tag, 433 const void *payload, 434 size_t len) 435{ 436 struct iovec vec[2]; 437 438 vec[0].iov_base = &tag; 439 vec[0].iov_len = sizeof(tag); 440 vec[1].iov_base = (void*)payload; 441 vec[1].iov_len = len; 442 443 return write_to_log(LOG_ID_SECURITY, vec, 2); 444} 445 446/* 447 * Like __android_log_bwrite, but takes the type as well. Doesn't work 448 * for the general case where we're generating lists of stuff, but very 449 * handy if we just want to dump an integer into the log. 450 */ 451LIBLOG_ABI_PUBLIC int __android_log_btwrite(int32_t tag, char type, 452 const void *payload, size_t len) 453{ 454 struct iovec vec[3]; 455 456 vec[0].iov_base = &tag; 457 vec[0].iov_len = sizeof(tag); 458 vec[1].iov_base = &type; 459 vec[1].iov_len = sizeof(type); 460 vec[2].iov_base = (void*)payload; 461 vec[2].iov_len = len; 462 463 return write_to_log(LOG_ID_EVENTS, vec, 3); 464} 465 466/* 467 * Like __android_log_bwrite, but used for writing strings to the 468 * event log. 469 */ 470LIBLOG_ABI_PUBLIC int __android_log_bswrite(int32_t tag, const char *payload) 471{ 472 struct iovec vec[4]; 473 char type = EVENT_TYPE_STRING; 474 uint32_t len = strlen(payload); 475 476 vec[0].iov_base = &tag; 477 vec[0].iov_len = sizeof(tag); 478 vec[1].iov_base = &type; 479 vec[1].iov_len = sizeof(type); 480 vec[2].iov_base = &len; 481 vec[2].iov_len = sizeof(len); 482 vec[3].iov_base = (void*)payload; 483 vec[3].iov_len = len; 484 485 return write_to_log(LOG_ID_EVENTS, vec, 4); 486} 487 488/* 489 * Like __android_log_security_bwrite, but used for writing strings to the 490 * security log. 491 */ 492LIBLOG_ABI_PUBLIC int __android_log_security_bswrite(int32_t tag, 493 const char *payload) 494{ 495 struct iovec vec[4]; 496 char type = EVENT_TYPE_STRING; 497 uint32_t len = strlen(payload); 498 499 vec[0].iov_base = &tag; 500 vec[0].iov_len = sizeof(tag); 501 vec[1].iov_base = &type; 502 vec[1].iov_len = sizeof(type); 503 vec[2].iov_base = &len; 504 vec[2].iov_len = sizeof(len); 505 vec[3].iov_base = (void*)payload; 506 vec[3].iov_len = len; 507 508 return write_to_log(LOG_ID_SECURITY, vec, 4); 509} 510