sepolicy: rework perfetto producer/profiler rules for "user" builds

This patch:
* allows for heap and perf profiling of all processes on the system
  (minus undumpable and otherwise incompatible domains). For apps, the
  rest of the platform will still perform checks based on
  profileable/debuggable manifest flags. For native processes, the
  profilers will check that the process runs as an allowlisted UID.
* allows for all apps (=appdomain) to act as perfetto tracing data
  writers (=perfetto_producer) for the ART java heap graph plugin
  (perfetto_hprof).
* allows for system_server to act a perfetto_producer for java heap
  graphs.

Bug: 247858731
Change-Id: I792ec1812d94b4fa9a8688ed74f2f62f6a7f33a6
This commit is contained in:
Ryan Savitski 2023-02-02 14:24:45 +00:00
parent e79c506fe4
commit 941ba723ba
16 changed files with 72 additions and 123 deletions

View file

@ -58,8 +58,6 @@ get_prop(appdomain, camera2_extensions_prop)
# Allow to ro.camerax.extensions.enabled # Allow to ro.camerax.extensions.enabled
get_prop(appdomain, camerax_extensions_prop) get_prop(appdomain, camerax_extensions_prop)
userdebug_or_eng(`perfetto_producer({ appdomain })')
# Prevent apps from causing presubmit failures. # Prevent apps from causing presubmit failures.
# Apps can cause selinux denials by accessing CE storage # Apps can cause selinux denials by accessing CE storage
# and/or external storage. In either case, the selinux denial is # and/or external storage. In either case, the selinux denial is
@ -358,6 +356,12 @@ allow appdomain user_profile_root_file:dir search;
allow appdomain user_profile_data_file:dir w_dir_perms; allow appdomain user_profile_data_file:dir w_dir_perms;
allow appdomain user_profile_data_file:file create_file_perms; allow appdomain user_profile_data_file:file create_file_perms;
# Allow writing performance tracing data into the perfetto traced daemon.
# Needed for java heap graph ART plugin (perfetto_hprof).
# The perfetto profiling daemon will check for the specific application's
# opt-in/opt-out.
perfetto_producer(appdomain)
# Send heap dumps to system_server via an already open file descriptor # Send heap dumps to system_server via an already open file descriptor
# % adb shell am set-watch-heap com.android.systemui 1048576 # % adb shell am set-watch-heap com.android.systemui 1048576
# % adb shell dumpsys procstats --start-testing # % adb shell dumpsys procstats --start-testing

View file

@ -142,18 +142,15 @@ neverallow app_zygote domain:{
alg_socket nfc_socket vsock_socket kcm_socket qipcrtr_socket smc_socket alg_socket nfc_socket vsock_socket kcm_socket qipcrtr_socket smc_socket
} *; } *;
# Only allow app_zygote to talk to the logd socket, and # Only allow app_zygote to talk to the logd socket, and su on eng/userdebug.
# su/heapprofd/traced_perf on eng/userdebug. This is because # This is because cap_setuid/cap_setgid allow to forge uid/gid in
# cap_setuid/cap_setgid allow to forge uid/gid in SCM_CREDENTIALS. # SCM_CREDENTIALS. Think twice before changing.
# Think twice before changing.
neverallow app_zygote { neverallow app_zygote {
domain domain
-app_zygote -app_zygote
-logd -logd
-system_server -system_server
userdebug_or_eng(`-su') userdebug_or_eng(`-su')
userdebug_or_eng(`-heapprofd')
userdebug_or_eng(`-traced_perf')
}:unix_dgram_socket *; }:unix_dgram_socket *;
neverallow app_zygote { neverallow app_zygote {
@ -161,8 +158,6 @@ neverallow app_zygote {
-app_zygote -app_zygote
-prng_seeder -prng_seeder
userdebug_or_eng(`-su') userdebug_or_eng(`-su')
userdebug_or_eng(`-heapprofd')
userdebug_or_eng(`-traced_perf')
}:unix_stream_socket *; }:unix_stream_socket *;
# Never allow ptrace # Never allow ptrace

View file

@ -30,13 +30,16 @@ userdebug_or_eng(`
}:process { ptrace signal sigchld sigstop sigkill }; }:process { ptrace signal sigchld sigstop sigkill };
') ')
# Read ART APEX data directory
allow crash_dump apex_art_data_file:dir { getattr search };
allow crash_dump apex_art_data_file:file r_file_perms;
### ###
### neverallow assertions ### neverallow assertions
### ###
# ptrace neverallow assertions are spread throughout the other policy # sigchld not explicitly forbidden since it's part of the
# files, so we avoid adding redundant assertions here # domain-transition-on-exec macros, and is by itself not sensitive
neverallow crash_dump { neverallow crash_dump {
apexd apexd
userdebug_or_eng(`-apexd') userdebug_or_eng(`-apexd')
@ -54,11 +57,7 @@ neverallow crash_dump {
vendor_init vendor_init
vold vold
userdebug_or_eng(`-vold') userdebug_or_eng(`-vold')
}:process { signal sigstop sigkill }; }:process { ptrace signal sigstop sigkill };
neverallow crash_dump self:process ptrace; neverallow crash_dump self:process ptrace;
neverallow crash_dump gpu_device:chr_file *; neverallow crash_dump gpu_device:chr_file *;
# Read ART APEX data directory
allow crash_dump apex_art_data_file:dir { getattr search };
allow crash_dump apex_art_data_file:file r_file_perms;

View file

@ -12,44 +12,49 @@ allow domain crash_dump:process sigchld;
# heap profiling, as initialization will fail if it does not have the # heap profiling, as initialization will fail if it does not have the
# necessary SELinux permissions. # necessary SELinux permissions.
get_prop(domain, heapprofd_prop); get_prop(domain, heapprofd_prop);
# Allow heap profiling on debug builds.
userdebug_or_eng(`can_profile_heap({
domain
-bpfloader
-init
-kernel
-keystore
-llkd
-logd
-logpersist
-recovery
-recovery_persist
-recovery_refresh
-ueventd
-vendor_init
-vold
})')
# As above, allow perf profiling most processes on debug builds. # See private/crash_dump.te
# zygote is excluded as system-wide profiling could end up with it define(`dumpable_domain',`{
# (unexpectedly) holding an open fd across a fork.
userdebug_or_eng(`can_profile_perf({
domain domain
-apexd
-bpfloader -bpfloader
-crash_dump
-crosvm # TODO(b/236672526): Remove exception for crosvm
-diced
-init -init
-kernel -kernel
-keystore -keystore
-llkd -llkd
-logd -logd
-ueventd
-vendor_init
-vold
}')
# Allow heap profiling by heapprofd.
# Zygotes are excluded due to potential issues with holding open file
# descriptors or other state across forks. Other exclusions conflict with
# neverallows, and are not considered important to profile.
can_profile_heap({
dumpable_domain
-app_zygote
-hal_configstore
-logpersist -logpersist
-recovery -recovery
-recovery_persist -recovery_persist
-recovery_refresh -recovery_refresh
-ueventd -webview_zygote
-vendor_init
-vold
-zygote -zygote
})') })
# Allow profiling using perf_event_open by traced_perf.
can_profile_perf({
dumpable_domain
-app_zygote
-hal_configstore
-webview_zygote
-zygote
})
# Everyone can access the IncFS list of features. # Everyone can access the IncFS list of features.
r_dir_file(domain, sysfs_fs_incfs_features); r_dir_file(domain, sysfs_fs_incfs_features);
@ -556,9 +561,9 @@ full_treble_only(`
userdebug_or_eng(`-su') # communications with su are permitted only on userdebug or eng builds userdebug_or_eng(`-su') # communications with su are permitted only on userdebug or eng builds
-init -init
-tombstoned # linker to tombstoned -tombstoned # linker to tombstoned
userdebug_or_eng(`-heapprofd') -heapprofd
userdebug_or_eng(`-traced') -traced
userdebug_or_eng(`-traced_perf') -traced_perf
}); });
') ')

View file

@ -45,14 +45,6 @@ allow ephemeral_app drmserver_service:service_manager find;
allow ephemeral_app radio_service:service_manager find; allow ephemeral_app radio_service:service_manager find;
allow ephemeral_app ephemeral_app_api_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.
perfetto_producer(ephemeral_app)
# Allow profiling if the app opts in by being marked profileable/debuggable.
can_profile_heap(ephemeral_app)
can_profile_perf(ephemeral_app)
# allow ephemeral apps to use UDP sockets provided by the system server but not # allow ephemeral apps to use UDP sockets provided by the system server but not
# modify them other than to connect # modify them other than to connect
allow ephemeral_app system_server:udp_socket { allow ephemeral_app system_server:udp_socket {

View file

@ -1,14 +1,4 @@
# Android heap profiling daemon. go/heapprofd. # Android heap profiling daemon. go/heapprofd.
#
# On user builds, this daemon is responsible for receiving the initial
# profiling configuration, finding matching target processes (if profiling by
# process name), and sending the activation signal to them (+ setting system
# properties for new processes to start profiling from startup). When profiling
# is triggered in a process, it spawns a private heapprofd subprocess (in its
# own SELinux domain), which will exclusively handle profiling of its parent.
#
# On debug builds, this central daemon performs profiling for all target
# processes (which talk directly to this daemon).
type heapprofd_exec, exec_type, file_type, system_file_type; type heapprofd_exec, exec_type, file_type, system_file_type;
type heapprofd_tmpfs, file_type; type heapprofd_tmpfs, file_type;
@ -56,23 +46,28 @@ allow heapprofd self:global_capability_class_set dac_read_search;
# For checking profileability. # For checking profileability.
allow heapprofd packages_list_file:file r_file_perms; allow heapprofd packages_list_file:file r_file_perms;
# This is going to happen on user but is benign because central heapprofd # Never allow profiling privileged or otherwise incompatible domains.
# does not actually need these permission. # Corresponding allow-rule is in private/domain.te.
# If the dac_read_search capability check is rejected, the kernel then tries
# to perform a dac_override capability check, so we need to dontaudit that
# as well.
dontaudit heapprofd self:global_capability_class_set { dac_read_search dac_override };
never_profile_heap(`{ never_profile_heap(`{
apexd
app_zygote
bpfloader bpfloader
diced
hal_configstore
init init
kernel kernel
keystore keystore
llkd llkd
logd logd
logpersist
recovery
recovery_persist
recovery_refresh
ueventd ueventd
vendor_init vendor_init
vold vold
webview_zygote
zygote
}') }')
full_treble_only(` full_treble_only(`

View file

@ -34,12 +34,3 @@ allow isolated_app webview_zygote:process sigchld;
allow isolated_app webview_zygote:unix_dgram_socket write; allow isolated_app webview_zygote:unix_dgram_socket write;
# Read system properties managed by webview_zygote. # Read system properties managed by webview_zygote.
allow isolated_app webview_zygote_tmpfs:file read; allow isolated_app webview_zygote_tmpfs:file 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.
perfetto_producer(isolated_app)
# Allow profiling if the main app has been marked as profileable or
# debuggable.
can_profile_heap(isolated_app)
can_profile_perf(isolated_app)

View file

@ -25,15 +25,6 @@ allow isolated_compute_app speech_recognition_service:service_manager find;
hal_client_domain(isolated_compute_app, hal_allocator) hal_client_domain(isolated_compute_app, hal_allocator)
hwbinder_use(isolated_compute_app) hwbinder_use(isolated_compute_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.
perfetto_producer(isolated_compute_app)
# Allow profiling if the main app has been marked as profileable or
# debuggable.
can_profile_heap(isolated_compute_app)
can_profile_perf(isolated_compute_app)
##### #####
##### Neverallow ##### Neverallow
##### #####

View file

@ -115,9 +115,6 @@ allow platform_app app_data_file:lnk_file create_file_perms;
# suppress denials caused by debugfs_tracing # suppress denials caused by debugfs_tracing
dontaudit platform_app debugfs_tracing:file rw_file_perms; dontaudit platform_app debugfs_tracing:file rw_file_perms;
# Allow platform apps to act as Perfetto producers.
perfetto_producer(platform_app)
# Allow platform apps to create VMs # Allow platform apps to create VMs
virtualizationservice_use(platform_app) virtualizationservice_use(platform_app)

View file

@ -126,20 +126,12 @@ allow priv_app preloads_media_file:dir r_dir_perms;
read_runtime_log_tags(priv_app) 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.
perfetto_producer(priv_app)
# Allow priv_apps to request and collect incident reports. # Allow priv_apps to request and collect incident reports.
# (Also requires DUMP and PACKAGE_USAGE_STATS permissions) # (Also requires DUMP and PACKAGE_USAGE_STATS permissions)
allow priv_app incident_service:service_manager find; allow priv_app incident_service:service_manager find;
binder_call(priv_app, incidentd) binder_call(priv_app, incidentd)
allow priv_app incidentd:fifo_file { read write }; allow priv_app incidentd:fifo_file { read write };
# Allow profiling if the app opts in by being marked profileable/debuggable.
can_profile_heap(priv_app)
can_profile_perf(priv_app)
# Allow priv_apps to check whether Dynamic System Update is enabled # Allow priv_apps to check whether Dynamic System Update is enabled
get_prop(priv_app, dynamic_system_prop) get_prop(priv_app, dynamic_system_prop)

View file

@ -218,14 +218,6 @@ allow sdk_sandbox system_linker_exec:file execute_no_trans;
allow sdk_sandbox shell_data_file:file r_file_perms; allow sdk_sandbox shell_data_file:file r_file_perms;
allow sdk_sandbox shell_data_file:dir r_dir_perms; allow sdk_sandbox shell_data_file:dir r_dir_perms;
# Write app-specific trace data to the Perfetto traced damon. This requires
# connecting to its producer socket and obtaining a (per-process) tmpfs fd.
perfetto_producer(sdk_sandbox)
# Allow profiling if the app opts in by being marked profileable/debuggable.
can_profile_heap(sdk_sandbox)
can_profile_perf(sdk_sandbox)
# allow sdk sandbox to use UDP sockets provided by the system server but not # allow sdk sandbox to use UDP sockets provided by the system server but not
# modify them other than to connect # modify them other than to connect
allow sdk_sandbox system_server:udp_socket { allow sdk_sandbox system_server:udp_socket {

View file

@ -180,9 +180,6 @@ get_prop(system_app, oem_unlock_prop)
# Settings app reads ro.usb.uvc.enabled # Settings app reads ro.usb.uvc.enabled
get_prop(system_app, usb_uvc_enabled_prop) get_prop(system_app, usb_uvc_enabled_prop)
# Allow system apps to act as Perfetto producers.
perfetto_producer(system_app)
### ###
### Neverallow rules ### Neverallow rules
### ###

View file

@ -421,7 +421,9 @@ allow system_server mediaserver:udp_socket rw_socket_perms;
allow system_server mediadrmserver:tcp_socket rw_socket_perms; allow system_server mediadrmserver:tcp_socket rw_socket_perms;
allow system_server mediadrmserver:udp_socket rw_socket_perms; allow system_server mediadrmserver:udp_socket rw_socket_perms;
userdebug_or_eng(`perfetto_producer({ system_server })') # Write trace data to the Perfetto traced daemon. This requires connecting to
# its producer socket and obtaining a (per-process) tmpfs fd.
perfetto_producer(system_server)
# Get file context # Get file context
allow system_server file_contexts_file:file r_file_perms; allow system_server file_contexts_file:file r_file_perms;

View file

@ -60,9 +60,14 @@ dontaudit traced_perf domain:process signal;
# Never allow access to app data files # Never allow access to app data files
neverallow traced_perf { app_data_file privapp_data_file system_app_data_file }:file *; neverallow traced_perf { app_data_file privapp_data_file system_app_data_file }:file *;
# Never allow profiling highly privileged processes. # Never allow profiling privileged or otherwise incompatible domains.
# Corresponding allow-rule is in private/domain.te.
never_profile_perf(`{ never_profile_perf(`{
apexd
app_zygote
bpfloader bpfloader
diced
hal_configstore
init init
kernel kernel
keystore keystore
@ -71,4 +76,6 @@ never_profile_perf(`{
ueventd ueventd
vendor_init vendor_init
vold vold
webview_zygote
zygote
}') }')

View file

@ -129,14 +129,6 @@ allow untrusted_app_all vendor_app_file:dir { open getattr read search };
allow untrusted_app_all vendor_app_file:file { r_file_perms execute }; allow untrusted_app_all vendor_app_file:file { r_file_perms execute };
allow untrusted_app_all vendor_app_file:lnk_file { open getattr read }; 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.
perfetto_producer(untrusted_app_all)
# Allow profiling if the app opts in by being marked profileable/debuggable.
can_profile_heap(untrusted_app_all)
can_profile_perf(untrusted_app_all)
# allow untrusted apps to use UDP sockets provided by the system server but not # allow untrusted apps to use UDP sockets provided by the system server but not
# modify them other than to connect # modify them other than to connect
allow untrusted_app_all system_server:udp_socket { allow untrusted_app_all system_server:udp_socket {

View file

@ -34,8 +34,6 @@ neverallow hal_configstore_server {
-prng_seeder -prng_seeder
userdebug_or_eng(`-su') userdebug_or_eng(`-su')
-tombstoned -tombstoned
userdebug_or_eng(`-heapprofd')
userdebug_or_eng(`-traced_perf')
}:{ unix_dgram_socket unix_stream_socket } *; }:{ unix_dgram_socket unix_stream_socket } *;
# Should never need access to anything on /data # Should never need access to anything on /data