blob: bd5f5e7a02f4145b2a1272d7c12c8b5baa6fdecd [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__
34#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
35#include <sys/_system_properties.h>
36
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -080037static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
38
Elliott Hughesc1a5ec52021-02-09 13:29:33 -080039static bool trylock() {
Mark Salyzyn6e315682017-03-09 08:09:43 -080040 /*
41 * If we trigger a signal handler in the middle of locked activity and the
42 * signal handler logs a message, we could get into a deadlock state.
43 */
44 /*
45 * Any contention, and we can turn around and use the non-cached method
46 * in less time than the system call associated with a mutex to deal with
47 * the contention.
48 */
Elliott Hughesc1a5ec52021-02-09 13:29:33 -080049 return pthread_mutex_trylock(&lock_loggable) == 0;
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -080050}
51
Mark Salyzyn6e315682017-03-09 08:09:43 -080052static void unlock() {
53 pthread_mutex_unlock(&lock_loggable);
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -080054}
55
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070056struct cache {
Mark Salyzyn6e315682017-03-09 08:09:43 -080057 const prop_info* pinfo;
58 uint32_t serial;
Mark Salyzyncbf691a2016-09-26 13:21:05 -070059};
60
61struct cache_char {
Mark Salyzyn6e315682017-03-09 08:09:43 -080062 struct cache cache;
63 unsigned char c;
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070064};
65
Mark Salyzyn6e315682017-03-09 08:09:43 -080066static int check_cache(struct cache* cache) {
67 return cache->pinfo && __system_property_serial(cache->pinfo) != cache->serial;
Mark Salyzynd4860192015-12-21 12:32:48 -080068}
69
Mark Salyzyn233e4752015-12-04 10:59:45 -080070#define BOOLEAN_TRUE 0xFF
71#define BOOLEAN_FALSE 0xFE
72
Mark Salyzyn6e315682017-03-09 08:09:43 -080073static void refresh_cache(struct cache_char* cache, const char* key) {
74 char buf[PROP_VALUE_MAX];
Mark Salyzyn655b9492014-10-02 11:12:28 -070075
Mark Salyzyn6e315682017-03-09 08:09:43 -080076 if (!cache->cache.pinfo) {
77 cache->cache.pinfo = __system_property_find(key);
Mark Salyzyncbf691a2016-09-26 13:21:05 -070078 if (!cache->cache.pinfo) {
Mark Salyzyn6e315682017-03-09 08:09:43 -080079 return;
Mark Salyzyn655b9492014-10-02 11:12:28 -070080 }
Mark Salyzyn6e315682017-03-09 08:09:43 -080081 }
82 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
83 __system_property_read(cache->cache.pinfo, 0, buf);
84 switch (buf[0]) {
85 case 't':
86 case 'T':
87 cache->c = strcasecmp(buf + 1, "rue") ? buf[0] : BOOLEAN_TRUE;
88 break;
89 case 'f':
90 case 'F':
91 cache->c = strcasecmp(buf + 1, "alse") ? buf[0] : BOOLEAN_FALSE;
92 break;
Mark Salyzyn233e4752015-12-04 10:59:45 -080093 default:
Mark Salyzyn6e315682017-03-09 08:09:43 -080094 cache->c = buf[0];
95 }
Mark Salyzyn500cd1c2015-03-12 15:46:29 -070096}
Mark Salyzyn655b9492014-10-02 11:12:28 -070097
Elliott Hughesc1a5ec52021-02-09 13:29:33 -080098static int __android_log_level(const char* tag, size_t tag_len) {
99 if (tag == nullptr || tag_len == 0) {
Tom Cherry77ddcd32020-01-27 08:35:13 -0800100 auto& tag_string = GetDefaultTag();
101 tag = tag_string.c_str();
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800102 tag_len = tag_string.size();
Tom Cherry77ddcd32020-01-27 08:35:13 -0800103 }
104
Mark Salyzyn6e315682017-03-09 08:09:43 -0800105 /*
106 * Single layer cache of four properties. Priorities are:
107 * log.tag.<tag>
108 * persist.log.tag.<tag>
109 * log.tag
110 * persist.log.tag
111 * Where the missing tag matches all tags and becomes the
112 * system global default. We do not support ro.log.tag* .
113 */
Elliott Hughes80883da2021-03-04 07:55:22 -0800114 static std::string* last_tag = new std::string;
Mark Salyzyn6e315682017-03-09 08:09:43 -0800115 static uint32_t global_serial;
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800116 uint32_t current_global_serial;
117 static cache_char tag_cache[2];
118 static cache_char global_cache[2];
Mark Salyzyn6e315682017-03-09 08:09:43 -0800119
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800120 static const char* log_namespace = "persist.log.tag.";
121 char key[strlen(log_namespace) + tag_len + 1];
Mark Salyzyn6e315682017-03-09 08:09:43 -0800122 strcpy(key, log_namespace);
123
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800124 bool locked = trylock();
125 bool change_detected, global_change_detected;
126 global_change_detected = change_detected = !locked;
Mark Salyzyn6e315682017-03-09 08:09:43 -0800127
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800128 char c = 0;
129 if (locked) {
130 // Check all known serial numbers for changes.
131 for (size_t i = 0; i < arraysize(tag_cache); ++i) {
Mark Salyzyn6e315682017-03-09 08:09:43 -0800132 if (check_cache(&tag_cache[i].cache)) {
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800133 change_detected = true;
Mark Salyzyn6e315682017-03-09 08:09:43 -0800134 }
135 }
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800136 for (size_t i = 0; i < arraysize(global_cache); ++i) {
Mark Salyzyn6e315682017-03-09 08:09:43 -0800137 if (check_cache(&global_cache[i].cache)) {
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800138 global_change_detected = true;
Mark Salyzyn6e315682017-03-09 08:09:43 -0800139 }
140 }
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700141
Mark Salyzyn6e315682017-03-09 08:09:43 -0800142 current_global_serial = __system_property_area_serial();
143 if (current_global_serial != global_serial) {
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800144 global_change_detected = change_detected = true;
Mark Salyzyn6e315682017-03-09 08:09:43 -0800145 }
146 }
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700147
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800148 if (tag_len != 0) {
149 bool local_change_detected = change_detected;
150 if (locked) {
151 // compare() rather than == because tag isn't guaranteed 0-terminated.
Elliott Hughes80883da2021-03-04 07:55:22 -0800152 if (last_tag->compare(0, last_tag->size(), tag, tag_len) != 0) {
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800153 // Invalidate log.tag.<tag> cache.
154 for (size_t i = 0; i < arraysize(tag_cache); ++i) {
Mark Salyzyn6e315682017-03-09 08:09:43 -0800155 tag_cache[i].cache.pinfo = NULL;
156 tag_cache[i].c = '\0';
Mark Salyzynd4860192015-12-21 12:32:48 -0800157 }
Elliott Hughes80883da2021-03-04 07:55:22 -0800158 last_tag->assign(tag, tag_len);
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800159 local_change_detected = true;
Mark Salyzyn6e315682017-03-09 08:09:43 -0800160 }
Mark Salyzynd4860192015-12-21 12:32:48 -0800161 }
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800162 *stpncpy(key + strlen(log_namespace), tag, tag_len) = '\0';
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700163
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800164 for (size_t i = 0; i < arraysize(tag_cache); ++i) {
165 cache_char* cache = &tag_cache[i];
166 cache_char temp_cache;
Mark Salyzyn655b9492014-10-02 11:12:28 -0700167
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800168 if (!locked) {
Mark Salyzyn6e315682017-03-09 08:09:43 -0800169 temp_cache.cache.pinfo = NULL;
170 temp_cache.c = '\0';
171 cache = &temp_cache;
172 }
173 if (local_change_detected) {
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800174 refresh_cache(cache, i == 0 ? key : key + strlen("persist."));
Mark Salyzyn6e315682017-03-09 08:09:43 -0800175 }
Mark Salyzynd4860192015-12-21 12:32:48 -0800176
Mark Salyzyn6e315682017-03-09 08:09:43 -0800177 if (cache->c) {
178 c = cache->c;
179 break;
180 }
Mark Salyzyn655b9492014-10-02 11:12:28 -0700181 }
Mark Salyzyn6e315682017-03-09 08:09:43 -0800182 }
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700183
Mark Salyzyn6e315682017-03-09 08:09:43 -0800184 switch (toupper(c)) { /* if invalid, resort to global */
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700185 case 'V':
186 case 'D':
187 case 'I':
188 case 'W':
189 case 'E':
190 case 'F': /* Not officially supported */
191 case 'A':
192 case 'S':
Mark Salyzyn233e4752015-12-04 10:59:45 -0800193 case BOOLEAN_FALSE: /* Not officially supported */
Mark Salyzyn6e315682017-03-09 08:09:43 -0800194 break;
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700195 default:
Mark Salyzyn6e315682017-03-09 08:09:43 -0800196 /* clear '.' after log.tag */
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800197 key[strlen(log_namespace) - 1] = '\0';
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700198
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800199 for (size_t i = 0; i < arraysize(global_cache); ++i) {
200 cache_char* cache = &global_cache[i];
201 cache_char temp_cache;
Mark Salyzynd4860192015-12-21 12:32:48 -0800202
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800203 if (!locked) {
Mark Salyzyn6e315682017-03-09 08:09:43 -0800204 temp_cache = *cache;
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800205 if (temp_cache.cache.pinfo != cache->cache.pinfo) { // check atomic
Mark Salyzyn6e315682017-03-09 08:09:43 -0800206 temp_cache.cache.pinfo = NULL;
207 temp_cache.c = '\0';
208 }
209 cache = &temp_cache;
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700210 }
Mark Salyzyn6e315682017-03-09 08:09:43 -0800211 if (global_change_detected) {
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800212 refresh_cache(cache, i == 0 ? key : key + strlen("persist."));
Mark Salyzyn6e315682017-03-09 08:09:43 -0800213 }
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700214
Mark Salyzyn6e315682017-03-09 08:09:43 -0800215 if (cache->c) {
216 c = cache->c;
217 break;
218 }
Mark Salyzyn6e315682017-03-09 08:09:43 -0800219 }
220 break;
221 }
222
Elliott Hughesc1a5ec52021-02-09 13:29:33 -0800223 if (locked) {
Mark Salyzyn6e315682017-03-09 08:09:43 -0800224 global_serial = current_global_serial;
225 unlock();
226 }
227
228 switch (toupper(c)) {
229 /* clang-format off */
Mark Salyzyn500cd1c2015-03-12 15:46:29 -0700230 case 'V': return ANDROID_LOG_VERBOSE;
231 case 'D': return ANDROID_LOG_DEBUG;
232 case 'I': return ANDROID_LOG_INFO;
233 case 'W': return ANDROID_LOG_WARN;
234 case 'E': return ANDROID_LOG_ERROR;
235 case 'F': /* FALLTHRU */ /* Not officially supported */
236 case 'A': return ANDROID_LOG_FATAL;
Mark Salyzyn233e4752015-12-04 10:59:45 -0800237 case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
Tom Cherry40044602020-01-16 15:58:02 -0800238 case 'S': return ANDROID_LOG_SILENT;
Tom Cherryf623f022019-01-10 10:37:36 -0800239 /* clang-format on */
Mark Salyzyn6e315682017-03-09 08:09:43 -0800240 }
Tom Cherry40044602020-01-16 15:58:02 -0800241 return -1;
Mark Salyzyn6e315682017-03-09 08:09:43 -0800242}
243
Tom Cherry3d6a8782019-02-08 11:46:19 -0800244int __android_log_is_loggable_len(int prio, const char* tag, size_t len, int default_prio) {
Tom Cherry40044602020-01-16 15:58:02 -0800245 int minimum_log_priority = __android_log_get_minimum_priority();
246 int property_log_level = __android_log_level(tag, len);
247
248 if (property_log_level >= 0 && minimum_log_priority != ANDROID_LOG_DEFAULT) {
249 return prio >= std::min(property_log_level, minimum_log_priority);
250 } else if (property_log_level >= 0) {
251 return prio >= property_log_level;
252 } else if (minimum_log_priority != ANDROID_LOG_DEFAULT) {
253 return prio >= minimum_log_priority;
254 } else {
255 return prio >= default_prio;
256 }
Mark Salyzyn6e315682017-03-09 08:09:43 -0800257}
258
Tom Cherry3d6a8782019-02-08 11:46:19 -0800259int __android_log_is_loggable(int prio, const char* tag, int default_prio) {
Tom Cherry40044602020-01-16 15:58:02 -0800260 auto len = tag ? strlen(tag) : 0;
261 return __android_log_is_loggable_len(prio, tag, len, default_prio);
Mark Salyzyn6e315682017-03-09 08:09:43 -0800262}
263
Tom Cherry3d6a8782019-02-08 11:46:19 -0800264int __android_log_is_debuggable() {
Tom Cherry5ad35682020-07-27 15:31:44 -0700265 static int is_debuggable = [] {
266 char value[PROP_VALUE_MAX] = {};
267 return __system_property_get("ro.debuggable", value) > 0 && !strcmp(value, "1");
268 }();
Mark Salyzyn6e315682017-03-09 08:09:43 -0800269
Tom Cherry5ad35682020-07-27 15:31:44 -0700270 return is_debuggable;
Mark Salyzyn509c1422016-03-25 15:50:46 -0700271}
272
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800273/*
Mark Salyzynd4860192015-12-21 12:32:48 -0800274 * For properties that are read often, but generally remain constant.
275 * Since a change is rare, we will accept a trylock failure gracefully.
276 * Use a separate lock from is_loggable to keep contention down b/25563384.
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800277 */
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700278struct cache2_char {
Mark Salyzyn6e315682017-03-09 08:09:43 -0800279 pthread_mutex_t lock;
280 uint32_t serial;
281 const char* key_persist;
282 struct cache_char cache_persist;
283 const char* key_ro;
284 struct cache_char cache_ro;
285 unsigned char (*const evaluate)(const struct cache2_char* self);
Mark Salyzynd4860192015-12-21 12:32:48 -0800286};
Mark Salyzyn4c68f3f2015-11-06 12:26:52 -0800287
Mark Salyzyn6e315682017-03-09 08:09:43 -0800288static inline unsigned char do_cache2_char(struct cache2_char* self) {
289 uint32_t current_serial;
290 int change_detected;
291 unsigned char c;
Mark Salyzyn2cdfd8e2015-09-08 08:32:01 -0700292
Mark Salyzyn6e315682017-03-09 08:09:43 -0800293 if (pthread_mutex_trylock(&self->lock)) {
294 /* We are willing to accept some race in this context */
295 return self->evaluate(self);
296 }
Mark Salyzyn2cdfd8e2015-09-08 08:32:01 -0700297
Tom Cherryf623f022019-01-10 10:37:36 -0800298 change_detected = check_cache(&self->cache_persist.cache) || check_cache(&self->cache_ro.cache);
Mark Salyzyn6e315682017-03-09 08:09:43 -0800299 current_serial = __system_property_area_serial();
300 if (current_serial != self->serial) {
301 change_detected = 1;
302 }
303 if (change_detected) {
304 refresh_cache(&self->cache_persist, self->key_persist);
305 refresh_cache(&self->cache_ro, self->key_ro);
306 self->serial = current_serial;
307 }
308 c = self->evaluate(self);
Mark Salyzynd4860192015-12-21 12:32:48 -0800309
Mark Salyzyn6e315682017-03-09 08:09:43 -0800310 pthread_mutex_unlock(&self->lock);
Mark Salyzynd4860192015-12-21 12:32:48 -0800311
Mark Salyzyn6e315682017-03-09 08:09:43 -0800312 return c;
Mark Salyzynd4860192015-12-21 12:32:48 -0800313}
314
Mark Salyzynd4860192015-12-21 12:32:48 -0800315/*
316 * Security state generally remains constant, but the DO must be able
317 * to turn off logging should it become spammy after an attack is detected.
318 */
Mark Salyzyn6e315682017-03-09 08:09:43 -0800319static unsigned char evaluate_security(const struct cache2_char* self) {
320 unsigned char c = self->cache_ro.c;
Mark Salyzynd4860192015-12-21 12:32:48 -0800321
Mark Salyzyn6e315682017-03-09 08:09:43 -0800322 return (c != BOOLEAN_FALSE) && c && (self->cache_persist.c == BOOLEAN_TRUE);
Mark Salyzynd4860192015-12-21 12:32:48 -0800323}
Mark Salyzyn233e4752015-12-04 10:59:45 -0800324
Tom Cherry3d6a8782019-02-08 11:46:19 -0800325int __android_log_security() {
Mark Salyzyn6e315682017-03-09 08:09:43 -0800326 static struct cache2_char security = {
Tom Cherryf623f022019-01-10 10:37:36 -0800327 PTHREAD_MUTEX_INITIALIZER, 0,
328 "persist.logd.security", {{NULL, 0xFFFFFFFF}, BOOLEAN_FALSE},
Rubin Xu68dbc9e2020-02-17 11:42:54 +0000329 "ro.organization_owned", {{NULL, 0xFFFFFFFF}, BOOLEAN_FALSE},
Tom Cherryf623f022019-01-10 10:37:36 -0800330 evaluate_security};
Mark Salyzyn233e4752015-12-04 10:59:45 -0800331
Mark Salyzyn6e315682017-03-09 08:09:43 -0800332 return do_cache2_char(&security);
Mark Salyzyncbf691a2016-09-26 13:21:05 -0700333}
334
Tom Cherryc377c7d2020-01-27 15:45:52 -0800335#else
336
337int __android_log_is_loggable(int prio, const char*, int) {
338 int minimum_priority = __android_log_get_minimum_priority();
339 if (minimum_priority == ANDROID_LOG_DEFAULT) {
340 minimum_priority = ANDROID_LOG_INFO;
341 }
342 return prio >= minimum_priority;
343}
344
345int __android_log_is_loggable_len(int prio, const char*, size_t, int def) {
346 return __android_log_is_loggable(prio, nullptr, def);
347}
348
349int __android_log_is_debuggable() {
350 return 1;
351}
352
Tom Cherrycbd31f92020-07-27 11:20:29 -0700353#endif