Migrate neverallow tests to Android.bp

A new module type se_neverallow_test is added, to migrate
sepolicy_neverallow modules. se_neverallow_test is affected by
SELINUX_IGNORE_NEVERALLOWS.

Bug: 33691272
Test: m selinux_policy
Test: intentionally create neverallow violations and m selinux_policy
Change-Id: I1582353f99f064ff78f3c547a0c13f2b772d54df
This commit is contained in:
Inseob Kim 2021-12-22 23:06:53 +09:00
parent 96c5222c94
commit 0de7fcc33a
4 changed files with 214 additions and 159 deletions

View file

@ -811,6 +811,10 @@ precompiled_se_policy_binary {
},
},
},
required: [
"sepolicy_neverallows",
"sepolicy_neverallows_vendor",
],
}
//////////////////////////////////
@ -987,6 +991,25 @@ se_bug_map {
vendor: true,
}
se_neverallow_test {
name: "sepolicy_neverallows",
srcs: plat_public_policy +
plat_private_policy +
system_ext_public_policy +
system_ext_private_policy +
product_public_policy +
product_private_policy,
}
se_neverallow_test {
name: "sepolicy_neverallows_vendor",
srcs: plat_policies_for_vendor + [
":se_build_files{.plat_vendor_for_vendor}",
":se_build_files{.vendor}",
":se_build_files{.odm}",
],
}
//////////////////////////////////
// se_freeze_test compares the plat sepolicy with the prebuilt sepolicy
// Additional directories can be specified via Makefile variables:

View file

