blob: b13662fa0064feba9281c4bebc60e03774fe0b74 [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 Salyzync1584562015-03-12 15:46:29 -070023#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
24#include <sys/_system_properties.h>
Mark Salyzyne4553732016-09-26 13:21:05 -070025#include <unistd.h>
Mark Salyzyn95687052014-10-02 11:12:28 -070026
Tom Cherry0391a872020-01-16 15:58:02 -080027#include <algorithm>
Tom Cherry2ec6a532020-01-27 08:35:13 -080028#include <shared_mutex>
Tom Cherry0391a872020-01-16 15:58:02 -080029
Mark Salyzyne4553732016-09-26 13:21:05 -070030#include <private/android_logger.h>
Mark Salyzyn95687052014-10-02 11:12:28 -070031
Tom Cherry2ec6a532020-01-27 08:35:13 -080032#include "logger_write.h"
33
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080034static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
35
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080036static int lock() {
37 /*
38 * If we trigger a signal handler in the middle of locked activity and the
39 * signal handler logs a message, we could get into a deadlock state.
40 */
41 /*
42 * Any contention, and we can turn around and use the non-cached method
43 * in less time than the system call associated with a mutex to deal with
44 * the contention.
45 */
46 return pthread_mutex_trylock(&lock_loggable);
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080047}
48
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080049static void unlock() {
50 pthread_mutex_unlock(&lock_loggable);
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080051}
52
Mark Salyzync1584562015-03-12 15:46:29 -070053struct cache {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080054 const prop_info* pinfo;
55 uint32_t serial;
Mark Salyzyne4553732016-09-26 13:21:05 -070056};
57
58struct cache_char {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080059 struct cache cache;
60 unsigned char c;
Mark Salyzync1584562015-03-12 15:46:29 -070061};
62
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080063static int check_cache(struct cache* cache) {
64 return cache->pinfo && __system_property_serial(cache->pinfo) != cache->serial;
Mark Salyzyna67d8a52015-12-21 12:32:48 -080065}
66
Mark Salyzynffbd86f2015-12-04 10:59:45 -080067#define BOOLEAN_TRUE 0xFF
68#define BOOLEAN_FALSE 0xFE
69
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080070static void refresh_cache(struct cache_char* cache, const char* key) {
71 char buf[PROP_VALUE_MAX];
Mark Salyzyn95687052014-10-02 11:12:28 -070072
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080073 if (!cache->cache.pinfo) {
74 cache->cache.pinfo = __system_property_find(key);
Mark Salyzyne4553732016-09-26 13:21:05 -070075 if (!cache->cache.pinfo) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080076 return;
Mark Salyzyn95687052014-10-02 11:12:28 -070077 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080078 }
79 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
80 __system_property_read(cache->cache.pinfo, 0, buf);
81 switch (buf[0]) {
82 case 't':
83 case 'T':
84 cache->c = strcasecmp(buf + 1, "rue") ? buf[0] : BOOLEAN_TRUE;
85 break;
86 case 'f':
87 case 'F':
88 cache->c = strcasecmp(buf + 1, "alse") ? buf[0] : BOOLEAN_FALSE;
89 break;
Mark Salyzynffbd86f2015-12-04 10:59:45 -080090 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080091 cache->c = buf[0];
92 }
Mark Salyzync1584562015-03-12 15:46:29 -070093}
Mark Salyzyn95687052014-10-02 11:12:28 -070094
Tom Cherry0391a872020-01-16 15:58:02 -080095static int __android_log_level(const char* tag, size_t len) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080096 /* sizeof() is used on this array below */
97 static const char log_namespace[] = "persist.log.tag.";
98 static const size_t base_offset = 8; /* skip "persist." */
Tom Cherry2ec6a532020-01-27 08:35:13 -080099
100 auto tag_lock = std::shared_lock{default_tag_lock, std::defer_lock};
101 if (tag == nullptr || len == 0) {
102 tag_lock.lock();
103 auto& tag_string = GetDefaultTag();
104 tag = tag_string.c_str();
105 len = tag_string.size();
106 }
107
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800108 /* sizeof(log_namespace) = strlen(log_namespace) + 1 */
Tom Cherry2ec6a532020-01-27 08:35:13 -0800109 char key[sizeof(log_namespace) + len];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800110 char* kp;
111 size_t i;
112 char c = 0;
113 /*
114 * Single layer cache of four properties. Priorities are:
115 * log.tag.<tag>
116 * persist.log.tag.<tag>
117 * log.tag
118 * persist.log.tag
119 * Where the missing tag matches all tags and becomes the
120 * system global default. We do not support ro.log.tag* .
121 */
Mark Salyzynd24dc952017-04-05 10:11:09 -0700122 static char* last_tag;
123 static size_t last_tag_len;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800124 static uint32_t global_serial;
125 /* some compilers erroneously see uninitialized use. !not_locked */
126 uint32_t current_global_serial = 0;
127 static struct cache_char tag_cache[2];
128 static struct cache_char global_cache[2];
129 int change_detected;
130 int global_change_detected;
131 int not_locked;
132
133 strcpy(key, log_namespace);
134
135 global_change_detected = change_detected = not_locked = lock();
136
137 if (!not_locked) {
Mark Salyzync1584562015-03-12 15:46:29 -0700138 /*
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800139 * check all known serial numbers to changes.
Mark Salyzync1584562015-03-12 15:46:29 -0700140 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800141 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
142 if (check_cache(&tag_cache[i].cache)) {
143 change_detected = 1;
144 }
145 }
146 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
147 if (check_cache(&global_cache[i].cache)) {
148 global_change_detected = 1;
149 }
150 }
Mark Salyzync1584562015-03-12 15:46:29 -0700151
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800152 current_global_serial = __system_property_area_serial();
153 if (current_global_serial != global_serial) {
154 change_detected = 1;
155 global_change_detected = 1;
156 }
157 }
Mark Salyzync1584562015-03-12 15:46:29 -0700158
Tom Cherry2ec6a532020-01-27 08:35:13 -0800159 if (len) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800160 int local_change_detected = change_detected;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800161 if (!not_locked) {
Mark Salyzynd24dc952017-04-05 10:11:09 -0700162 if (!last_tag || !last_tag[0] || (last_tag[0] != tag[0]) ||
163 strncmp(last_tag + 1, tag + 1, last_tag_len - 1)) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800164 /* invalidate log.tag.<tag> cache */
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800165 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800166 tag_cache[i].cache.pinfo = NULL;
167 tag_cache[i].c = '\0';
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800168 }
Mark Salyzynd24dc952017-04-05 10:11:09 -0700169 if (last_tag) last_tag[0] = '\0';
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800170 local_change_detected = 1;
171 }
Mark Salyzynd24dc952017-04-05 10:11:09 -0700172 if (!last_tag || !last_tag[0]) {
173 if (!last_tag) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800174 last_tag = static_cast<char*>(calloc(1, len + 1));
Mark Salyzynd24dc952017-04-05 10:11:09 -0700175 last_tag_len = 0;
176 if (last_tag) last_tag_len = len + 1;
177 } else if (len >= last_tag_len) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800178 last_tag = static_cast<char*>(realloc(last_tag, len + 1));
Mark Salyzynd24dc952017-04-05 10:11:09 -0700179 last_tag_len = 0;
180 if (last_tag) last_tag_len = len + 1;
181 }
182 if (last_tag) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800183 strncpy(last_tag, tag, len);
184 last_tag[len] = '\0';
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800185 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800186 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800187 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800188 strncpy(key + sizeof(log_namespace) - 1, tag, len);
189 key[sizeof(log_namespace) - 1 + len] = '\0';
Mark Salyzync1584562015-03-12 15:46:29 -0700190
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800191 kp = key;
192 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
193 struct cache_char* cache = &tag_cache[i];
194 struct cache_char temp_cache;
Mark Salyzyn95687052014-10-02 11:12:28 -0700195
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800196 if (not_locked) {
197 temp_cache.cache.pinfo = NULL;
198 temp_cache.c = '\0';
199 cache = &temp_cache;
200 }
201 if (local_change_detected) {
202 refresh_cache(cache, kp);
203 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800204
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800205 if (cache->c) {
206 c = cache->c;
207 break;
208 }
Mark Salyzync1584562015-03-12 15:46:29 -0700209
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800210 kp = key + base_offset;
Mark Salyzyn95687052014-10-02 11:12:28 -0700211 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800212 }
Mark Salyzync1584562015-03-12 15:46:29 -0700213
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800214 switch (toupper(c)) { /* if invalid, resort to global */
Mark Salyzync1584562015-03-12 15:46:29 -0700215 case 'V':
216 case 'D':
217 case 'I':
218 case 'W':
219 case 'E':
220 case 'F': /* Not officially supported */
221 case 'A':
222 case 'S':
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800223 case BOOLEAN_FALSE: /* Not officially supported */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800224 break;
Mark Salyzync1584562015-03-12 15:46:29 -0700225 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800226 /* clear '.' after log.tag */
227 key[sizeof(log_namespace) - 2] = '\0';
Mark Salyzync1584562015-03-12 15:46:29 -0700228
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800229 kp = key;
230 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
231 struct cache_char* cache = &global_cache[i];
232 struct cache_char temp_cache;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800233
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800234 if (not_locked) {
235 temp_cache = *cache;
236 if (temp_cache.cache.pinfo != cache->cache.pinfo) { /* check atomic */
237 temp_cache.cache.pinfo = NULL;
238 temp_cache.c = '\0';
239 }
240 cache = &temp_cache;
Mark Salyzync1584562015-03-12 15:46:29 -0700241 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800242 if (global_change_detected) {
243 refresh_cache(cache, kp);
244 }
Mark Salyzync1584562015-03-12 15:46:29 -0700245
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800246 if (cache->c) {
247 c = cache->c;
248 break;
249 }
Mark Salyzync1584562015-03-12 15:46:29 -0700250
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800251 kp = key + base_offset;
252 }
253 break;
254 }
255
256 if (!not_locked) {
257 global_serial = current_global_serial;
258 unlock();
259 }
260
261 switch (toupper(c)) {
262 /* clang-format off */
Mark Salyzync1584562015-03-12 15:46:29 -0700263 case 'V': return ANDROID_LOG_VERBOSE;
264 case 'D': return ANDROID_LOG_DEBUG;
265 case 'I': return ANDROID_LOG_INFO;
266 case 'W': return ANDROID_LOG_WARN;
267 case 'E': return ANDROID_LOG_ERROR;
268 case 'F': /* FALLTHRU */ /* Not officially supported */
269 case 'A': return ANDROID_LOG_FATAL;
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800270 case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
Tom Cherry0391a872020-01-16 15:58:02 -0800271 case 'S': return ANDROID_LOG_SILENT;
Tom Cherry71ba1642019-01-10 10:37:36 -0800272 /* clang-format on */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800273 }
Tom Cherry0391a872020-01-16 15:58:02 -0800274 return -1;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800275}
276
Tom Cherry2d9779e2019-02-08 11:46:19 -0800277int __android_log_is_loggable_len(int prio, const char* tag, size_t len, int default_prio) {
Tom Cherry0391a872020-01-16 15:58:02 -0800278 int minimum_log_priority = __android_log_get_minimum_priority();
279 int property_log_level = __android_log_level(tag, len);
280
281 if (property_log_level >= 0 && minimum_log_priority != ANDROID_LOG_DEFAULT) {
282 return prio >= std::min(property_log_level, minimum_log_priority);
283 } else if (property_log_level >= 0) {
284 return prio >= property_log_level;
285 } else if (minimum_log_priority != ANDROID_LOG_DEFAULT) {
286 return prio >= minimum_log_priority;
287 } else {
288 return prio >= default_prio;
289 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800290}
291
Tom Cherry2d9779e2019-02-08 11:46:19 -0800292int __android_log_is_loggable(int prio, const char* tag, int default_prio) {
Tom Cherry0391a872020-01-16 15:58:02 -0800293 auto len = tag ? strlen(tag) : 0;
294 return __android_log_is_loggable_len(prio, tag, len, default_prio);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800295}
296
Tom Cherry2d9779e2019-02-08 11:46:19 -0800297int __android_log_is_debuggable() {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800298 static uint32_t serial;
299 static struct cache_char tag_cache;
300 static const char key[] = "ro.debuggable";
301 int ret;
302
303 if (tag_cache.c) { /* ro property does not change after set */
304 ret = tag_cache.c == '1';
305 } else if (lock()) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800306 struct cache_char temp_cache = {{NULL, 0xFFFFFFFF}, '\0'};
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800307 refresh_cache(&temp_cache, key);
308 ret = temp_cache.c == '1';
309 } else {
310 int change_detected = check_cache(&tag_cache.cache);
311 uint32_t current_serial = __system_property_area_serial();
312 if (current_serial != serial) {
313 change_detected = 1;
Mark Salyzyn95687052014-10-02 11:12:28 -0700314 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800315 if (change_detected) {
316 refresh_cache(&tag_cache, key);
317 serial = current_serial;
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700318 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800319 ret = tag_cache.c == '1';
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700320
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800321 unlock();
322 }
323
324 return ret;
Mark Salyzyn7ef52492016-03-25 15:50:46 -0700325}
326
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800327/*
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800328 * For properties that are read often, but generally remain constant.
329 * Since a change is rare, we will accept a trylock failure gracefully.
330 * Use a separate lock from is_loggable to keep contention down b/25563384.
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800331 */
Mark Salyzyne4553732016-09-26 13:21:05 -0700332struct cache2_char {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800333 pthread_mutex_t lock;
334 uint32_t serial;
335 const char* key_persist;
336 struct cache_char cache_persist;
337 const char* key_ro;
338 struct cache_char cache_ro;
339 unsigned char (*const evaluate)(const struct cache2_char* self);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800340};
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800341
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800342static inline unsigned char do_cache2_char(struct cache2_char* self) {
343 uint32_t current_serial;
344 int change_detected;
345 unsigned char c;
Mark Salyzyn500afc72015-09-08 08:32:01 -0700346
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800347 if (pthread_mutex_trylock(&self->lock)) {
348 /* We are willing to accept some race in this context */
349 return self->evaluate(self);
350 }
Mark Salyzyn500afc72015-09-08 08:32:01 -0700351
Tom Cherry71ba1642019-01-10 10:37:36 -0800352 change_detected = check_cache(&self->cache_persist.cache) || check_cache(&self->cache_ro.cache);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800353 current_serial = __system_property_area_serial();
354 if (current_serial != self->serial) {
355 change_detected = 1;
356 }
357 if (change_detected) {
358 refresh_cache(&self->cache_persist, self->key_persist);
359 refresh_cache(&self->cache_ro, self->key_ro);
360 self->serial = current_serial;
361 }
362 c = self->evaluate(self);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800363
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800364 pthread_mutex_unlock(&self->lock);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800365
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800366 return c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800367}
368
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800369static unsigned char evaluate_persist_ro(const struct cache2_char* self) {
370 unsigned char c = self->cache_persist.c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800371
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800372 if (c) {
373 return c;
374 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800375
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800376 return self->cache_ro.c;
Mark Salyzyn500afc72015-09-08 08:32:01 -0700377}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800378
379/*
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800380 * Timestamp state generally remains constant, but can change at any time
381 * to handle developer requirements.
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800382 */
Tom Cherry2d9779e2019-02-08 11:46:19 -0800383clockid_t android_log_clockid() {
Tom Cherry71ba1642019-01-10 10:37:36 -0800384 static struct cache2_char clockid = {PTHREAD_MUTEX_INITIALIZER, 0,
385 "persist.logd.timestamp", {{NULL, 0xFFFFFFFF}, '\0'},
386 "ro.logd.timestamp", {{NULL, 0xFFFFFFFF}, '\0'},
387 evaluate_persist_ro};
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800388
Tom Cherry71ba1642019-01-10 10:37:36 -0800389 return (tolower(do_cache2_char(&clockid)) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800390}
391
392/*
393 * Security state generally remains constant, but the DO must be able
394 * to turn off logging should it become spammy after an attack is detected.
395 */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800396static unsigned char evaluate_security(const struct cache2_char* self) {
397 unsigned char c = self->cache_ro.c;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800398
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800399 return (c != BOOLEAN_FALSE) && c && (self->cache_persist.c == BOOLEAN_TRUE);
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800400}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800401
Tom Cherry2d9779e2019-02-08 11:46:19 -0800402int __android_log_security() {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800403 static struct cache2_char security = {
Tom Cherry71ba1642019-01-10 10:37:36 -0800404 PTHREAD_MUTEX_INITIALIZER, 0,
405 "persist.logd.security", {{NULL, 0xFFFFFFFF}, BOOLEAN_FALSE},
406 "ro.device_owner", {{NULL, 0xFFFFFFFF}, BOOLEAN_FALSE},
407 evaluate_security};
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800408
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800409 return do_cache2_char(&security);
Mark Salyzyne4553732016-09-26 13:21:05 -0700410}
411
412/*
413 * Interface that represents the logd buffer size determination so that others
414 * need not guess our intentions.
415 */
416
417/* Property helper */
418static bool check_flag(const char* prop, const char* flag) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800419 const char* cp = strcasestr(prop, flag);
420 if (!cp) {
421 return false;
422 }
423 /* We only will document comma (,) */
424 static const char sep[] = ",:;|+ \t\f";
425 if ((cp != prop) && !strchr(sep, cp[-1])) {
426 return false;
427 }
428 cp += strlen(flag);
429 return !*cp || !!strchr(sep, *cp);
Mark Salyzyne4553732016-09-26 13:21:05 -0700430}
431
432/* cache structure */
433struct cache_property {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800434 struct cache cache;
435 char property[PROP_VALUE_MAX];
Mark Salyzyne4553732016-09-26 13:21:05 -0700436};
437
Tom Cherry71ba1642019-01-10 10:37:36 -0800438static void refresh_cache_property(struct cache_property* cache, const char* key) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800439 if (!cache->cache.pinfo) {
440 cache->cache.pinfo = __system_property_find(key);
Mark Salyzyne4553732016-09-26 13:21:05 -0700441 if (!cache->cache.pinfo) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800442 return;
Mark Salyzyne4553732016-09-26 13:21:05 -0700443 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800444 }
445 cache->cache.serial = __system_property_serial(cache->cache.pinfo);
446 __system_property_read(cache->cache.pinfo, 0, cache->property);
Mark Salyzyne4553732016-09-26 13:21:05 -0700447}
448
449/* get boolean with the logger twist that supports eng adjustments */
Tom Cherry2d9779e2019-02-08 11:46:19 -0800450bool __android_logger_property_get_bool(const char* key, int flag) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800451 struct cache_property property = {{NULL, 0xFFFFFFFF}, {0}};
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800452 if (flag & BOOL_DEFAULT_FLAG_PERSIST) {
Mark Salyzynd24dc952017-04-05 10:11:09 -0700453 char newkey[strlen("persist.") + strlen(key) + 1];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800454 snprintf(newkey, sizeof(newkey), "ro.%s", key);
455 refresh_cache_property(&property, newkey);
456 property.cache.pinfo = NULL;
Tom Cherry71ba1642019-01-10 10:37:36 -0800457 property.cache.serial = 0xFFFFFFFF;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800458 snprintf(newkey, sizeof(newkey), "persist.%s", key);
459 refresh_cache_property(&property, newkey);
460 property.cache.pinfo = NULL;
Tom Cherry71ba1642019-01-10 10:37:36 -0800461 property.cache.serial = 0xFFFFFFFF;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800462 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700463
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800464 refresh_cache_property(&property, key);
Mark Salyzyne4553732016-09-26 13:21:05 -0700465
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800466 if (check_flag(property.property, "true")) {
467 return true;
468 }
469 if (check_flag(property.property, "false")) {
470 return false;
471 }
Mark Salyzyn9fcaaba2017-04-18 08:43:16 -0700472 if (property.property[0]) {
473 flag &= ~(BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE);
474 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800475 if (check_flag(property.property, "eng")) {
476 flag |= BOOL_DEFAULT_FLAG_ENG;
477 }
478 /* this is really a "not" flag */
479 if (check_flag(property.property, "svelte")) {
480 flag |= BOOL_DEFAULT_FLAG_SVELTE;
481 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700482
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800483 /* Sanity Check */
484 if (flag & (BOOL_DEFAULT_FLAG_SVELTE | BOOL_DEFAULT_FLAG_ENG)) {
485 flag &= ~BOOL_DEFAULT_FLAG_TRUE_FALSE;
486 flag |= BOOL_DEFAULT_TRUE;
487 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700488
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800489 if ((flag & BOOL_DEFAULT_FLAG_SVELTE) &&
Tom Cherry71ba1642019-01-10 10:37:36 -0800490 __android_logger_property_get_bool("ro.config.low_ram", BOOL_DEFAULT_FALSE)) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800491 return false;
492 }
493 if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) {
494 return false;
495 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700496
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800497 return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
Mark Salyzyne4553732016-09-26 13:21:05 -0700498}
499
Tom Cherry2d9779e2019-02-08 11:46:19 -0800500bool __android_logger_valid_buffer_size(unsigned long value) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800501 static long pages, pagesize;
502 unsigned long maximum;
Mark Salyzyne4553732016-09-26 13:21:05 -0700503
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800504 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
505 return false;
506 }
507
508 if (!pages) {
509 pages = sysconf(_SC_PHYS_PAGES);
510 }
511 if (pages < 1) {
512 return true;
513 }
514
515 if (!pagesize) {
516 pagesize = sysconf(_SC_PAGESIZE);
517 if (pagesize <= 1) {
518 pagesize = PAGE_SIZE;
Mark Salyzyne4553732016-09-26 13:21:05 -0700519 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800520 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700521
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800522 /* maximum memory impact a somewhat arbitrary ~3% */
523 pages = (pages + 31) / 32;
524 maximum = pages * pagesize;
Mark Salyzyne4553732016-09-26 13:21:05 -0700525
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800526 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
527 return true;
528 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700529
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800530 return value <= maximum;
Mark Salyzyne4553732016-09-26 13:21:05 -0700531}
532
533struct cache2_property_size {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800534 pthread_mutex_t lock;
535 uint32_t serial;
536 const char* key_persist;
537 struct cache_property cache_persist;
538 const char* key_ro;
539 struct cache_property cache_ro;
540 unsigned long (*const evaluate)(const struct cache2_property_size* self);
Mark Salyzyne4553732016-09-26 13:21:05 -0700541};
542
Tom Cherry71ba1642019-01-10 10:37:36 -0800543static inline unsigned long do_cache2_property_size(struct cache2_property_size* self) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800544 uint32_t current_serial;
545 int change_detected;
546 unsigned long v;
Mark Salyzyne4553732016-09-26 13:21:05 -0700547
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800548 if (pthread_mutex_trylock(&self->lock)) {
549 /* We are willing to accept some race in this context */
550 return self->evaluate(self);
551 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700552
Tom Cherry71ba1642019-01-10 10:37:36 -0800553 change_detected = check_cache(&self->cache_persist.cache) || check_cache(&self->cache_ro.cache);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800554 current_serial = __system_property_area_serial();
555 if (current_serial != self->serial) {
556 change_detected = 1;
557 }
558 if (change_detected) {
559 refresh_cache_property(&self->cache_persist, self->key_persist);
560 refresh_cache_property(&self->cache_ro, self->key_ro);
561 self->serial = current_serial;
562 }
563 v = self->evaluate(self);
Mark Salyzyne4553732016-09-26 13:21:05 -0700564
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800565 pthread_mutex_unlock(&self->lock);
Mark Salyzyne4553732016-09-26 13:21:05 -0700566
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800567 return v;
Mark Salyzyne4553732016-09-26 13:21:05 -0700568}
569
Tom Cherry71ba1642019-01-10 10:37:36 -0800570static unsigned long property_get_size_from_cache(const struct cache_property* cache) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800571 char* cp;
572 unsigned long value = strtoul(cache->property, &cp, 10);
Mark Salyzyne4553732016-09-26 13:21:05 -0700573
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800574 switch (*cp) {
Mark Salyzyne4553732016-09-26 13:21:05 -0700575 case 'm':
576 case 'M':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800577 value *= 1024;
Tom Cherry71ba1642019-01-10 10:37:36 -0800578 [[fallthrough]];
Mark Salyzyne4553732016-09-26 13:21:05 -0700579 case 'k':
580 case 'K':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800581 value *= 1024;
Tom Cherry71ba1642019-01-10 10:37:36 -0800582 [[fallthrough]];
Mark Salyzyne4553732016-09-26 13:21:05 -0700583 case '\0':
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800584 break;
Mark Salyzyne4553732016-09-26 13:21:05 -0700585
586 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800587 value = 0;
588 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700589
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800590 if (!__android_logger_valid_buffer_size(value)) {
591 value = 0;
592 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700593
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800594 return value;
Mark Salyzyne4553732016-09-26 13:21:05 -0700595}
596
Tom Cherry71ba1642019-01-10 10:37:36 -0800597static unsigned long evaluate_property_get_size(const struct cache2_property_size* self) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800598 unsigned long size = property_get_size_from_cache(&self->cache_persist);
599 if (size) {
600 return size;
601 }
602 return property_get_size_from_cache(&self->cache_ro);
Mark Salyzyne4553732016-09-26 13:21:05 -0700603}
604
Tom Cherry2d9779e2019-02-08 11:46:19 -0800605unsigned long __android_logger_get_buffer_size(log_id_t logId) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800606 static const char global_tunable[] = "persist.logd.size"; /* Settings App */
607 static const char global_default[] = "ro.logd.size"; /* BoardConfig.mk */
608 static struct cache2_property_size global = {
Tom Cherry71ba1642019-01-10 10:37:36 -0800609 /* clang-format off */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800610 PTHREAD_MUTEX_INITIALIZER, 0,
Tom Cherry71ba1642019-01-10 10:37:36 -0800611 global_tunable, { { NULL, 0xFFFFFFFF }, {} },
612 global_default, { { NULL, 0xFFFFFFFF }, {} },
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800613 evaluate_property_get_size
Tom Cherry71ba1642019-01-10 10:37:36 -0800614 /* clang-format on */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800615 };
Mark Salyzynd24dc952017-04-05 10:11:09 -0700616 char key_persist[strlen(global_tunable) + strlen(".security") + 1];
617 char key_ro[strlen(global_default) + strlen(".security") + 1];
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800618 struct cache2_property_size local = {
Tom Cherry71ba1642019-01-10 10:37:36 -0800619 /* clang-format off */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800620 PTHREAD_MUTEX_INITIALIZER, 0,
Tom Cherry71ba1642019-01-10 10:37:36 -0800621 key_persist, { { NULL, 0xFFFFFFFF }, {} },
622 key_ro, { { NULL, 0xFFFFFFFF }, {} },
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800623 evaluate_property_get_size
Tom Cherry71ba1642019-01-10 10:37:36 -0800624 /* clang-format on */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800625 };
626 unsigned long property_size, default_size;
Mark Salyzyne4553732016-09-26 13:21:05 -0700627
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800628 default_size = do_cache2_property_size(&global);
629 if (!default_size) {
Tom Cherry71ba1642019-01-10 10:37:36 -0800630 default_size = __android_logger_property_get_bool("ro.config.low_ram", BOOL_DEFAULT_FALSE)
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800631 ? LOG_BUFFER_MIN_SIZE /* 64K */
632 : LOG_BUFFER_SIZE; /* 256K */
633 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700634
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800635 snprintf(key_persist, sizeof(key_persist), "%s.%s", global_tunable,
636 android_log_id_to_name(logId));
Tom Cherry71ba1642019-01-10 10:37:36 -0800637 snprintf(key_ro, sizeof(key_ro), "%s.%s", global_default, android_log_id_to_name(logId));
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800638 property_size = do_cache2_property_size(&local);
Mark Salyzyne4553732016-09-26 13:21:05 -0700639
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800640 if (!property_size) {
641 property_size = default_size;
642 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700643
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800644 if (!property_size) {
645 property_size = LOG_BUFFER_SIZE;
646 }
Mark Salyzyne4553732016-09-26 13:21:05 -0700647
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800648 return property_size;
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800649}