liblog: Add __android_log_security()

Return non-zero if ro.device_owner is set and not false
and persist.logd.security is true.

Bug: 26029733
Change-Id: Ie82ae11ae35e9c79017b6e873fefb39d79a1d4fe
This commit is contained in:
Mark Salyzyn 2015-12-04 10:59:45 -08:00
parent 4ab13d0256
commit ffbd86ff25
3 changed files with 87 additions and 1 deletions

View file

@ -620,6 +620,8 @@ typedef enum log_id {
*/
int __android_log_is_loggable(int prio, const char *tag, int default_prio);
int __android_log_security(); /* Device Owner is present */
int __android_log_error_write(int tag, const char *subTag, int32_t uid, const char *data,
uint32_t dataLen);

View file

@ -45,6 +45,9 @@ struct cache {
char c;
};
#define BOOLEAN_TRUE 0xFF
#define BOOLEAN_FALSE 0xFE
static void refresh_cache(struct cache *cache, const char *key)
{
uint32_t serial;
@ -62,7 +65,16 @@ static void refresh_cache(struct cache *cache, const char *key)
}
cache->serial = serial;
__system_property_read(cache->pinfo, 0, buf);
cache->c = buf[0];
switch(buf[0]) {
case 't': case 'T':
cache->c = strcasecmp(buf + 1, "rue") ? buf[0] : BOOLEAN_TRUE;
break;
case 'f': case 'F':
cache->c = strcasecmp(buf + 1, "alse") ? buf[0] : BOOLEAN_FALSE;
break;
default:
cache->c = buf[0];
}
}
static int __android_log_level(const char *tag, int default_prio)
@ -147,6 +159,7 @@ static int __android_log_level(const char *tag, int default_prio)
case 'F': /* Not officially supported */
case 'A':
case 'S':
case BOOLEAN_FALSE: /* Not officially supported */
break;
default:
/* clear '.' after log.tag */
@ -180,6 +193,7 @@ static int __android_log_level(const char *tag, int default_prio)
case 'E': return ANDROID_LOG_ERROR;
case 'F': /* FALLTHRU */ /* Not officially supported */
case 'A': return ANDROID_LOG_FATAL;
case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
case 'S': return -1; /* ANDROID_LOG_SUPPRESS */
}
return default_prio;
@ -226,3 +240,36 @@ clockid_t android_log_clockid()
return (tolower(c) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME;
}
/*
* security state generally remains constant, since a change is
* rare, we can accept a trylock failure gracefully.
*/
static pthread_mutex_t lock_security = PTHREAD_MUTEX_INITIALIZER;
int __android_log_security()
{
static struct cache r_do_cache = { NULL, -1, BOOLEAN_FALSE };
static struct cache p_security_cache = { NULL, -1, BOOLEAN_FALSE };
int retval;
if (pthread_mutex_trylock(&lock_security)) {
/* We are willing to accept some race in this context */
retval = (r_do_cache.c != BOOLEAN_FALSE) && r_do_cache.c &&
(p_security_cache.c == BOOLEAN_TRUE);
} else {
static uint32_t serial;
uint32_t current_serial = __system_property_area_serial();
if (current_serial != serial) {
refresh_cache(&r_do_cache, "ro.device_owner");
refresh_cache(&p_security_cache, "persist.logd.security");
serial = current_serial;
}
retval = (r_do_cache.c != BOOLEAN_FALSE) && r_do_cache.c &&
(p_security_cache.c == BOOLEAN_TRUE);
pthread_mutex_unlock(&lock_security);
}
return retval;
}

View file

@ -164,6 +164,43 @@ TEST(liblog, __android_log_btwrite__android_logger_list_read) {
android_logger_list_close(logger_list);
}
TEST(liblog, __security) {
static const char persist_key[] = "persist.logd.security";
static const char readonly_key[] = "ro.device_owner";
static const char nothing_val[] = "_NOTHING_TO_SEE_HERE_";
char persist[PROP_VALUE_MAX];
char readonly[PROP_VALUE_MAX];
property_get(persist_key, persist, "");
property_get(readonly_key, readonly, nothing_val);
if (!strcmp(readonly, nothing_val)) {
EXPECT_FALSE(__android_log_security());
fprintf(stderr, "Warning, setting ro.device_owner to a domain\n");
property_set(readonly_key, "com.google.android.SecOps.DeviceOwner");
} else if (!strcasecmp(readonly, "false") || !readonly[0]) {
EXPECT_FALSE(__android_log_security());
return;
}
if (!strcasecmp(persist, "true")) {
EXPECT_TRUE(__android_log_security());
} else {
EXPECT_FALSE(__android_log_security());
}
property_set(persist_key, "TRUE");
EXPECT_TRUE(__android_log_security());
property_set(persist_key, "FALSE");
EXPECT_FALSE(__android_log_security());
property_set(persist_key, "true");
EXPECT_TRUE(__android_log_security());
property_set(persist_key, "false");
EXPECT_FALSE(__android_log_security());
property_set(persist_key, "");
EXPECT_FALSE(__android_log_security());
property_set(persist_key, persist);
}
static unsigned signaled;
log_time signal_time;