platform_system_sepolicy/build/soong/compat_cil.go
Inseob Kim 73f43ff847 Remove compat test from treble sepolicy tests
Treble sepolicy tests check whether previous versions are compatible to
ToT sepolicy or not. treble_sepolicy_tests_for_release.mk implements it,
but it also includes a compat test whether ToT sepolicy + {ver} mapping
+ {ver} plat_pub_versioned.cil can be built together or not. We
definitely need such tests, but we already have a test called "compat
test" which does exactly that, and testing it again with Treble sepolicy
tests is just redundant. The only difference between those two is that
Treble sepolicy tests can also test system_ext and product compat files,
which was contributed by a partner.

The ultimate goal here is to migrate *.mk to Soong, thus merging these
two tests (compat, Treble) into one. As we've already migrated the
compat test to Soong, this change removes the compat test part from
treble sepolicy tests. Instead, the compat test will be extended so it
can test system_ext and product compat files too.
prebuilts/api/{ver}/plat_pub_versioned.cil and
prebuilts/api/{ver}/vendor_sepolicy.cil are also removed as they aren't
used anymore: vendor_sepolicy.cil is an empty stub, and
plat_pub_versioned.cil can be built from the prebuilt source files.

Bug: 33691272
Test: m selinux_policy
Change-Id: I72f5ad0e8bbe6a7c0bbcc02f0f902b953df6ff1a
2022-02-16 04:09:29 +00:00

270 lines
8.7 KiB
Go

