blob: 936502985837a98ee1b8882e173abf9351a841da [file] [log] [blame]
Mark Salyzyn655b9492014-10-02 11:12:28 -07001/*
2** Copyright 2014, 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
Tom Cherryf623f022019-01-10 10:37:36 -080017#include <log/log_properties.h>
18
Mark Salyzyn655b9492014-10-02 11:12:28 -070019#include <ctype.h>
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070020#include <pthread.h>
21#include <stdlib.h>
Mark Salyzyn655b9492014-10-02 11:12:28 -070022#include <string.h>
Mark Salyzyncbf691a2016-09-26 13:21:05 -070023#include <unistd.h>
Mark Salyzyn655b9492014-10-02 11:12:28 -070024
Tom Cherry40044602020-01-16 15:58:02 -080025#include <algorithm>
26
Elliott Hughesc1a5ec52021-02-09 13:29:33 -080027#include <android-base/macros.h>
28
Mark Salyzyncbf691a2016-09-26 13:21:05 -070029#include <private/android_logger.h>
Mark Salyzyn655b9492014-10-02 11:12:28 -070030
Tom Cherry77ddcd32020-01-27 08:35:13 -080031#include "logger_write.h"
32
Tom Cherryc377c7d2020-01-27 15:45:52 -080033#ifdef __ANDROID__
Elliott Hughesb74a5062024-08-09 14:01:15 +000034#include <sys/system_properties.h>
Tom Cherryc377c7d2020-01-27 15:45:52 -080035
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -080036static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
37
Elliott Hughesc1a5ec52021-02-09 13:29:33 -080038static bool trylock() {
Mark Salyzyn6e315682017-03-09 08:09:43 -080039 /*
40 * If we trigger a signal handler in the middle of locked activity and the
41 * signal handler logs a message, we could get into a deadlock state.
42 */
43 /*
44 * Any contention, and we can turn around and use the non-cached method
45 * in less time than the system call associated with a mutex to deal with
46 * the contention.
47 */
Elliott Hughesc1a5ec52021-02-09 13:29:33 -080048 return pthread_mutex_trylock(&lock_loggable) == 0;
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -080049}
50
Mark Salyzyn6e315682017-03-09 08:09:43 -080051static void unlock() {
52 pthread_mutex_unlock(&lock_loggable);
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -080053}
54
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070055struct cache {
Mark Salyzyn6e315682017-03-09 08:09:43 -080056 const prop_info* pinfo;
57 uint32_t serial;
Mark Salyzyncbf691a2016-09-26 13:21:05 -070058};
59
60struct cache_char {
Mark Salyzyn6e315682017-03-09 08:09:43 -080061 struct cache cache;
62 unsigned char c;
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070063};
64
Mark Salyzyn6e315682017-03-09 08:09:43 -080065static int check_cache(struct cache* cache) {
66 return cache->pinfo && __system_property_serial(cache->pinfo) != cache->serial;
Mark Salyzynd4860192015-12-21 12:32:48 -080067}
68
Mark Salyzyn233e4752015-12-04 10:59:45 -080069#define BOOLEAN_TRUE 0xFF
70#define BOOLEAN_FALSE 0xFE
71
Mark Salyzyn6e315682017-03-09 08:09:43 -080072static void refresh_cache(struct cache_char* cache, const char* key) {
73 char buf[PROP_VALUE_MAX];
Mark Salyzyn655b9492014-10-02 11:12:28 -070074
Mark Salyzyn6e315682017-03-09 08:09:43 -080075 if (!cache->cache.pinfo) {
76 cache->cache.pinfo = __system_property_find(key);
Mark Salyzyncbf691a2016-09-26 13:21:05 -070077 if (!cache->cache.pinfo) {
Mark Salyzyn6e315682017-03-09 08:09:43 -080078 return;
Mark Salyzyn655b9492014-10-02 11:12:28 -070079 }
Mark Salyzyn6e315682017-03-09 08:09:43 -080080 }
81 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
82 __system_property_read(cache->cache.pinfo, 0, buf);
83 switch (buf[0]) {
84 case 't':
85 case 'T':
86 cache->c = strcasecmp(buf + 1, "rue") ? buf[0] : BOOLEAN_TRUE;
87 break;
88 case 'f':
89 case 'F':
90 cache->c = strcasecmp(buf + 1, "alse") ? buf[0] : BOOLEAN_FALSE;
91 break;
Mark Salyzyn233e4752015-12-04 10:59:45 -080092 default:
Mark Salyzyn6e315682017-03-09 08:09:43 -080093 cache->c = buf[0];
94 }
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070095}
Mark Salyzyn655b9492014-10-02 11:12:28 -070096
Elliott Hughesc1a5ec52021-02-09 13:29:33 -080097static int __android_log_level(const char* tag, size_t tag_len) {
98 if (tag == nullptr || tag_len == 0) {
Tom Cherry77ddcd32020-01-27 08:35:13 -080099 auto& tag_string = GetDefaultTag();
100 tag = tag_string.c_str();
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800101 tag_len = tag_string.size();
Tom Cherry77ddcd32020-01-27 08:35:13 -0800102 }
103
Mark Salyzyn6e315682017-03-09 08:09:43 -0800104 /*
105 * Single layer cache of four properties. Priorities are:
106 * log.tag.<tag>
107 * persist.log.tag.<tag>
108 * log.tag
109 * persist.log.tag
110 * Where the missing tag matches all tags and becomes the
111 * system global default. We do not support ro.log.tag* .
112 */
Elliott Hughes80883da2021-03-04 07:55:22 -0800113 static std::string* last_tag = new std::string;
Mark Salyzyn6e315682017-03-09 08:09:43 -0800114 static uint32_t global_serial;
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800115 uint32_t current_global_serial;
116 static cache_char tag_cache[2];
117 static cache_char global_cache[2];
Mark Salyzyn6e315682017-03-09 08:09:43 -0800118
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800119 static const char* log_namespace = "persist.log.tag.";
120 char key[strlen(log_namespace) + tag_len + 1];
Mark Salyzyn6e315682017-03-09 08:09:43 -0800121 strcpy(key, log_namespace);
122
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800123 bool locked = trylock();
124 bool change_detected, global_change_detected;
125 global_change_detected = change_detected = !locked;
Mark Salyzyn6e315682017-03-09 08:09:43 -0800126
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800127 char c = 0;
128 if (locked) {
129 // Check all known serial numbers for changes.
130 for (size_t i = 0; i < arraysize(tag_cache); ++i) {
Mark Salyzyn6e315682017-03-09 08:09:43 -0800131 if (check_cache(&tag_cache[i].cache)) {
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800132 change_detected = true;
Mark Salyzyn6e315682017-03-09 08:09:43 -0800133 }
134 }
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800135 for (size_t i = 0; i < arraysize(global_cache); ++i) {
Mark Salyzyn6e315682017-03-09 08:09:43 -0800136 if (check_cache(&global_cache[i].cache)) {
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800137 global_change_detected = true;
Mark Salyzyn6e315682017-03-09 08:09:43 -0800138 }
139 }
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700140
Mark Salyzyn6e315682017-03-09 08:09:43 -0800141 current_global_serial = __system_property_area_serial();
142 if (current_global_serial != global_serial) {
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800143 global_change_detected = change_detected = true;
Mark Salyzyn6e315682017-03-09 08:09:43 -0800144 }
145 }
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700146
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800147 if (tag_len != 0) {
148 bool local_change_detected = change_detected;
149 if (locked) {
150 // compare() rather than == because tag isn't guaranteed 0-terminated.
Elliott Hughes80883da2021-03-04 07:55:22 -0800151 if (last_tag->compare(0, last_tag->size(), tag, tag_len) != 0) {
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800152 // Invalidate log.tag.<tag> cache.
153 for (size_t i = 0; i < arraysize(tag_cache); ++i) {
Mark Salyzyn6e315682017-03-09 08:09:43 -0800154 tag_cache[i].cache.pinfo = NULL;
155 tag_cache[i].c = '\0';
Mark Salyzynd4860192015-12-21 12:32:48 -0800156 }
Elliott Hughes80883da2021-03-04 07:55:22 -0800157 last_tag->assign(tag, tag_len);
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800158 local_change_detected = true;
Mark Salyzyn6e315682017-03-09 08:09:43 -0800159 }
Mark Salyzynd4860192015-12-21 12:32:48 -0800160 }
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800161 *stpncpy(key + strlen(log_namespace), tag, tag_len) = '\0';
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700162
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800163 for (size_t i = 0; i < arraysize(tag_cache); ++i) {
164 cache_char* cache = &tag_cache[i];
165 cache_char temp_cache;
Mark Salyzyn655b9492014-10-02 11:12:28 -0700166
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800167 if (!locked) {
Mark Salyzyn6e315682017-03-09 08:09:43 -0800168 temp_cache.cache.pinfo = NULL;
169 temp_cache.c = '\0';
170 cache = &temp_cache;
171 }
172 if (local_change_detected) {
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800173 refresh_cache(cache, i == 0 ? key : key + strlen("persist."));
Mark Salyzyn6e315682017-03-09 08:09:43 -0800174 }
Mark Salyzynd4860192015-12-21 12:32:48 -0800175
Mark Salyzyn6e315682017-03-09 08:09:43 -0800176 if (cache->c) {
177 c = cache->c;
178 break;
179 }
Mark Salyzyn655b9492014-10-02 11:12:28 -0700180 }
Mark Salyzyn6e315682017-03-09 08:09:43 -0800181 }
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700182
Mark Salyzyn6e315682017-03-09 08:09:43 -0800183 switch (toupper(c)) { /* if invalid, resort to global */
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700184 case 'V':
185 case 'D':
186 case 'I':
187 case 'W':
188 case 'E':
189 case 'F': /* Not officially supported */
190 case 'A':
191 case 'S':
Mark Salyzyn233e4752015-12-04 10:59:45 -0800192 case BOOLEAN_FALSE: /* Not officially supported */
Mark Salyzyn6e315682017-03-09 08:09:43 -0800193 break;
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700194 default:
Mark Salyzyn6e315682017-03-09 08:09:43 -0800195 /* clear '.' after log.tag */
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800196 key[strlen(log_namespace) - 1] = '\0';
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700197
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800198 for (size_t i = 0; i < arraysize(global_cache); ++i) {
199 cache_char* cache = &global_cache[i];
200 cache_char temp_cache;
Mark Salyzynd4860192015-12-21 12:32:48 -0800201
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800202 if (!locked) {
Mark Salyzyn6e315682017-03-09 08:09:43 -0800203 temp_cache = *cache;
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800204 if (temp_cache.cache.pinfo != cache->cache.pinfo) { // check atomic
Mark Salyzyn6e315682017-03-09 08:09:43 -0800205 temp_cache.cache.pinfo = NULL;
206 temp_cache.c = '\0';
207 }
208 cache = &temp_cache;
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700209 }
Mark Salyzyn6e315682017-03-09 08:09:43 -0800210 if (global_change_detected) {
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800211 refresh_cache(cache, i == 0 ? key : key + strlen("persist."));
Mark Salyzyn6e315682017-03-09 08:09:43 -0800212 }
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700213
Mark Salyzyn6e315682017-03-09 08:09:43 -0800214 if (cache->c) {
215 c = cache->c;
216 break;
217 }
Mark Salyzyn6e315682017-03-09 08:09:43 -0800218 }
219 break;
220 }
221
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800222 if (locked) {
Mark Salyzyn6e315682017-03-09 08:09:43 -0800223 global_serial = current_global_serial;
224 unlock();
225 }
226
227 switch (toupper(c)) {
228 /* clang-format off */
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700229 case 'V': return ANDROID_LOG_VERBOSE;
230 case 'D': return ANDROID_LOG_DEBUG;
231 case 'I': return ANDROID_LOG_INFO;
232 case 'W': return ANDROID_LOG_WARN;
233 case 'E': return ANDROID_LOG_ERROR;
234 case 'F': /* FALLTHRU */ /* Not officially supported */
235 case 'A': return ANDROID_LOG_FATAL;
Mark Salyzyn233e4752015-12-04 10:59:45 -0800236 case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
Tom Cherry40044602020-01-16 15:58:02 -0800237 case 'S': return ANDROID_LOG_SILENT;
Tom Cherryf623f022019-01-10 10:37:36 -0800238 /* clang-format on */
Mark Salyzyn6e315682017-03-09 08:09:43 -0800239 }
Tom Cherry40044602020-01-16 15:58:02 -0800240 return -1;
Mark Salyzyn6e315682017-03-09 08:09:43 -0800241}
242
Tom Cherry3d6a8782019-02-08 11:46:19 -0800243int __android_log_is_loggable_len(int prio, const char* tag, size_t len, int default_prio) {
Tom Cherry40044602020-01-16 15:58:02 -0800244 int minimum_log_priority = __android_log_get_minimum_priority();
245 int property_log_level = __android_log_level(tag, len);
246
247 if (property_log_level >= 0 && minimum_log_priority != ANDROID_LOG_DEFAULT) {
248 return prio >= std::min(property_log_level, minimum_log_priority);
249 } else if (property_log_level >= 0) {
250 return prio >= property_log_level;
251 } else if (minimum_log_priority != ANDROID_LOG_DEFAULT) {
252 return prio >= minimum_log_priority;
253 } else {
254 return prio >= default_prio;
255 }
Mark Salyzyn6e315682017-03-09 08:09:43 -0800256}
257
Tom Cherry3d6a8782019-02-08 11:46:19 -0800258int __android_log_is_loggable(int prio, const char* tag, int default_prio) {
Tom Cherry40044602020-01-16 15:58:02 -0800259 auto len = tag ? strlen(tag) : 0;
260 return __android_log_is_loggable_len(prio, tag, len, default_prio);
Mark Salyzyn6e315682017-03-09 08:09:43 -0800261}
262
Tom Cherry3d6a8782019-02-08 11:46:19 -0800263int __android_log_is_debuggable() {
Bruno Martinsf2a33452020-04-19 15:14:42 +0100264 if (ANDROID_DEBUGGABLE) {
265 return 1;
266 } else {
267 static int is_debuggable = [] {
268 char value[PROP_VALUE_MAX] = {};
269 return __system_property_get("ro.debuggable", value) > 0 && !strcmp(value, "1");
270 }();
Mark Salyzyn6e315682017-03-09 08:09:43 -0800271
Bruno Martinsf2a33452020-04-19 15:14:42 +0100272 return is_debuggable;
273 }
Mark Salyzyn509c1422016-03-25 15:50:46 -0700274}
275
Pavel Grafov2d9372b2023-11-21 19:09:56 +0000276int __android_log_security() {
277 static pthread_mutex_t security_lock = PTHREAD_MUTEX_INITIALIZER;
278 static cache_char security_prop = {{NULL, 0xFFFFFFFF}, BOOLEAN_FALSE};
279 static uint32_t security_serial = 0;
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800280
Pavel Grafov2d9372b2023-11-21 19:09:56 +0000281 if (pthread_mutex_trylock(&security_lock)) {
Mark Salyzyn6e315682017-03-09 08:09:43 -0800282 /* We are willing to accept some race in this context */
Pavel Grafov2d9372b2023-11-21 19:09:56 +0000283 return security_prop.c == BOOLEAN_TRUE;
Mark Salyzyn6e315682017-03-09 08:09:43 -0800284 }
Mark Salyzyn2cdfd8e2015-09-08 08:32:01 -0700285
Pavel Grafov2d9372b2023-11-21 19:09:56 +0000286 int change_detected = check_cache(&security_prop.cache);
287 uint32_t current_serial = __system_property_area_serial();
288 if (current_serial != security_serial) {
Mark Salyzyn6e315682017-03-09 08:09:43 -0800289 change_detected = 1;
290 }
291 if (change_detected) {
Pavel Grafov2d9372b2023-11-21 19:09:56 +0000292 refresh_cache(&security_prop, "persist.logd.security");
293 security_serial = current_serial;
Mark Salyzyn6e315682017-03-09 08:09:43 -0800294 }
Mark Salyzynd4860192015-12-21 12:32:48 -0800295
Pavel Grafov2d9372b2023-11-21 19:09:56 +0000296 int res = security_prop.c == BOOLEAN_TRUE;
Mark Salyzynd4860192015-12-21 12:32:48 -0800297
Pavel Grafov2d9372b2023-11-21 19:09:56 +0000298 pthread_mutex_unlock(&security_lock);
Mark Salyzynd4860192015-12-21 12:32:48 -0800299
Pavel Grafov2d9372b2023-11-21 19:09:56 +0000300 return res;
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700301}
302
Tom Cherryc377c7d2020-01-27 15:45:52 -0800303#else
304
305int __android_log_is_loggable(int prio, const char*, int) {
306 int minimum_priority = __android_log_get_minimum_priority();
307 if (minimum_priority == ANDROID_LOG_DEFAULT) {
308 minimum_priority = ANDROID_LOG_INFO;
309 }
310 return prio >= minimum_priority;
311}
312
313int __android_log_is_loggable_len(int prio, const char*, size_t, int def) {
314 return __android_log_is_loggable(prio, nullptr, def);
315}
316
317int __android_log_is_debuggable() {
318 return 1;
319}
320
Elliott Hughes9e72ac22023-11-30 15:15:11 -0800321int __android_log_security() {
322 return 0;
323}
324
Tom Cherrycbd31f92020-07-27 11:20:29 -0700325#endif