diff --git a/Android.bp b/Android.bp index 4d4fb99b7..cdf9b6b4c 100644 --- a/Android.bp +++ b/Android.bp @@ -1003,3 +1003,12 @@ se_policy_conf { cts: true, exclude_build_test: true, } + +////////////////////////////////// +// se_freeze_test compares the plat sepolicy with the prebuilt sepolicy +// Additional directories can be specified via Makefile variables: +// SEPOLICY_FREEZE_TEST_EXTRA_DIRS and SEPOLICY_FREEZE_TEST_EXTRA_PREBUILT_DIRS. +////////////////////////////////// +se_freeze_test { + name: "sepolicy_freeze_test", +} diff --git a/Android.mk b/Android.mk index 4f595f54e..cc9fe55ba 100644 --- a/Android.mk +++ b/Android.mk @@ -67,10 +67,6 @@ endif PRODUCT_PUBLIC_POLICY := $(PRODUCT_PUBLIC_SEPOLICY_DIRS) PRODUCT_PRIVATE_POLICY := $(PRODUCT_PRIVATE_SEPOLICY_DIRS) -# Extra sepolicy and prebuilts directories for sepolicy_freeze_test -FREEZE_TEST_EXTRA_DIRS := $(SEPOLICY_FREEZE_TEST_EXTRA_DIRS) -FREEZE_TEST_EXTRA_PREBUILT_DIRS := $(SEPOLICY_FREEZE_TEST_EXTRA_PREBUILT_DIRS) - ifneq (,$(SYSTEM_EXT_PUBLIC_POLICY)$(SYSTEM_EXT_PRIVATE_POLICY)) HAS_SYSTEM_EXT_SEPOLICY_DIR := true endif @@ -413,13 +409,7 @@ endif # with_asan ifneq ($(PLATFORM_SEPOLICY_VERSION),$(TOT_SEPOLICY_VERSION)) LOCAL_REQUIRED_MODULES += \ - sepolicy_freeze_test \ - -else -ifneq (,$(FREEZE_TEST_EXTRA_DIRS)$(FREEZE_TEST_EXTRA_PREBUILT_DIRS)) -$(error SEPOLICY_FREEZE_TEST_EXTRA_DIRS or SEPOLICY_FREEZE_TEST_EXTRA_PREBUILT_DIRS\ -cannot be set before system/sepolicy freezes.) -endif # (,$(FREEZE_TEST_EXTRA_DIRS)$(FREEZE_TEST_EXTRA_PREBUILT_DIRS)) + sepolicy_freeze_test endif # ($(PLATFORM_SEPOLICY_VERSION),$(TOT_SEPOLICY_VERSION)) include $(BUILD_PHONY_PACKAGE) @@ -1540,55 +1530,6 @@ plat_sepolicy := all_fc_files := all_fc_args := -################################# -include $(CLEAR_VARS) -LOCAL_MODULE := sepolicy_freeze_test -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 - -define ziplist -$(if $(and $1,$2), "$(firstword $1) $(firstword $2)"\ - $(call ziplist,$(wordlist 2,$(words $1),$1),$(wordlist 2,$(words $2),$2))) -endef - -base_plat_public := $(LOCAL_PATH)/public -base_plat_private := $(LOCAL_PATH)/private -base_plat_public_prebuilt := \ - $(LOCAL_PATH)/prebuilts/api/$(PLATFORM_SEPOLICY_VERSION)/public -base_plat_private_prebuilt := \ - $(LOCAL_PATH)/prebuilts/api/$(PLATFORM_SEPOLICY_VERSION)/private - -all_frozen_files := $(call build_policy,$(sepolicy_build_files), \ -$(base_plat_public) $(base_plat_private) $(base_plat_public_prebuilt) $(base_plat_private_prebuilt)) - -$(LOCAL_BUILT_MODULE): PRIVATE_BASE_PLAT_PUBLIC := $(base_plat_public) -$(LOCAL_BUILT_MODULE): PRIVATE_BASE_PLAT_PRIVATE := $(base_plat_private) -$(LOCAL_BUILT_MODULE): PRIVATE_BASE_PLAT_PUBLIC_PREBUILT := $(base_plat_public_prebuilt) -$(LOCAL_BUILT_MODULE): PRIVATE_BASE_PLAT_PRIVATE_PREBUILT := $(base_plat_private_prebuilt) -$(LOCAL_BUILT_MODULE): PRIVATE_EXTRA := $(sort $(FREEZE_TEST_EXTRA_DIRS)) -$(LOCAL_BUILT_MODULE): PRIVATE_EXTRA_PREBUILT := $(sort $(FREEZE_TEST_EXTRA_PREBUILT_DIRS)) -$(LOCAL_BUILT_MODULE): $(all_frozen_files) -ifneq ($(PLATFORM_SEPOLICY_VERSION),$(TOT_SEPOLICY_VERSION)) - @diff -rq -x bug_map $(PRIVATE_BASE_PLAT_PUBLIC_PREBUILT) $(PRIVATE_BASE_PLAT_PUBLIC) - @diff -rq -x bug_map $(PRIVATE_BASE_PLAT_PRIVATE_PREBUILT) $(PRIVATE_BASE_PLAT_PRIVATE) -ifneq (,$(FREEZE_TEST_EXTRA_DIRS)$(FREEZE_TEST_EXTRA_PREBUILT_DIRS)) - @for pair in $(call ziplist, $(PRIVATE_EXTRA_PREBUILT), $(PRIVATE_EXTRA)); \ - do diff -rq -x bug_map $$pair; done -endif # (,$(FREEZE_TEST_EXTRA_DIRS)$(FREEZE_TEST_EXTRA_PREBUILT_DIRS)) -endif # ($(PLATFORM_SEPOLICY_VERSION),$(TOT_SEPOLICY_VERSION)) - $(hide) touch $@ - -base_plat_public := -base_plat_private := -base_plat_public_prebuilt := -base_plat_private_prebuilt := -all_frozen_files := - ################################# diff --git a/build/soong/Android.bp b/build/soong/Android.bp index 228211253..3126430b6 100644 --- a/build/soong/Android.bp +++ b/build/soong/Android.bp @@ -38,6 +38,7 @@ bootstrap_go_package { "policy.go", "selinux.go", "selinux_contexts.go", + "sepolicy_freeze.go", "sepolicy_vers.go", "versioned_policy.go", ], diff --git a/build/soong/sepolicy_freeze.go b/build/soong/sepolicy_freeze.go new file mode 100644 index 000000000..c5513d012 --- /dev/null +++ b/build/soong/sepolicy_freeze.go @@ -0,0 +1,121 @@ +// 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 ( + "path/filepath" + "sort" + + "android/soong/android" +) + +func init() { + ctx := android.InitRegistrationContext + ctx.RegisterSingletonModuleType("se_freeze_test", freezeTestFactory) +} + +// se_freeze_test compares the plat sepolicy with the prebuilt sepolicy. Additional directories can +// be specified via Makefile variables: SEPOLICY_FREEZE_TEST_EXTRA_DIRS and +// SEPOLICY_FREEZE_TEST_EXTRA_PREBUILT_DIRS. +func freezeTestFactory() android.SingletonModule { + f := &freezeTestModule{} + android.InitAndroidModule(f) + return f +} + +type freezeTestModule struct { + android.SingletonModuleBase + freezeTestTimestamp android.ModuleOutPath +} + +func (f *freezeTestModule) GenerateSingletonBuildActions(ctx android.SingletonContext) { + // does nothing; se_freeze_test is a singeton because two freeze test modules don't make sense. +} + +func (f *freezeTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { + platformVersion := ctx.DeviceConfig().PlatformSepolicyVersion() + totVersion := ctx.DeviceConfig().TotSepolicyVersion() + + extraDirs := ctx.DeviceConfig().SepolicyFreezeTestExtraDirs() + extraPrebuiltDirs := ctx.DeviceConfig().SepolicyFreezeTestExtraPrebuiltDirs() + f.freezeTestTimestamp = android.PathForModuleOut(ctx, "freeze_test") + + if platformVersion == totVersion { + if len(extraDirs) > 0 || len(extraPrebuiltDirs) > 0 { + ctx.ModuleErrorf("SEPOLICY_FREEZE_TEST_EXTRA_DIRS or SEPOLICY_FREEZE_TEST_EXTRA_PREBUILT_DIRS cannot be set before system/sepolicy freezes.") + return + } + + // we still build a rule to prevent possible regression + android.WriteFileRule(ctx, f.freezeTestTimestamp, ";; no freeze tests needed before system/sepolicy freezes") + return + } + + if len(extraDirs) != len(extraPrebuiltDirs) { + ctx.ModuleErrorf("SEPOLICY_FREEZE_TEST_EXTRA_DIRS and SEPOLICY_FREEZE_TEST_EXTRA_PREBUILT_DIRS must have the same number of directories.") + return + } + + platPublic := filepath.Join(ctx.ModuleDir(), "public") + platPrivate := filepath.Join(ctx.ModuleDir(), "private") + prebuiltPublic := filepath.Join(ctx.ModuleDir(), "prebuilts", "api", platformVersion, "public") + prebuiltPrivate := filepath.Join(ctx.ModuleDir(), "prebuilts", "api", platformVersion, "private") + + sourceDirs := append(extraDirs, platPublic, platPrivate) + prebuiltDirs := append(extraPrebuiltDirs, prebuiltPublic, prebuiltPrivate) + + var implicits []string + for _, dir := range append(sourceDirs, prebuiltDirs...) { + glob, err := ctx.GlobWithDeps(dir+"/**/*", []string{"bug_map"} /* exclude */) + if err != nil { + ctx.ModuleErrorf("failed to glob sepolicy dir %q: %s", dir, err.Error()) + return + } + implicits = append(implicits, glob...) + } + sort.Strings(implicits) + + rule := android.NewRuleBuilder(pctx, ctx) + + for idx, _ := range sourceDirs { + rule.Command().Text("diff"). + Flag("-r"). + Flag("-q"). + FlagWithArg("-x ", "bug_map"). // exclude + Text(sourceDirs[idx]). + Text(prebuiltDirs[idx]) + } + + rule.Command().Text("touch"). + Output(f.freezeTestTimestamp). + Implicits(android.PathsForSource(ctx, implicits)) + + rule.Build("sepolicy_freeze_test", "sepolicy_freeze_test") +} + +func (f *freezeTestModule) AndroidMkEntries() []android.AndroidMkEntries { + return []android.AndroidMkEntries{android.AndroidMkEntries{ + Class: "FAKE", + // OutputFile is needed, even though BUILD_PHONY_PACKAGE doesn't use it. + // Without OutputFile this module won't be exported to Makefile. + OutputFile: android.OptionalPathForPath(f.freezeTestTimestamp), + Include: "$(BUILD_PHONY_PACKAGE)", + ExtraEntries: []android.AndroidMkExtraEntriesFunc{ + func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { + entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", f.freezeTestTimestamp.String()) + }, + }, + }} +}