blob: afd2396ef454233eb0199b6b33ed20d60edab6ec [file] [log] [blame]
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +08001// 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 (
Inseob Kim16d3be32022-01-07 09:15:27 +090018 "fmt"
19
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080020 "github.com/google/blueprint/proptools"
21
22 "android/soong/android"
23)
24
Inseob Kim16d3be32022-01-07 09:15:27 +090025var (
26 compatTestDepTag = dependencyTag{name: "compat_test"}
27)
28
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080029func init() {
Inseob Kim16d3be32022-01-07 09:15:27 +090030 ctx := android.InitRegistrationContext
31 ctx.RegisterModuleType("se_compat_cil", compatCilFactory)
32 ctx.RegisterSingletonModuleType("se_compat_test", compatTestFactory)
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080033}
34
35// se_compat_cil collects and installs backwards compatibility cil files.
36func compatCilFactory() android.Module {
37 c := &compatCil{}
38 c.AddProperties(&c.properties)
39 android.InitAndroidArchModule(c, android.DeviceSupported, android.MultilibCommon)
40 return c
41}
42
43type compatCil struct {
44 android.ModuleBase
45 properties compatCilProperties
46 installSource android.Path
47 installPath android.InstallPath
48}
49
50type compatCilProperties struct {
Inseob Kim41964032022-04-22 07:50:22 +090051 // List of source files. Can reference se_build_files type modules with the ":module" syntax.
Paul Duffin532bde12021-07-09 22:53:03 +010052 Srcs []string `android:"path"`
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080053
54 // Output file name. Defaults to module name if unspecified.
55 Stem *string
56}
57
58func (c *compatCil) stem() string {
59 return proptools.StringDefault(c.properties.Stem, c.Name())
60}
61
62func (c *compatCil) expandSeSources(ctx android.ModuleContext) android.Paths {
Inseob Kim41964032022-04-22 07:50:22 +090063 return android.PathsForModuleSrc(ctx, c.properties.Srcs)
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080064}
65
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080066func (c *compatCil) GenerateAndroidBuildActions(ctx android.ModuleContext) {
67 if c.ProductSpecific() || c.SocSpecific() || c.DeviceSpecific() {
68 ctx.ModuleErrorf("Compat cil files only support system and system_ext partitions")
69 }
70
71 srcPaths := c.expandSeSources(ctx)
72 out := android.PathForModuleGen(ctx, c.Name())
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080073 ctx.Build(pctx, android.BuildParams{
74 Rule: android.Cat,
75 Inputs: srcPaths,
76 Output: out,
77 Description: "Combining compat cil for " + c.Name(),
78 })
79
80 c.installPath = android.PathForModuleInstall(ctx, "etc", "selinux", "mapping")
81 c.installSource = out
82 ctx.InstallFile(c.installPath, c.stem(), c.installSource)
83}
84
85func (c *compatCil) AndroidMkEntries() []android.AndroidMkEntries {
86 return []android.AndroidMkEntries{android.AndroidMkEntries{
87 Class: "ETC",
88 OutputFile: android.OptionalPathForPath(c.installSource),
89 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
90 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
Colin Cross6c7f9372022-01-11 19:35:43 -080091 entries.SetPath("LOCAL_MODULE_PATH", c.installPath)
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080092 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", c.stem())
93 },
94 },
95 }}
96}
Inseob Kim16d3be32022-01-07 09:15:27 +090097
98func (c *compatCil) OutputFiles(tag string) (android.Paths, error) {
99 switch tag {
100 case "":
101 return android.Paths{c.installSource}, nil
102 default:
103 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
104 }
105}
106
107var _ android.OutputFileProducer = (*compatCil)(nil)
108
109// se_compat_test checks if compat files ({ver}.cil, {ver}.compat.cil) files are compatible with
110// current policy.
111func compatTestFactory() android.SingletonModule {
112 f := &compatTestModule{}
113 android.InitAndroidModule(f)
114 android.AddLoadHook(f, func(ctx android.LoadHookContext) {
115 f.loadHook(ctx)
116 })
117 return f
118}
119
120type compatTestModule struct {
121 android.SingletonModuleBase
122
123 compatTestTimestamp android.ModuleOutPath
124}
125
126func (f *compatTestModule) createPlatPubVersionedModule(ctx android.LoadHookContext, ver string) {
127 confName := fmt.Sprintf("pub_policy_%s.conf", ver)
128 cilName := fmt.Sprintf("pub_policy_%s.cil", ver)
129 platPubVersionedName := fmt.Sprintf("plat_pub_versioned_%s.cil", ver)
130
131 ctx.CreateModule(policyConfFactory, &nameProperties{
132 Name: proptools.StringPtr(confName),
133 }, &policyConfProperties{
134 Srcs: []string{
135 fmt.Sprintf(":se_build_files{.plat_public_%s}", ver),
Inseob Kim73f43ff2022-02-14 23:01:04 +0900136 fmt.Sprintf(":se_build_files{.system_ext_public_%s}", ver),
137 fmt.Sprintf(":se_build_files{.product_public_%s}", ver),
Inseob Kim16d3be32022-01-07 09:15:27 +0900138 ":se_build_files{.reqd_mask}",
139 },
140 Installable: proptools.BoolPtr(false),
141 })
142
143 ctx.CreateModule(policyCilFactory, &nameProperties{
144 Name: proptools.StringPtr(cilName),
145 }, &policyCilProperties{
146 Src: proptools.StringPtr(":" + confName),
147 Filter_out: []string{":reqd_policy_mask.cil"},
148 Secilc_check: proptools.BoolPtr(false),
149 Installable: proptools.BoolPtr(false),
150 })
151
152 ctx.CreateModule(versionedPolicyFactory, &nameProperties{
153 Name: proptools.StringPtr(platPubVersionedName),
154 }, &versionedPolicyProperties{
155 Base: proptools.StringPtr(":" + cilName),
156 Target_policy: proptools.StringPtr(":" + cilName),
157 Version: proptools.StringPtr(ver),
158 Installable: proptools.BoolPtr(false),
159 })
160}
161
162func (f *compatTestModule) createCompatTestModule(ctx android.LoadHookContext, ver string) {
163 srcs := []string{
164 ":plat_sepolicy.cil",
165 ":system_ext_sepolicy.cil",
166 ":product_sepolicy.cil",
167 fmt.Sprintf(":plat_%s.cil", ver),
168 fmt.Sprintf(":%s.compat.cil", ver),
169 fmt.Sprintf(":system_ext_%s.cil", ver),
170 fmt.Sprintf(":system_ext_%s.compat.cil", ver),
171 fmt.Sprintf(":product_%s.cil", ver),
172 }
173
174 if ver == ctx.DeviceConfig().BoardSepolicyVers() {
175 srcs = append(srcs,
176 ":plat_pub_versioned.cil",
177 ":vendor_sepolicy.cil",
178 ":odm_sepolicy.cil",
179 )
180 } else {
181 srcs = append(srcs, fmt.Sprintf(":plat_pub_versioned_%s.cil", ver))
182 }
183
184 compatTestName := fmt.Sprintf("%s_compat_test", ver)
185 ctx.CreateModule(policyBinaryFactory, &nameProperties{
186 Name: proptools.StringPtr(compatTestName),
187 }, &policyBinaryProperties{
188 Srcs: srcs,
189 Ignore_neverallow: proptools.BoolPtr(true),
190 Installable: proptools.BoolPtr(false),
191 })
192}
193
194func (f *compatTestModule) loadHook(ctx android.LoadHookContext) {
195 for _, ver := range ctx.DeviceConfig().PlatformSepolicyCompatVersions() {
196 f.createPlatPubVersionedModule(ctx, ver)
197 f.createCompatTestModule(ctx, ver)
198 }
199}
200
201func (f *compatTestModule) DepsMutator(ctx android.BottomUpMutatorContext) {
202 for _, ver := range ctx.DeviceConfig().PlatformSepolicyCompatVersions() {
203 ctx.AddDependency(f, compatTestDepTag, fmt.Sprintf("%s_compat_test", ver))
204 }
205}
206
207func (f *compatTestModule) GenerateSingletonBuildActions(ctx android.SingletonContext) {
208 // does nothing; se_compat_test is a singeton because two compat test modules don't make sense.
209}
210
211func (f *compatTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
212 var inputs android.Paths
213 ctx.VisitDirectDepsWithTag(compatTestDepTag, func(child android.Module) {
214 o, ok := child.(android.OutputFileProducer)
215 if !ok {
216 panic(fmt.Errorf("Module %q should be an OutputFileProducer but it isn't", ctx.OtherModuleName(child)))
217 }
218
219 outputs, err := o.OutputFiles("")
220 if err != nil {
221 panic(fmt.Errorf("Module %q error while producing output: %v", ctx.OtherModuleName(child), err))
222 }
223 if len(outputs) != 1 {
224 panic(fmt.Errorf("Module %q should produce exactly one output, but did %q", ctx.OtherModuleName(child), outputs.Strings()))
225 }
226
227 inputs = append(inputs, outputs[0])
228 })
229
230 f.compatTestTimestamp = android.PathForModuleOut(ctx, "timestamp")
231 rule := android.NewRuleBuilder(pctx, ctx)
232 rule.Command().Text("touch").Output(f.compatTestTimestamp).Implicits(inputs)
233 rule.Build("compat", "compat test timestamp for: "+f.Name())
234}
235
236func (f *compatTestModule) AndroidMkEntries() []android.AndroidMkEntries {
237 return []android.AndroidMkEntries{android.AndroidMkEntries{
238 Class: "FAKE",
239 // OutputFile is needed, even though BUILD_PHONY_PACKAGE doesn't use it.
240 // Without OutputFile this module won't be exported to Makefile.
241 OutputFile: android.OptionalPathForPath(f.compatTestTimestamp),
242 Include: "$(BUILD_PHONY_PACKAGE)",
243 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
244 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
245 entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", f.compatTestTimestamp.String())
246 },
247 },
248 }}
249}