blob: 0f81efc80c7fe29845a38590ad5b79e20c192334 [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 */
113 static char *last_tag;
114 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) {
152 if (!last_tag
153 || (last_tag[0] != tag[0])
154 || strcmp(last_tag + 1, tag + 1)) {
155 /* 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 }
160 free(last_tag);
161 last_tag = NULL;
162 local_change_detected = 1;
Mark Salyzync1584562015-03-12 15:46:29 -0700163 }
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800164 if (!last_tag) {
165 last_tag = strdup(tag);
166 }
Mark Salyzync1584562015-03-12 15:46:29 -0700167 }
Mark Salyzyn95687052014-10-02 11:12:28 -0700168 strcpy(key + sizeof(log_namespace) - 1, tag);
169
Mark Salyzync1584562015-03-12 15:46:29 -0700170 kp = key;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800171 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
172 struct cache *cache = &tag_cache[i];
173 struct cache temp_cache;
174
175 if (not_locked) {
176 temp_cache.pinfo = NULL;
177 temp_cache.c = '\0';
178 cache = &temp_cache;
179 }
180 if (local_change_detected) {
181 refresh_cache(cache, kp);
Mark Salyzync1584562015-03-12 15:46:29 -0700182 }
183
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800184 if (cache->c) {
185 c = cache->c;
Mark Salyzync1584562015-03-12 15:46:29 -0700186 break;
187 }
188
189 kp = key + base_offset;
Mark Salyzyn1f028b22014-10-08 15:58:40 -0700190 }
Mark Salyzyn95687052014-10-02 11:12:28 -0700191 }
Mark Salyzync1584562015-03-12 15:46:29 -0700192
193 switch (toupper(c)) { /* if invalid, resort to global */
194 case 'V':
195 case 'D':
196 case 'I':
197 case 'W':
198 case 'E':
199 case 'F': /* Not officially supported */
200 case 'A':
201 case 'S':
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800202 case BOOLEAN_FALSE: /* Not officially supported */
Mark Salyzync1584562015-03-12 15:46:29 -0700203 break;
204 default:
205 /* clear '.' after log.tag */
206 key[sizeof(log_namespace) - 2] = '\0';
207
208 kp = key;
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800209 for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
210 struct cache *cache = &global_cache[i];
211 struct cache temp_cache;
212
213 if (not_locked) {
214 temp_cache = *cache;
215 if (temp_cache.pinfo != cache->pinfo) { /* check atomic */
216 temp_cache.pinfo = NULL;
217 temp_cache.c = '\0';
218 }
219 cache = &temp_cache;
220 }
221 if (global_change_detected) {
222 refresh_cache(cache, kp);
Mark Salyzync1584562015-03-12 15:46:29 -0700223 }
224
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800225 if (cache->c) {
226 c = cache->c;
Mark Salyzync1584562015-03-12 15:46:29 -0700227 break;
228 }
229
230 kp = key + base_offset;
231 }
232 break;
233 }
234
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800235 if (!not_locked) {
236 global_serial = current_global_serial;
237 unlock();
238 }
Mark Salyzync1584562015-03-12 15:46:29 -0700239
240 switch (toupper(c)) {
241 case 'V': return ANDROID_LOG_VERBOSE;
242 case 'D': return ANDROID_LOG_DEBUG;
243 case 'I': return ANDROID_LOG_INFO;
244 case 'W': return ANDROID_LOG_WARN;
245 case 'E': return ANDROID_LOG_ERROR;
246 case 'F': /* FALLTHRU */ /* Not officially supported */
247 case 'A': return ANDROID_LOG_FATAL;
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800248 case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
Mark Salyzync1584562015-03-12 15:46:29 -0700249 case 'S': return -1; /* ANDROID_LOG_SUPPRESS */
Mark Salyzyn95687052014-10-02 11:12:28 -0700250 }
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800251 return default_prio;
Mark Salyzyn95687052014-10-02 11:12:28 -0700252}
253
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800254int __android_log_is_loggable(int prio, const char *tag, int default_prio)
Mark Salyzyn95687052014-10-02 11:12:28 -0700255{
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800256 int logLevel = __android_log_level(tag, default_prio);
Mark Salyzyn95687052014-10-02 11:12:28 -0700257 return logLevel >= 0 && prio >= logLevel;
258}
Mark Salyzyn500afc72015-09-08 08:32:01 -0700259
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800260/*
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800261 * For properties that are read often, but generally remain constant.
262 * Since a change is rare, we will accept a trylock failure gracefully.
263 * Use a separate lock from is_loggable to keep contention down b/25563384.
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800264 */
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800265struct cache2 {
266 pthread_mutex_t lock;
267 uint32_t serial;
268 const char *key_persist;
269 struct cache cache_persist;
270 const char *key_ro;
271 struct cache cache_ro;
272 unsigned char (*const evaluate)(const struct cache2 *self);
273};
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800274
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800275static inline unsigned char do_cache2(struct cache2 *self)
Mark Salyzyn500afc72015-09-08 08:32:01 -0700276{
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800277 uint32_t current_serial;
278 int change_detected;
279 unsigned char c;
Mark Salyzyn500afc72015-09-08 08:32:01 -0700280
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800281 if (pthread_mutex_trylock(&self->lock)) {
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800282 /* We are willing to accept some race in this context */
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800283 return self->evaluate(self);
Mark Salyzyn500afc72015-09-08 08:32:01 -0700284 }
Mark Salyzyn500afc72015-09-08 08:32:01 -0700285
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800286 change_detected = check_cache(&self->cache_persist)
287 || check_cache(&self->cache_ro);
288 current_serial = __system_property_area_serial();
289 if (current_serial != self->serial) {
290 change_detected = 1;
291 }
292 if (change_detected) {
293 refresh_cache(&self->cache_persist, self->key_persist);
294 refresh_cache(&self->cache_ro, self->key_ro);
295 self->serial = current_serial;
296 }
297 c = self->evaluate(self);
298
299 pthread_mutex_unlock(&self->lock);
300
301 return c;
302}
303
304static unsigned char evaluate_persist_ro(const struct cache2 *self)
305{
306 unsigned char c = self->cache_persist.c;
307
308 if (c) {
309 return c;
310 }
311
312 return self->cache_ro.c;
Mark Salyzyn500afc72015-09-08 08:32:01 -0700313}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800314
315/*
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800316 * Timestamp state generally remains constant, but can change at any time
317 * to handle developer requirements.
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800318 */
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800319clockid_t android_log_clockid()
320{
321 static struct cache2 clockid = {
322 PTHREAD_MUTEX_INITIALIZER,
323 0,
324 "persist.logd.timestamp",
325 { NULL, -1, '\0' },
326 "ro.logd.timestamp",
327 { NULL, -1, '\0' },
328 evaluate_persist_ro
329 };
330
331 return (tolower(do_cache2(&clockid)) == 'm')
332 ? CLOCK_MONOTONIC
333 : CLOCK_REALTIME;
334}
335
336/*
337 * Security state generally remains constant, but the DO must be able
338 * to turn off logging should it become spammy after an attack is detected.
339 */
340static unsigned char evaluate_security(const struct cache2 *self)
341{
342 unsigned char c = self->cache_ro.c;
343
344 return (c != BOOLEAN_FALSE) && c && (self->cache_persist.c == BOOLEAN_TRUE);
345}
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800346
347int __android_log_security()
348{
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800349 static struct cache2 security = {
350 PTHREAD_MUTEX_INITIALIZER,
351 0,
352 "persist.logd.security",
353 { NULL, -1, BOOLEAN_FALSE },
354 "ro.device_owner",
355 { NULL, -1, BOOLEAN_FALSE },
356 evaluate_security
357 };
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800358
Mark Salyzyna67d8a52015-12-21 12:32:48 -0800359 return do_cache2(&security);
Mark Salyzynffbd86f2015-12-04 10:59:45 -0800360}