Introduce crash_dump debugging helper.
Replace the global debuggerd with a per-process debugging helper that
gets exec'ed by the process that crashed.
Bug: http://b/30705528
Test: crasher/crasher64, `debuggerd <pid>`, `kill -ABRT <pid>`
Change-Id: Iad1b7478f7a4e2690720db4b066417d8b66834ed
diff --git a/private/access_vectors b/private/access_vectors
index 6393c16..efd4924 100644
--- a/private/access_vectors
+++ b/private/access_vectors
@@ -577,12 +577,6 @@
user_changed
}
-class debuggerd
-{
- dump_tombstone
- dump_backtrace
-}
-
class drmservice {
consumeRights
setPlaybackStatus
diff --git a/private/domain.te b/private/domain.te
index b0c7ac7..b1171f4 100644
--- a/private/domain.te
+++ b/private/domain.te
@@ -1,9 +1,14 @@
+# Transition to crash_dump when /system/bin/crash_dump* is executed.
+# This occurs when the process crashes.
+domain_auto_trans(domain, crash_dump_exec, crash_dump);
+allow domain crash_dump:process sigchld;
+
# Limit ability to ptrace or read sensitive /proc/pid files of processes
# with other UIDs to these whitelisted domains.
neverallow {
domain
- -debuggerd
-vold
+ -crash_dump
-dumpstate
-storaged
-system_server
diff --git a/private/file_contexts b/private/file_contexts
index f6e1be1..3209073 100644
--- a/private/file_contexts
+++ b/private/file_contexts
@@ -126,6 +126,8 @@
/dev/socket/racoon u:object_r:racoon_socket:s0
/dev/socket/rild u:object_r:rild_socket:s0
/dev/socket/rild-debug u:object_r:rild_debug_socket:s0
+/dev/socket/tombstoned_crash u:object_r:tombstoned_crash_socket:s0
+/dev/socket/tombstoned_intercept u:object_r:tombstoned_intercept_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
@@ -192,8 +194,9 @@
/system/bin/keystore u:object_r:keystore_exec:s0
/system/bin/fingerprintd u:object_r:fingerprintd_exec:s0
/system/bin/gatekeeperd u:object_r:gatekeeperd_exec:s0
-/system/bin/debuggerd u:object_r:debuggerd_exec:s0
-/system/bin/debuggerd64 u:object_r:debuggerd_exec:s0
+/system/bin/crash_dump32 u:object_r:crash_dump_exec:s0
+/system/bin/crash_dump64 u:object_r:crash_dump_exec:s0
+/system/bin/tombstoned u:object_r:tombstoned_exec:s0
/system/bin/wpa_supplicant u:object_r:wpa_exec:s0
/system/bin/recovery-persist u:object_r:recovery_persist_exec:s0
/system/bin/recovery-refresh u:object_r:recovery_refresh_exec:s0
diff --git a/private/security_classes b/private/security_classes
index 680d3dd..19fd5db 100644
--- a/private/security_classes
+++ b/private/security_classes
@@ -103,8 +103,5 @@
# Keystore Key
class keystore_key # userspace
-# debuggerd service
-class debuggerd # userspace
-
class drmservice # userspace
# FLASK
diff --git a/private/system_server.te b/private/system_server.te
index 7e0c2fb..0e35660 100644
--- a/private/system_server.te
+++ b/private/system_server.te
@@ -2,7 +2,7 @@
# public, but conceptually should go with this
# Define a type for tmpfs-backed ashmem regions.
tmpfs_domain(system_server)
-# Create a socket for connections from debuggerd.
+# Create a socket for connections from crash_dump.
type_transition system_server system_data_file:sock_file system_ndebug_socket "ndebugsocket";
allow system_server zygote_tmpfs:file read;
diff --git a/private/debuggerd.te b/private/tombstoned.te
similarity index 79%
rename from private/debuggerd.te
rename to private/tombstoned.te
index bd835af..73fdb1b 100644
--- a/private/debuggerd.te
+++ b/private/tombstoned.te
@@ -1,3 +1,3 @@
# type_transition must be private policy the domain_trans rules could stay
# public, but conceptually should go with this
-init_daemon_domain(debuggerd)
+init_daemon_domain(tombstoned)
diff --git a/public/adbd.te b/public/adbd.te
index 17a98d9..d60f8f1 100644
--- a/public/adbd.te
+++ b/public/adbd.te
@@ -120,8 +120,8 @@
### Neverallow rules
###
-# No transitions from adbd to non-shell domains. adbd only ever
-# transitions to the shell domain. In particular, we never want
-# to see a transition from adbd to su (aka "adb root")
-neverallow adbd { domain -shell }:process transition;
+# No transitions from adbd to non-shell, non-crash_dump domains. adbd only ever
+# transitions to the shell domain (except when it crashes). In particular, we
+# never want to see a transition from adbd to su (aka "adb root")
+neverallow adbd { domain -crash_dump -shell }:process transition;
neverallow adbd { domain userdebug_or_eng(`-su') }:process dyntransition;
diff --git a/public/app.te b/public/app.te
index 57b76f1..e350f45 100644
--- a/public/app.te
+++ b/public/app.te
@@ -353,10 +353,12 @@
{ sigkill sigstop signal };
# Transition to a non-app domain.
-# Exception for the shell domain and the su domain, can transition to runas,
-# etc.
+# Exception for the shell and su domains, can transition to runas, etc.
+# Exception for crash_dump.
+neverallow { appdomain -shell userdebug_or_eng(`-su') } { domain -appdomain -crash_dump }:process
+ { transition };
neverallow { appdomain -shell userdebug_or_eng(`-su') } { domain -appdomain }:process
- { transition dyntransition };
+ { dyntransition };
# Write to rootfs.
neverallow appdomain rootfs:dir_file_class_set
diff --git a/public/crash_dump.te b/public/crash_dump.te
new file mode 100644
index 0000000..af74247
--- /dev/null
+++ b/public/crash_dump.te
@@ -0,0 +1,50 @@
+type crash_dump, domain;
+type crash_dump_exec, exec_type, file_type;
+
+allow crash_dump self:capability { sys_ptrace kill };
+allow crash_dump {
+ domain
+ -init
+ -crash_dump
+ -keystore
+ -logd
+}:process { ptrace signal sigchld sigstop sigkill };
+userdebug_or_eng(`
+ allow crash_dump logd:process { ptrace signal sigchld sigstop sigkill };
+')
+
+# Use inherited file descriptors
+allow crash_dump domain:fd use;
+allow crash_dump domain:fifo_file write;
+
+r_dir_file(crash_dump, domain)
+allow crash_dump exec_type:file r_file_perms;
+
+# Read /data/dalvik-cache.
+allow crash_dump dalvikcache_data_file:dir { search getattr };
+allow crash_dump dalvikcache_data_file:file r_file_perms;
+
+# Unwind through libart.
+allow crash_dump libart_file:file r_file_perms;
+
+# Talk to tombstoned
+unix_socket_connect(crash_dump, tombstoned_crash, tombstoned)
+
+# Talk to ActivityManager.
+unix_socket_connect(crash_dump, system_ndebug, system_server)
+
+# Append to ANR files.
+allow crash_dump anr_data_file:file { append getattr };
+
+# Append to tombstone files.
+allow crash_dump tombstone_data_file:file { append getattr };
+
+read_logd(crash_dump)
+
+###
+### neverallow assertions
+###
+
+# A domain transition must occur for crash_dump to get the privileges needed to trace the process.
+# Do not allow the execution of crash_dump without a domain transition.
+neverallow domain crash_dump_exec:file execute_no_trans;
diff --git a/public/debuggerd.te b/public/debuggerd.te
deleted file mode 100644
index e8e9302..0000000
--- a/public/debuggerd.te
+++ /dev/null
@@ -1,77 +0,0 @@
-# debugger interface
-type debuggerd, domain;
-type debuggerd_exec, exec_type, file_type;
-
-typeattribute debuggerd mlstrustedsubject;
-allow debuggerd self:capability { dac_override sys_ptrace chown kill fowner setuid setgid };
-allow debuggerd self:capability2 { syslog };
-allow debuggerd domain:dir r_dir_perms;
-allow debuggerd domain:file r_file_perms;
-allow debuggerd domain:lnk_file read;
-allow debuggerd {
- domain
- -adbd
- -debuggerd
- -healthd
- -init
- -keystore
- -logd
- -ueventd
- -watchdogd
-}:process { execmem ptrace getattr };
-
-userdebug_or_eng(`
- allow debuggerd logd:process { execmem ptrace getattr };
-')
-
-allow debuggerd tombstone_data_file:dir rw_dir_perms;
-allow debuggerd tombstone_data_file:file create_file_perms;
-allow debuggerd shared_relro_file:dir r_dir_perms;
-allow debuggerd shared_relro_file:file r_file_perms;
-allow debuggerd domain:process { sigstop sigkill signal };
-allow debuggerd { exec_type libart_file }:file r_file_perms;
-allow debuggerd apk_data_file:file r_file_perms;
-allow debuggerd apk_data_file:dir search;
-# Access app library
-allow debuggerd system_data_file:file open;
-# Allow debuggerd to redirect a dump_backtrace request to itself.
-# This only happens on 64 bit systems, where all requests go to the 64 bit
-# debuggerd and get redirected to the 32 bit debuggerd if the process is 32 bit.
-
-allow debuggerd {
- audioserver
- bluetooth
- cameraserver
- drmserver
- inputflinger
- mediacodec
- mediadrmserver
- mediaextractor
- mediaserver
- sdcardd
- surfaceflinger
-}:debuggerd dump_backtrace;
-
-# Connect to system_server via /data/system/ndebugsocket.
-unix_socket_connect(debuggerd, system_ndebug, system_server)
-
-# Get stack traces for VTS executables
-userdebug_or_eng(`
- allow debuggerd nativetest_data_file:dir search;
- allow debuggerd nativetest_data_file:file r_file_perms;
-')
-
-userdebug_or_eng(`
- allow debuggerd input_device:dir r_dir_perms;
- allow debuggerd input_device:chr_file rw_file_perms;
-')
-
-# logd access
-read_logd(debuggerd)
-
-# Check SELinux permissions.
-selinux_check_access(debuggerd)
-
-# Read /data/dalvik-cache.
-allow debuggerd dalvikcache_data_file:dir { search getattr };
-allow debuggerd dalvikcache_data_file:file r_file_perms;
diff --git a/public/domain.te b/public/domain.te
index fdfcf94..9151fd3 100644
--- a/public/domain.te
+++ b/public/domain.te
@@ -53,12 +53,6 @@
allow domain coredump_file:dir ra_dir_perms;
')
-###
-### Talk to debuggerd.
-###
-allow domain debuggerd:process sigchld;
-allow domain debuggerd:unix_stream_socket connectto;
-
# Root fs.
allow domain rootfs:dir search;
allow domain rootfs:lnk_file read;
@@ -106,7 +100,7 @@
auditallow {
domain
-appdomain
- -debuggerd
+ -crash_dump
-dex2oat
-dumpstate
-profman
@@ -462,6 +456,16 @@
neverallow { domain -system_server -webview_zygote } webview_zygote:unix_stream_socket connectto;
neverallow { domain -system_server } webview_zygote_socket:sock_file write;
+neverallow {
+ domain
+ -tombstoned
+ -crash_dump
+ -dumpstate
+ -system_server
+} tombstoned:unix_stream_socket connectto;
+neverallow { domain -crash_dump } tombstoned_crash_socket:sock_file write;
+neverallow { domain -dumpstate -system_server } tombstoned_intercept_socket:sock_file write;
+
# Android does not support System V IPCs.
#
# The reason for this is due to the fact that, by design, they lead to global
@@ -691,3 +695,6 @@
domain
-recovery
} self:capability setfcap;
+
+# Enforce AT_SECURE for executing crash_dump.
+neverallow domain crash_dump:process noatsecure;
diff --git a/public/domain_deprecated.te b/public/domain_deprecated.te
index d092d09..1f535c3 100644
--- a/public/domain_deprecated.te
+++ b/public/domain_deprecated.te
@@ -123,5 +123,5 @@
# Get SELinux enforcing status.
allow domain_deprecated selinuxfs:dir r_dir_perms;
allow domain_deprecated selinuxfs:file r_file_perms;
-auditallow { domain_deprecated -appdomain -debuggerd -init -installd -keystore -postinstall_dexopt -runas -servicemanager -system_server -ueventd -zygote } selinuxfs:dir { open getattr read ioctl lock }; # search granted in domain
-auditallow { domain_deprecated -appdomain -debuggerd -init -installd -keystore -postinstall_dexopt -runas -servicemanager -system_server -ueventd -zygote } selinuxfs:file { open read ioctl lock }; # getattr granted in domain
+auditallow { domain_deprecated -appdomain -init -installd -keystore -postinstall_dexopt -runas -servicemanager -system_server -ueventd -zygote } selinuxfs:dir { open getattr read ioctl lock }; # search granted in domain
+auditallow { domain_deprecated -appdomain -init -installd -keystore -postinstall_dexopt -runas -servicemanager -system_server -ueventd -zygote } selinuxfs:file { open read ioctl lock }; # getattr granted in domain
diff --git a/public/dumpstate.te b/public/dumpstate.te
index ee617e5..d64a4b4 100644
--- a/public/dumpstate.te
+++ b/public/dumpstate.te
@@ -65,19 +65,9 @@
sdcardd
surfaceflinger
}:process signal;
-# Ask debuggerd for the backtraces of these processes.
-allow dumpstate {
- audioserver
- cameraserver
- drmserver
- inputflinger
- mediacodec
- mediadrmserver
- mediaextractor
- mediaserver
- sdcardd
- surfaceflinger
-}:debuggerd dump_backtrace;
+
+# Connect to tombstoned to intercept dumps.
+unix_socket_connect(dumpstate, tombstoned_intercept, tombstoned)
# TODO: added to match above sysfs rule. Remove me?
allow dumpstate sysfs_usb:file w_file_perms;
diff --git a/public/file.te b/public/file.te
index 077b25a..4b27c88 100644
--- a/public/file.te
+++ b/public/file.te
@@ -236,6 +236,8 @@
type rild_debug_socket, file_type;
type system_wpa_socket, file_type;
type system_ndebug_socket, file_type;
+type tombstoned_crash_socket, file_type, mlstrustedobject;
+type tombstoned_intercept_socket, file_type;
type uncrypt_socket, file_type;
type vold_socket, file_type;
type webview_zygote_socket, file_type;
diff --git a/public/logd.te b/public/logd.te
index 6478123..b7fc11a 100644
--- a/public/logd.te
+++ b/public/logd.te
@@ -36,7 +36,7 @@
neverallow logd domain:process ptrace;
# ... and nobody may ptrace me (except on userdebug or eng builds)
-neverallow { domain userdebug_or_eng(`-debuggerd') } logd:process ptrace;
+neverallow { domain userdebug_or_eng(`-crash_dump') } logd:process ptrace;
# Write to /system.
neverallow logd system_file:dir_file_class_set write;
diff --git a/public/su.te b/public/su.te
index 38d7f5c..8cb386d 100644
--- a/public/su.te
+++ b/public/su.te
@@ -36,7 +36,6 @@
dontaudit su service_manager_type:service_manager *;
dontaudit su servicemanager:service_manager list;
dontaudit su keystore:keystore_key *;
- dontaudit su domain:debuggerd *;
dontaudit su domain:drmservice *;
dontaudit su unlabeled:filesystem *;
dontaudit su postinstall_file:filesystem *;
diff --git a/public/system_server.te b/public/system_server.te
index 0e1b9c0..d2e6ade 100644
--- a/public/system_server.te
+++ b/public/system_server.te
@@ -28,6 +28,7 @@
# May kill zygote on crashes.
allow system_server zygote:process sigkill;
+allow system_server crash_dump:process sigkill;
# Read /system/bin/app_process.
allow system_server zygote_exec:file r_file_perms;
@@ -178,14 +179,15 @@
binder_call(system_server, hal_wifi)
binder_call(system_server, wpa)
-# Ask debuggerd to dump backtraces for native stacks of interest.
-#
+# Talk to tombstoned to get ANR traces.
+unix_socket_connect(system_server, tombstoned_intercept, tombstoned)
+
+# Send signals to trigger ANR traces.
# This is derived from the list that system server defines as interesting native processes
# to dump during ANRs or watchdog aborts, defined in NATIVE_STACKS_OF_INTEREST in
# frameworks/base/services/core/java/com/android/server/Watchdog.java.
allow system_server {
audioserver
- bluetooth
cameraserver
drmserver
inputflinger
@@ -196,7 +198,7 @@
mediaanalytics
sdcardd
surfaceflinger
-}:debuggerd dump_backtrace;
+}:process { signal };
# Use sockets received over binder from various services.
allow system_server audioserver:tcp_socket rw_socket_perms;
@@ -624,9 +626,13 @@
# getting worse. b/28035297
neverallow system_server { file_type -toolbox_exec -logcat_exec }:file execute_no_trans;
-# System server should never transition to a new domain. This compliments
-# and enforces the already pre-existing PR_SET_NO_NEW_PRIVS flag.
-neverallow system_server *:process { transition dyntransition };
+# Ensure that system_server doesn't perform any domain transitions other than
+# transitioning to the crash_dump domain when a crash occurs.
+neverallow system_server { domain -crash_dump }:process transition;
+neverallow system_server *:process dyntransition;
+
+# Only allow crash_dump to connect to system_ndebug_socket.
+neverallow { domain -init -system_server -crash_dump } system_ndebug_socket:sock_file { open write };
# system_server should never be executing dex2oat. This is either
# a bug (for example, bug 16317188), or represents an attempt by
diff --git a/public/tombstoned.te b/public/tombstoned.te
new file mode 100644
index 0000000..c830d93
--- /dev/null
+++ b/public/tombstoned.te
@@ -0,0 +1,12 @@
+# debugger interface
+type tombstoned, domain, mlstrustedsubject;
+type tombstoned_exec, exec_type, file_type;
+
+# Write to arbitrary pipes given to us.
+allow tombstoned domain:fd use;
+allow tombstoned domain:fifo_file write;
+
+allow tombstoned domain:dir r_dir_perms;
+allow tombstoned domain:file r_file_perms;
+allow tombstoned tombstone_data_file:dir rw_dir_perms;
+allow tombstoned tombstone_data_file:file create_file_perms;
diff --git a/public/webview_zygote.te b/public/webview_zygote.te
index 93bbbb1..29e5ba4 100644
--- a/public/webview_zygote.te
+++ b/public/webview_zygote.te
@@ -53,8 +53,8 @@
# Only permit transition to isolated_app.
neverallow webview_zygote { domain -isolated_app }:process dyntransition;
-# Only setcon() transitions, no exec() based transitions
-neverallow webview_zygote *:process transition;
+# Only setcon() transitions, no exec() based transitions, except for crash_dump.
+neverallow webview_zygote { domain -crash_dump }:process transition;
# Must not exec() a program without changing domains.
# Having said that, exec() above is not allowed.