From 342362ae3e1afa577a73dc7f154a9de7da96edc4 Mon Sep 17 00:00:00 2001
From: Benjamin Gordon <bmgordon@google.com>
Date: Thu, 6 Sep 2018 16:19:40 -0600
Subject: [PATCH] sepolicy: grant dac_read_search to domains with dac_override

kernel commit 2a4c22426955d4fc04069811997b7390c0fb858e (fs: switch order
of CAP_DAC_OVERRIDE and CAP_DAC_READ_SEARCH checks) swapped the order of
dac_override and dac_read_search checks.  Domains that have dac_override
will now generate spurious denials for dac_read_search unless they also
have that permission.  Since dac_override is a strict superset of
dac_read_search, grant dac_read_search to all domains that already have
dac_override to get rid of the denials.

Bug: 114280985
Bug: crbug.com/877588
Test: Booted on a device running 4.14.
Change-Id: I5c1c136b775cceeb7f170e139e8d4279e73267a4
---
 private/llkd.te                 |  2 +-
 private/storaged.te             |  2 +-
 private/vold_prepare_subdirs.te |  2 +-
 private/zygote.te               |  2 +-
 public/dnsmasq.te               |  2 +-
 public/domain.te                | 53 +++++++++++++++++++--------------
 public/dumpstate.te             |  2 +-
 public/init.te                  |  2 +-
 public/install_recovery.te      |  2 +-
 public/installd.te              |  2 +-
 public/lmkd.te                  |  2 +-
 public/netd.te                  |  2 +-
 public/perfprofd.te             |  2 +-
 public/postinstall_dexopt.te    |  2 +-
 public/recovery.te              |  1 +
 public/runas.te                 |  2 +-
 public/sdcardd.te               |  2 +-
 public/ueventd.te               |  2 +-
 public/uncrypt.te               |  2 +-
 public/vendor_init.te           |  2 +-
 public/vold.te                  |  2 +-
 21 files changed, 50 insertions(+), 42 deletions(-)

