Inseob Kim | d581661 | 2021-09-15 03:01:05 +0000 | [diff] [blame] | 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 | |
| 15 | package selinux |
| 16 | |
| 17 | import ( |
Inseob Kim | d581661 | 2021-09-15 03:01:05 +0000 | [diff] [blame] | 18 | "sort" |
| 19 | |
| 20 | "android/soong/android" |
| 21 | ) |
| 22 | |
Inseob Kim | 36d9d39 | 2023-09-04 17:40:03 +0900 | [diff] [blame^] | 23 | var currentCilTag = dependencyTag{name: "current_cil"} |
| 24 | var prebuiltCilTag = dependencyTag{name: "prebuilt_cil"} |
| 25 | |
Inseob Kim | d581661 | 2021-09-15 03:01:05 +0000 | [diff] [blame] | 26 | func init() { |
| 27 | ctx := android.InitRegistrationContext |
LaMont Jones | 3ee8984 | 2023-05-16 16:59:17 +0000 | [diff] [blame] | 28 | ctx.RegisterParallelSingletonModuleType("se_freeze_test", freezeTestFactory) |
Inseob Kim | d581661 | 2021-09-15 03:01:05 +0000 | [diff] [blame] | 29 | } |
| 30 | |
| 31 | // se_freeze_test compares the plat sepolicy with the prebuilt sepolicy. Additional directories can |
| 32 | // be specified via Makefile variables: SEPOLICY_FREEZE_TEST_EXTRA_DIRS and |
| 33 | // SEPOLICY_FREEZE_TEST_EXTRA_PREBUILT_DIRS. |
| 34 | func freezeTestFactory() android.SingletonModule { |
| 35 | f := &freezeTestModule{} |
| 36 | android.InitAndroidModule(f) |
Inseob Kim | 36d9d39 | 2023-09-04 17:40:03 +0900 | [diff] [blame^] | 37 | android.AddLoadHook(f, func(ctx android.LoadHookContext) { |
| 38 | f.loadHook(ctx) |
| 39 | }) |
Inseob Kim | d581661 | 2021-09-15 03:01:05 +0000 | [diff] [blame] | 40 | return f |
| 41 | } |
| 42 | |
| 43 | type freezeTestModule struct { |
| 44 | android.SingletonModuleBase |
| 45 | freezeTestTimestamp android.ModuleOutPath |
| 46 | } |
| 47 | |
Inseob Kim | 36d9d39 | 2023-09-04 17:40:03 +0900 | [diff] [blame^] | 48 | func (f *freezeTestModule) shouldSkip(ctx android.EarlyModuleContext) bool { |
Inseob Kim | d581661 | 2021-09-15 03:01:05 +0000 | [diff] [blame] | 49 | platformVersion := ctx.DeviceConfig().PlatformSepolicyVersion() |
| 50 | totVersion := ctx.DeviceConfig().TotSepolicyVersion() |
| 51 | |
Inseob Kim | 36d9d39 | 2023-09-04 17:40:03 +0900 | [diff] [blame^] | 52 | return platformVersion == totVersion |
| 53 | } |
| 54 | |
| 55 | func (f *freezeTestModule) loadHook(ctx android.LoadHookContext) { |
Inseob Kim | d581661 | 2021-09-15 03:01:05 +0000 | [diff] [blame] | 56 | extraDirs := ctx.DeviceConfig().SepolicyFreezeTestExtraDirs() |
| 57 | extraPrebuiltDirs := ctx.DeviceConfig().SepolicyFreezeTestExtraPrebuiltDirs() |
Inseob Kim | d581661 | 2021-09-15 03:01:05 +0000 | [diff] [blame] | 58 | |
Inseob Kim | 36d9d39 | 2023-09-04 17:40:03 +0900 | [diff] [blame^] | 59 | if f.shouldSkip(ctx) { |
Inseob Kim | d581661 | 2021-09-15 03:01:05 +0000 | [diff] [blame] | 60 | if len(extraDirs) > 0 || len(extraPrebuiltDirs) > 0 { |
| 61 | ctx.ModuleErrorf("SEPOLICY_FREEZE_TEST_EXTRA_DIRS or SEPOLICY_FREEZE_TEST_EXTRA_PREBUILT_DIRS cannot be set before system/sepolicy freezes.") |
| 62 | return |
| 63 | } |
| 64 | |
Inseob Kim | d581661 | 2021-09-15 03:01:05 +0000 | [diff] [blame] | 65 | return |
| 66 | } |
| 67 | |
| 68 | if len(extraDirs) != len(extraPrebuiltDirs) { |
| 69 | ctx.ModuleErrorf("SEPOLICY_FREEZE_TEST_EXTRA_DIRS and SEPOLICY_FREEZE_TEST_EXTRA_PREBUILT_DIRS must have the same number of directories.") |
| 70 | return |
| 71 | } |
Inseob Kim | 36d9d39 | 2023-09-04 17:40:03 +0900 | [diff] [blame^] | 72 | } |
Inseob Kim | d581661 | 2021-09-15 03:01:05 +0000 | [diff] [blame] | 73 | |
Inseob Kim | 36d9d39 | 2023-09-04 17:40:03 +0900 | [diff] [blame^] | 74 | func (f *freezeTestModule) prebuiltCilModuleName(ctx android.EarlyModuleContext) string { |
| 75 | return ctx.DeviceConfig().PlatformSepolicyVersion() + "_plat_pub_policy.cil" |
| 76 | } |
Inseob Kim | d581661 | 2021-09-15 03:01:05 +0000 | [diff] [blame] | 77 | |
Inseob Kim | 36d9d39 | 2023-09-04 17:40:03 +0900 | [diff] [blame^] | 78 | func (f *freezeTestModule) DepsMutator(ctx android.BottomUpMutatorContext) { |
| 79 | if f.shouldSkip(ctx) { |
| 80 | return |
| 81 | } |
| 82 | |
| 83 | ctx.AddDependency(f, currentCilTag, "base_plat_pub_policy.cil") |
| 84 | ctx.AddDependency(f, prebuiltCilTag, f.prebuiltCilModuleName(ctx)) |
| 85 | } |
| 86 | |
| 87 | func (f *freezeTestModule) GenerateSingletonBuildActions(ctx android.SingletonContext) { |
| 88 | // does nothing; se_freeze_test is a singeton because two freeze test modules don't make sense. |
| 89 | } |
| 90 | |
| 91 | func (f *freezeTestModule) outputFileOfDep(ctx android.ModuleContext, depTag dependencyTag) android.Path { |
| 92 | deps := ctx.GetDirectDepsWithTag(depTag) |
| 93 | if len(deps) != 1 { |
| 94 | ctx.ModuleErrorf("%d deps having tag %q; expected only one dep", len(deps), depTag) |
| 95 | return nil |
| 96 | } |
| 97 | |
| 98 | dep := deps[0] |
| 99 | outputFileProducer, ok := dep.(android.OutputFileProducer) |
| 100 | if !ok { |
| 101 | ctx.ModuleErrorf("module %q is not an output file producer", dep.String()) |
| 102 | return nil |
| 103 | } |
| 104 | |
| 105 | output, err := outputFileProducer.OutputFiles("") |
| 106 | if err != nil { |
| 107 | ctx.ModuleErrorf("module %q failed to produce output: %w", dep.String(), err) |
| 108 | return nil |
| 109 | } |
| 110 | if len(output) != 1 { |
| 111 | ctx.ModuleErrorf("module %q produced %d outputs; expected only one output", dep.String(), len(output)) |
| 112 | return nil |
| 113 | } |
| 114 | |
| 115 | return output[0] |
| 116 | } |
| 117 | |
| 118 | func (f *freezeTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { |
| 119 | f.freezeTestTimestamp = android.PathForModuleOut(ctx, "freeze_test") |
| 120 | |
| 121 | if f.shouldSkip(ctx) { |
| 122 | // we still build a rule to prevent possible regression |
| 123 | android.WriteFileRule(ctx, f.freezeTestTimestamp, ";; no freeze tests needed before system/sepolicy freezes") |
| 124 | return |
| 125 | } |
| 126 | |
| 127 | // Freeze test 1: compare ToT sepolicy and prebuilt sepolicy |
| 128 | currentCil := f.outputFileOfDep(ctx, currentCilTag) |
| 129 | prebuiltCil := f.outputFileOfDep(ctx, prebuiltCilTag) |
| 130 | if ctx.Failed() { |
| 131 | return |
| 132 | } |
| 133 | |
| 134 | rule := android.NewRuleBuilder(pctx, ctx) |
| 135 | rule.Command().BuiltTool("sepolicy_freeze_test"). |
| 136 | FlagWithInput("-c ", currentCil). |
| 137 | FlagWithInput("-p ", prebuiltCil) |
| 138 | |
| 139 | // Freeze test 2: compare extra directories |
| 140 | // We don't know the exact structure of extra directories, so just directly compare them |
| 141 | extraDirs := ctx.DeviceConfig().SepolicyFreezeTestExtraDirs() |
| 142 | extraPrebuiltDirs := ctx.DeviceConfig().SepolicyFreezeTestExtraPrebuiltDirs() |
Inseob Kim | d581661 | 2021-09-15 03:01:05 +0000 | [diff] [blame] | 143 | |
| 144 | var implicits []string |
Inseob Kim | 36d9d39 | 2023-09-04 17:40:03 +0900 | [diff] [blame^] | 145 | for _, dir := range append(extraDirs, extraPrebuiltDirs...) { |
Inseob Kim | d581661 | 2021-09-15 03:01:05 +0000 | [diff] [blame] | 146 | glob, err := ctx.GlobWithDeps(dir+"/**/*", []string{"bug_map"} /* exclude */) |
| 147 | if err != nil { |
| 148 | ctx.ModuleErrorf("failed to glob sepolicy dir %q: %s", dir, err.Error()) |
| 149 | return |
| 150 | } |
| 151 | implicits = append(implicits, glob...) |
| 152 | } |
| 153 | sort.Strings(implicits) |
| 154 | |
Inseob Kim | 36d9d39 | 2023-09-04 17:40:03 +0900 | [diff] [blame^] | 155 | for idx, _ := range extraDirs { |
Inseob Kim | d581661 | 2021-09-15 03:01:05 +0000 | [diff] [blame] | 156 | rule.Command().Text("diff"). |
| 157 | Flag("-r"). |
| 158 | Flag("-q"). |
| 159 | FlagWithArg("-x ", "bug_map"). // exclude |
Inseob Kim | 36d9d39 | 2023-09-04 17:40:03 +0900 | [diff] [blame^] | 160 | Text(extraDirs[idx]). |
| 161 | Text(extraPrebuiltDirs[idx]) |
Inseob Kim | d581661 | 2021-09-15 03:01:05 +0000 | [diff] [blame] | 162 | } |
| 163 | |
| 164 | rule.Command().Text("touch"). |
| 165 | Output(f.freezeTestTimestamp). |
| 166 | Implicits(android.PathsForSource(ctx, implicits)) |
| 167 | |
| 168 | rule.Build("sepolicy_freeze_test", "sepolicy_freeze_test") |
| 169 | } |
| 170 | |
| 171 | func (f *freezeTestModule) AndroidMkEntries() []android.AndroidMkEntries { |
| 172 | return []android.AndroidMkEntries{android.AndroidMkEntries{ |
| 173 | Class: "FAKE", |
| 174 | // OutputFile is needed, even though BUILD_PHONY_PACKAGE doesn't use it. |
| 175 | // Without OutputFile this module won't be exported to Makefile. |
| 176 | OutputFile: android.OptionalPathForPath(f.freezeTestTimestamp), |
| 177 | Include: "$(BUILD_PHONY_PACKAGE)", |
| 178 | ExtraEntries: []android.AndroidMkExtraEntriesFunc{ |
| 179 | func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { |
| 180 | entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", f.freezeTestTimestamp.String()) |
| 181 | }, |
| 182 | }, |
| 183 | }} |
| 184 | } |