logd: restrict access to /dev/event-log-tags

Create an event_log_tags_file label and use it for
/dev/event-log-tags.  Only trusted system log readers are allowed
direct read access to this file, no write access.  Untrusted domain
requests lack direct access, and are thus checked for credentials via
the "plan b" long path socket to the event log tag service.

Test: gTest logd-unit-tests, liblog-unit-tests and logcat-unit-tests
Bug: 31456426
Bug: 30566487
Change-Id: Ib9b71ca225d4436d764c9bc340ff7b1c9c252a9e
diff --git a/private/file_contexts b/private/file_contexts
index 0ce3dbc..33b201e 100644
--- a/private/file_contexts
+++ b/private/file_contexts
@@ -75,6 +75,7 @@
 /dev/cpuctl(/.*)?	u:object_r:cpuctl_device:s0
 /dev/device-mapper	u:object_r:dm_device:s0
 /dev/eac		u:object_r:audio_device:s0
+/dev/event-log-tags     u:object_r:runtime_event_log_tags_file:s0
 /dev/fscklogs(/.*)?	u:object_r:fscklogs:s0
 /dev/full		u:object_r:full_device:s0
 /dev/fuse		u:object_r:fuse_device:s0
diff --git a/private/logd.te b/private/logd.te
index 73a3feb..35117d0 100644
--- a/private/logd.te
+++ b/private/logd.te
@@ -5,4 +5,34 @@
 # logd is not allowed to write anywhere other than /data/misc/logd, and then
 # only on userdebug or eng builds
 # TODO: deal with tmpfs_domain pub/priv split properly
