blob: baad4136d01e22fce13f530d40ac0f61f77752bf [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)
LaMont Jones3ee89842023-05-16 16:59:17 +000032 ctx.RegisterParallelSingletonModuleType("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
Inseob Kim61d6beb2023-08-23 08:37:20 +000046 installSource android.OptionalPath
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080047 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
Inseob Kim61d6beb2023-08-23 08:37:20 +000056
57 // Target version that this module supports. This module will be ignored if platform sepolicy
58 // version is same as this module's version.
59 Version *string
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080060}
61
62func (c *compatCil) stem() string {
63 return proptools.StringDefault(c.properties.Stem, c.Name())
64}
65
66func (c *compatCil) expandSeSources(ctx android.ModuleContext) android.Paths {
Inseob Kim41964032022-04-22 07:50:22 +090067 return android.PathsForModuleSrc(ctx, c.properties.Srcs)
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080068}
69
Inseob Kim61d6beb2023-08-23 08:37:20 +000070func (c *compatCil) shouldSkipBuild(ctx android.ModuleContext) bool {
71 return proptools.String(c.properties.Version) == ctx.DeviceConfig().PlatformSepolicyVersion()
72}
73
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080074func (c *compatCil) GenerateAndroidBuildActions(ctx android.ModuleContext) {
75 if c.ProductSpecific() || c.SocSpecific() || c.DeviceSpecific() {
76 ctx.ModuleErrorf("Compat cil files only support system and system_ext partitions")
77 }
78
Inseob Kim61d6beb2023-08-23 08:37:20 +000079 if c.shouldSkipBuild(ctx) {
80 return
81 }
82
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080083 srcPaths := c.expandSeSources(ctx)
84 out := android.PathForModuleGen(ctx, c.Name())
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080085 ctx.Build(pctx, android.BuildParams{
86 Rule: android.Cat,
87 Inputs: srcPaths,
88 Output: out,
89 Description: "Combining compat cil for " + c.Name(),
90 })
91
92 c.installPath = android.PathForModuleInstall(ctx, "etc", "selinux", "mapping")
Inseob Kim61d6beb2023-08-23 08:37:20 +000093 c.installSource = android.OptionalPathForPath(out)
94 ctx.InstallFile(c.installPath, c.stem(), out)
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080095}
96
97func (c *compatCil) AndroidMkEntries() []android.AndroidMkEntries {
Inseob Kim61d6beb2023-08-23 08:37:20 +000098 if !c.installSource.Valid() {
99 return nil
100 }
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +0800101 return []android.AndroidMkEntries{android.AndroidMkEntries{
102 Class: "ETC",
Inseob Kim61d6beb2023-08-23 08:37:20 +0000103 OutputFile: c.installSource,
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +0800104 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
105 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
Colin Cross6c7f9372022-01-11 19:35:43 -0800106 entries.SetPath("LOCAL_MODULE_PATH", c.installPath)
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +0800107 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", c.stem())
108 },
109 },
110 }}
111}
Inseob Kim16d3be32022-01-07 09:15:27 +0900112
113func (c *compatCil) OutputFiles(tag string) (android.Paths, error) {
114 switch tag {
115 case "":
Inseob Kim61d6beb2023-08-23 08:37:20 +0000116 if c.installSource.Valid() {
117 return android.Paths{c.installSource.Path()}, nil
118 } else {
119 return nil, nil
120 }
Inseob Kim16d3be32022-01-07 09:15:27 +0900121 default:
122 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
123 }
124}
125
126var _ android.OutputFileProducer = (*compatCil)(nil)
127
128// se_compat_test checks if compat files ({ver}.cil, {ver}.compat.cil) files are compatible with
129// current policy.
130func compatTestFactory() android.SingletonModule {
131 f := &compatTestModule{}
Inseob Kim085f22f2023-11-09 11:13:01 +0900132 f.AddProperties(&f.properties)
Inseob Kim16d3be32022-01-07 09:15:27 +0900133 android.InitAndroidModule(f)
134 android.AddLoadHook(f, func(ctx android.LoadHookContext) {
135 f.loadHook(ctx)
136 })
137 return f
138}
139
140type compatTestModule struct {
141 android.SingletonModuleBase
Inseob Kim085f22f2023-11-09 11:13:01 +0900142 properties struct {
143 // Default modules for conf
144 Defaults []string
145 }
Inseob Kim16d3be32022-01-07 09:15:27 +0900146
147 compatTestTimestamp android.ModuleOutPath
148}
149
150func (f *compatTestModule) createPlatPubVersionedModule(ctx android.LoadHookContext, ver string) {
151 confName := fmt.Sprintf("pub_policy_%s.conf", ver)
152 cilName := fmt.Sprintf("pub_policy_%s.cil", ver)
153 platPubVersionedName := fmt.Sprintf("plat_pub_versioned_%s.cil", ver)
154
155 ctx.CreateModule(policyConfFactory, &nameProperties{
156 Name: proptools.StringPtr(confName),
157 }, &policyConfProperties{
158 Srcs: []string{
159 fmt.Sprintf(":se_build_files{.plat_public_%s}", ver),
Inseob Kim73f43ff2022-02-14 23:01:04 +0900160 fmt.Sprintf(":se_build_files{.system_ext_public_%s}", ver),
161 fmt.Sprintf(":se_build_files{.product_public_%s}", ver),
Inseob Kim16d3be32022-01-07 09:15:27 +0900162 ":se_build_files{.reqd_mask}",
163 },
164 Installable: proptools.BoolPtr(false),
Inseob Kim085f22f2023-11-09 11:13:01 +0900165 }, &struct {
166 Defaults []string
167 }{
168 Defaults: f.properties.Defaults,
Inseob Kim16d3be32022-01-07 09:15:27 +0900169 })
170
171 ctx.CreateModule(policyCilFactory, &nameProperties{
172 Name: proptools.StringPtr(cilName),
173 }, &policyCilProperties{
174 Src: proptools.StringPtr(":" + confName),
175 Filter_out: []string{":reqd_policy_mask.cil"},
176 Secilc_check: proptools.BoolPtr(false),
177 Installable: proptools.BoolPtr(false),
178 })
179
180 ctx.CreateModule(versionedPolicyFactory, &nameProperties{
181 Name: proptools.StringPtr(platPubVersionedName),
182 }, &versionedPolicyProperties{
183 Base: proptools.StringPtr(":" + cilName),
184 Target_policy: proptools.StringPtr(":" + cilName),
185 Version: proptools.StringPtr(ver),
186 Installable: proptools.BoolPtr(false),
187 })
188}
189
190func (f *compatTestModule) createCompatTestModule(ctx android.LoadHookContext, ver string) {
191 srcs := []string{
192 ":plat_sepolicy.cil",
193 ":system_ext_sepolicy.cil",
194 ":product_sepolicy.cil",
195 fmt.Sprintf(":plat_%s.cil", ver),
196 fmt.Sprintf(":%s.compat.cil", ver),
197 fmt.Sprintf(":system_ext_%s.cil", ver),
198 fmt.Sprintf(":system_ext_%s.compat.cil", ver),
199 fmt.Sprintf(":product_%s.cil", ver),
200 }
201
202 if ver == ctx.DeviceConfig().BoardSepolicyVers() {
203 srcs = append(srcs,
204 ":plat_pub_versioned.cil",
205 ":vendor_sepolicy.cil",
206 ":odm_sepolicy.cil",
207 )
208 } else {
209 srcs = append(srcs, fmt.Sprintf(":plat_pub_versioned_%s.cil", ver))
210 }
211
212 compatTestName := fmt.Sprintf("%s_compat_test", ver)
213 ctx.CreateModule(policyBinaryFactory, &nameProperties{
214 Name: proptools.StringPtr(compatTestName),
215 }, &policyBinaryProperties{
216 Srcs: srcs,
217 Ignore_neverallow: proptools.BoolPtr(true),
218 Installable: proptools.BoolPtr(false),
219 })
220}
221
222func (f *compatTestModule) loadHook(ctx android.LoadHookContext) {
223 for _, ver := range ctx.DeviceConfig().PlatformSepolicyCompatVersions() {
224 f.createPlatPubVersionedModule(ctx, ver)
225 f.createCompatTestModule(ctx, ver)
226 }
227}
228
229func (f *compatTestModule) DepsMutator(ctx android.BottomUpMutatorContext) {
230 for _, ver := range ctx.DeviceConfig().PlatformSepolicyCompatVersions() {
231 ctx.AddDependency(f, compatTestDepTag, fmt.Sprintf("%s_compat_test", ver))
232 }
233}
234
235func (f *compatTestModule) GenerateSingletonBuildActions(ctx android.SingletonContext) {
236 // does nothing; se_compat_test is a singeton because two compat test modules don't make sense.
237}
238
239func (f *compatTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
240 var inputs android.Paths
241 ctx.VisitDirectDepsWithTag(compatTestDepTag, func(child android.Module) {
242 o, ok := child.(android.OutputFileProducer)
243 if !ok {
244 panic(fmt.Errorf("Module %q should be an OutputFileProducer but it isn't", ctx.OtherModuleName(child)))
245 }
246
247 outputs, err := o.OutputFiles("")
248 if err != nil {
249 panic(fmt.Errorf("Module %q error while producing output: %v", ctx.OtherModuleName(child), err))
250 }
251 if len(outputs) != 1 {
252 panic(fmt.Errorf("Module %q should produce exactly one output, but did %q", ctx.OtherModuleName(child), outputs.Strings()))
253 }
254
255 inputs = append(inputs, outputs[0])
256 })
257
258 f.compatTestTimestamp = android.PathForModuleOut(ctx, "timestamp")
259 rule := android.NewRuleBuilder(pctx, ctx)
260 rule.Command().Text("touch").Output(f.compatTestTimestamp).Implicits(inputs)
261 rule.Build("compat", "compat test timestamp for: "+f.Name())
262}
263
264func (f *compatTestModule) AndroidMkEntries() []android.AndroidMkEntries {
265 return []android.AndroidMkEntries{android.AndroidMkEntries{
266 Class: "FAKE",
267 // OutputFile is needed, even though BUILD_PHONY_PACKAGE doesn't use it.
268 // Without OutputFile this module won't be exported to Makefile.
269 OutputFile: android.OptionalPathForPath(f.compatTestTimestamp),
270 Include: "$(BUILD_PHONY_PACKAGE)",
271 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
272 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
273 entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", f.compatTestTimestamp.String())
274 },
275 },
276 }}
277}