Support multiple se_flags modules
Instead of centralized one se_flags module under system/sepolicy, additional se_flags modules can be defined anywhere to support defining downstream branches' own flagging. Bug: 321875465 Test: TH Test: soong test Change-Id: I6e45c859b7f09e27ba1d60033b0db1424472cb63
This commit is contained in:
parent
4105da26f9
commit
bf7f4a4401
6 changed files with 253 additions and 16 deletions
|
@ -47,5 +47,6 @@ bootstrap_go_package {
|
|||
"service_fuzzer_bindings.go",
|
||||
"validate_bindings.go",
|
||||
],
|
||||
testSrcs: ["selinux_test.go"],
|
||||
pluginFor: ["soong_build"],
|
||||
}
|
||||
|
|
|
@ -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 @@ func (f *flaggableModuleBase) flagModuleBase() *flaggableModuleBase {
|
|||
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
|
||||
}
|
||||
|
|
|
@ -129,7 +129,7 @@ func policyConfDefaultFactory() android.Module {
|
|||
c := &policyConfDefaults{}
|
||||
c.AddProperties(
|
||||
&policyConfProperties{},
|
||||
&flagsProperties{},
|
||||
&flaggableModuleProperties{},
|
||||
)
|
||||
android.InitDefaultsModule(c)
|
||||
return c
|
||||
|
@ -270,6 +270,10 @@ func (c *policyConf) transformPolicyToConf(ctx android.ModuleContext) android.Ou
|
|||
return conf
|
||||
}
|
||||
|
||||
func (c *policyConf) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||
c.flagDeps(ctx)
|
||||
}
|
||||
|
||||
func (c *policyConf) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
if !c.installable() {
|
||||
c.SkipInstall()
|
||||
|
|
|
@ -110,6 +110,8 @@ func (m *selinuxContextsModule) onlyInRecovery() bool {
|
|||
}
|
||||
|
||||
func (m *selinuxContextsModule) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||
m.flagDeps(ctx)
|
||||
|
||||
if m.deps != nil {
|
||||
m.deps(ctx)
|
||||
}
|
||||
|
@ -182,7 +184,7 @@ func contextsDefaultsFactory() android.Module {
|
|||
m.AddProperties(
|
||||
&selinuxContextsProperties{},
|
||||
&seappProperties{},
|
||||
&flagsProperties{},
|
||||
&flaggableModuleProperties{},
|
||||
)
|
||||
android.InitDefaultsModule(m)
|
||||
return m
|
||||
|
|
96
build/soong/selinux_test.go
Normal file
96
build/soong/selinux_test.go
Normal file
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue