1*e4a36f41SAndroid Build Coastguard Worker// Copyright 2021 The Android Open Source Project 2*e4a36f41SAndroid Build Coastguard Worker// 3*e4a36f41SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*e4a36f41SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*e4a36f41SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*e4a36f41SAndroid Build Coastguard Worker// 7*e4a36f41SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*e4a36f41SAndroid Build Coastguard Worker// 9*e4a36f41SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*e4a36f41SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*e4a36f41SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*e4a36f41SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*e4a36f41SAndroid Build Coastguard Worker// limitations under the License. 14*e4a36f41SAndroid Build Coastguard Worker 15*e4a36f41SAndroid Build Coastguard Workerpackage selinux 16*e4a36f41SAndroid Build Coastguard Worker 17*e4a36f41SAndroid Build Coastguard Workerimport ( 18*e4a36f41SAndroid Build Coastguard Worker "sort" 19*e4a36f41SAndroid Build Coastguard Worker 20*e4a36f41SAndroid Build Coastguard Worker "android/soong/android" 21*e4a36f41SAndroid Build Coastguard Worker) 22*e4a36f41SAndroid Build Coastguard Worker 23*e4a36f41SAndroid Build Coastguard Workervar currentCilTag = dependencyTag{name: "current_cil"} 24*e4a36f41SAndroid Build Coastguard Workervar prebuiltCilTag = dependencyTag{name: "prebuilt_cil"} 25*e4a36f41SAndroid Build Coastguard Worker 26*e4a36f41SAndroid Build Coastguard Workerfunc init() { 27*e4a36f41SAndroid Build Coastguard Worker ctx := android.InitRegistrationContext 28*e4a36f41SAndroid Build Coastguard Worker ctx.RegisterModuleType("se_freeze_test", freezeTestFactory) 29*e4a36f41SAndroid Build Coastguard Worker} 30*e4a36f41SAndroid Build Coastguard Worker 31*e4a36f41SAndroid Build Coastguard Worker// se_freeze_test compares the plat sepolicy with the prebuilt sepolicy. Additional directories can 32*e4a36f41SAndroid Build Coastguard Worker// be specified via Makefile variables: SEPOLICY_FREEZE_TEST_EXTRA_DIRS and 33*e4a36f41SAndroid Build Coastguard Worker// SEPOLICY_FREEZE_TEST_EXTRA_PREBUILT_DIRS. 34*e4a36f41SAndroid Build Coastguard Workerfunc freezeTestFactory() android.Module { 35*e4a36f41SAndroid Build Coastguard Worker f := &freezeTestModule{} 36*e4a36f41SAndroid Build Coastguard Worker android.InitAndroidArchModule(f, android.DeviceSupported, android.MultilibCommon) 37*e4a36f41SAndroid Build Coastguard Worker android.AddLoadHook(f, func(ctx android.LoadHookContext) { 38*e4a36f41SAndroid Build Coastguard Worker f.loadHook(ctx) 39*e4a36f41SAndroid Build Coastguard Worker }) 40*e4a36f41SAndroid Build Coastguard Worker return f 41*e4a36f41SAndroid Build Coastguard Worker} 42*e4a36f41SAndroid Build Coastguard Worker 43*e4a36f41SAndroid Build Coastguard Workertype freezeTestModule struct { 44*e4a36f41SAndroid Build Coastguard Worker android.ModuleBase 45*e4a36f41SAndroid Build Coastguard Worker freezeTestTimestamp android.ModuleOutPath 46*e4a36f41SAndroid Build Coastguard Worker} 47*e4a36f41SAndroid Build Coastguard Worker 48*e4a36f41SAndroid Build Coastguard Workerfunc (f *freezeTestModule) shouldRunTest(ctx android.EarlyModuleContext) bool { 49*e4a36f41SAndroid Build Coastguard Worker val, _ := ctx.Config().GetBuildFlag("RELEASE_BOARD_API_LEVEL_FROZEN") 50*e4a36f41SAndroid Build Coastguard Worker return val == "true" 51*e4a36f41SAndroid Build Coastguard Worker} 52*e4a36f41SAndroid Build Coastguard Worker 53*e4a36f41SAndroid Build Coastguard Workerfunc (f *freezeTestModule) loadHook(ctx android.LoadHookContext) { 54*e4a36f41SAndroid Build Coastguard Worker extraDirs := ctx.DeviceConfig().SepolicyFreezeTestExtraDirs() 55*e4a36f41SAndroid Build Coastguard Worker extraPrebuiltDirs := ctx.DeviceConfig().SepolicyFreezeTestExtraPrebuiltDirs() 56*e4a36f41SAndroid Build Coastguard Worker 57*e4a36f41SAndroid Build Coastguard Worker if !f.shouldRunTest(ctx) { 58*e4a36f41SAndroid Build Coastguard Worker if len(extraDirs) > 0 || len(extraPrebuiltDirs) > 0 { 59*e4a36f41SAndroid Build Coastguard Worker ctx.ModuleErrorf("SEPOLICY_FREEZE_TEST_EXTRA_DIRS or SEPOLICY_FREEZE_TEST_EXTRA_PREBUILT_DIRS cannot be set before system/sepolicy freezes.") 60*e4a36f41SAndroid Build Coastguard Worker return 61*e4a36f41SAndroid Build Coastguard Worker } 62*e4a36f41SAndroid Build Coastguard Worker 63*e4a36f41SAndroid Build Coastguard Worker return 64*e4a36f41SAndroid Build Coastguard Worker } 65*e4a36f41SAndroid Build Coastguard Worker 66*e4a36f41SAndroid Build Coastguard Worker if len(extraDirs) != len(extraPrebuiltDirs) { 67*e4a36f41SAndroid Build Coastguard Worker ctx.ModuleErrorf("SEPOLICY_FREEZE_TEST_EXTRA_DIRS and SEPOLICY_FREEZE_TEST_EXTRA_PREBUILT_DIRS must have the same number of directories.") 68*e4a36f41SAndroid Build Coastguard Worker return 69*e4a36f41SAndroid Build Coastguard Worker } 70*e4a36f41SAndroid Build Coastguard Worker} 71*e4a36f41SAndroid Build Coastguard Worker 72*e4a36f41SAndroid Build Coastguard Workerfunc (f *freezeTestModule) prebuiltCilModuleName(ctx android.EarlyModuleContext) string { 73*e4a36f41SAndroid Build Coastguard Worker return ctx.DeviceConfig().PlatformSepolicyVersion() + "_plat_pub_policy.cil" 74*e4a36f41SAndroid Build Coastguard Worker} 75*e4a36f41SAndroid Build Coastguard Worker 76*e4a36f41SAndroid Build Coastguard Workerfunc (f *freezeTestModule) DepsMutator(ctx android.BottomUpMutatorContext) { 77*e4a36f41SAndroid Build Coastguard Worker if !f.shouldRunTest(ctx) { 78*e4a36f41SAndroid Build Coastguard Worker return 79*e4a36f41SAndroid Build Coastguard Worker } 80*e4a36f41SAndroid Build Coastguard Worker 81*e4a36f41SAndroid Build Coastguard Worker ctx.AddDependency(f, currentCilTag, "base_plat_pub_policy.cil") 82*e4a36f41SAndroid Build Coastguard Worker ctx.AddDependency(f, prebuiltCilTag, f.prebuiltCilModuleName(ctx)) 83*e4a36f41SAndroid Build Coastguard Worker} 84*e4a36f41SAndroid Build Coastguard Worker 85*e4a36f41SAndroid Build Coastguard Workerfunc (f *freezeTestModule) outputFileOfDep(ctx android.ModuleContext, depTag dependencyTag) android.Path { 86*e4a36f41SAndroid Build Coastguard Worker deps := ctx.GetDirectDepsWithTag(depTag) 87*e4a36f41SAndroid Build Coastguard Worker if len(deps) != 1 { 88*e4a36f41SAndroid Build Coastguard Worker ctx.ModuleErrorf("%d deps having tag %q; expected only one dep", len(deps), depTag) 89*e4a36f41SAndroid Build Coastguard Worker return nil 90*e4a36f41SAndroid Build Coastguard Worker } 91*e4a36f41SAndroid Build Coastguard Worker 92*e4a36f41SAndroid Build Coastguard Worker dep := deps[0] 93*e4a36f41SAndroid Build Coastguard Worker output := android.OutputFilesForModule(ctx, dep, "") 94*e4a36f41SAndroid Build Coastguard Worker if len(output) != 1 { 95*e4a36f41SAndroid Build Coastguard Worker ctx.ModuleErrorf("module %q produced %d outputs; expected only one output", dep.String(), len(output)) 96*e4a36f41SAndroid Build Coastguard Worker return nil 97*e4a36f41SAndroid Build Coastguard Worker } 98*e4a36f41SAndroid Build Coastguard Worker 99*e4a36f41SAndroid Build Coastguard Worker return output[0] 100*e4a36f41SAndroid Build Coastguard Worker} 101*e4a36f41SAndroid Build Coastguard Worker 102*e4a36f41SAndroid Build Coastguard Workerfunc (f *freezeTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 103*e4a36f41SAndroid Build Coastguard Worker if ctx.ModuleName() != "se_freeze_test" || ctx.ModuleDir() != "system/sepolicy" { 104*e4a36f41SAndroid Build Coastguard Worker // two freeze test modules don't make sense. 105*e4a36f41SAndroid Build Coastguard Worker ctx.ModuleErrorf("There can only be 1 se_freeze_test module named se_freeze_test in system/sepolicy") 106*e4a36f41SAndroid Build Coastguard Worker } 107*e4a36f41SAndroid Build Coastguard Worker 108*e4a36f41SAndroid Build Coastguard Worker f.freezeTestTimestamp = android.PathForModuleOut(ctx, "freeze_test") 109*e4a36f41SAndroid Build Coastguard Worker 110*e4a36f41SAndroid Build Coastguard Worker if !f.shouldRunTest(ctx) { 111*e4a36f41SAndroid Build Coastguard Worker // we still build a rule to prevent possible regression 112*e4a36f41SAndroid Build Coastguard Worker android.WriteFileRule(ctx, f.freezeTestTimestamp, ";; no freeze tests needed before system/sepolicy freezes") 113*e4a36f41SAndroid Build Coastguard Worker return 114*e4a36f41SAndroid Build Coastguard Worker } 115*e4a36f41SAndroid Build Coastguard Worker 116*e4a36f41SAndroid Build Coastguard Worker // Freeze test 1: compare ToT sepolicy and prebuilt sepolicy 117*e4a36f41SAndroid Build Coastguard Worker currentCil := f.outputFileOfDep(ctx, currentCilTag) 118*e4a36f41SAndroid Build Coastguard Worker prebuiltCil := f.outputFileOfDep(ctx, prebuiltCilTag) 119*e4a36f41SAndroid Build Coastguard Worker if ctx.Failed() { 120*e4a36f41SAndroid Build Coastguard Worker return 121*e4a36f41SAndroid Build Coastguard Worker } 122*e4a36f41SAndroid Build Coastguard Worker 123*e4a36f41SAndroid Build Coastguard Worker rule := android.NewRuleBuilder(pctx, ctx) 124*e4a36f41SAndroid Build Coastguard Worker rule.Command().BuiltTool("sepolicy_freeze_test"). 125*e4a36f41SAndroid Build Coastguard Worker FlagWithInput("-c ", currentCil). 126*e4a36f41SAndroid Build Coastguard Worker FlagWithInput("-p ", prebuiltCil) 127*e4a36f41SAndroid Build Coastguard Worker 128*e4a36f41SAndroid Build Coastguard Worker // Freeze test 2: compare extra directories 129*e4a36f41SAndroid Build Coastguard Worker // We don't know the exact structure of extra directories, so just directly compare them 130*e4a36f41SAndroid Build Coastguard Worker extraDirs := ctx.DeviceConfig().SepolicyFreezeTestExtraDirs() 131*e4a36f41SAndroid Build Coastguard Worker extraPrebuiltDirs := ctx.DeviceConfig().SepolicyFreezeTestExtraPrebuiltDirs() 132*e4a36f41SAndroid Build Coastguard Worker 133*e4a36f41SAndroid Build Coastguard Worker var implicits []string 134*e4a36f41SAndroid Build Coastguard Worker for _, dir := range append(extraDirs, extraPrebuiltDirs...) { 135*e4a36f41SAndroid Build Coastguard Worker glob, err := ctx.GlobWithDeps(dir+"/**/*", []string{"bug_map"} /* exclude */) 136*e4a36f41SAndroid Build Coastguard Worker if err != nil { 137*e4a36f41SAndroid Build Coastguard Worker ctx.ModuleErrorf("failed to glob sepolicy dir %q: %s", dir, err.Error()) 138*e4a36f41SAndroid Build Coastguard Worker return 139*e4a36f41SAndroid Build Coastguard Worker } 140*e4a36f41SAndroid Build Coastguard Worker implicits = append(implicits, glob...) 141*e4a36f41SAndroid Build Coastguard Worker } 142*e4a36f41SAndroid Build Coastguard Worker sort.Strings(implicits) 143*e4a36f41SAndroid Build Coastguard Worker 144*e4a36f41SAndroid Build Coastguard Worker for idx, _ := range extraDirs { 145*e4a36f41SAndroid Build Coastguard Worker rule.Command().Text("diff"). 146*e4a36f41SAndroid Build Coastguard Worker Flag("-r"). 147*e4a36f41SAndroid Build Coastguard Worker Flag("-q"). 148*e4a36f41SAndroid Build Coastguard Worker FlagWithArg("-x ", "bug_map"). // exclude 149*e4a36f41SAndroid Build Coastguard Worker Text(extraDirs[idx]). 150*e4a36f41SAndroid Build Coastguard Worker Text(extraPrebuiltDirs[idx]) 151*e4a36f41SAndroid Build Coastguard Worker } 152*e4a36f41SAndroid Build Coastguard Worker 153*e4a36f41SAndroid Build Coastguard Worker rule.Command().Text("touch"). 154*e4a36f41SAndroid Build Coastguard Worker Output(f.freezeTestTimestamp). 155*e4a36f41SAndroid Build Coastguard Worker Implicits(android.PathsForSource(ctx, implicits)) 156*e4a36f41SAndroid Build Coastguard Worker 157*e4a36f41SAndroid Build Coastguard Worker rule.Build("sepolicy_freeze_test", "sepolicy_freeze_test") 158*e4a36f41SAndroid Build Coastguard Worker} 159*e4a36f41SAndroid Build Coastguard Worker 160*e4a36f41SAndroid Build Coastguard Workerfunc (f *freezeTestModule) AndroidMkEntries() []android.AndroidMkEntries { 161*e4a36f41SAndroid Build Coastguard Worker return []android.AndroidMkEntries{android.AndroidMkEntries{ 162*e4a36f41SAndroid Build Coastguard Worker Class: "FAKE", 163*e4a36f41SAndroid Build Coastguard Worker // OutputFile is needed, even though BUILD_PHONY_PACKAGE doesn't use it. 164*e4a36f41SAndroid Build Coastguard Worker // Without OutputFile this module won't be exported to Makefile. 165*e4a36f41SAndroid Build Coastguard Worker OutputFile: android.OptionalPathForPath(f.freezeTestTimestamp), 166*e4a36f41SAndroid Build Coastguard Worker Include: "$(BUILD_PHONY_PACKAGE)", 167*e4a36f41SAndroid Build Coastguard Worker ExtraEntries: []android.AndroidMkExtraEntriesFunc{ 168*e4a36f41SAndroid Build Coastguard Worker func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { 169*e4a36f41SAndroid Build Coastguard Worker entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", f.freezeTestTimestamp.String()) 170*e4a36f41SAndroid Build Coastguard Worker }, 171*e4a36f41SAndroid Build Coastguard Worker }, 172*e4a36f41SAndroid Build Coastguard Worker }} 173*e4a36f41SAndroid Build Coastguard Worker} 174