• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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