From c80f9e037bedb09d08a261f255f87ea105fa371b Mon Sep 17 00:00:00 2001 From: Primiano Tucci <primiano@google.com> Date: Thu, 21 Dec 2017 03:51:15 +0100 Subject: [PATCH] Perfetto SELinux policies Perfetto is a performance instrumentation and logging framework, living in AOSP's /external/pefetto. Perfetto introduces in the system one binary and two daemons (the binary can specialize in either depending on the cmdline). 1) traced: unprivileged daemon. This is architecturally similar to logd. It exposes two UNIX sockets: - /dev/socket/traced_producer : world-accessible, allows to stream tracing data. A tmpfs file descriptor is sent via SCM_RIGHTS from traced to each client process, which needs to be able to mmap it R/W (but not X) - /dev/socket/traced_consumer : privilege-accessible (only from: shell, statsd). It allows to configure tracing and read the trace buffer. 2) traced_probes: privileged daemon. This needs to: - access tracingfs (/d/tracing) to turn tracing on and off. - exec atrace - connect to traced_producer to stream data to traced. init.rc file: https://android-review.googlesource.com/c/platform/external/perfetto/+/575382/14/perfetto.rc Bug: 70942310 Change-Id: Ia3b5fdacbd5a8e6e23b82f1d6fabfa07e4abc405 --- private/compat/26.0/26.0.ignore.cil | 8 +++++ private/domain.te | 1 + private/ephemeral_app.te | 6 ++++ private/file_contexts | 4 +++ private/isolated_app.te | 6 ++++ private/priv_app.te | 6 ++++ private/shell.te | 10 ++++++ private/statsd.te | 4 ++- private/traced.te | 38 ++++++++++++++++++++ private/traced_probes.te | 55 +++++++++++++++++++++++++++++ private/untrusted_app_all.te | 6 ++++ private/untrusted_v2_app.te | 6 ++++ public/domain.te | 3 +- public/file.te | 2 ++ 14 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 private/traced.te create mode 100644 private/traced_probes.te diff --git a/private/compat/26.0/26.0.ignore.cil b/private/compat/26.0/26.0.ignore.cil index 77d1b4fc1..f70cb7c75 100644 --- a/private/compat/26.0/26.0.ignore.cil +++ b/private/compat/26.0/26.0.ignore.cil @@ -55,6 +55,14 @@ tombstone_wifi_data_file traceur_app traceur_app_tmpfs + traced + traced_consumer_socket + traced_exec + traced_probes + traced_probes_exec + traced_probes_tmpfs + traced_producer_socket + traced_tmpfs update_engine_log_data_file vendor_init vold_prepare_subdirs diff --git a/private/domain.te b/private/domain.te index 1fd75bc78..72c3855e3 100644 --- a/private/domain.te +++ b/private/domain.te @@ -71,6 +71,7 @@ full_treble_only(` -dumpstate -init userdebug_or_eng(`-perfprofd') + userdebug_or_eng(`-traced_probes') -shell userdebug_or_eng(`-traceur_app') -vendor_init diff --git a/private/ephemeral_app.te b/private/ephemeral_app.te index 7694739bd..dbfbcf9e8 100644 --- a/private/ephemeral_app.te +++ b/private/ephemeral_app.te @@ -35,6 +35,12 @@ allow ephemeral_app drmserver_service:service_manager find; allow ephemeral_app radio_service:service_manager find; allow ephemeral_app ephemeral_app_api_service:service_manager find; +# Write app-specific trace data to the Perfetto traced damon. This requires +# connecting to its producer socket and obtaining a (per-process) tmpfs fd. +allow ephemeral_app traced:fd use; +allow ephemeral_app traced_tmpfs:file { read write getattr map }; +unix_socket_connect(ephemeral_app, traced_producer, traced) + ### ### neverallow rules ### diff --git a/private/file_contexts b/private/file_contexts index 0765ef0b4..de959d450 100644 --- a/private/file_contexts +++ b/private/file_contexts @@ -146,6 +146,8 @@ /dev/socket/tombstoned_crash u:object_r:tombstoned_crash_socket:s0 /dev/socket/tombstoned_java_trace u:object_r:tombstoned_java_trace_socket:s0 /dev/socket/tombstoned_intercept u:object_r:tombstoned_intercept_socket:s0 +/dev/socket/traced_producer u:object_r:traced_producer_socket:s0 +/dev/socket/traced_consumer u:object_r:traced_consumer_socket:s0 /dev/socket/uncrypt u:object_r:uncrypt_socket:s0 /dev/socket/vold u:object_r:vold_socket:s0 /dev/socket/webview_zygote u:object_r:webview_zygote_socket:s0 @@ -240,6 +242,8 @@ /system/bin/lmkd u:object_r:lmkd_exec:s0 /system/bin/inputflinger u:object_r:inputflinger_exec:s0 /system/bin/logd u:object_r:logd_exec:s0 +/system/bin/traced u:object_r:traced_exec:s0 +/system/bin/traced_probes u:object_r:traced_probes_exec:s0 /system/bin/uncrypt u:object_r:uncrypt_exec:s0 /system/bin/update_verifier u:object_r:update_verifier_exec:s0 /system/bin/logwrapper u:object_r:system_file:s0 diff --git a/private/isolated_app.te b/private/isolated_app.te index 30253af60..06ed2c82c 100644 --- a/private/isolated_app.te +++ b/private/isolated_app.te @@ -47,6 +47,12 @@ allow isolated_app webview_zygote_tmpfs:file read; # suppress denials to /data/local/tmp dontaudit isolated_app shell_data_file:dir search; +# Write app-specific trace data to the Perfetto traced damon. This requires +# connecting to its producer socket and obtaining a (per-process) tmpfs fd. +allow isolated_app traced:fd use; +allow isolated_app traced_tmpfs:file { read write getattr map }; +unix_socket_connect(isolated_app, traced_producer, traced) + ##### ##### Neverallow ##### diff --git a/private/priv_app.te b/private/priv_app.te index ea1ce5b16..92bfc570a 100644 --- a/private/priv_app.te +++ b/private/priv_app.te @@ -116,6 +116,12 @@ allow priv_app selinuxfs:file r_file_perms; read_runtime_log_tags(priv_app) +# Write app-specific trace data to the Perfetto traced damon. This requires +# connecting to its producer socket and obtaining a (per-process) tmpfs fd. +allow priv_app traced:fd use; +allow priv_app traced_tmpfs:file { read write getattr map }; +unix_socket_connect(priv_app, traced_producer, traced) + # suppress denials when safetynet scans /system dontaudit priv_app exec_type:file getattr; dontaudit priv_app device:dir read; diff --git a/private/shell.te b/private/shell.te index 5299532ac..a3c49db37 100644 --- a/private/shell.te +++ b/private/shell.te @@ -26,3 +26,13 @@ binder_call(shell, storaged) # Perform SELinux access checks, needed for CTS selinux_check_access(shell) selinux_check_context(shell) + +# Control Perfetto traced and obtain traces from it. +# Needed for Studio and debugging. +unix_socket_connect(shell, traced_consumer, traced) + +# Allow shell binaries to write trace data to Perfetto. Used for testing and +# cmdline utils. +allow shell traced:fd use; +allow shell traced_tmpfs:file { read write getattr map }; +unix_socket_connect(shell, traced_producer, traced) diff --git a/private/statsd.te b/private/statsd.te index 9d78ebb40..6b7f8cdd7 100644 --- a/private/statsd.te +++ b/private/statsd.te @@ -30,6 +30,9 @@ binder_call(statsd, statscompanion_service) read_logd(statsd) control_logd(statsd) +# Allow to control Perfetto traced and consume its traces. +unix_socket_connect(statsd, traced_consumer, traced) + # Grant statsd with permissions to register the services. allow statsd { statscompanion_service @@ -71,4 +74,3 @@ neverallow { domain -statsd -init -vold -vendor_init } stats_data_file:file *; # Limited access to the directory itself. neverallow { domain -statsd -init -vold -vendor_init } stats_data_file:dir *; - diff --git a/private/traced.te b/private/traced.te new file mode 100644 index 000000000..bb7a09191 --- /dev/null +++ b/private/traced.te @@ -0,0 +1,38 @@ +# Perfetto user-space tracing daemon (unprivileged) +type traced, domain, coredomain; +type traced_exec, exec_type, file_type; + +# Allow init to exec the daemon. +init_daemon_domain(traced) + +# Allow traced to start with a lower scheduling class and change +# class accordingly to what defined in the config provided by +# the privileged process that controls it. +allow traced self:global_capability_class_set { sys_nice }; + +### +### Neverallow rules +### +### traced should NEVER do any of this + +# Disallow mapping executable memory (execstack and exec are already disallowed +# globally in domain.te). +neverallow traced self:process execmem; + +# Block device access. +neverallow traced dev_type:blk_file { read write }; + +# ptrace any other process +neverallow traced domain:process ptrace; + +# Disallows access to /data files, still allowing to write to file descriptors +# passed through the socket. +neverallow traced { data_file_type -system_data_file -zoneinfo_data_file }:dir *; +neverallow traced system_data_file:dir ~{ getattr search }; +neverallow traced zoneinfo_data_file:dir ~r_dir_perms; +neverallow traced { data_file_type -zoneinfo_data_file }:lnk_file *; +neverallow traced { data_file_type -zoneinfo_data_file }:file ~write; + +# Only init is allowed to enter the traced domain via exec() +neverallow { domain -init } traced:process transition; +neverallow * traced:process dyntransition; diff --git a/private/traced_probes.te b/private/traced_probes.te new file mode 100644 index 000000000..15c51d4cd --- /dev/null +++ b/private/traced_probes.te @@ -0,0 +1,55 @@ +# Perfetto tracing probes, has tracefs access. +type traced_probes, domain, coredomain; +type traced_probes_exec, exec_type, file_type; + +# Allow init to exec the daemon. +init_daemon_domain(traced_probes) + +# Write trace data to the Perfetto traced damon. This requires connecting to its +# producer socket and obtaining a (per-process) tmpfs fd. +allow traced_probes traced:fd use; +allow traced_probes traced_tmpfs:file { read write getattr map }; +unix_socket_connect(traced_probes, traced_producer, traced) + +# Allow traced_probes to access tracefs. +# TODO(primiano): For the moment this is userdebug/eng only until we get an +# approval for user builds. +userdebug_or_eng(` +allow traced_probes debugfs_tracing:dir r_dir_perms; +allow traced_probes debugfs_tracing:file rw_file_perms; +allow traced_probes debugfs_tracing_debug:file rw_file_perms; +allow traced_probes debugfs_trace_marker:file getattr; +') + +# Allow traced_probes to start with a higher scheduling class and then downgrade +# itself. +allow traced_probes self:global_capability_class_set { sys_nice }; + +# Allow procfs access +r_dir_file(traced_probes, domain) + +### +### Neverallow rules +### +### traced_probes should NEVER do any of this + +# Disallow mapping executable memory (execstack and exec are already disallowed +# globally in domain.te). +neverallow traced_probes self:process execmem; + +# Block device access. +neverallow traced_probes dev_type:blk_file { read write }; + +# ptrace any other app +neverallow traced_probes domain:process ptrace; + +# Disallows access to /data files. +neverallow traced { data_file_type -system_data_file -zoneinfo_data_file }:dir *; +neverallow traced system_data_file:dir ~{ getattr search }; +neverallow traced zoneinfo_data_file:dir ~r_dir_perms; +neverallow traced { data_file_type -zoneinfo_data_file }:lnk_file *; +neverallow traced { data_file_type -zoneinfo_data_file }:file *; + +# Only init is allowed to enter the traced_probes domain via exec() +neverallow { domain -init } traced_probes:process transition; +neverallow * traced_probes:process dyntransition; diff --git a/private/untrusted_app_all.te b/private/untrusted_app_all.te index f96cae0e1..e76407bc0 100644 --- a/private/untrusted_app_all.te +++ b/private/untrusted_app_all.te @@ -105,3 +105,9 @@ allow untrusted_app_all preloads_data_file:dir search; allow untrusted_app_all vendor_app_file:dir { open getattr read search }; allow untrusted_app_all vendor_app_file:file { open getattr read execute }; allow untrusted_app_all vendor_app_file:lnk_file { open getattr read }; + +# Write app-specific trace data to the Perfetto traced damon. This requires +# connecting to its producer socket and obtaining a (per-process) tmpfs fd. +allow untrusted_app_all traced:fd use; +allow untrusted_app_all traced_tmpfs:file { read write getattr map }; +unix_socket_connect(untrusted_app_all, traced_producer, traced) diff --git a/private/untrusted_v2_app.te b/private/untrusted_v2_app.te index 60634aefb..8f4bceb2c 100644 --- a/private/untrusted_v2_app.te +++ b/private/untrusted_v2_app.te @@ -39,3 +39,9 @@ allow untrusted_v2_app app_api_service:service_manager find; # gdbserver for ndk-gdb ptrace attaches to app process. allow untrusted_v2_app self:process ptrace; + +# Write app-specific trace data to the Perfetto traced damon. This requires +# connecting to its producer socket and obtaining a (per-process) tmpfs fd. +allow untrusted_v2_app traced:fd use; +allow untrusted_v2_app traced_tmpfs:file { read write getattr map }; +unix_socket_connect(untrusted_v2_app, traced_producer, traced) diff --git a/public/domain.te b/public/domain.te index 142c10b20..70d8ae20f 100644 --- a/public/domain.te +++ b/public/domain.te @@ -149,7 +149,8 @@ allow domain sysfs:lnk_file { getattr read }; # libc references /data/misc/zoneinfo for timezone related information # This directory is considered to be a VNDK-stable -r_dir_file(domain, zoneinfo_data_file) +allow domain zoneinfo_data_file:file r_file_perms; +allow domain zoneinfo_data_file:dir r_dir_perms; # Lots of processes access current CPU information r_dir_file(domain, sysfs_devices_system_cpu) diff --git a/public/file.te b/public/file.te index c536a8a5a..9660da2c4 100644 --- a/public/file.te +++ b/public/file.te @@ -315,6 +315,8 @@ type system_ndebug_socket, file_type, data_file_type, core_data_file_type, cored type tombstoned_crash_socket, file_type, coredomain_socket, mlstrustedobject; type tombstoned_java_trace_socket, file_type, mlstrustedobject; type tombstoned_intercept_socket, file_type, coredomain_socket; +type traced_producer_socket, file_type, coredomain_socket; +type traced_consumer_socket, file_type, coredomain_socket; type uncrypt_socket, file_type, coredomain_socket; type vold_socket, file_type, coredomain_socket; type webview_zygote_socket, file_type, coredomain_socket; -- GitLab