Merge "Support multiple se_flags modules" into main am: f9f826fb30
Original change: https://android-review.googlesource.com/c/platform/system/sepolicy/+/2963582
Change-Id: Ie6758c95131388b40c8731151529672e271dc430
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/build/soong/Android.bp b/build/soong/Android.bp
index 0abfdf6..3f2e2df 100644
--- a/build/soong/Android.bp
+++ b/build/soong/Android.bp
@@ -47,5 +47,6 @@
"service_fuzzer_bindings.go",
"validate_bindings.go",
],
+ testSrcs: ["selinux_test.go"],
pluginFor: ["soong_build"],
}
diff --git a/build/soong/flags.go b/build/soong/flags.go
index b1aebac..c7aeb32 100644
--- a/build/soong/flags.go
+++ b/build/soong/flags.go
@@ -15,22 +15,141 @@
package selinux
import (
+ "maps"
+
"android/soong/android"
+
+ "github.com/google/blueprint"
)
+var (
+ flagsDepTag = dependencyTag{name: "flags"}
+ buildFlagsDepTag = dependencyTag{name: "build_flags"}
+)
+
+func init() {
+ ctx := android.InitRegistrationContext
+ ctx.RegisterModuleType("se_flags", flagsFactory)
+ ctx.RegisterModuleType("se_flags_collector", flagsCollectorFactory)
+}
+
type flagsProperties struct {
- // List of flags to be passed to M4 macro.
+ // List of build time flags for flag-guarding.
Flags []string
+
+ // List of se_flags_collector modules to export flags to.
+ Export_to []string
+}
+
+type flagsModule struct {
+ android.ModuleBase
+ properties flagsProperties
+}
+
+type flagsInfo struct {
+ Flags []string
+}
+
+var flagsProviderKey = blueprint.NewProvider[flagsInfo]()
+
+// se_flags contains a list of build time flags for sepolicy. Build time flags are defined under
+// .scl files (e.g. build/release/build_flags.scl). By importing flags with se_flags modules,
+// sepolicy rules can be guarded by `is_flag_enabled` / `is_flag_disabled` macro.
+//
+// For example, an Android.bp file could have:
+//
+// se_flags {
+// name: "aosp_selinux_flags",
+// flags: ["RELEASE_AVF_ENABLE_DEVICE_ASSIGNMENT"],
+// export_to: ["all_selinux_flags"],
+// }
+//
+// And then one could flag-guard .te file rules:
+//
+// is_flag_enabled(RELEASE_AVF_ENABLE_DEVICE_ASSIGNMENT, `
+// type vfio_handler, domain, coredomain;
+// binder_use(vfio_handler)
+// ')
+//
+// or contexts entries:
+//
+// is_flag_enabled(RELEASE_AVF_ENABLE_DEVICE_ASSIGNMENT, `
+// android.system.virtualizationservice_internal.IVfioHandler u:object_r:vfio_handler_service:s0
+// ')
+func flagsFactory() android.Module {
+ module := &flagsModule{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidModule(module)
+ return module
+}
+
+func (f *flagsModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // dep se_flag_collector -> se_flags
+ for _, export := range f.properties.Export_to {
+ ctx.AddReverseDependency(ctx.Module(), flagsDepTag, export)
+ }
+}
+
+func (f *flagsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ android.SetProvider(ctx, flagsProviderKey, flagsInfo{
+ Flags: f.properties.Flags,
+ })
+}
+
+type buildFlagsInfo struct {
+ BuildFlags map[string]string
+}
+
+var buildFlagsProviderKey = blueprint.NewProvider[buildFlagsInfo]()
+
+type flagsCollectorModule struct {
+ android.ModuleBase
+ buildFlags map[string]string
+}
+
+// se_flags_collector module collects flags from exported se_flags modules (see export_to property
+// of se_flags modules), and then converts them into build-time flags. It will be used to generate
+// M4 macros to flag-guard sepolicy.
+func flagsCollectorFactory() android.Module {
+ module := &flagsCollectorModule{}
+ android.InitAndroidModule(module)
+ return module
+}
+
+func (f *flagsCollectorModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ var flags []string
+ ctx.VisitDirectDepsWithTag(flagsDepTag, func(m android.Module) {
+ if dep, ok := android.OtherModuleProvider(ctx, m, flagsProviderKey); ok {
+ flags = append(flags, dep.Flags...)
+ } else {
+ ctx.ModuleErrorf("unknown dependency %q", ctx.OtherModuleName(m))
+ }
+ })
+ buildFlags := make(map[string]string)
+ for _, flag := range android.SortedUniqueStrings(flags) {
+ if val, ok := ctx.Config().GetBuildFlag(flag); ok {
+ buildFlags[flag] = val
+ }
+ }
+ android.SetProvider(ctx, buildFlagsProviderKey, buildFlagsInfo{
+ BuildFlags: buildFlags,
+ })
+}
+
+type flaggableModuleProperties struct {
+ // List of se_flag_collector modules to be passed to M4 macro.
+ Build_flags []string
}
type flaggableModule interface {
android.Module
flagModuleBase() *flaggableModuleBase
+ flagDeps(ctx android.BottomUpMutatorContext)
getBuildFlags(ctx android.ModuleContext) map[string]string
}
type flaggableModuleBase struct {
- properties flagsProperties
+ properties flaggableModuleProperties
}
func initFlaggableModule(m flaggableModule) {
@@ -42,13 +161,19 @@
return f
}
+func (f *flaggableModuleBase) flagDeps(ctx android.BottomUpMutatorContext) {
+ ctx.AddDependency(ctx.Module(), buildFlagsDepTag, f.properties.Build_flags...)
+}
+
// getBuildFlags returns a map from flag names to flag values.
func (f *flaggableModuleBase) getBuildFlags(ctx android.ModuleContext) map[string]string {
ret := make(map[string]string)
- for _, flag := range android.SortedUniqueStrings(f.properties.Flags) {
- if val, ok := ctx.Config().GetBuildFlag(flag); ok {
- ret[flag] = val
+ ctx.VisitDirectDepsWithTag(buildFlagsDepTag, func(m android.Module) {
+ if dep, ok := android.OtherModuleProvider(ctx, m, buildFlagsProviderKey); ok {
+ maps.Copy(ret, dep.BuildFlags)
+ } else {
+ ctx.PropertyErrorf("build_flags", "unknown dependency %q", ctx.OtherModuleName(m))
}
- }
+ })
return ret
}
diff --git a/build/soong/policy.go b/build/soong/policy.go
index 9d87275..cbcc57a 100644
--- a/build/soong/policy.go
+++ b/build/soong/policy.go
@@ -129,7 +129,7 @@
c := &policyConfDefaults{}
c.AddProperties(
&policyConfProperties{},
- &flagsProperties{},
+ &flaggableModuleProperties{},
)
android.InitDefaultsModule(c)
return c
@@ -270,6 +270,10 @@
return conf
}
+func (c *policyConf) DepsMutator(ctx android.BottomUpMutatorContext) {
+ c.flagDeps(ctx)
+}
+
func (c *policyConf) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if !c.installable() {
c.SkipInstall()
diff --git a/build/soong/selinux_contexts.go b/build/soong/selinux_contexts.go
index 5cc9c70..1282b90 100644
--- a/build/soong/selinux_contexts.go
+++ b/build/soong/selinux_contexts.go
@@ -110,6 +110,8 @@
}
func (m *selinuxContextsModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+ m.flagDeps(ctx)
+
if m.deps != nil {
m.deps(ctx)
}
@@ -182,7 +184,7 @@
m.AddProperties(
&selinuxContextsProperties{},
&seappProperties{},
- &flagsProperties{},
+ &flaggableModuleProperties{},
)
android.InitDefaultsModule(m)
return m
diff --git a/build/soong/selinux_test.go b/build/soong/selinux_test.go
new file mode 100644
index 0000000..dd980a5
--- /dev/null
+++ b/build/soong/selinux_test.go
@@ -0,0 +1,96 @@
+// Copyright 2024 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 (
+ "os"
+ "reflect"
+ "testing"
+
+ "android/soong/android"
+)
+
+func TestMain(m *testing.M) {
+ os.Exit(m.Run())
+}
+
+var prepareForTest = android.GroupFixturePreparers(
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ buildFlags := make(map[string]string)
+ buildFlags["RELEASE_FLAGS_BAR"] = "true"
+ buildFlags["RELEASE_FLAGS_FOO1"] = "false"
+ // "RELEASE_FLAGS_FOO2" is missing
+ buildFlags["RELEASE_AVF_ENABLE_DEVICE_ASSIGNMENT"] = "true"
+ variables.BuildFlags = buildFlags
+ }),
+ android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("se_flags", flagsFactory)
+ ctx.RegisterModuleType("se_flags_collector", flagsCollectorFactory)
+ }),
+)
+
+func TestFlagCollector(t *testing.T) {
+ t.Parallel()
+
+ ctx := android.GroupFixturePreparers(
+ prepareForTest,
+ android.FixtureAddTextFile("package_bar/Android.bp", `
+ se_flags {
+ name: "se_flags_bar",
+ flags: ["RELEASE_FLAGS_BAR"],
+ export_to: ["se_flags_collector"],
+ }
+ `),
+ android.FixtureAddTextFile("package_foo/Android.bp", `
+ se_flags {
+ name: "se_flags_foo",
+ flags: ["RELEASE_FLAGS_FOO1", "RELEASE_FLAGS_FOO2"],
+ export_to: ["se_flags_collector"],
+ }
+ `),
+ android.FixtureAddTextFile("system/sepolicy/Android.bp", `
+ se_flags {
+ name: "se_flags",
+ flags: ["RELEASE_AVF_ENABLE_DEVICE_ASSIGNMENT"],
+ export_to: ["se_flags_collector"],
+ }
+ se_flags_collector {
+ name: "se_flags_collector",
+ }
+ `),
+ ).RunTest(t).TestContext
+
+ collectorModule := ctx.ModuleForTests("se_flags_collector", "").Module()
+ collectorData, ok := android.OtherModuleProvider(ctx.OtherModuleProviderAdaptor(), collectorModule, buildFlagsProviderKey)
+ if !ok {
+ t.Errorf("se_flags_collector must provide buildFlags")
+ return
+ }
+
+ actual := flagsToM4Macros(collectorData.BuildFlags)
+ expected := []string{
+ "-D target_flag_RELEASE_AVF_ENABLE_DEVICE_ASSIGNMENT=true",
+ "-D target_flag_RELEASE_FLAGS_BAR=true",
+ "-D target_flag_RELEASE_FLAGS_FOO1=false",
+ }
+ if !reflect.DeepEqual(actual, expected) {
+ t.Errorf("M4 macros were not exported correctly"+
+ "\nactual: %v"+
+ "\nexpected: %v",
+ actual,
+ expected,
+ )
+ }
+}
diff --git a/flagging/Android.bp b/flagging/Android.bp
index 55e116b..8f7355a 100644
--- a/flagging/Android.bp
+++ b/flagging/Android.bp
@@ -12,24 +12,33 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// This file contains a list of flags for sepolicy.
-se_policy_conf_defaults {
- name: "se_policy_conf_flags_defaults",
- srcs: [":sepolicy_flagging_macros"],
+// This module contains a list of build time flags (defined on AOSP) for sepolicy.
+// Additional se_flags modules can be added anywhere for additional flags.
+se_flags {
+ name: "aosp_selinux_flags",
flags: [
"RELEASE_AVF_ENABLE_DEVICE_ASSIGNMENT",
"RELEASE_HARDWARE_BLUETOOTH_RANGING_SERVICE",
],
+ export_to: ["all_selinux_flags"],
+}
+
+// se_flags_collector collects flags from exported se_flags modules and converts it to build flags.
+se_flags_collector {
+ name: "all_selinux_flags",
+}
+
+se_policy_conf_defaults {
+ name: "se_policy_conf_flags_defaults",
+ srcs: [":sepolicy_flagging_macros"],
+ build_flags: ["all_selinux_flags"],
}
contexts_defaults {
name: "contexts_flags_defaults",
srcs: [":sepolicy_flagging_macros"],
neverallow_files: [":sepolicy_flagging_macros"], // for seapp_contexts
- flags: [
- "RELEASE_AVF_ENABLE_DEVICE_ASSIGNMENT",
- "RELEASE_HARDWARE_BLUETOOTH_RANGING_SERVICE",
- ],
+ build_flags: ["all_selinux_flags"],
}
filegroup {