Coverage Report

Created: 2025-07-23 06:46

/src/perfetto/buildtools/android-logging/liblog/logger_write.cpp
Line
Count
Source (jump to first uncovered line)
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 "logger_write.h"
18
19
#include <errno.h>
20
#include <inttypes.h>
21
#include <libgen.h>
22
#include <stdlib.h>
23
#include <string.h>
24
#include <sys/time.h>
25
26
#ifdef __BIONIC__
27
#include <android/set_abort_message.h>
28
#endif
29
30
#include <atomic>
31
32
#include <android-base/errno_restorer.h>
33
#include <android-base/macros.h>
34
#include <private/android_filesystem_config.h>
35
#include <private/android_logger.h>
36
37
#include "android/log.h"
38
#include "log/log_read.h"
39
#include "logger.h"
40
#include "uio.h"
41
42
#ifdef __ANDROID__
43
#include "logd_writer.h"
44
#include "pmsg_writer.h"
45
#endif
46
47
#if defined(__APPLE__)
48
#include <pthread.h>
49
#elif defined(__linux__) && !defined(__ANDROID__)
50
#include <syscall.h>
51
#elif defined(_WIN32)
52
#include <windows.h>
53
#endif
54
55
using android::base::ErrnoRestorer;
56
57
0
#define LOG_BUF_SIZE 1024
58
59
#if defined(__ANDROID__)
60
static int check_log_uid_permissions() {
61
  uid_t uid = getuid();
62
63
  /* Matches clientHasLogCredentials() in logd */
64
  if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) {
65
    uid = geteuid();
66
    if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) {
67
      gid_t gid = getgid();
68
      if ((gid != AID_SYSTEM) && (gid != AID_ROOT) && (gid != AID_LOG)) {
69
        gid = getegid();
70
        if ((gid != AID_SYSTEM) && (gid != AID_ROOT) && (gid != AID_LOG)) {
71
          int num_groups;
72
          gid_t* groups;
73
74
          num_groups = getgroups(0, NULL);
75
          if (num_groups <= 0) {
76
            return -EPERM;
77
          }
78
          groups = static_cast<gid_t*>(calloc(num_groups, sizeof(gid_t)));
79
          if (!groups) {
80
            return -ENOMEM;
81
          }
82
          num_groups = getgroups(num_groups, groups);
83
          while (num_groups > 0) {
84
            if (groups[num_groups - 1] == AID_LOG) {
85
              break;
86
            }
87
            --num_groups;
88
          }
89
          free(groups);
90
          if (num_groups <= 0) {
91
            return -EPERM;
92
          }
93
        }
94
      }
95
    }
96
  }
97
  return 0;
98
}
99
#endif
100
101
/*
102
 * Release any logger resources. A new log write will immediately re-acquire.
103
 */