diff --git a/private/llkd.te b/private/llkd.te
index 900d403f2..3f84eb6c1 100644
--- a/private/llkd.te
+++ b/private/llkd.te
@@ -8,7 +8,7 @@ get_prop(llkd, llkd_prop)
 allow llkd self:global_capability_class_set kill;
 userdebug_or_eng(`
   allow llkd self:global_capability_class_set sys_ptrace;
-  allow llkd self:global_capability_class_set dac_override;
+  allow llkd self:global_capability_class_set { dac_override dac_read_search };
 ')
 
 # llkd optionally locks itself in memory, to prevent it from being
diff --git a/private/storaged.te b/private/storaged.te
index b7321fda4..8f70531a7 100644
--- a/private/storaged.te
+++ b/private/storaged.te
@@ -48,7 +48,7 @@ allow storaged package_native_service:service_manager find;
 
 # Kernel does extra check on CAP_DAC_OVERRIDE for libbinder when storaged is
 # running as root. See b/35323867 #3.
-dontaudit storaged self:global_capability_class_set dac_override;
+dontaudit storaged self:global_capability_class_set { dac_override dac_read_search };
 
 # For collecting bugreports.
 allow storaged dumpstate:fifo_file write;
diff --git a/private/vold_prepare_subdirs.te b/private/vold_prepare_subdirs.te
index 0a115584a..0d062e991 100644
--- a/private/vold_prepare_subdirs.te
+++ b/private/vold_prepare_subdirs.te
@@ -7,7 +7,7 @@ allow vold_prepare_subdirs devpts:chr_file rw_file_perms;
 allow vold_prepare_subdirs vold:fd use;
 allow vold_prepare_subdirs vold:fifo_file { read write };
 allow vold_prepare_subdirs file_contexts_file:file r_file_perms;
-allow vold_prepare_subdirs self:global_capability_class_set { chown dac_override fowner };
+allow vold_prepare_subdirs self:global_capability_class_set { chown dac_override dac_read_search fowner };
 allow vold_prepare_subdirs self:process setfscreate;
 allow vold_prepare_subdirs {
   system_data_file
diff --git a/private/zygote.te b/private/zygote.te
index 610916e29..91c923019 100644
--- a/private/zygote.te
+++ b/private/zygote.te
@@ -7,7 +7,7 @@ init_daemon_domain(zygote)
 read_runtime_log_tags(zygote)
 
 # Override DAC on files and switch uid/gid.
-allow zygote self:global_capability_class_set { dac_override setgid setuid fowner chown };
+allow zygote self:global_capability_class_set { dac_override dac_read_search setgid setuid fowner chown };
 
 # Drop capabilities from bounding set.
 allow zygote self:global_capability_class_set setpcap;
diff --git a/public/dnsmasq.te b/public/dnsmasq.te
index 3aaefd3e6..e97e964e5 100644
--- a/public/dnsmasq.te
+++ b/public/dnsmasq.te
@@ -6,7 +6,7 @@ net_domain(dnsmasq)
 allowxperm dnsmasq self:udp_socket ioctl priv_sock_ioctls;
 
 # TODO:  Run with dhcp group to avoid need for dac_override.
-allow dnsmasq self:global_capability_class_set dac_override;
+allow dnsmasq self:global_capability_class_set { dac_override dac_read_search };
 
 allow dnsmasq self:global_capability_class_set { net_admin net_raw net_bind_service setgid setuid };
 
diff --git a/public/domain.te b/public/domain.te
index 670aa1a3b..1f38b7319 100644
--- a/public/domain.te
+++ b/public/domain.te
@@ -1377,29 +1377,36 @@ full_treble_only(`
 # Minimize dac_override and dac_read_search.
 # Instead of granting them it is usually better to add the domain to
 # a Unix group or change the permissions of a file.
-neverallow {
-  domain
-  -dnsmasq
-  -dumpstate
-  -init
-  -installd
-  -install_recovery
-  userdebug_or_eng(`-llkd')
-  -lmkd
-  -netd
-  -perfprofd
-  -postinstall_dexopt
-  -recovery
-  -sdcardd
-  -tee
-  -ueventd
-  -uncrypt
-  -vendor_init
-  -vold
-  -vold_prepare_subdirs
-  -zygote
-} self:global_capability_class_set dac_override;
-neverallow { domain -traced_probes } self:global_capability_class_set dac_read_search;
+define(`dac_override_allowed', `{
+  dnsmasq
+  dumpstate
+  init
+  installd
+  install_recovery
+  userdebug_or_eng(`llkd')
+  lmkd
+  netd
+  perfprofd
+  postinstall_dexopt
+  recovery
+  sdcardd
+  tee
+  ueventd
+  uncrypt
+  vendor_init
+  vold
+  vold_prepare_subdirs
+  zygote
+}')
+neverallow ~dac_override_allowed self:global_capability_class_set dac_override;
+# Since the kernel checks dac_read_search before dac_override, domains that
+# have dac_override should also have dac_read_search to eliminate spurious
+# denials.  Some domains have dac_read_search without having dac_override, so
+# this list should be a superset of the one above.
+neverallow ~{
+  dac_override_allowed
+  traced_probes
+} self:global_capability_class_set dac_read_search;
 
 # If an already existing file is opened with O_CREAT, the kernel might generate
 # a false report of a create denial. Silence these denials and make sure that
diff --git a/public/dumpstate.te b/public/dumpstate.te
index e7fa83f0c..295217dfd 100644
--- a/public/dumpstate.te
+++ b/public/dumpstate.te
@@ -33,7 +33,7 @@ allow dumpstate toolbox_exec:file rx_file_perms;
 allow dumpstate system_file:dir r_dir_perms;
 
 # Create and write into /data/anr/
-allow dumpstate self:global_capability_class_set { dac_override chown fowner fsetid };
+allow dumpstate self:global_capability_class_set { dac_override dac_read_search chown fowner fsetid };
 allow dumpstate anr_data_file:dir rw_dir_perms;
 allow dumpstate anr_data_file:file create_file_perms;
 
diff --git a/public/init.te b/public/init.te
index d898603c8..36d9800ea 100644
--- a/public/init.te
+++ b/public/init.te
@@ -105,7 +105,7 @@ allow init metadata_file:dir mounton;
 allow init tmpfs:dir relabelfrom;
 
 # Create directories under /dev/cpuctl after chowning it to system.
-allow init self:global_capability_class_set dac_override;
+allow init self:global_capability_class_set { dac_override dac_read_search };
 
 # Set system clock.
 allow init self:global_capability_class_set sys_time;
diff --git a/public/install_recovery.te b/public/install_recovery.te
index ab688386e..24819c2ea 100644
--- a/public/install_recovery.te
+++ b/public/install_recovery.te
@@ -2,7 +2,7 @@
 type install_recovery, domain;
 type install_recovery_exec, exec_type, file_type;
 
-allow install_recovery self:global_capability_class_set dac_override;
+allow install_recovery self:global_capability_class_set { dac_override dac_read_search };
 
 # /system/bin/install-recovery.sh is a shell script.
 # Needs to execute /system/bin/sh
diff --git a/public/installd.te b/public/installd.te
index 8d7301bcd..12495c435 100644
--- a/public/installd.te
+++ b/public/installd.te
@@ -2,7 +2,7 @@
 type installd, domain;
 type installd_exec, exec_type, file_type;
 typeattribute installd mlstrustedsubject;
-allow installd self:global_capability_class_set { chown dac_override fowner fsetid setgid setuid sys_admin };
+allow installd self:global_capability_class_set { chown dac_override dac_read_search fowner fsetid setgid setuid sys_admin };
 
 # Allow labeling of files under /data/app/com.example/oat/
 allow installd dalvikcache_data_file:dir relabelto;
diff --git a/public/lmkd.te b/public/lmkd.te
index a82e0a068..2eb2ccaca 100644
--- a/public/lmkd.te
+++ b/public/lmkd.te
@@ -2,7 +2,7 @@
 type lmkd, domain, mlstrustedsubject;
 type lmkd_exec, exec_type, file_type;
 
-allow lmkd self:global_capability_class_set { dac_override sys_resource kill };
+allow lmkd self:global_capability_class_set { dac_override dac_read_search sys_resource kill };
 
 # lmkd locks itself in memory, to prevent it from being
 # swapped out and unable to kill other memory hogs.
diff --git a/public/netd.te b/public/netd.te
index 1315398c0..a4a65a98c 100644
--- a/public/netd.te
+++ b/public/netd.te
@@ -61,7 +61,7 @@ allow netd fs_bpf:file create_file_perms;
 # TODO: netd previously thought it needed these permissions to do WiFi related
 #       work.  However, after all the WiFi stuff is gone, we still need them.
 #       Why?
-allow netd self:global_capability_class_set { dac_override chown };
+allow netd self:global_capability_class_set { dac_override dac_read_search chown };
 
 # Needed to update /data/misc/net/rt_tables
 allow netd net_data_file:file create_file_perms;
diff --git a/public/perfprofd.te b/public/perfprofd.te
index 83a1319b8..f780a0db7 100644
--- a/public/perfprofd.te
+++ b/public/perfprofd.te
@@ -23,7 +23,7 @@ userdebug_or_eng(`
   # perfprofd reads a config file from /data/data/com.google.android.gms/files
   allow perfprofd { privapp_data_file app_data_file }:file r_file_perms;
   allow perfprofd { privapp_data_file app_data_file }:dir search;
-  allow perfprofd self:global_capability_class_set { dac_override };
+  allow perfprofd self:global_capability_class_set { dac_override dac_read_search };
 
   # perfprofd opens a file for writing in /data/misc/perfprofd
   allow perfprofd perfprofd_data_file:file create_file_perms;
diff --git a/public/postinstall_dexopt.te b/public/postinstall_dexopt.te
index ffd8bc574..8b6d6cc17 100644
--- a/public/postinstall_dexopt.te
+++ b/public/postinstall_dexopt.te
@@ -5,7 +5,7 @@
 
 type postinstall_dexopt, domain;
 
-allow postinstall_dexopt self:global_capability_class_set { chown dac_override fowner fsetid setgid setuid };
+allow postinstall_dexopt self:global_capability_class_set { chown dac_override dac_read_search fowner fsetid setgid setuid };
 
 allow postinstall_dexopt postinstall_file:filesystem getattr;
 allow postinstall_dexopt postinstall_file:dir { getattr search };
diff --git a/public/recovery.te b/public/recovery.te
index 130f4a2c1..9db6f5ef8 100644
--- a/public/recovery.te
+++ b/public/recovery.te
@@ -15,6 +15,7 @@ recovery_only(`
   allow recovery self:global_capability_class_set {
     chown
     dac_override
+    dac_read_search
     fowner
     setuid
     setgid
diff --git a/public/runas.te b/public/runas.te
index 053a87f6b..6c5de7cf8 100644
--- a/public/runas.te
+++ b/public/runas.te
@@ -18,7 +18,7 @@ allow runas system_data_file:lnk_file getattr;
 allow runas system_data_file:lnk_file read;
 
 # run-as checks and changes to the app data dir.
-dontaudit runas self:global_capability_class_set dac_override;
+dontaudit runas self:global_capability_class_set { dac_override dac_read_search };
 allow runas app_data_file:dir { getattr search };
 
 # run-as switches to the app UID/GID.
diff --git a/public/sdcardd.te b/public/sdcardd.te
index 4a88f54d0..6749d16e5 100644
--- a/public/sdcardd.te
+++ b/public/sdcardd.te
@@ -10,7 +10,7 @@ allow sdcardd mnt_media_rw_file:dir r_dir_perms;
 allow sdcardd storage_file:dir search;
 allow sdcardd storage_stub_file:dir { search mounton };
 allow sdcardd sdcard_type:filesystem { mount unmount };
-allow sdcardd self:global_capability_class_set { setuid setgid dac_override sys_admin sys_resource };
+allow sdcardd self:global_capability_class_set { setuid setgid dac_override dac_read_search sys_admin sys_resource };
 
 allow sdcardd sdcard_type:dir create_dir_perms;
 allow sdcardd sdcard_type:file create_file_perms;
diff --git a/public/ueventd.te b/public/ueventd.te
index dfd4f2ca1..0863302dd 100644
--- a/public/ueventd.te
+++ b/public/ueventd.te
@@ -5,7 +5,7 @@ type ueventd, domain;
 # Write to /dev/kmsg.
 allow ueventd kmsg_device:chr_file rw_file_perms;
 
-allow ueventd self:global_capability_class_set { chown mknod net_admin setgid fsetid sys_rawio dac_override fowner };
+allow ueventd self:global_capability_class_set { chown mknod net_admin setgid fsetid sys_rawio dac_override dac_read_search fowner };
 allow ueventd device:file create_file_perms;
 
 r_dir_file(ueventd, rootfs)
diff --git a/public/uncrypt.te b/public/uncrypt.te
index 367498028..a0fb37228 100644
--- a/public/uncrypt.te
+++ b/public/uncrypt.te
@@ -2,7 +2,7 @@
 type uncrypt, domain, mlstrustedsubject;
 type uncrypt_exec, exec_type, file_type;
 
-allow uncrypt self:global_capability_class_set dac_override;
+allow uncrypt self:global_capability_class_set { dac_override dac_read_search };
 
 userdebug_or_eng(`
   # For debugging, allow /data/local/tmp access
diff --git a/public/vendor_init.te b/public/vendor_init.te
index 007c563dc..e28ce1cd5 100644
--- a/public/vendor_init.te
+++ b/public/vendor_init.te
@@ -22,7 +22,7 @@ allow vendor_init configfs:dir create_dir_perms;
 allow vendor_init configfs:{ file lnk_file } create_file_perms;
 
 # Create directories under /dev/cpuctl after chowning it to system.
-allow vendor_init self:global_capability_class_set dac_override;
+allow vendor_init self:global_capability_class_set { dac_override dac_read_search };
 
 # mkdir, symlink, write, rm/rmdir, chown/chmod, restorecon/restorecon_recursive from init.rc files.
 # chown/chmod require open+read+setattr required for open()+fchown/fchmod().
diff --git a/public/vold.te b/public/vold.te
index e40c251b1..604c104e8 100644
--- a/public/vold.te
+++ b/public/vold.te
@@ -79,7 +79,7 @@ allow vold shell_data_file:dir { create getattr setattr };
 allow vold tmpfs:filesystem { mount unmount };
 allow vold tmpfs:dir create_dir_perms;
 allow vold tmpfs:dir mounton;
-allow vold self:global_capability_class_set { net_admin dac_override mknod sys_admin chown fowner fsetid };
+allow vold self:global_capability_class_set { net_admin dac_override dac_read_search mknod sys_admin chown fowner fsetid };
 allow vold self:netlink_kobject_uevent_socket create_socket_perms_no_ioctl;
 # TODO(b/80418809): remove direct access to private app data
 userdebug_or_eng(`auditallow vold { app_data_file privapp_data_file }:dir search;')
-- 
GitLab