blob: 2f8f886bdc10b1c0d441cbd2edd302861f337ce0 [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
17#include <ctype.h>
Mark Salyzync1584562015-03-12 15:46:29 -070018#include <pthread.h>
19#include <stdlib.h>
Mark Salyzyn95687052014-10-02 11:12:28 -070020#include <string.h>
Mark Salyzync1584562015-03-12 15:46:29 -070021#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
22#include <sys/_system_properties.h>
Mark Salyzyn95687052014-10-02 11:12:28 -070023
24#include <android/log.h>
25
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080026static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
27
Mark Salyzyna67d8a52015-12-21 12:32:48 -080028static int lock()
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080029{
30 /*
31 * If we trigger a signal handler in the middle of locked activity and the
32 * signal handler logs a message, we could get into a deadlock state.
33 */
Mark Salyzyna67d8a52015-12-21 12:32:48 -080034 /*
35 * Any contention, and we can turn around and use the non-cached method
36 * in less time than the system call associated with a mutex to deal with
37 * the contention.
38 */
39 return pthread_mutex_trylock(&lock_loggable);
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080040}
41
42static void unlock()
43{
44 pthread_mutex_unlock(&lock_loggable);
45}
46
Mark Salyzync1584562015-03-12 15:46:29 -070047struct cache {
48 const prop_info *pinfo;
49 uint32_t serial;
Mark Salyzynb004a7f2015-12-08 14:52:11 -080050 unsigned char c;
Mark Salyzync1584562015-03-12 15:46:29 -070051};
52
Mark Salyzyna67d8a52015-12-21 12:32:48 -080053static int check_cache(struct cache *cache)
54{
55 return cache->pinfo
56 && __system_property_serial(cache->pinfo) != cache->serial;
57}
58
Mark Salyzynffbd86f2015-12-04 10:59:45 -080059#define BOOLEAN_TRUE 0xFF
60#define BOOLEAN_FALSE 0xFE
61
Mark Salyzync1584562015-03-12 15:46:29 -070062static void refresh_cache(struct cache *cache, const char *key)
Mark Salyzyn95687052014-10-02 11:12:28 -070063{
Mark Salyzync1584562015-03-12 15:46:29 -070064 uint32_t serial;
Mark Salyzyn95687052014-10-02 11:12:28 -070065 char buf[PROP_VALUE_MAX];
66
Mark Salyzync1584562015-03-12 15:46:29 -070067 if (!cache->pinfo) {
68 cache->pinfo = __system_property_find(key);
69 if (!cache->pinfo) {
70 return;
71 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -080072 cache->serial = -1;
Mark Salyzyn95687052014-10-02 11:12:28 -070073 }
Mark Salyzync1584562015-03-12 15:46:29 -070074 serial = __system_property_serial(cache->pinfo);
75 if (serial == cache->serial) {
76 return;
77 }
78 cache->serial = serial;
79 __system_property_read(cache->pinfo, 0, buf);
Mark Salyzynffbd86f2015-12-04 10:59:45 -080080 switch(buf[0]) {
81 case 't': case 'T':
82 cache->c = strcasecmp(buf + 1, "rue") ? buf[0] : BOOLEAN_TRUE;
83 break;
84 case 'f': case 'F':
85 cache->c = strcasecmp(buf + 1, "alse") ? buf[0] : BOOLEAN_FALSE;
86 break;
87 default:
88 cache->c = buf[0];
89 }
Mark Salyzync1584562015-03-12 15:46:29 -070090}
Mark Salyzyn95687052014-10-02 11:12:28 -070091
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080092static int __android_log_level(const char *tag, int default_prio)
Mark Salyzync1584562015-03-12 15:46:29 -070093{
94 /* sizeof() is used on this array below */
95 static const char log_namespace[] = "persist.log.tag.";
96 static const size_t base_offset = 8; /* skip "persist." */
97 /* calculate the size of our key temporary buffer */
98 const size_t taglen = (tag && *tag) ? strlen(tag) : 0;
99 /* sizeof(log_namespace) = strlen(log_namespace) + 1 */
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800100 char key[sizeof(log_namespace) + taglen]; /* may be > PROPERTY_KEY_MAX */
Mark Salyzync1584562015-03-12 15:46:29 -0700101 char *kp;
102 size_t i;
103 char c = 0;
104 /*
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 */
Colin Cross7a106f72016-01-29 16:21:31 -0800113 static char last_tag[PROP_NAME_MAX];
Mark Salyzync1584562015-03-12 15:46:29 -0700114 static uint32_t global_serial;
Mark Salyzyn31ca3c32015-12-22 10:49:02 -0800115 /* some compilers erroneously see uninitialized use. !not_locked */
116 uint32_t current_global_serial = 0;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800117 static struct cache tag_cache[2];
118 static struct cache global_cache[2];
119 int change_detected;
120 int global_change_detected;
121 int not_locked;
Mark Salyzync1584562015-03-12 15:46:29 -0700122
123 strcpy(key, log_namespace);
124
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800125 global_change_detected = change_detected = not_locked = lock();
Mark Salyzync1584562015-03-12 15:46:29 -0700126
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800127 if (!not_locked) {
128 /*
129 * check all known serial numbers to changes.
130 */
131 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
132 if (check_cache(&tag_cache[i])) {
133 change_detected = 1;
134 }
135 }
136 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
137 if (check_cache(&global_cache[i])) {
138 global_change_detected = 1;
139 }
140 }
141
142 current_global_serial = __system_property_area_serial();
143 if (current_global_serial != global_serial) {
144 change_detected = 1;
145 global_change_detected = 1;
146 }
147 }
Mark Salyzync1584562015-03-12 15:46:29 -0700148
149 if (taglen) {
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800150 int local_change_detected = change_detected;
151 if (!not_locked) {
Colin Cross7a106f72016-01-29 16:21:31 -0800152 if (!last_tag[0]
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800153 || (last_tag[0] != tag[0])
Colin Cross7a106f72016-01-29 16:21:31 -0800154 || strncmp(last_tag + 1, tag + 1, sizeof(last_tag) - 1)) {
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800155 /* invalidate log.tag.<tag> cache */
156 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
157 tag_cache[i].pinfo = NULL;
158 tag_cache[i].c = '\0';
159 }
Colin Cross7a106f72016-01-29 16:21:31 -0800160 last_tag[0] = '\0';
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800161 local_change_detected = 1;
Mark Salyzync1584562015-03-12 15:46:29 -0700162 }
Colin Cross7a106f72016-01-29 16:21:31 -0800163 if (!last_tag[0]) {
164 strncpy(last_tag, tag, sizeof(last_tag));
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800165 }
Mark Salyzync1584562015-03-12 15:46:29 -0700166 }
Mark Salyzyn95687052014-10-02 11:12:28 -0700167 strcpy(key + sizeof(log_namespace) - 1, tag);
168
Mark Salyzync1584562015-03-12 15:46:29 -0700169 kp = key;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800170 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
171 struct cache *cache = &tag_cache[i];
172 struct cache temp_cache;
173
174 if (not_locked) {
175 temp_cache.pinfo = NULL;
176 temp_cache.c = '\0';
177 cache = &temp_cache;
178 }
179 if (local_change_detected) {
180 refresh_cache(cache, kp);
Mark Salyzync1584562015-03-12 15:46:29 -0700181 }
182
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800183 if (cache->c) {
184 c = cache->c;
Mark Salyzync1584562015-03-12 15:46:29 -0700185 break;
186 }
187
188 kp = key + base_offset;
Mark Salyzyn1f028b22014-10-08 15:58:40 -0700189 }
Mark Salyzyn95687052014-10-02 11:12:28 -0700190 }
Mark Salyzync1584562015-03-12 15:46:29 -0700191
192 switch (toupper(c)) { /* if invalid, resort to global */
193 case 'V':
194 case 'D':
195 case 'I':
196 case 'W':
197 case 'E':
198 case 'F': /* Not officially supported */
199 case 'A':
200 case 'S':
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800201 case BOOLEAN_FALSE: /* Not officially supported */
Mark Salyzync1584562015-03-12 15:46:29 -0700202 break;
203 default:
204 /* clear '.' after log.tag */
205 key[sizeof(log_namespace) - 2] = '\0';
206
207 kp = key;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800208 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
209 struct cache *cache = &global_cache[i];
210 struct cache temp_cache;
211
212 if (not_locked) {
213 temp_cache = *cache;
214 if (temp_cache.pinfo != cache->pinfo) { /* check atomic */
215 temp_cache.pinfo = NULL;
216 temp_cache.c = '\0';
217 }
218 cache = &temp_cache;
219 }
220 if (global_change_detected) {
221 refresh_cache(cache, kp);
Mark Salyzync1584562015-03-12 15:46:29 -0700222 }
223
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800224 if (cache->c) {
225 c = cache->c;
Mark Salyzync1584562015-03-12 15:46:29 -0700226 break;
227 }
228
229 kp = key + base_offset;
230 }
231 break;
232 }
233
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800234 if (!not_locked) {
235 global_serial = current_global_serial;
236 unlock();
237 }
Mark Salyzync1584562015-03-12 15:46:29 -0700238
239 switch (toupper(c)) {
240 case 'V': return ANDROID_LOG_VERBOSE;
241 case 'D': return ANDROID_LOG_DEBUG;
242 case 'I': return ANDROID_LOG_INFO;
243 case 'W': return ANDROID_LOG_WARN;
244 case 'E': return ANDROID_LOG_ERROR;
245 case 'F': /* FALLTHRU */ /* Not officially supported */
246 case 'A': return ANDROID_LOG_FATAL;
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800247 case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
Mark Salyzync1584562015-03-12 15:46:29 -0700248 case 'S': return -1; /* ANDROID_LOG_SUPPRESS */
Mark Salyzyn95687052014-10-02 11:12:28 -0700249 }
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800250 return default_prio;
Mark Salyzyn95687052014-10-02 11:12:28 -0700251}
252
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800253int __android_log_is_loggable(int prio, const char *tag, int default_prio)
Mark Salyzyn95687052014-10-02 11:12:28 -0700254{
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800255 int logLevel = __android_log_level(tag, default_prio);
Mark Salyzyn95687052014-10-02 11:12:28 -0700256 return logLevel >= 0 && prio >= logLevel;
257}
Mark Salyzyn500afc72015-09-08 08:32:01 -0700258
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800259/*
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800260 * For properties that are read often, but generally remain constant.
261 * Since a change is rare, we will accept a trylock failure gracefully.
262 * Use a separate lock from is_loggable to keep contention down b/25563384.
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800263 */
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800264struct cache2 {
265 pthread_mutex_t lock;
266 uint32_t serial;
267 const char *key_persist;
268 struct cache cache_persist;
269 const char *key_ro;
270 struct cache cache_ro;
271 unsigned char (*const evaluate)(const struct cache2 *self);
272};
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800273
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800274static inline unsigned char do_cache2(struct cache2 *self)
Mark Salyzyn500afc72015-09-08 08:32:01 -0700275{
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800276 uint32_t current_serial;
277 int change_detected;
278 unsigned char c;
Mark Salyzyn500afc72015-09-08 08:32:01 -0700279
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800280 if (pthread_mutex_trylock(&self->lock)) {
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800281 /* We are willing to accept some race in this context */
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800282 return self->evaluate(self);
Mark Salyzyn500afc72015-09-08 08:32:01 -0700283 }
Mark Salyzyn500afc72015-09-08 08:32:01 -0700284
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800285 change_detected = check_cache(&self->cache_persist)
286 || check_cache(&self->cache_ro);
287 current_serial = __system_property_area_serial();
288 if (current_serial != self->serial) {
289 change_detected = 1;
290 }
291 if (change_detected) {
292 refresh_cache(&self->cache_persist, self->key_persist);
293 refresh_cache(&self->cache_ro, self->key_ro);
294 self->serial = current_serial;
295 }
296 c = self->evaluate(self);
297
298 pthread_mutex_unlock(&self->lock);
299
300 return c;
301}
302
303static unsigned char evaluate_persist_ro(const struct cache2 *self)
304{
305 unsigned char c = self->cache_persist.c;
306
307 if (c) {
308 return c;
309 }
310
311 return self->cache_ro.c;
Mark Salyzyn500afc72015-09-08 08:32:01 -0700312}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800313
314/*
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800315 * Timestamp state generally remains constant, but can change at any time
316 * to handle developer requirements.
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800317 */
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800318clockid_t android_log_clockid()
319{
320 static struct cache2 clockid = {
321 PTHREAD_MUTEX_INITIALIZER,
322 0,
323 "persist.logd.timestamp",
324 { NULL, -1, '\0' },
325 "ro.logd.timestamp",
326 { NULL, -1, '\0' },
327 evaluate_persist_ro
328 };
329
330 return (tolower(do_cache2(&clockid)) == 'm')
331 ? CLOCK_MONOTONIC
332 : CLOCK_REALTIME;
333}
334
335/*
336 * Security state generally remains constant, but the DO must be able
337 * to turn off logging should it become spammy after an attack is detected.
338 */
339static unsigned char evaluate_security(const struct cache2 *self)
340{
341 unsigned char c = self->cache_ro.c;
342
343 return (c != BOOLEAN_FALSE) && c && (self->cache_persist.c == BOOLEAN_TRUE);
344}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800345
346int __android_log_security()
347{
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800348 static struct cache2 security = {
349 PTHREAD_MUTEX_INITIALIZER,
350 0,
351 "persist.logd.security",
352 { NULL, -1, BOOLEAN_FALSE },
353 "ro.device_owner",
354 { NULL, -1, BOOLEAN_FALSE },
355 evaluate_security
356 };
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800357
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800358 return do_cache2(&security);
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800359}