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 ( |
| 18 | "path/filepath" |
| 19 | "sort" |
| 20 | |
| 21 | "android/soong/android" |
| 22 | ) |
| 23 | |
| 24 | func 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. |
| 32 | func freezeTestFactory() android.SingletonModule { |
| 33 | f := &freezeTestModule{} |
| 34 | android.InitAndroidModule(f) |
| 35 | return f |
| 36 | } |
| 37 | |
| 38 | type freezeTestModule struct { |
| 39 | android.SingletonModuleBase |
| 40 | freezeTestTimestamp android.ModuleOutPath |
| 41 | } |
| 42 | |
| 43 | func (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 | |
| 47 | func (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 | |
| 108 | func (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 | } |