1// Copyright 2021 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package selinux 16 17import ( 18 "path/filepath" 19 "sort" 20 21 "android/soong/android" 22) 23 24func init() { 25 ctx := android.InitRegistrationContext 26 ctx.RegisterSingletonModuleType("se_freeze_test", freezeTestFactory) 27} 28 29// se_freeze_test compares the plat sepolicy with the prebuilt sepolicy. Additional directories can 30// be specified via Makefile variables: SEPOLICY_FREEZE_TEST_EXTRA_DIRS and 31// SEPOLICY_FREEZE_TEST_EXTRA_PREBUILT_DIRS. 32func freezeTestFactory() android.SingletonModule { 33 f := &freezeTestModule{} 34 android.InitAndroidModule(f) 35 return f 36} 37 38type freezeTestModule struct { 39 android.SingletonModuleBase 40 freezeTestTimestamp android.ModuleOutPath 41} 42 43func (f *freezeTestModule) GenerateSingletonBuildActions(ctx android.SingletonContext) { 44 // does nothing; se_freeze_test is a singeton because two freeze test modules don't make sense. 45} 46 47func (f *freezeTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 48 platformVersion := ctx.DeviceConfig().PlatformSepolicyVersion() 49 totVersion := ctx.DeviceConfig().TotSepolicyVersion() 50 51 extraDirs := ctx.DeviceConfig().SepolicyFreezeTestExtraDirs() 52 extraPrebuiltDirs := ctx.DeviceConfig().SepolicyFreezeTestExtraPrebuiltDirs() 53 f.freezeTestTimestamp = android.PathForModuleOut(ctx, "freeze_test") 54 55 if platformVersion == totVersion { 56 if len(extraDirs) > 0 || len(extraPrebuiltDirs) > 0 { 57 ctx.ModuleErrorf("SEPOLICY_FREEZE_TEST_EXTRA_DIRS or SEPOLICY_FREEZE_TEST_EXTRA_PREBUILT_DIRS cannot be set before system/sepolicy freezes.") 58 return 59 } 60 61 // we still build a rule to prevent possible regression 62 android.WriteFileRule(ctx, f.freezeTestTimestamp, ";; no freeze tests needed before system/sepolicy freezes") 63 return 64 } 65 66 if len(extraDirs) != len(extraPrebuiltDirs) { 67 ctx.ModuleErrorf("SEPOLICY_FREEZE_TEST_EXTRA_DIRS and SEPOLICY_FREEZE_TEST_EXTRA_PREBUILT_DIRS must have the same number of directories.") 68 return 69 } 70 71 platPublic := filepath.Join(ctx.ModuleDir(), "public") 72 platPrivate := filepath.Join(ctx.ModuleDir(), "private") 73 prebuiltPublic := filepath.Join(ctx.ModuleDir(), "prebuilts", "api", platformVersion, "public") 74 prebuiltPrivate := filepath.Join(ctx.ModuleDir(), "prebuilts", "api", platformVersion, "private") 75 76 sourceDirs := append(extraDirs, platPublic, platPrivate) 77 prebuiltDirs := append(extraPrebuiltDirs, prebuiltPublic, prebuiltPrivate) 78 79 var implicits []string 80 for _, dir := range append(sourceDirs, prebuiltDirs...) { 81 glob, err := ctx.GlobWithDeps(dir+"/**/*", []string{"bug_map"} /* exclude */) 82 if err != nil { 83 ctx.ModuleErrorf("failed to glob sepolicy dir %q: %s", dir, err.Error()) 84 return 85 } 86 implicits = append(implicits, glob...) 87 } 88 sort.Strings(implicits) 89 90 rule := android.NewRuleBuilder(pctx, ctx) 91 92 for idx, _ := range sourceDirs { 93 rule.Command().Text("diff"). 94 Flag("-r"). 95 Flag("-q"). 96 FlagWithArg("-x ", "bug_map"). // exclude 97 Text(sourceDirs[idx]). 98 Text(prebuiltDirs[idx]) 99 } 100 101 rule.Command().Text("touch"). 102 Output(f.freezeTestTimestamp). 103 Implicits(android.PathsForSource(ctx, implicits)) 104 105 rule.Build("sepolicy_freeze_test", "sepolicy_freeze_test") 106} 107 108func (f *freezeTestModule) AndroidMkEntries() []android.AndroidMkEntries { 109 return []android.AndroidMkEntries{android.AndroidMkEntries{ 110 Class: "FAKE", 111 // OutputFile is needed, even though BUILD_PHONY_PACKAGE doesn't use it. 112 // Without OutputFile this module won't be exported to Makefile. 113 OutputFile: android.OptionalPathForPath(f.freezeTestTimestamp), 114 Include: "$(BUILD_PHONY_PACKAGE)", 115 ExtraEntries: []android.AndroidMkExtraEntriesFunc{ 116 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { 117 entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", f.freezeTestTimestamp.String()) 118 }, 119 }, 120 }} 121} 122