From 94c88932d8a8e77ea13f6c210f3cfa656b5ce598 Mon Sep 17 00:00:00 2001
From: Nick Kralevich <nnk@google.com>
Date: Tue, 27 Nov 2018 13:45:47 -0800
Subject: [PATCH] Add compile time check for expanded attribute neverallow
 failure

The SELinux policy language supports an expandattribute statement.
Similar to the C "inline" declaration, this expands the permissions
associated with types, instead of using the attribute directly. Please
see
https://android.googlesource.com/platform/external/selinux/+/1089665e31a647a5f0ba2eabe8ac6232b384bed9
for more detail on this language option.

Expansion of attributes causes consistency problems with CTS. If a
neverallow rule exists which refers to an expanded attribute, the CTS
neverallow test will fail, because the policy does not have the
attribute embedded in it. Examples:

  * b/119783042 (fixed in 536d3413b84c4340f9d8cea96a3239490784169f)
  * b/67296580 (fixed in 6f7e8609f9f79877f818b231b8b0b8b906483780)
  * b/63809360 (fixed in 89f215e6a0985e746f1993ed047c1971201db529)
  etc...

Instead of waiting for the CTS test to fail, modify the Android.mk file
so that we do checks similar to CTS. This allows us to fail at compile
time instead of waiting for a CTS bug. For example, for b/119783042,
instead of the compile succeeding, it will now fail with the following
error message:

  [ 70% 190/268] build out/target/product/crosshatch/obj/ETC/sepolicy_neverallows_intermediates/sepolicy_neverallows
  FAILED: out/target/product/crosshatch/obj/ETC/sepolicy_neverallows_intermediates/sepolicy_neverallows
  /bin/bash -c "(ASAN_OPTIONS=detect_leaks=0 out/host/linux-x86/bin/checkpolicy -M -c
  30 -o out/target/product/crosshatch/obj/ETC/sepolicy_neverallows_intermediates/sepolicy_neverallows.tmp
  out/target/product/crosshatch/obj/ETC/sepolicy_neverallows_intermediates/policy.conf ) &&
  (out/host/linux-x86/bin/sepolicy-analyze
  out/target/product/crosshatch/obj/ETC/sepolicy_neverallows_intermediates/sepolicy_neverallows.tmp
  neverallow -w -f out/target/product/crosshatch/obj/ETC/sepolicy_neverallows_intermediates/policy_2.conf
  || 	  ( echo \"\" 1>&2; echo \"sepolicy-analyze failed. This is most likely due to the use\" 1>&2;
  echo \"of an expanded attribute in a neverallow assertion. Please fix\" 1>&2;
  echo \"the policy.\" 1>&2; exit 1 ) ) &&
  (touch out/target/product/crosshatch/obj/ETC/sepolicy_neverallows_intermediates/sepolicy_neverallows.tmp )
  && (mv out/target/product/crosshatch/obj/ETC/sepolicy_neverallows_intermediates/sepolicy_neverallows.tmp
  out/target/product/crosshatch/obj/ETC/sepolicy_neverallows_intermediates/sepolicy_neverallows )"
  libsepol.report_failure: neverallow violated by allow vold hal_bootctl_default:binder { call };
  libsepol.check_assertions: 1 neverallow failures occurred

  sepolicy-analyze failed. This is most likely due to the use
  of an expanded attribute in a neverallow assertion. Please fix
  the policy.
  15:44:27 ninja failed with: exit status 1

Test: Revert 536d3413b84c4340f9d8cea96a3239490784169f and verify compile
      fails as above.
Test: Compile succeeds
Bug: 119783042

Change-Id: I5df405b337bb744b838dadf53a2234d8ed94bf39
---
 Android.mk | 35 ++++++++++++++++++++++++++++++-----
 1 file changed, 30 insertions(+), 5 deletions(-)

diff --git a/Android.mk b/Android.mk
index 9a41e8c19..9900bfb90 100644
--- a/Android.mk
+++ b/Android.mk
@@ -307,16 +307,41 @@ $(PLAT_PUBLIC_POLICY) $(PLAT_PRIVATE_POLICY) $(PLAT_VENDOR_POLICY) $(BOARD_SEPOL
 	$(transform-policy-to-conf)
 	$(hide) sed '/^\s*dontaudit.*;/d' $@ | sed '/^\s*dontaudit/,/;/d' > $@.dontaudit
 
-$(LOCAL_BUILT_MODULE): $(sepolicy_policy.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy
-	rm -f $@
+# sepolicy_policy_2.conf - All of the policy for the device.  This is only used to
+# check neverallow rules using sepolicy-analyze, similar to CTS.
+sepolicy_policy_2.conf := $(intermediates)/policy_2.conf
+$(sepolicy_policy_2.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
+$(sepolicy_policy_2.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
+$(sepolicy_policy_2.conf): PRIVATE_TARGET_BUILD_VARIANT := user
+$(sepolicy_policy_2.conf): PRIVATE_EXCLUDE_BUILD_TEST := true
+$(sepolicy_policy_2.conf): PRIVATE_TGT_ARCH := $(my_target_arch)
+$(sepolicy_policy_2.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan)
+$(sepolicy_policy_2.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
+$(sepolicy_policy_2.conf): PRIVATE_SEPOLICY_SPLIT := $(PRODUCT_SEPOLICY_SPLIT)
+$(sepolicy_policy_2.conf): $(call build_policy, $(sepolicy_build_files), \
+$(PLAT_PUBLIC_POLICY) $(PLAT_PRIVATE_POLICY) $(PLAT_VENDOR_POLICY) $(BOARD_SEPOLICY_DIRS))
+	$(transform-policy-to-conf)
+	$(hide) sed '/^\s*dontaudit.*;/d' $@ | sed '/^\s*dontaudit/,/;/d' > $@.dontaudit
+
+$(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY_1 := $(sepolicy_policy.conf)
+$(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY_2 := $(sepolicy_policy_2.conf)
+$(LOCAL_BUILT_MODULE): $(sepolicy_policy.conf) $(sepolicy_policy_2.conf) \
+  $(HOST_OUT_EXECUTABLES)/checkpolicy $(HOST_OUT_EXECUTABLES)/sepolicy-analyze
 ifneq ($(SELINUX_IGNORE_NEVERALLOWS),true)
 	$(hide) $(CHECKPOLICY_ASAN_OPTIONS) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -c \
-		$(POLICYVERS) -o $@ $<
-else # ($(SELINUX_IGNORE_NEVERALLOWS),true)
-	$(hide) touch $@
+		$(POLICYVERS) -o $@.tmp $(PRIVATE_SEPOLICY_1)
+	$(hide) $(HOST_OUT_EXECUTABLES)/sepolicy-analyze $@.tmp neverallow -w -f $(PRIVATE_SEPOLICY_2) || \
+	  ( echo "" 1>&2; \
+	    echo "sepolicy-analyze failed. This is most likely due to the use" 1>&2; \
+	    echo "of an expanded attribute in a neverallow assertion. Please fix" 1>&2; \
+	    echo "the policy." 1>&2; \
+	    exit 1 )
 endif # ($(SELINUX_IGNORE_NEVERALLOWS),true)
+	$(hide) touch $@.tmp
+	$(hide) mv $@.tmp $@
 
 sepolicy_policy.conf :=
+sepolicy_policy_2.conf :=
 built_sepolicy_neverallows := $(LOCAL_BUILT_MODULE)
 
 ##################################
-- 
GitLab