@ -549,165 +549,8 @@ product_public_policy_$(PLATFORM_SEPOLICY_VERSION) := $(PRODUCT_PUBLIC_POLICY)
product_private_policy_$(PLATFORM_SEPOLICY_VERSION) := $(PRODUCT_PRIVATE_POLICY)
endif
#################################
include $(CLEAR_VARS)
LOCAL_MODULE := sepolicy_neverallows
LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 legacy_unencumbered
LOCAL_LICENSE_CONDITIONS := notice unencumbered
LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
LOCAL_MODULE_CLASS := FAKE
LOCAL_MODULE_TAGS := optional
include $(BUILD_SYSTEM)/base_rules.mk
# sepolicy_policy.conf - All of the policy for the device. This is only used to
# check neverallow rules.
# In a mixed build target, vendor policies are checked separately, on the module
# sepolicy_neverallows_vendor.
all_plat_policy := $(PLAT_PUBLIC_POLICY) $(PLAT_PRIVATE_POLICY) $(PLAT_VENDOR_POLICY) \
$(SYSTEM_EXT_PUBLIC_POLICY) $(SYSTEM_EXT_PRIVATE_POLICY) \
$(PRODUCT_PUBLIC_POLICY) $(PRODUCT_PRIVATE_POLICY)
ifeq ($(mixed_sepolicy_build),true)
policy_files := $(call build_policy, $(sepolicy_build_files), $(all_plat_policy))
else
policy_files := $(call build_policy, $(sepolicy_build_files), \
$(all_plat_policy) $(BOARD_VENDOR_SEPOLICY_DIRS) $(BOARD_ODM_SEPOLICY_DIRS))
endif
sepolicy_policy.conf := $(intermediates)/policy.conf
$(sepolicy_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
$(sepolicy_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
$(sepolicy_policy.conf): PRIVATE_TARGET_BUILD_VARIANT := user
$(sepolicy_policy.conf): PRIVATE_TGT_ARCH := $(my_target_arch)
$(sepolicy_policy.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan)
$(sepolicy_policy.conf): PRIVATE_TGT_WITH_NATIVE_COVERAGE := $(with_native_coverage)
$(sepolicy_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
$(sepolicy_policy.conf): PRIVATE_SEPOLICY_SPLIT := $(PRODUCT_SEPOLICY_SPLIT)
$(sepolicy_policy.conf): PRIVATE_ENFORCE_DEBUGFS_RESTRICTION := $(enforce_debugfs_restriction)
$(sepolicy_policy.conf): PRIVATE_POLICY_FILES := $(policy_files)
$(sepolicy_policy.conf): $(policy_files) $(M4)
$(transform-policy-to-conf)
$(hide) sed '/^\s*dontaudit.*;/d' $@ | sed '/^\s*dontaudit/,/;/d' > $@.dontaudit
# 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_TGT_WITH_NATIVE_COVERAGE := $(with_native_coverage)
$(sepolicy_policy_2.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
$(sepolicy_policy_2.conf): PRIVATE_SEPOLICY_SPLIT := $(PRODUCT_SEPOLICY_SPLIT)
$(sepolicy_policy_2.conf): PRIVATE_ENFORCE_DEBUGFS_RESTRICTION := $(enforce_debugfs_restriction)
$(sepolicy_policy_2.conf): PRIVATE_POLICY_FILES := $(policy_files)
$(sepolicy_policy_2.conf): $(policy_files) $(M4)
$(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 $@.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)
#################################
# sepolicy_neverallows_vendor: neverallow check module for vendors in a mixed build target
ifeq ($(mixed_sepolicy_build),true)
include $(CLEAR_VARS)
LOCAL_MODULE := sepolicy_neverallows_vendor
LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 legacy_unencumbered
LOCAL_LICENSE_CONDITIONS := notice unencumbered
LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
LOCAL_MODULE_CLASS := FAKE
LOCAL_MODULE_TAGS := optional
include $(BUILD_SYSTEM)/base_rules.mk
# Check neverallow with prebuilt policy files
policy_files := $(call build_policy, $(sepolicy_build_files), \
$(plat_public_policy_$(BOARD_SEPOLICY_VERS)) $(plat_private_policy_$(BOARD_SEPOLICY_VERS)) \
$(system_ext_public_policy_$(BOARD_SEPOLICY_VERS)) $(system_ext_private_policy_$(BOARD_SEPOLICY_VERS)) \
$(product_public_policy_$(BOARD_SEPOLICY_VERS)) $(product_private_policy_$(BOARD_SEPOLICY_VERS)) \
$(BOARD_PLAT_VENDOR_POLICY) $(BOARD_VENDOR_SEPOLICY_DIRS) $(BOARD_ODM_SEPOLICY_DIRS))
# sepolicy_policy.conf - All of the policy for the device. This is only used to
# check neverallow rules.
sepolicy_policy.conf := $(intermediates)/policy_vendor.conf
$(sepolicy_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
$(sepolicy_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
$(sepolicy_policy.conf): PRIVATE_TARGET_BUILD_VARIANT := user
$(sepolicy_policy.conf): PRIVATE_TGT_ARCH := $(my_target_arch)
$(sepolicy_policy.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan)
$(sepolicy_policy.conf): PRIVATE_TGT_WITH_NATIVE_COVERAGE := $(with_native_coverage)
$(sepolicy_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
$(sepolicy_policy.conf): PRIVATE_SEPOLICY_SPLIT := $(PRODUCT_SEPOLICY_SPLIT)
$(sepolicy_policy.conf): PRIVATE_ENFORCE_DEBUGFS_RESTRICTION := $(enforce_debugfs_restriction)
$(sepolicy_policy.conf): PRIVATE_POLICY_FILES := $(policy_files)
$(sepolicy_policy.conf): $(policy_files) $(M4)
$(transform-policy-to-conf)
$(hide) sed '/^\s*dontaudit.*;/d' $@ | sed '/^\s*dontaudit/,/;/d' > $@.dontaudit
# 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_vendor_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_TGT_WITH_NATIVE_COVERAGE := $(with_native_coverage)
$(sepolicy_policy_2.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
$(sepolicy_policy_2.conf): PRIVATE_SEPOLICY_SPLIT := $(PRODUCT_SEPOLICY_SPLIT)
$(sepolicy_policy_2.conf): PRIVATE_ENFORCE_DEBUGFS_RESTRICTION := $(enforce_debugfs_restriction)
$(sepolicy_policy_2.conf): PRIVATE_POLICY_FILES := $(policy_files)
$(sepolicy_policy_2.conf): $(policy_files) $(M4)
$(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 $@.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)
endif # ifeq ($(mixed_sepolicy_build),true)
built_sepolicy_neverallows := $(call intermediates-dir-for,ETC,sepolicy_neverallows)/sepolicy_neverallows
built_sepolicy_neverallows += $(call intermediates-dir-for,ETC,sepolicy_neverallows_vendor)/sepolicy_neverallows_vendor
##################################
# Policy files are now built with Android.bp. Grab them from intermediate.

View file

@ -36,6 +36,7 @@ bootstrap_go_package {
"cil_compat_map.go",
"compat_cil.go",
"filegroup.go",
"neverallow_test.go",
"policy.go",
"selinux.go",
"selinux_contexts.go",

View file

@ -0,0 +1,188 @@
// Copyright 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package selinux
import (
"github.com/google/blueprint/proptools"
"fmt"
"strconv"
"android/soong/android"
)
func init() {
ctx := android.InitRegistrationContext
ctx.RegisterModuleType("se_neverallow_test", neverallowTestFactory)
}
type neverallowTestProperties struct {
// Policy files to be tested.
Srcs []string `android:"path"`
}
type neverallowTestModule struct {
android.ModuleBase
properties neverallowTestProperties
testTimestamp android.ModuleOutPath
}
type nameProperties struct {
Name *string
}
var checkpolicyTag = dependencyTag{name: "checkpolicy"}
var sepolicyAnalyzeTag = dependencyTag{name: "sepolicy_analyze"}
// se_neverallow_test builds given policy files and checks whether any neverallow violations exist.
// This module creates two conf files, one with build test and one without build test. Policy with
// build test will be compiled with checkpolicy, and policy without build test will be tested with
// sepolicy-analyze's neverallow tool. This module's check can be skipped by setting
// SELINUX_IGNORE_NEVERALLOWS := true.
func neverallowTestFactory() android.Module {
n := &neverallowTestModule{}
n.AddProperties(&n.properties)
android.InitAndroidModule(n)
android.AddLoadHook(n, func(ctx android.LoadHookContext) {
n.loadHook(ctx)
})
return n
}
// Child conf module name for checkpolicy test.
func (n *neverallowTestModule) checkpolicyConfModuleName() string {
return n.Name() + ".checkpolicy.conf"
}
// Child conf module name for sepolicy-analyze test.
func (n *neverallowTestModule) sepolicyAnalyzeConfModuleName() string {
return n.Name() + ".sepolicy_analyze.conf"
}
func (n *neverallowTestModule) loadHook(ctx android.LoadHookContext) {
checkpolicyConf := n.checkpolicyConfModuleName()
ctx.CreateModule(policyConfFactory, &nameProperties{
Name: proptools.StringPtr(checkpolicyConf),
}, &policyConfProperties{
Srcs: n.properties.Srcs,
Build_variant: proptools.StringPtr("user"),
Installable: proptools.BoolPtr(false),
})
sepolicyAnalyzeConf := n.sepolicyAnalyzeConfModuleName()
ctx.CreateModule(policyConfFactory, &nameProperties{
Name: proptools.StringPtr(sepolicyAnalyzeConf),
}, &policyConfProperties{
Srcs: n.properties.Srcs,
Build_variant: proptools.StringPtr("user"),
Exclude_build_test: proptools.BoolPtr(true),
Installable: proptools.BoolPtr(false),
})
}
func (n *neverallowTestModule) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddDependency(n, checkpolicyTag, n.checkpolicyConfModuleName())
ctx.AddDependency(n, sepolicyAnalyzeTag, n.sepolicyAnalyzeConfModuleName())
}
func (n *neverallowTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
n.testTimestamp = android.PathForModuleOut(ctx, "timestamp")
if ctx.Config().SelinuxIgnoreNeverallows() {
// just touch
android.WriteFileRule(ctx, n.testTimestamp, "")
return
}
var checkpolicyConfPaths android.Paths
var sepolicyAnalyzeConfPaths android.Paths
ctx.VisitDirectDeps(func(child android.Module) {
depTag := ctx.OtherModuleDependencyTag(child)
if depTag != checkpolicyTag && depTag != sepolicyAnalyzeTag {
return
}
o, ok := child.(android.OutputFileProducer)
if !ok {
panic(fmt.Errorf("Module %q isn't an OutputFileProducer", ctx.OtherModuleName(child)))
}
outputs, err := o.OutputFiles("")
if err != nil {
panic(fmt.Errorf("Module %q error while producing output: %v", ctx.OtherModuleName(child), err))
}
switch ctx.OtherModuleDependencyTag(child) {
case checkpolicyTag:
checkpolicyConfPaths = outputs
case sepolicyAnalyzeTag:
sepolicyAnalyzeConfPaths = outputs
}
})
if len(checkpolicyConfPaths) != 1 {
panic(fmt.Errorf("Module %q should produce exactly one output", n.checkpolicyConfModuleName()))
}
if len(sepolicyAnalyzeConfPaths) != 1 {
panic(fmt.Errorf("Module %q should produce exactly one output", n.sepolicyAnalyzeConfModuleName()))
}
checkpolicyConfPath := checkpolicyConfPaths[0]
sepolicyAnalyzeConfPath := sepolicyAnalyzeConfPaths[0]
rule := android.NewRuleBuilder(pctx, ctx)
// Step 1. Build a binary policy from the conf file including build test
binaryPolicy := android.PathForModuleOut(ctx, "policy")
rule.Command().BuiltTool("checkpolicy").
Flag("-M").
FlagWithArg("-c ", strconv.Itoa(PolicyVers)).
FlagWithOutput("-o ", binaryPolicy).
Input(checkpolicyConfPath)
// Step 2. Run sepolicy-analyze with the conf file without the build test and binary policy
// file from Step 1
msg := `sepolicy-analyze failed. This is most likely due to the use\n` +
`of an expanded attribute in a neverallow assertion. Please fix\n` +
`the policy.`
rule.Command().BuiltTool("sepolicy-analyze").
Input(binaryPolicy).
Text("neverallow").
Flag("-w").
FlagWithInput("-f ", sepolicyAnalyzeConfPath).
Text("|| (echo").
Flag("-e").
Text(`"` + msg + `"`).
Text("; exit 1)")
rule.Temporary(binaryPolicy)
rule.Command().Text("touch").Output(n.testTimestamp)
rule.Build("neverallow", "Neverallow check: "+ctx.ModuleName())
}
func (n *neverallowTestModule) AndroidMkEntries() []android.AndroidMkEntries {
return []android.AndroidMkEntries{android.AndroidMkEntries{
OutputFile: android.OptionalPathForPath(n.testTimestamp),
Class: "ETC",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
},
},
}}
}