-neverallow logd { file_type -logd_tmpfs userdebug_or_eng(`-coredump_file') }:file { create write append };
+neverallow logd {
+  file_type
+  -logd_tmpfs
+  -runtime_event_log_tags_file
+  userdebug_or_eng(`-coredump_file')
+}:file { create write append };
+
+# protect the event-log-tags file
+neverallow {
+  domain
+  -appdomain # covered below
+  -bootstat
+  -dumpstate
+  -logd
+  userdebug_or_eng(`-logpersist')
+  -servicemanager
+  -system_server
+  -surfaceflinger
+  -zygote
+} runtime_event_log_tags_file:file no_rw_file_perms;
+
+neverallow {
+  appdomain
+  -bluetooth
+  -platform_app
+  -priv_app
+  -radio
+  -shell
+  userdebug_or_eng(`-su')
+  -system_app
+} runtime_event_log_tags_file:file no_rw_file_perms;
diff --git a/private/logpersist.te b/private/logpersist.te
index 88733de..5f4da0e 100644
--- a/private/logpersist.te
+++ b/private/logpersist.te
@@ -12,6 +12,7 @@
 
   control_logd(logpersist)
   unix_socket_connect(logpersist, logdr, logd)
+  read_runtime_log_tags(logpersist)
 
 ')
 
diff --git a/private/platform_app.te b/private/platform_app.te
index 8d03251..6747848 100644
--- a/private/platform_app.te
+++ b/private/platform_app.te
@@ -59,3 +59,5 @@
 # Access to ephemeral APKs
 allow platform_app ephemeral_apk_data_file:dir r_dir_perms;
 allow platform_app ephemeral_apk_data_file:file r_file_perms;
+
+read_runtime_log_tags(platform_app)
diff --git a/private/priv_app.te b/private/priv_app.te
index 568afe6..dd4ac2c 100644
--- a/private/priv_app.te
+++ b/private/priv_app.te
@@ -110,6 +110,8 @@
 # TODO: narrow this to just MediaProvider
 allow priv_app mnt_media_rw_file:dir search;
 
+read_runtime_log_tags(priv_app)
+
 ###
 ### neverallow rules
 ###
diff --git a/private/radio.te b/private/radio.te
index 76dbf1c..95e7f0a 100644
--- a/private/radio.te
+++ b/private/radio.te
@@ -1 +1,3 @@
 app_domain(radio)
+
+read_runtime_log_tags(radio)
diff --git a/private/servicemanager.te b/private/servicemanager.te
index 1514b0f..6f382a7 100644
--- a/private/servicemanager.te
+++ b/private/servicemanager.te
@@ -1,3 +1,5 @@
 # type_transition must be private policy the domain_trans rules could stay
 # public, but conceptually should go with this
 init_daemon_domain(servicemanager)
+
+read_runtime_log_tags(servicemanager)
diff --git a/private/system_app.te b/private/system_app.te
index c53f7a8..66c1e4d 100644
--- a/private/system_app.te
+++ b/private/system_app.te
@@ -79,3 +79,4 @@
 r_dir_file(system_app, sysfs_type)
 
 control_logd(system_app)
+read_runtime_log_tags(system_app)
diff --git a/private/zygote.te b/private/zygote.te
index 5d55b1e..f9213ce 100644
--- a/private/zygote.te
+++ b/private/zygote.te
@@ -4,6 +4,8 @@
 
 init_daemon_domain(zygote)
 
+read_runtime_log_tags(zygote)
+
 # Override DAC on files and switch uid/gid.
 allow zygote self:capability { dac_override setgid setuid fowner chown };
 
diff --git a/public/bluetooth.te b/public/bluetooth.te
index 209a68b..eda60de 100644
--- a/public/bluetooth.te
+++ b/public/bluetooth.te
@@ -63,6 +63,8 @@
 binder_call(bluetooth, hal_bluetooth)
 binder_call(bluetooth, hal_telephony)
 
+read_runtime_log_tags(bluetooth)
+
 ###
 ### Neverallow rules
 ###
diff --git a/public/bootstat.te b/public/bootstat.te
index 7fc5892..f5c7268 100644
--- a/public/bootstat.te
+++ b/public/bootstat.te
@@ -2,6 +2,8 @@
 type bootstat, domain;
 type bootstat_exec, exec_type, file_type;
 
+read_runtime_log_tags(bootstat)
+
 # Allow persistent storage in /data/misc/bootstat.
 allow bootstat bootstat_data_file:dir rw_dir_perms;
 allow bootstat bootstat_data_file:file create_file_perms;
diff --git a/public/dumpstate.te b/public/dumpstate.te
index 4882b98..a70614d 100644
--- a/public/dumpstate.te
+++ b/public/dumpstate.te
@@ -130,6 +130,7 @@
 # logd access
 read_logd(dumpstate)
 control_logd(dumpstate)
+read_runtime_log_tags(dumpstate)
 
 # Read /proc/net
 allow dumpstate proc_net:file r_file_perms;
diff --git a/public/file.te b/public/file.te
index 527e496..7bf44cc 100644
--- a/public/file.te
+++ b/public/file.te
@@ -76,6 +76,8 @@
 type unlabeled, file_type;
 # Default type for anything under /system.
 type system_file, file_type;
+# Speedup access for trusted applications to the runtime event tags
+type runtime_event_log_tags_file, file_type;
 # Type for /system/*/libart*
 type libart_file, file_type;
 # Type for /system/bin/logcat.
diff --git a/public/init.te b/public/init.te
index 1d984c2..4b29891 100644
--- a/public/init.te
+++ b/public/init.te
@@ -138,6 +138,7 @@
 allow init {
   file_type
   -app_data_file
+  -runtime_event_log_tags_file
   -exec_type
   -keystore_data_file
   -misc_logd_file
diff --git a/public/logd.te b/public/logd.te
index b7fc11a..5defed5 100644
--- a/public/logd.te
+++ b/public/logd.te
@@ -23,6 +23,15 @@
 allow logd kernel:system syslog_mod;
 
 control_logd(logd)
+read_runtime_log_tags(logd)
+
+allow runtime_event_log_tags_file tmpfs:filesystem associate;
+# Typically harmlessly blindly trying to access via liblog
+# event tag mapping while in the untrusted_app domain.
+# Access for that domain is controlled and gated via the
+# event log tag service (albeit at a performance penalty,
+# expected to be locally cached).
+dontaudit domain runtime_event_log_tags_file:file { open read };
 
 ###
 ### Neverallow rules
@@ -47,3 +56,6 @@
 # Only init is allowed to enter the logd domain via exec()
 neverallow { domain -init } logd:process transition;
 neverallow * logd:process dyntransition;
+
+# protect the event-log-tags file
+neverallow * runtime_event_log_tags_file:file no_w_file_perms;
diff --git a/public/surfaceflinger.te b/public/surfaceflinger.te
index 68e86b1..d09a350 100644
--- a/public/surfaceflinger.te
+++ b/public/surfaceflinger.te
@@ -4,6 +4,8 @@
 
 typeattribute surfaceflinger mlstrustedsubject;
 
+read_runtime_log_tags(surfaceflinger)
+
 # Perform HwBinder IPC.
 hwbinder_use(surfaceflinger)
 binder_call(surfaceflinger, hal_graphics_allocator)
diff --git a/public/system_server.te b/public/system_server.te
index aef97b5..2426283 100644
--- a/public/system_server.te
+++ b/public/system_server.te
@@ -464,6 +464,7 @@
 
 # Read from log daemon.
 read_logd(system_server)
+read_runtime_log_tags(system_server)
 
 # Be consistent with DAC permissions. Allow system_server to write to
 # /sys/module/lowmemorykiller/parameters/adj
diff --git a/public/te_macros b/public/te_macros
index 0a423ac..c9ab6e0 100644
--- a/public/te_macros
+++ b/public/te_macros
@@ -345,6 +345,13 @@
 ')
 
 #####################################
+# read_runtime_log_tags(domain)
+# ability to directly map the runtime event log tags
+define(`read_runtime_log_tags', `
+allow $1 runtime_event_log_tags_file:file r_file_perms;
+')
+
+#####################################
 # control_logd(domain)
 # Ability to control
 # android log daemon via sockets