blob: 37670ecd6039a1c52f0fdada7ef842bcb8164b9c [file] [log] [blame]
Mark Salyzyn95687052014-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 Cherry71ba1642019-01-10 10:37:36 -080017#include <log/log_properties.h>
18
Mark Salyzyn95687052014-10-02 11:12:28 -070019#include <ctype.h>
Mark Salyzync1584562015-03-12 15:46:29 -070020#include <pthread.h>
21#include <stdlib.h>
Mark Salyzyn95687052014-10-02 11:12:28 -070022#include <string.h>
Mark Salyzyne4553732016-09-26 13:21:05 -070023#include <unistd.h>
Mark Salyzyn95687052014-10-02 11:12:28 -070024
Tom Cherry0391a872020-01-16 15:58:02 -080025#include <algorithm>
26
Mark Salyzyne4553732016-09-26 13:21:05 -070027#include <private/android_logger.h>
Mark Salyzyn95687052014-10-02 11:12:28 -070028
Tom Cherry2ec6a532020-01-27 08:35:13 -080029#include "logger_write.h"
30
Tom Cherrye2187bf2020-01-27 15:45:52 -080031#ifdef __ANDROID__
32#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
33#include <sys/_system_properties.h>
34
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080035static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
36
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080037static int lock() {
38 /*
39 * If we trigger a signal handler in the middle of locked activity and the
40 * signal handler logs a message, we could get into a deadlock state.
41 */
42 /*
43 * Any contention, and we can turn around and use the non-cached method
44 * in less time than the system call associated with a mutex to deal with
45 * the contention.
46 */
47 return pthread_mutex_trylock(&lock_loggable);
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080048}
49
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080050static void unlock() {
51 pthread_mutex_unlock(&lock_loggable);
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080052}
53
Mark Salyzync1584562015-03-12 15:46:29 -070054struct cache {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080055 const prop_info* pinfo;
56 uint32_t serial;
Mark Salyzyne4553732016-09-26 13:21:05 -070057};
58
59struct cache_char {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080060 struct cache cache;
61 unsigned char c;
Mark Salyzync1584562015-03-12 15:46:29 -070062};
63
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080064static int check_cache(struct cache* cache) {
65 return cache->pinfo && __system_property_serial(cache->pinfo) != cache->serial;
Mark Salyzyna67d8a52015-12-21 12:32:48 -080066}
67
Mark Salyzynffbd86f2015-12-04 10:59:45 -080068#define BOOLEAN_TRUE 0xFF
69#define BOOLEAN_FALSE 0xFE
70
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080071static void refresh_cache(struct cache_char* cache, const char* key) {
72 char buf[PROP_VALUE_MAX];
Mark Salyzyn95687052014-10-02 11:12:28 -070073
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080074 if (!cache->cache.pinfo) {
75 cache->cache.pinfo = __system_property_find(key);
Mark Salyzyne4553732016-09-26 13:21:05 -070076 if (!cache->cache.pinfo) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080077 return;
Mark Salyzyn95687052014-10-02 11:12:28 -070078 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080079 }
80 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
81 __system_property_read(cache->cache.pinfo, 0, buf);
82 switch (buf[0]) {
83 case 't':
84 case 'T':
85 cache->c = strcasecmp(buf + 1, "rue") ? buf[0] : BOOLEAN_TRUE;
86 break;
87 case 'f':
88 case 'F':
89 cache->c = strcasecmp(buf + 1, "alse") ? buf[0] : BOOLEAN_FALSE;
90 break;
Mark Salyzynffbd86f2015-12-04 10:59:45 -080091 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080092 cache->c = buf[0];
93 }
Mark Salyzync1584562015-03-12 15:46:29 -070094}
Mark Salyzyn95687052014-10-02 11:12:28 -070095
Tom Cherry0391a872020-01-16 15:58:02 -080096static int __android_log_level(const char* tag, size_t len) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080097 /* sizeof() is used on this array below */
98 static const char log_namespace[] = "persist.log.tag.";
99 static const size_t base_offset = 8; /* skip "persist." */
Tom Cherry2ec6a532020-01-27 08:35:13 -0800100
Tom Cherry2ec6a532020-01-27 08:35:13 -0800101 if (tag == nullptr || len == 0) {
Tom Cherry2ec6a532020-01-27 08:35:13 -0800102 auto& tag_string = GetDefaultTag();
103 tag = tag_string.c_str();
104 len = tag_string.size();
105 }
106
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800107 /* sizeof(log_namespace) = strlen(log_namespace) + 1 */
Tom Cherry2ec6a532020-01-27 08:35:13 -0800108 char key[sizeof(log_namespace) + len];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800109 char* kp;
110 size_t i;
111 char c = 0;
112 /*
113 * Single layer cache of four properties. Priorities are:
114 * log.tag.<tag>
115 * persist.log.tag.<tag>
116 * log.tag
117 * persist.log.tag
118 * Where the missing tag matches all tags and becomes the
119 * system global default. We do not support ro.log.tag* .
120 */
Mark Salyzynd24dc952017-04-05 10:11:09 -0700121 static char* last_tag;
122 static size_t last_tag_len;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800123 static uint32_t global_serial;
124 /* some compilers erroneously see uninitialized use. !not_locked */
125 uint32_t current_global_serial = 0;
126 static struct cache_char tag_cache[2];
127 static struct cache_char global_cache[2];
128 int change_detected;
129 int global_change_detected;
130 int not_locked;
131
132 strcpy(key, log_namespace);
133
134 global_change_detected = change_detected = not_locked = lock();
135
136 if (!not_locked) {
Mark Salyzync1584562015-03-12 15:46:29 -0700137 /*
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800138 * check all known serial numbers to changes.
Mark Salyzync1584562015-03-12 15:46:29 -0700139 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800140 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
141 if (check_cache(&tag_cache[i].cache)) {
142 change_detected = 1;
143 }
144 }
145 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
146 if (check_cache(&global_cache[i].cache)) {
147 global_change_detected = 1;
148 }
149 }
Mark Salyzync1584562015-03-12 15:46:29 -0700150
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800151 current_global_serial = __system_property_area_serial();
152 if (current_global_serial != global_serial) {
153 change_detected = 1;
154 global_change_detected = 1;
155 }
156 }
Mark Salyzync1584562015-03-12 15:46:29 -0700157
Tom Cherry2ec6a532020-01-27 08:35:13 -0800158 if (len) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800159 int local_change_detected = change_detected;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800160 if (!not_locked) {
Mark Salyzynd24dc952017-04-05 10:11:09 -0700161 if (!last_tag || !last_tag[0] || (last_tag[0] != tag[0]) ||
162 strncmp(last_tag + 1, tag + 1, last_tag_len - 1)) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800163 /* invalidate log.tag.<tag> cache */
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800164 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800165 tag_cache[i].cache.pinfo = NULL;
166 tag_cache[i].c = '\0';
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800167 }
Mark Salyzynd24dc952017-04-05 10:11:09 -0700168 if (last_tag) last_tag[0] = '\0';
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800169 local_change_detected = 1;
170 }
Mark Salyzynd24dc952017-04-05 10:11:09 -0700171 if (!last_tag || !last_tag[0]) {
172 if (!last_tag) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800173 last_tag = static_cast<char*>(calloc(1, len + 1));
Mark Salyzynd24dc952017-04-05 10:11:09 -0700174 last_tag_len = 0;
175 if (last_tag) last_tag_len = len + 1;
176 } else if (len >= last_tag_len) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800177 last_tag = static_cast<char*>(realloc(last_tag, len + 1));
Mark Salyzynd24dc952017-04-05 10:11:09 -0700178 last_tag_len = 0;
179 if (last_tag) last_tag_len = len + 1;
180 }
181 if (last_tag) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800182 strncpy(last_tag, tag, len);
183 last_tag[len] = '\0';
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800184 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800185 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800186 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800187 strncpy(key + sizeof(log_namespace) - 1, tag, len);
188 key[sizeof(log_namespace) - 1 + len] = '\0';
Mark Salyzync1584562015-03-12 15:46:29 -0700189
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800190 kp = key;
191 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
192 struct cache_char* cache = &tag_cache[i];
193 struct cache_char temp_cache;
Mark Salyzyn95687052014-10-02 11:12:28 -0700194
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800195 if (not_locked) {
196 temp_cache.cache.pinfo = NULL;
197 temp_cache.c = '\0';
198 cache = &temp_cache;
199 }
200 if (local_change_detected) {
201 refresh_cache(cache, kp);
202 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800203
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800204 if (cache->c) {
205 c = cache->c;
206 break;
207 }
Mark Salyzync1584562015-03-12 15:46:29 -0700208
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800209 kp = key + base_offset;
Mark Salyzyn95687052014-10-02 11:12:28 -0700210 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800211 }
Mark Salyzync1584562015-03-12 15:46:29 -0700212
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800213 switch (toupper(c)) { /* if invalid, resort to global */
Mark Salyzync1584562015-03-12 15:46:29 -0700214 case 'V':
215 case 'D':
216 case 'I':
217 case 'W':
218 case 'E':
219 case 'F': /* Not officially supported */
220 case 'A':
221 case 'S':
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800222 case BOOLEAN_FALSE: /* Not officially supported */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800223 break;
Mark Salyzync1584562015-03-12 15:46:29 -0700224 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800225 /* clear '.' after log.tag */
226 key[sizeof(log_namespace) - 2] = '\0';
Mark Salyzync1584562015-03-12 15:46:29 -0700227
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800228 kp = key;
229 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
230 struct cache_char* cache = &global_cache[i];
231 struct cache_char temp_cache;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800232
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800233 if (not_locked) {
234 temp_cache = *cache;
235 if (temp_cache.cache.pinfo != cache->cache.pinfo) { /* check atomic */
236 temp_cache.cache.pinfo = NULL;
237 temp_cache.c = '\0';
238 }
239 cache = &temp_cache;
Mark Salyzync1584562015-03-12 15:46:29 -0700240 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800241 if (global_change_detected) {
242 refresh_cache(cache, kp);
243 }
Mark Salyzync1584562015-03-12 15:46:29 -0700244
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800245 if (cache->c) {
246 c = cache->c;
247 break;
248 }
Mark Salyzync1584562015-03-12 15:46:29 -0700249
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800250 kp = key + base_offset;
251 }
252 break;
253 }
254
255 if (!not_locked) {
256 global_serial = current_global_serial;
257 unlock();
258 }
259
260 switch (toupper(c)) {
261 /* clang-format off */
Mark Salyzync1584562015-03-12 15:46:29 -0700262 case 'V': return ANDROID_LOG_VERBOSE;
263 case 'D': return ANDROID_LOG_DEBUG;
264 case 'I': return ANDROID_LOG_INFO;
265 case 'W': return ANDROID_LOG_WARN;
266 case 'E': return ANDROID_LOG_ERROR;
267 case 'F': /* FALLTHRU */ /* Not officially supported */
268 case 'A': return ANDROID_LOG_FATAL;
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800269 case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
Tom Cherry0391a872020-01-16 15:58:02 -0800270 case 'S': return ANDROID_LOG_SILENT;
Tom Cherry71ba1642019-01-10 10:37:36 -0800271 /* clang-format on */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800272 }
Tom Cherry0391a872020-01-16 15:58:02 -0800273 return -1;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800274}
275
Tom Cherry2d9779e2019-02-08 11:46:19 -0800276int __android_log_is_loggable_len(int prio, const char* tag, size_t len, int default_prio) {
Tom Cherry0391a872020-01-16 15:58:02 -0800277 int minimum_log_priority = __android_log_get_minimum_priority();
278 int property_log_level = __android_log_level(tag, len);
279
280 if (property_log_level >= 0 && minimum_log_priority != ANDROID_LOG_DEFAULT) {
281 return prio >= std::min(property_log_level, minimum_log_priority);
282 } else if (property_log_level >= 0) {
283 return prio >= property_log_level;
284 } else if (minimum_log_priority != ANDROID_LOG_DEFAULT) {
285 return prio >= minimum_log_priority;
286 } else {
287 return prio >= default_prio;
288 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800289}
290
Tom Cherry2d9779e2019-02-08 11:46:19 -0800291int __android_log_is_loggable(int prio, const char* tag, int default_prio) {
Tom Cherry0391a872020-01-16 15:58:02 -0800292 auto len = tag ? strlen(tag) : 0;
293 return __android_log_is_loggable_len(prio, tag, len, default_prio);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800294}
295
Tom Cherry2d9779e2019-02-08 11:46:19 -0800296int __android_log_is_debuggable() {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800297 static uint32_t serial;
298 static struct cache_char tag_cache;
299 static const char key[] = "ro.debuggable";
300 int ret;
301
302 if (tag_cache.c) { /* ro property does not change after set */
303 ret = tag_cache.c == '1';
304 } else if (lock()) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800305 struct cache_char temp_cache = {{NULL, 0xFFFFFFFF}, '\0'};
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800306 refresh_cache(&temp_cache, key);
307 ret = temp_cache.c == '1';
308 } else {
309 int change_detected = check_cache(&tag_cache.cache);
310 uint32_t current_serial = __system_property_area_serial();
311 if (current_serial != serial) {
312 change_detected = 1;
Mark Salyzyn95687052014-10-02 11:12:28 -0700313 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800314 if (change_detected) {
315 refresh_cache(&tag_cache, key);
316 serial = current_serial;
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700317 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800318 ret = tag_cache.c == '1';
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700319
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800320 unlock();
321 }
322
323 return ret;
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700324}
325
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800326/*
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800327 * For properties that are read often, but generally remain constant.
328 * Since a change is rare, we will accept a trylock failure gracefully.
329 * Use a separate lock from is_loggable to keep contention down b/25563384.
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800330 */
Mark Salyzyne4553732016-09-26 13:21:05 -0700331struct cache2_char {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800332 pthread_mutex_t lock;
333 uint32_t serial;
334 const char* key_persist;
335 struct cache_char cache_persist;
336 const char* key_ro;
337 struct cache_char cache_ro;
338 unsigned char (*const evaluate)(const struct cache2_char* self);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800339};
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800340
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800341static inline unsigned char do_cache2_char(struct cache2_char* self) {
342 uint32_t current_serial;
343 int change_detected;
344 unsigned char c;
Mark Salyzyn500afc72015-09-08 08:32:01 -0700345
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800346 if (pthread_mutex_trylock(&self->lock)) {
347 /* We are willing to accept some race in this context */
348 return self->evaluate(self);
349 }
Mark Salyzyn500afc72015-09-08 08:32:01 -0700350
Tom Cherry71ba1642019-01-10 10:37:36 -0800351 change_detected = check_cache(&self->cache_persist.cache) || check_cache(&self->cache_ro.cache);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800352 current_serial = __system_property_area_serial();
353 if (current_serial != self->serial) {
354 change_detected = 1;
355 }
356 if (change_detected) {
357 refresh_cache(&self->cache_persist, self->key_persist);
358 refresh_cache(&self->cache_ro, self->key_ro);
359 self->serial = current_serial;
360 }
361 c = self->evaluate(self);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800362
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800363 pthread_mutex_unlock(&self->lock);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800364
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800365 return c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800366}
367
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800368static unsigned char evaluate_persist_ro(const struct cache2_char* self) {
369 unsigned char c = self->cache_persist.c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800370
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800371 if (c) {
372 return c;
373 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800374
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800375 return self->cache_ro.c;
Mark Salyzyn500afc72015-09-08 08:32:01 -0700376}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800377
378/*
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800379 * Timestamp state generally remains constant, but can change at any time
380 * to handle developer requirements.
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800381 */
Tom Cherry2d9779e2019-02-08 11:46:19 -0800382clockid_t android_log_clockid() {
Tom Cherry71ba1642019-01-10 10:37:36 -0800383 static struct cache2_char clockid = {PTHREAD_MUTEX_INITIALIZER, 0,
384 "persist.logd.timestamp", {{NULL, 0xFFFFFFFF}, '\0'},
385 "ro.logd.timestamp", {{NULL, 0xFFFFFFFF}, '\0'},
386 evaluate_persist_ro};
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800387
Tom Cherry71ba1642019-01-10 10:37:36 -0800388 return (tolower(do_cache2_char(&clockid)) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800389}
390
391/*
392 * Security state generally remains constant, but the DO must be able
393 * to turn off logging should it become spammy after an attack is detected.
394 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800395static unsigned char evaluate_security(const struct cache2_char* self) {
396 unsigned char c = self->cache_ro.c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800397
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800398 return (c != BOOLEAN_FALSE) && c && (self->cache_persist.c == BOOLEAN_TRUE);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800399}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800400
Tom Cherry2d9779e2019-02-08 11:46:19 -0800401int __android_log_security() {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800402 static struct cache2_char security = {
Tom Cherry71ba1642019-01-10 10:37:36 -0800403 PTHREAD_MUTEX_INITIALIZER, 0,
404 "persist.logd.security", {{NULL, 0xFFFFFFFF}, BOOLEAN_FALSE},
Rubin Xu7a5cbfc2020-02-17 11:42:54 +0000405 "ro.organization_owned", {{NULL, 0xFFFFFFFF}, BOOLEAN_FALSE},
Tom Cherry71ba1642019-01-10 10:37:36 -0800406 evaluate_security};
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800407
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800408 return do_cache2_char(&security);
Mark Salyzyne4553732016-09-26 13:21:05 -0700409}
410
411/*
412 * Interface that represents the logd buffer size determination so that others
413 * need not guess our intentions.
414 */
415
416/* Property helper */
417static bool check_flag(const char* prop, const char* flag) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800418 const char* cp = strcasestr(prop, flag);
419 if (!cp) {
420 return false;
421 }
422 /* We only will document comma (,) */
423 static const char sep[] = ",:;|+ \t\f";
424 if ((cp != prop) && !strchr(sep, cp[-1])) {
425 return false;
426 }
427 cp += strlen(flag);
428 return !*cp || !!strchr(sep, *cp);
Mark Salyzyne4553732016-09-26 13:21:05 -0700429}
430
431/* cache structure */
432struct cache_property {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800433 struct cache cache;
434 char property[PROP_VALUE_MAX];
Mark Salyzyne4553732016-09-26 13:21:05 -0700435};
436
Tom Cherry71ba1642019-01-10 10:37:36 -0800437static void refresh_cache_property(struct cache_property* cache, const char* key) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800438 if (!cache->cache.pinfo) {
439 cache->cache.pinfo = __system_property_find(key);
Mark Salyzyne4553732016-09-26 13:21:05 -0700440 if (!cache->cache.pinfo) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800441 return;
Mark Salyzyne4553732016-09-26 13:21:05 -0700442 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800443 }
444 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
445 __system_property_read(cache->cache.pinfo, 0, cache->property);
Mark Salyzyne4553732016-09-26 13:21:05 -0700446}
447
448/* get boolean with the logger twist that supports eng adjustments */
Tom Cherry2d9779e2019-02-08 11:46:19 -0800449bool __android_logger_property_get_bool(const char* key, int flag) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800450 struct cache_property property = {{NULL, 0xFFFFFFFF}, {0}};
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800451 if (flag & BOOL_DEFAULT_FLAG_PERSIST) {
Mark Salyzynd24dc952017-04-05 10:11:09 -0700452 char newkey[strlen("persist.") + strlen(key) + 1];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800453 snprintf(newkey, sizeof(newkey), "ro.%s", key);
454 refresh_cache_property(&property, newkey);
455 property.cache.pinfo = NULL;
Tom Cherry71ba1642019-01-10 10:37:36 -0800456 property.cache.serial = 0xFFFFFFFF;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800457 snprintf(newkey, sizeof(newkey), "persist.%s", key);
458 refresh_cache_property(&property, newkey);
459 property.cache.pinfo = NULL;
Tom Cherry71ba1642019-01-10 10:37:36 -0800460 property.cache.serial = 0xFFFFFFFF;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800461 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700462
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800463 refresh_cache_property(&property, key);
Mark Salyzyne4553732016-09-26 13:21:05 -0700464
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800465 if (check_flag(property.property, "true")) {
466 return true;
467 }
468 if (check_flag(property.property, "false")) {
469 return false;
470 }
Mark Salyzyn9fcaaba2017-04-18 08:43:16 -0700471 if (property.property[0]) {
472 flag &= ~(BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE);
473 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800474 if (check_flag(property.property, "eng")) {
475 flag |= BOOL_DEFAULT_FLAG_ENG;
476 }
477 /* this is really a "not" flag */
478 if (check_flag(property.property, "svelte")) {
479 flag |= BOOL_DEFAULT_FLAG_SVELTE;
480 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700481
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800482 /* Sanity Check */
483 if (flag & (BOOL_DEFAULT_FLAG_SVELTE | BOOL_DEFAULT_FLAG_ENG)) {
484 flag &= ~BOOL_DEFAULT_FLAG_TRUE_FALSE;
485 flag |= BOOL_DEFAULT_TRUE;
486 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700487
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800488 if ((flag & BOOL_DEFAULT_FLAG_SVELTE) &&
Tom Cherry71ba1642019-01-10 10:37:36 -0800489 __android_logger_property_get_bool("ro.config.low_ram", BOOL_DEFAULT_FALSE)) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800490 return false;
491 }
492 if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) {
493 return false;
494 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700495
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800496 return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
Mark Salyzyne4553732016-09-26 13:21:05 -0700497}
498
Tom Cherry2d9779e2019-02-08 11:46:19 -0800499bool __android_logger_valid_buffer_size(unsigned long value) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800500 static long pages, pagesize;
501 unsigned long maximum;
Mark Salyzyne4553732016-09-26 13:21:05 -0700502
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800503 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
504 return false;
505 }
506
507 if (!pages) {
508 pages = sysconf(_SC_PHYS_PAGES);
509 }
510 if (pages < 1) {
511 return true;
512 }
513
514 if (!pagesize) {
515 pagesize = sysconf(_SC_PAGESIZE);
516 if (pagesize <= 1) {
517 pagesize = PAGE_SIZE;
Mark Salyzyne4553732016-09-26 13:21:05 -0700518 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800519 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700520
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800521 /* maximum memory impact a somewhat arbitrary ~3% */
522 pages = (pages + 31) / 32;
523 maximum = pages * pagesize;
Mark Salyzyne4553732016-09-26 13:21:05 -0700524
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800525 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
526 return true;
527 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700528
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800529 return value <= maximum;
Mark Salyzyne4553732016-09-26 13:21:05 -0700530}
531
532struct cache2_property_size {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800533 pthread_mutex_t lock;
534 uint32_t serial;
535 const char* key_persist;
536 struct cache_property cache_persist;
537 const char* key_ro;
538 struct cache_property cache_ro;
539 unsigned long (*const evaluate)(const struct cache2_property_size* self);
Mark Salyzyne4553732016-09-26 13:21:05 -0700540};
541
Tom Cherry71ba1642019-01-10 10:37:36 -0800542static inline unsigned long do_cache2_property_size(struct cache2_property_size* self) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800543 uint32_t current_serial;
544 int change_detected;
545 unsigned long v;
Mark Salyzyne4553732016-09-26 13:21:05 -0700546
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800547 if (pthread_mutex_trylock(&self->lock)) {
548 /* We are willing to accept some race in this context */
549 return self->evaluate(self);
550 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700551
Tom Cherry71ba1642019-01-10 10:37:36 -0800552 change_detected = check_cache(&self->cache_persist.cache) || check_cache(&self->cache_ro.cache);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800553 current_serial = __system_property_area_serial();
554 if (current_serial != self->serial) {
555 change_detected = 1;
556 }
557 if (change_detected) {
558 refresh_cache_property(&self->cache_persist, self->key_persist);
559 refresh_cache_property(&self->cache_ro, self->key_ro);
560 self->serial = current_serial;
561 }
562 v = self->evaluate(self);
Mark Salyzyne4553732016-09-26 13:21:05 -0700563
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800564 pthread_mutex_unlock(&self->lock);
Mark Salyzyne4553732016-09-26 13:21:05 -0700565
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800566 return v;
Mark Salyzyne4553732016-09-26 13:21:05 -0700567}
568
Tom Cherry71ba1642019-01-10 10:37:36 -0800569static unsigned long property_get_size_from_cache(const struct cache_property* cache) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800570 char* cp;
571 unsigned long value = strtoul(cache->property, &cp, 10);
Mark Salyzyne4553732016-09-26 13:21:05 -0700572
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800573 switch (*cp) {
Mark Salyzyne4553732016-09-26 13:21:05 -0700574 case 'm':
575 case 'M':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800576 value *= 1024;
Tom Cherry71ba1642019-01-10 10:37:36 -0800577 [[fallthrough]];
Mark Salyzyne4553732016-09-26 13:21:05 -0700578 case 'k':
579 case 'K':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800580 value *= 1024;
Tom Cherry71ba1642019-01-10 10:37:36 -0800581 [[fallthrough]];
Mark Salyzyne4553732016-09-26 13:21:05 -0700582 case '\0':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800583 break;
Mark Salyzyne4553732016-09-26 13:21:05 -0700584
585 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800586 value = 0;
587 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700588
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800589 if (!__android_logger_valid_buffer_size(value)) {
590 value = 0;
591 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700592
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800593 return value;
Mark Salyzyne4553732016-09-26 13:21:05 -0700594}
595
Tom Cherry71ba1642019-01-10 10:37:36 -0800596static unsigned long evaluate_property_get_size(const struct cache2_property_size* self) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800597 unsigned long size = property_get_size_from_cache(&self->cache_persist);
598 if (size) {
599 return size;
600 }
601 return property_get_size_from_cache(&self->cache_ro);
Mark Salyzyne4553732016-09-26 13:21:05 -0700602}
603
Tom Cherry2d9779e2019-02-08 11:46:19 -0800604unsigned long __android_logger_get_buffer_size(log_id_t logId) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800605 static const char global_tunable[] = "persist.logd.size"; /* Settings App */
606 static const char global_default[] = "ro.logd.size"; /* BoardConfig.mk */
607 static struct cache2_property_size global = {
Tom Cherry71ba1642019-01-10 10:37:36 -0800608 /* clang-format off */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800609 PTHREAD_MUTEX_INITIALIZER, 0,
Tom Cherry71ba1642019-01-10 10:37:36 -0800610 global_tunable, { { NULL, 0xFFFFFFFF }, {} },
611 global_default, { { NULL, 0xFFFFFFFF }, {} },
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800612 evaluate_property_get_size
Tom Cherry71ba1642019-01-10 10:37:36 -0800613 /* clang-format on */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800614 };
Mark Salyzynd24dc952017-04-05 10:11:09 -0700615 char key_persist[strlen(global_tunable) + strlen(".security") + 1];
616 char key_ro[strlen(global_default) + strlen(".security") + 1];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800617 struct cache2_property_size local = {
Tom Cherry71ba1642019-01-10 10:37:36 -0800618 /* clang-format off */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800619 PTHREAD_MUTEX_INITIALIZER, 0,
Tom Cherry71ba1642019-01-10 10:37:36 -0800620 key_persist, { { NULL, 0xFFFFFFFF }, {} },
621 key_ro, { { NULL, 0xFFFFFFFF }, {} },
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800622 evaluate_property_get_size
Tom Cherry71ba1642019-01-10 10:37:36 -0800623 /* clang-format on */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800624 };
625 unsigned long property_size, default_size;
Mark Salyzyne4553732016-09-26 13:21:05 -0700626
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800627 default_size = do_cache2_property_size(&global);
628 if (!default_size) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800629 default_size = __android_logger_property_get_bool("ro.config.low_ram", BOOL_DEFAULT_FALSE)
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800630 ? LOG_BUFFER_MIN_SIZE /* 64K */
631 : LOG_BUFFER_SIZE; /* 256K */
632 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700633
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800634 snprintf(key_persist, sizeof(key_persist), "%s.%s", global_tunable,
635 android_log_id_to_name(logId));
Tom Cherry71ba1642019-01-10 10:37:36 -0800636 snprintf(key_ro, sizeof(key_ro), "%s.%s", global_default, android_log_id_to_name(logId));
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800637 property_size = do_cache2_property_size(&local);
Mark Salyzyne4553732016-09-26 13:21:05 -0700638
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800639 if (!property_size) {
640 property_size = default_size;
641 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700642
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800643 if (!property_size) {
644 property_size = LOG_BUFFER_SIZE;
645 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700646
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800647 return property_size;
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800648}
Tom Cherrye2187bf2020-01-27 15:45:52 -0800649
650#else
651
652int __android_log_is_loggable(int prio, const char*, int) {
653 int minimum_priority = __android_log_get_minimum_priority();
654 if (minimum_priority == ANDROID_LOG_DEFAULT) {
655 minimum_priority = ANDROID_LOG_INFO;
656 }
657 return prio >= minimum_priority;
658}
659
660int __android_log_is_loggable_len(int prio, const char*, size_t, int def) {
661 return __android_log_is_loggable(prio, nullptr, def);
662}
663
664int __android_log_is_debuggable() {
665 return 1;
666}
667
668#endif