104
0
void __android_log_close() {
105
#ifdef __ANDROID__
106
  LogdClose();
107
  PmsgClose();
108
#endif
109
0
}
110
111
#if defined(__GLIBC__) || defined(_WIN32)
112
0
static const char* getprogname() {
113
0
#if defined(__GLIBC__)
114
0
  return program_invocation_short_name;
115
#elif defined(_WIN32)
116
  static bool first = true;
117
  static char progname[MAX_PATH] = {};
118
119
  if (first) {
120
    char path[PATH_MAX + 1];
121
    DWORD result = GetModuleFileName(nullptr, path, sizeof(path) - 1);
122
    if (result == 0 || result == sizeof(path) - 1) return "";
123
    path[PATH_MAX - 1] = 0;
124
125
    char* path_basename = basename(path);
126
127
    snprintf(progname, sizeof(progname), "%s", path_basename);
128
    first = false;
129
  }
130
131
  return progname;
132
#endif
133
0
}
134
#endif
135
136
// It's possible for logging to happen during static initialization before our globals are
137
// initialized, so we place this std::string in a function such that it is initialized on the first
138
// call.
139
0
std::string& GetDefaultTag() {
140
0
  static std::string default_tag = getprogname();
141
0
  return default_tag;
142
0
}
143
144
0
void __android_log_set_default_tag(const char* tag) {
145
0
  GetDefaultTag().assign(tag, 0, LOGGER_ENTRY_MAX_PAYLOAD);
146
0
}
147
148
static std::atomic_int32_t minimum_log_priority = ANDROID_LOG_DEFAULT;
149
0
int32_t __android_log_set_minimum_priority(int32_t priority) {
150
0
  return minimum_log_priority.exchange(priority, std::memory_order_relaxed);
151
0
}
152
153
0
int32_t __android_log_get_minimum_priority() {
154
0
  return minimum_log_priority;
155
0
}
156
157
#ifdef __ANDROID__
158
static __android_logger_function logger_function = __android_log_logd_logger;
159
#else
160
static __android_logger_function logger_function = __android_log_stderr_logger;
161
#endif
162
163
0
void __android_log_set_logger(__android_logger_function logger) {
164
0
  logger_function = logger;
165
0
}
166
167
0
void __android_log_default_aborter(const char* abort_message) {
168
#ifdef __ANDROID__
169
  android_set_abort_message(abort_message);
170
#else
171
0
  UNUSED(abort_message);
172
0
#endif
173
0
  abort();
174
0
}
175
176
static __android_aborter_function aborter_function = __android_log_default_aborter;
177
178
0
void __android_log_set_aborter(__android_aborter_function aborter) {
179
0
  aborter_function = aborter;
180
0
}
181
182
0
void __android_log_call_aborter(const char* abort_message) {
183
0
  aborter_function(abort_message);
184
0
}
185
186
#ifdef __ANDROID__
187
static int write_to_log(log_id_t log_id, struct iovec* vec, size_t nr) {
188
  int ret;
189
  struct timespec ts;
190
191
  if (log_id == LOG_ID_KERNEL) {
192
    return -EINVAL;
193
  }
194
195
  clock_gettime(CLOCK_REALTIME, &ts);
196
197
  if (log_id == LOG_ID_SECURITY) {
198
    if (vec[0].iov_len < 4) {
199
      return -EINVAL;
200
    }
201
202
    ret = check_log_uid_permissions();
203
    if (ret < 0) {
204
      return ret;
205
    }
206
    if (!__android_log_security()) {
207
      /* If only we could reset downstream logd counter */
208
      return -EPERM;
209
    }
210
  } else if (log_id == LOG_ID_EVENTS || log_id == LOG_ID_STATS) {
211
    if (vec[0].iov_len < 4) {
212
      return -EINVAL;
213
    }
214
  }
215
216
  ret = LogdWrite(log_id, &ts, vec, nr);
217
  PmsgWrite(log_id, &ts, vec, nr);
218
219
  return ret;
220
}
221
#else
222
0
static int write_to_log(log_id_t, struct iovec*, size_t) {
223
  // Non-Android text logs should go to __android_log_stderr_logger, not here.
224
  // Non-Android binary logs are always dropped.
225
0
  return 1;
226
0
}
227
#endif
228
229
// Copied from base/threads.cpp
230
0
static uint64_t GetThreadId() {
231
#if defined(__BIONIC__)
232
  return gettid();
233
#elif defined(__APPLE__)
234
  uint64_t tid;
235
  pthread_threadid_np(NULL, &tid);
236
  return tid;
237
#elif defined(__linux__)
238
  return syscall(__NR_gettid);
239
#elif defined(_WIN32)
240
  return GetCurrentThreadId();
241
#endif
242
0
}
243
244
0
void __android_log_stderr_logger(const struct __android_log_message* log_message) {
245
0
  struct tm now;
246
0
  time_t t = time(nullptr);
247
248
#if defined(_WIN32)
249
  localtime_s(&now, &t);
250
#else
251
0
  localtime_r(&t, &now);
252
0
#endif
253
254
0
  char timestamp[32];
255
0
  strftime(timestamp, sizeof(timestamp), "%m-%d %H:%M:%S", &now);
256
257
0
  static const char log_characters[] = "XXVDIWEF";
258
0
  static_assert(arraysize(log_characters) - 1 == ANDROID_LOG_SILENT,
259
0
                "Mismatch in size of log_characters and values in android_LogPriority");
260
0
  int32_t priority =
261
0
      log_message->priority > ANDROID_LOG_SILENT ? ANDROID_LOG_FATAL : log_message->priority;
262
0
  char priority_char = log_characters[priority];
263
0
  uint64_t tid = GetThreadId();
264
265
0
  if (log_message->file != nullptr) {
266
0
    fprintf(stderr, "%s %c %s %5d %5" PRIu64 " %s:%u] %s\n",
267
0
            log_message->tag ? log_message->tag : "nullptr", priority_char, timestamp, getpid(),
268
0
            tid, log_message->file, log_message->line, log_message->message);
269
0
  } else {
270
0
    fprintf(stderr, "%s %c %s %5d %5" PRIu64 " %s\n",
271
0
            log_message->tag ? log_message->tag : "nullptr", priority_char, timestamp, getpid(),
272
0
            tid, log_message->message);
273
0
  }
274
0
}
275
276
0
void __android_log_logd_logger(const struct __android_log_message* log_message) {
277
0
  int buffer_id = log_message->buffer_id == LOG_ID_DEFAULT ? LOG_ID_MAIN : log_message->buffer_id;
278
279
0
  struct iovec vec[3];
280
0
  vec[0].iov_base =
281
0
      const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(&log_message->priority));
