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