// 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 (
"fmt"
"github.com/google/blueprint/proptools"
"android/soong/android"
)
var (
compatTestDepTag = dependencyTag{name: "compat_test"}
)
func init() {
ctx := android.InitRegistrationContext
ctx.RegisterModuleType("se_compat_cil", compatCilFactory)
ctx.RegisterSingletonModuleType("se_compat_test", compatTestFactory)
}
// se_compat_cil collects and installs backwards compatibility cil files.
func compatCilFactory() android.Module {
c := &compatCil{}
c.AddProperties(&c.properties)
android.InitAndroidArchModule(c, android.DeviceSupported, android.MultilibCommon)
return c
}
type compatCil struct {
android.ModuleBase
properties compatCilProperties
installSource android.Path
installPath android.InstallPath
}
type compatCilProperties struct {
// List of source files. Can reference se_filegroup type modules with the ":module" syntax.
Srcs []string `android:"path"`
// Output file name. Defaults to module name if unspecified.
Stem *string
}
func (c *compatCil) stem() string {
return proptools.StringDefault(c.properties.Stem, c.Name())
}
func (c *compatCil) expandSeSources(ctx android.ModuleContext) android.Paths {
srcPaths := make(android.Paths, 0, len(c.properties.Srcs))
for _, src := range c.properties.Srcs {
if m := android.SrcIsModule(src); m != "" {
module := android.GetModuleFromPathDep(ctx, m, "")
if module == nil {
// Error would have been handled by ExtractSourcesDeps
continue
}
if fg, ok := module.(*fileGroup); ok {
if c.SystemExtSpecific() {
srcPaths = append(srcPaths, fg.SystemExtPrivateSrcs()...)
} else {
srcPaths = append(srcPaths, fg.SystemPrivateSrcs()...)
}
} else {
ctx.PropertyErrorf("srcs", "%q is not an se_filegroup", m)
}
} else {
srcPaths = append(srcPaths, android.PathForModuleSrc(ctx, src))
}
}
return srcPaths
}
func (c *compatCil) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if c.ProductSpecific() || c.SocSpecific() || c.DeviceSpecific() {
ctx.ModuleErrorf("Compat cil files only support system and system_ext partitions")
}
srcPaths := c.expandSeSources(ctx)
out := android.PathForModuleGen(ctx, c.Name())
ctx.Build(pctx, android.BuildParams{
Rule: android.Cat,
Inputs: srcPaths,
Output: out,
Description: "Combining compat cil for " + c.Name(),
})
c.installPath = android.PathForModuleInstall(ctx, "etc", "selinux", "mapping")
c.installSource = out
ctx.InstallFile(c.installPath, c.stem(), c.installSource)
}
func (c *compatCil) AndroidMkEntries() []android.AndroidMkEntries {
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "ETC",
OutputFile: android.OptionalPathForPath(c.installSource),
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetPath("LOCAL_MODULE_PATH", c.installPath)
entries.SetString("LOCAL_INSTALLED_MODULE_STEM", c.stem())
},
},
}}
}
func (c *compatCil) OutputFiles(tag string) (android.Paths, error) {
switch tag {
case "":
return android.Paths{c.installSource}, nil
default:
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
}
var _ android.OutputFileProducer = (*compatCil)(nil)
// se_compat_test checks if compat files ({ver}.cil, {ver}.compat.cil) files are compatible with
// current policy.
func compatTestFactory() android.SingletonModule {
f := &compatTestModule{}
android.InitAndroidModule(f)
android.AddLoadHook(f, func(ctx android.LoadHookContext) {
f.loadHook(ctx)
})
return f
}
type compatTestModule struct {
android.SingletonModuleBase
compatTestTimestamp android.ModuleOutPath
}
func (f *compatTestModule) createPlatPubVersionedModule(ctx android.LoadHookContext, ver string) {
confName := fmt.Sprintf("pub_policy_%s.conf", ver)
cilName := fmt.Sprintf("pub_policy_%s.cil", ver)
platPubVersionedName := fmt.Sprintf("plat_pub_versioned_%s.cil", ver)
ctx.CreateModule(policyConfFactory, &nameProperties{
Name: proptools.StringPtr(confName),
}, &policyConfProperties{
Srcs: []string{
fmt.Sprintf(":se_build_files{.plat_public_%s}", ver),
fmt.Sprintf(":se_build_files{.system_ext_public_%s}", ver),
fmt.Sprintf(":se_build_files{.product_public_%s}", ver),
":se_build_files{.reqd_mask}",
},
Installable: proptools.BoolPtr(false),
})
ctx.CreateModule(policyCilFactory, &nameProperties{
Name: proptools.StringPtr(cilName),
}, &policyCilProperties{
Src: proptools.StringPtr(":" + confName),
Filter_out: []string{":reqd_policy_mask.cil"},
Secilc_check: proptools.BoolPtr(false),
Installable: proptools.BoolPtr(false),
})
ctx.CreateModule(versionedPolicyFactory, &nameProperties{
Name: proptools.StringPtr(platPubVersionedName),
}, &versionedPolicyProperties{
Base: proptools.StringPtr(":" + cilName),
Target_policy: proptools.StringPtr(":" + cilName),
Version: proptools.StringPtr(ver),
Installable: proptools.BoolPtr(false),
})
}
func (f *compatTestModule) createCompatTestModule(ctx android.LoadHookContext, ver string) {
srcs := []string{
":plat_sepolicy.cil",
":system_ext_sepolicy.cil",
":product_sepolicy.cil",
fmt.Sprintf(":plat_%s.cil", ver),
fmt.Sprintf(":%s.compat.cil", ver),
fmt.Sprintf(":system_ext_%s.cil", ver),
fmt.Sprintf(":system_ext_%s.compat.cil", ver),
fmt.Sprintf(":product_%s.cil", ver),
}
if ver == ctx.DeviceConfig().BoardSepolicyVers() {
srcs = append(srcs,
":plat_pub_versioned.cil",
":vendor_sepolicy.cil",
":odm_sepolicy.cil",
)
} else {
srcs = append(srcs, fmt.Sprintf(":plat_pub_versioned_%s.cil", ver))
}
compatTestName := fmt.Sprintf("%s_compat_test", ver)
ctx.CreateModule(policyBinaryFactory, &nameProperties{
Name: proptools.StringPtr(compatTestName),
}, &policyBinaryProperties{
Srcs: srcs,
Ignore_neverallow: proptools.BoolPtr(true),
Installable: proptools.BoolPtr(false),
})
}
func (f *compatTestModule) loadHook(ctx android.LoadHookContext) {
for _, ver := range ctx.DeviceConfig().PlatformSepolicyCompatVersions() {
f.createPlatPubVersionedModule(ctx, ver)
f.createCompatTestModule(ctx, ver)
}
}
func (f *compatTestModule) DepsMutator(ctx android.BottomUpMutatorContext) {
for _, ver := range ctx.DeviceConfig().PlatformSepolicyCompatVersions() {
ctx.AddDependency(f, compatTestDepTag, fmt.Sprintf("%s_compat_test", ver))
}
}
func (f *compatTestModule) GenerateSingletonBuildActions(ctx android.SingletonContext) {
// does nothing; se_compat_test is a singeton because two compat test modules don't make sense.
}
func (f *compatTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
var inputs android.Paths
ctx.VisitDirectDepsWithTag(compatTestDepTag, func(child android.Module) {
o, ok := child.(android.OutputFileProducer)
if !ok {
panic(fmt.Errorf("Module %q should be an OutputFileProducer but it isn't", ctx.OtherModuleName(child)))
}
outputs, err := o.OutputFiles("")
if err != nil {
panic(fmt.Errorf("Module %q error while producing output: %v", ctx.OtherModuleName(child), err))
}
if len(outputs) != 1 {
panic(fmt.Errorf("Module %q should produce exactly one output, but did %q", ctx.OtherModuleName(child), outputs.Strings()))
}
inputs = append(inputs, outputs[0])
})
f.compatTestTimestamp = android.PathForModuleOut(ctx, "timestamp")
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().Text("touch").Output(f.compatTestTimestamp).Implicits(inputs)
rule.Build("compat", "compat test timestamp for: "+f.Name())
}
func (f *compatTestModule) 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.compatTestTimestamp),
Include: "$(BUILD_PHONY_PACKAGE)",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", f.compatTestTimestamp.String())
},
},
}}
}