282
0
  vec[0].iov_len = 1;
283
0
  vec[1].iov_base = const_cast<void*>(static_cast<const void*>(log_message->tag));
284
0
  vec[1].iov_len = strlen(log_message->tag) + 1;
285
0
  vec[2].iov_base = const_cast<void*>(static_cast<const void*>(log_message->message));
286
0
  vec[2].iov_len = strlen(log_message->message) + 1;
287
288
0
  write_to_log(static_cast<log_id_t>(buffer_id), vec, 3);
289
0
}
290
291
0
int __android_log_write(int prio, const char* tag, const char* msg) {
292
0
  return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
293
0
}
294
295
0
void __android_log_write_log_message(__android_log_message* log_message) {
296
0
  ErrnoRestorer errno_restorer;
297
298
0
  if (log_message->buffer_id != LOG_ID_DEFAULT && log_message->buffer_id != LOG_ID_MAIN &&
299
0
      log_message->buffer_id != LOG_ID_SYSTEM && log_message->buffer_id != LOG_ID_RADIO &&
300
0
      log_message->buffer_id != LOG_ID_CRASH) {
301
0
    return;
302
0
  }
303
304
0
  if (log_message->tag == nullptr) {
305
0
    log_message->tag = GetDefaultTag().c_str();
306
0
  }
307
308
#if __BIONIC__
309
  if (log_message->priority == ANDROID_LOG_FATAL) {
310
    android_set_abort_message(log_message->message);
311
  }
312
#endif
313
314
0
  logger_function(log_message);
315
0
}
316
317
0
int __android_log_buf_write(int bufID, int prio, const char* tag, const char* msg) {
318
0
  ErrnoRestorer errno_restorer;
319
320
0
  if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
321
0
    return -EPERM;
322
0
  }
323
324
0
  __android_log_message log_message = {
325
0
      sizeof(__android_log_message), bufID, prio, tag, nullptr, 0, msg};
326
0
  __android_log_write_log_message(&log_message);
327
0
  return 1;
328
0
}
329
330
0
int __android_log_vprint(int prio, const char* tag, const char* fmt, va_list ap) {
331
0
  ErrnoRestorer errno_restorer;
332
333
0
  if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
334
0
    return -EPERM;
335
0
  }
336
337
0
  __attribute__((uninitialized)) char buf[LOG_BUF_SIZE];
338
339
0
  vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
340
341
0
  __android_log_message log_message = {
342
0
      sizeof(__android_log_message), LOG_ID_MAIN, prio, tag, nullptr, 0, buf};
343
0
  __android_log_write_log_message(&log_message);
344
0
  return 1;
345
0
}
346
347
0
int __android_log_print(int prio, const char* tag, const char* fmt, ...) {
348
0
  ErrnoRestorer errno_restorer;
349
350
0
  if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
351
0
    return -EPERM;
352
0
  }
353
354
0
  va_list ap;
355
0
  __attribute__((uninitialized)) char buf[LOG_BUF_SIZE];
356
357
0
  va_start(ap, fmt);
358
0
  vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
359
0
  va_end(ap);
360
361
0
  __android_log_message log_message = {
362
0
      sizeof(__android_log_message), LOG_ID_MAIN, prio, tag, nullptr, 0, buf};
363
0
  __android_log_write_log_message(&log_message);
364
0
  return 1;
365
0
}
366
367
0
int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt, ...) {
368
0
  ErrnoRestorer errno_restorer;
369
370
0
  if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
371
0
    return -EPERM;
372
0
  }
373
374
0
  va_list ap;
375
0
  __attribute__((uninitialized)) char buf[LOG_BUF_SIZE];
376
377
0
  va_start(ap, fmt);
378
0
  vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
379
0
  va_end(ap);
380
381
0
  __android_log_message log_message = {
382
0
      sizeof(__android_log_message), bufID, prio, tag, nullptr, 0, buf};
383
0
  __android_log_write_log_message(&log_message);
384
0
  return 1;
385
0
}
386
387
0
void __android_log_assert(const char* cond, const char* tag, const char* fmt, ...) {
388
0
  __attribute__((uninitialized)) char buf[LOG_BUF_SIZE];
389
390
0
  if (fmt) {
391
0
    va_list ap;
392
0
    va_start(ap, fmt);
393
0
    vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
394
0
    va_end(ap);
395
0
  } else {
396
    /* Msg not provided, log condition.  N.B. Do not use cond directly as
397
     * format string as it could contain spurious '%' syntax (e.g.
398
     * "%d" in "blocks%devs == 0").
399
     */
400
0
    if (cond)
401
0
      snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond);
402
0
    else
403
0
      strcpy(buf, "Unspecified assertion failed");
404
0
  }
405
406
  // Log assertion failures to stderr for the benefit of "adb shell" users
407
  // and gtests (http://b/23675822).
408
0
  TEMP_FAILURE_RETRY(write(2, buf, strlen(buf)));
409
0
  TEMP_FAILURE_RETRY(write(2, "\n", 1));
410
411
0
  __android_log_write(ANDROID_LOG_FATAL, tag, buf);
412
0
  __android_log_call_aborter(buf);
413
0
  abort();
414
0
}
415
416
0
int __android_log_bwrite(int32_t tag, const void* payload, size_t len) {
417
0
  ErrnoRestorer errno_restorer;
418
419
0
  struct iovec vec[2];
420
421
0
  vec[0].iov_base = &tag;
422
0
  vec[0].iov_len = sizeof(tag);
423
0
  vec[1].iov_base = (void*)payload;
424
0
  vec[1].iov_len = len;
425
426
0
  return write_to_log(LOG_ID_EVENTS, vec, 2);
427
0
}
428
429
0
int __android_log_stats_bwrite(int32_t tag, const void* payload, size_t len) {
430
0
  ErrnoRestorer errno_restorer;
431
432
0
  struct iovec vec[2];
433
434
0
  vec[0].iov_base = &tag;
435
0
  vec[0].iov_len = sizeof(tag);
436
0
  vec[1].iov_base = (void*)payload;
437
0
  vec[1].iov_len = len;
438
439
0
  return write_to_log(LOG_ID_STATS, vec, 2);
440
0
}
441
442
0
int __android_log_security_bwrite(int32_t tag, const void* payload, size_t len) {
443
0
  ErrnoRestorer errno_restorer;
444
445
0
  struct iovec vec[2];
446
447
0
  vec[0].iov_base = &tag;
448
0
  vec[0].iov_len = sizeof(tag);
449
0
  vec[1].iov_base = (void*)payload;
450
0
  vec[1].iov_len = len;
451
452
0
  return write_to_log(LOG_ID_SECURITY, vec, 2);
453
0
}
454
455
/*
456
 * Like __android_log_bwrite, but takes the type as well.  Doesn't work
457
 * for the general case where we're generating lists of stuff, but very
458
 * handy if we just want to dump an integer into the log.
459
 */
460
0
int __android_log_btwrite(int32_t tag, char type, const void* payload, size_t len) {
461
0
  ErrnoRestorer errno_restorer;
462
463
0
  struct iovec vec[3];
464
465
0
  vec[0].iov_base = &tag;
466
0
  vec[0].iov_len = sizeof(tag);
467
0
  vec[1].iov_base = &type;
468
0
  vec[1].iov_len = sizeof(type);
469
0
  vec[2].iov_base = (void*)payload;
470
0
  vec[2].iov_len = len;
471
472
0
  return write_to_log(LOG_ID_EVENTS, vec, 3);
473
0
}
474
475
/*
476
 * Like __android_log_bwrite, but used for writing strings to the
477
 * event log.
478
 */
479
0
int __android_log_bswrite(int32_t tag, const char* payload) {
480
0
  ErrnoRestorer errno_restorer;
481
482
0
  struct iovec vec[4];
483
0
  char type = EVENT_TYPE_STRING;
484
0
  uint32_t len = strlen(payload);
485
486
0
  vec[0].iov_base = &tag;
487
0
  vec[0].iov_len = sizeof(tag);
488
0
  vec[1].iov_base = &type;
489
0
  vec[1].iov_len = sizeof(type);
490
0
  vec[2].iov_base = &len;
491
0
  vec[2].iov_len = sizeof(len);
492
0
  vec[3].iov_base = (void*)payload;
493
0
  vec[3].iov_len = len;
494
495
0
  return write_to_log(LOG_ID_EVENTS, vec, 4);
496
0
}
497
498
/*
499
 * Like __android_log_security_bwrite, but used for writing strings to the
500
 * security log.
501
 */
502
0
int __android_log_security_bswrite(int32_t tag, const char* payload) {
503
0
  ErrnoRestorer errno_restorer;
504
505
0
  struct iovec vec[4];
506
0
  char type = EVENT_TYPE_STRING;
507
0
  uint32_t len = strlen(payload);
508
509
0
  vec[0].iov_base = &tag;
510
0
  vec[0].iov_len = sizeof(tag);
511
0
  vec[1].iov_base = &type;
512
0
  vec[1].iov_len = sizeof(type);
513
0
  vec[2].iov_base = &len;
514
0
  vec[2].iov_len = sizeof(len);
515
0
  vec[3].iov_base = (void*)payload;
516
0
  vec[3].iov_len = len;
517
518
0
  return write_to_log(LOG_ID_SECURITY, vec, 4);
519
0
}