blob: d4c81e8b0c52dd27950553805cea46795885f519 [file] [log] [blame]
Inseob Kimb554e592019-04-15 20:10:46 +09001// Copyright (C) 2019 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 "fmt"
19 "io"
Inseob Kimb554e592019-04-15 20:10:46 +090020
Inseob Kimcd616492020-03-24 23:06:40 +090021 "github.com/google/blueprint"
Inseob Kimb554e592019-04-15 20:10:46 +090022 "github.com/google/blueprint/proptools"
23
24 "android/soong/android"
Inseob Kimcd616492020-03-24 23:06:40 +090025 "android/soong/sysprop"
Inseob Kimb554e592019-04-15 20:10:46 +090026)
27
Inseob Kimb554e592019-04-15 20:10:46 +090028type selinuxContextsProperties struct {
29 // Filenames under sepolicy directories, which will be used to generate contexts file.
30 Srcs []string `android:"path"`
31
Yuntao Xu42e732c2021-11-18 22:33:02 +000032 // Output file name. Defaults to module name
33 Stem *string
34
Inseob Kimb554e592019-04-15 20:10:46 +090035 Product_variables struct {
Inseob Kimb554e592019-04-15 20:10:46 +090036 Address_sanitize struct {
Inseob Kim6d3d5a62021-12-21 20:55:32 +090037 Srcs []string `android:"path"`
Inseob Kimb554e592019-04-15 20:10:46 +090038 }
39 }
40
Inseob Kimb554e592019-04-15 20:10:46 +090041 // Whether the comments in generated contexts file will be removed or not.
42 Remove_comment *bool
43
44 // Whether the result context file is sorted with fc_sort or not.
45 Fc_sort *bool
46
47 // Make this module available when building for recovery
48 Recovery_available *bool
Inseob Kimb554e592019-04-15 20:10:46 +090049}
50
Inseob Kim2dac2672021-12-29 17:54:57 +090051type seappProperties struct {
52 // Files containing neverallow rules.
53 Neverallow_files []string `android:"path"`
54
55 // Precompiled sepolicy binary file which will be fed to checkseapp.
56 Sepolicy *string `android:"path"`
57}
58
Inseob Kimb554e592019-04-15 20:10:46 +090059type selinuxContextsModule struct {
60 android.ModuleBase
Inseob Kim6cd0ddd2023-10-25 23:48:16 +090061 android.DefaultableModuleBase
62 flaggableModuleBase
Inseob Kimb554e592019-04-15 20:10:46 +090063
Jooyung Han804e2342023-06-20 15:38:50 +090064 properties selinuxContextsProperties
65 seappProperties seappProperties
66 build func(ctx android.ModuleContext, inputs android.Paths) android.Path
67 deps func(ctx android.BottomUpMutatorContext)
68 outputPath android.Path
69 installPath android.InstallPath
Inseob Kimb554e592019-04-15 20:10:46 +090070}
71
Inseob Kim6cd0ddd2023-10-25 23:48:16 +090072var _ flaggableModule = (*selinuxContextsModule)(nil)
73
Inseob Kimb554e592019-04-15 20:10:46 +090074var (
Inseob Kimcd616492020-03-24 23:06:40 +090075 reuseContextsDepTag = dependencyTag{name: "reuseContexts"}
76 syspropLibraryDepTag = dependencyTag{name: "sysprop_library"}
Inseob Kimb554e592019-04-15 20:10:46 +090077)
78
79func init() {
80 pctx.HostBinToolVariable("fc_sort", "fc_sort")
81
Inseob Kim6cd0ddd2023-10-25 23:48:16 +090082 android.RegisterModuleType("contexts_defaults", contextsDefaultsFactory)
Inseob Kimb554e592019-04-15 20:10:46 +090083 android.RegisterModuleType("file_contexts", fileFactory)
84 android.RegisterModuleType("hwservice_contexts", hwServiceFactory)
85 android.RegisterModuleType("property_contexts", propertyFactory)
86 android.RegisterModuleType("service_contexts", serviceFactory)
Janis Danisevskisc40681f2020-07-25 13:02:29 -070087 android.RegisterModuleType("keystore2_key_contexts", keystoreKeyFactory)
Inseob Kim2dac2672021-12-29 17:54:57 +090088 android.RegisterModuleType("seapp_contexts", seappFactory)
Inseob Kimc7596c42022-02-25 11:45:41 +090089 android.RegisterModuleType("vndservice_contexts", vndServiceFactory)
Inseob Kimb5e23532022-02-16 02:26:11 +000090
91 android.RegisterModuleType("file_contexts_test", fileContextsTestFactory)
92 android.RegisterModuleType("property_contexts_test", propertyContextsTestFactory)
93 android.RegisterModuleType("hwservice_contexts_test", hwserviceContextsTestFactory)
94 android.RegisterModuleType("service_contexts_test", serviceContextsTestFactory)
Inseob Kimc7596c42022-02-25 11:45:41 +090095 android.RegisterModuleType("vndservice_contexts_test", vndServiceContextsTestFactory)
Inseob Kimb554e592019-04-15 20:10:46 +090096}
97
Colin Cross040f1512019-10-02 10:36:09 -070098func (m *selinuxContextsModule) InstallInRoot() bool {
Inseob Kimfa6fe472021-01-12 13:40:27 +090099 return m.InRecovery()
100}
101
102func (m *selinuxContextsModule) InstallInRecovery() bool {
103 // ModuleBase.InRecovery() checks the image variant
104 return m.InRecovery()
105}
106
107func (m *selinuxContextsModule) onlyInRecovery() bool {
108 // ModuleBase.InstallInRecovery() checks commonProperties.Recovery property
109 return m.ModuleBase.InstallInRecovery()
Colin Cross040f1512019-10-02 10:36:09 -0700110}
111
Inseob Kimcd616492020-03-24 23:06:40 +0900112func (m *selinuxContextsModule) DepsMutator(ctx android.BottomUpMutatorContext) {
Inseob Kimbf7f4a42024-02-14 13:53:39 +0900113 m.flagDeps(ctx)
114
Inseob Kimcd616492020-03-24 23:06:40 +0900115 if m.deps != nil {
116 m.deps(ctx)
117 }
Inseob Kimfa6fe472021-01-12 13:40:27 +0900118
119 if m.InRecovery() && !m.onlyInRecovery() {
120 ctx.AddFarVariationDependencies([]blueprint.Variation{
121 {Mutator: "image", Variation: android.CoreVariation},
122 }, reuseContextsDepTag, ctx.ModuleName())
123 }
Inseob Kimcd616492020-03-24 23:06:40 +0900124}
125
126func (m *selinuxContextsModule) propertyContextsDeps(ctx android.BottomUpMutatorContext) {
127 for _, lib := range sysprop.SyspropLibraries(ctx.Config()) {
128 ctx.AddFarVariationDependencies([]blueprint.Variation{}, syspropLibraryDepTag, lib)
129 }
130}
131
Yuntao Xu42e732c2021-11-18 22:33:02 +0000132func (m *selinuxContextsModule) stem() string {
133 return proptools.StringDefault(m.properties.Stem, m.Name())
134}
135
Inseob Kimb554e592019-04-15 20:10:46 +0900136func (m *selinuxContextsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900137 if m.InRecovery() {
Colin Cross040f1512019-10-02 10:36:09 -0700138 // Installing context files at the root of the recovery partition
139 m.installPath = android.PathForModuleInstall(ctx)
Inseob Kimb554e592019-04-15 20:10:46 +0900140 } else {
141 m.installPath = android.PathForModuleInstall(ctx, "etc", "selinux")
142 }
143
Inseob Kimfa6fe472021-01-12 13:40:27 +0900144 if m.InRecovery() && !m.onlyInRecovery() {
Inseob Kimb554e592019-04-15 20:10:46 +0900145 dep := ctx.GetDirectDepWithTag(m.Name(), reuseContextsDepTag)
146
147 if reuseDeps, ok := dep.(*selinuxContextsModule); ok {
148 m.outputPath = reuseDeps.outputPath
Yuntao Xu42e732c2021-11-18 22:33:02 +0000149 ctx.InstallFile(m.installPath, m.stem(), m.outputPath)
Inseob Kimb554e592019-04-15 20:10:46 +0900150 return
151 }
152 }
153
Inseob Kim6d3d5a62021-12-21 20:55:32 +0900154 m.outputPath = m.build(ctx, android.PathsForModuleSrc(ctx, m.properties.Srcs))
Yuntao Xu42e732c2021-11-18 22:33:02 +0000155 ctx.InstallFile(m.installPath, m.stem(), m.outputPath)
mrziwangdc268a72024-06-06 14:42:10 -0700156
157 ctx.SetOutputFiles([]android.Path{m.outputPath}, "")
Inseob Kimb554e592019-04-15 20:10:46 +0900158}
159
160func newModule() *selinuxContextsModule {
161 m := &selinuxContextsModule{}
162 m.AddProperties(
163 &m.properties,
Inseob Kim2dac2672021-12-29 17:54:57 +0900164 &m.seappProperties,
Inseob Kimb554e592019-04-15 20:10:46 +0900165 )
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900166 initFlaggableModule(m)
Inseob Kimb554e592019-04-15 20:10:46 +0900167 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900168 android.InitDefaultableModule(m)
Inseob Kimb554e592019-04-15 20:10:46 +0900169 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
170 m.selinuxContextsHook(ctx)
171 })
172 return m
173}
174
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900175type contextsDefaults struct {
176 android.ModuleBase
177 android.DefaultsModuleBase
178}
179
180// contexts_defaults provides a set of properties that can be inherited by other contexts modules.
181// (file_contexts, property_contexts, seapp_contexts, etc.) A module can use the properties from a
182// contexts_defaults using `defaults: ["<:default_module_name>"]`. Properties of both modules are
183// erged (when possible) by prepending the default module's values to the depending module's values.
184func contextsDefaultsFactory() android.Module {
185 m := &contextsDefaults{}
186 m.AddProperties(
187 &selinuxContextsProperties{},
188 &seappProperties{},
Inseob Kimbf7f4a42024-02-14 13:53:39 +0900189 &flaggableModuleProperties{},
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900190 )
191 android.InitDefaultsModule(m)
192 return m
193}
194
Inseob Kimb554e592019-04-15 20:10:46 +0900195func (m *selinuxContextsModule) selinuxContextsHook(ctx android.LoadHookContext) {
196 // TODO: clean this up to use build/soong/android/variable.go after b/79249983
197 var srcs []string
198
Inseob Kimb554e592019-04-15 20:10:46 +0900199 for _, sanitize := range ctx.Config().SanitizeDevice() {
200 if sanitize == "address" {
201 srcs = append(srcs, m.properties.Product_variables.Address_sanitize.Srcs...)
202 break
203 }
204 }
205
206 m.properties.Srcs = append(m.properties.Srcs, srcs...)
207}
208
209func (m *selinuxContextsModule) AndroidMk() android.AndroidMkData {
Colin Crossf82aed02021-11-04 17:25:55 -0700210 nameSuffix := ""
211 if m.InRecovery() && !m.onlyInRecovery() {
212 nameSuffix = ".recovery"
213 }
Inseob Kimb554e592019-04-15 20:10:46 +0900214 return android.AndroidMkData{
Colin Crossf82aed02021-11-04 17:25:55 -0700215 Class: "ETC",
216 OutputFile: android.OptionalPathForPath(m.outputPath),
217 SubName: nameSuffix,
218 Extra: []android.AndroidMkExtraFunc{
219 func(w io.Writer, outputFile android.Path) {
Colin Cross6c7f9372022-01-11 19:35:43 -0800220 fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", m.installPath.String())
Yuntao Xu42e732c2021-11-18 22:33:02 +0000221 fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.stem())
Colin Crossf82aed02021-11-04 17:25:55 -0700222 },
Inseob Kimb554e592019-04-15 20:10:46 +0900223 },
224 }
225}
226
Inseob Kimfa6fe472021-01-12 13:40:27 +0900227func (m *selinuxContextsModule) ImageMutatorBegin(ctx android.BaseModuleContext) {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000228 if proptools.Bool(m.properties.Recovery_available) && m.ModuleBase.InstallInRecovery() {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900229 ctx.PropertyErrorf("recovery_available",
230 "doesn't make sense at the same time as `recovery: true`")
Inseob Kimb554e592019-04-15 20:10:46 +0900231 }
232}
233
Jihoon Kang03f4d9d2024-06-21 06:36:33 +0000234func (m *selinuxContextsModule) VendorVariantNeeded(ctx android.BaseModuleContext) bool {
235 return false
236}
237
238func (m *selinuxContextsModule) ProductVariantNeeded(ctx android.BaseModuleContext) bool {
239 return false
240}
241
Inseob Kimfa6fe472021-01-12 13:40:27 +0900242func (m *selinuxContextsModule) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000243 return !m.ModuleBase.InstallInRecovery()
Inseob Kimfa6fe472021-01-12 13:40:27 +0900244}
245
246func (m *selinuxContextsModule) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
247 return false
248}
249
250func (m *selinuxContextsModule) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
251 return false
252}
253
Inseob Kim6cc75f42021-04-29 13:53:20 +0000254func (m *selinuxContextsModule) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
255 return false
256}
257
Inseob Kimfa6fe472021-01-12 13:40:27 +0900258func (m *selinuxContextsModule) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000259 return m.ModuleBase.InstallInRecovery() || proptools.Bool(m.properties.Recovery_available)
Inseob Kimfa6fe472021-01-12 13:40:27 +0900260}
261
262func (m *selinuxContextsModule) ExtraImageVariations(ctx android.BaseModuleContext) []string {
263 return nil
264}
265
Jihoon Kang8298ae52024-06-13 21:30:15 +0000266func (m *selinuxContextsModule) SetImageVariation(ctx android.BaseModuleContext, variation string) {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900267}
268
269var _ android.ImageInterface = (*selinuxContextsModule)(nil)
270
Inseob Kimcd616492020-03-24 23:06:40 +0900271func (m *selinuxContextsModule) buildGeneralContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900272 builtContext := pathForModuleOut(ctx, ctx.ModuleName()+"_m4out")
Inseob Kimb554e592019-04-15 20:10:46 +0900273
Colin Cross242c8bc2020-11-16 17:58:17 -0800274 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kimb554e592019-04-15 20:10:46 +0900275
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900276 newlineFile := pathForModuleOut(ctx, "newline")
Inseob Kim35e9d412023-01-04 15:27:32 +0900277
278 rule.Command().Text("echo").FlagWithOutput("> ", newlineFile)
279 rule.Temporary(newlineFile)
280
281 var inputsWithNewline android.Paths
282 for _, input := range inputs {
283 inputsWithNewline = append(inputsWithNewline, input, newlineFile)
284 }
285
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900286 flags := m.getBuildFlags(ctx)
Inseob Kimb554e592019-04-15 20:10:46 +0900287 rule.Command().
Dan Willemsen3c3e59b2019-06-19 10:52:50 -0700288 Tool(ctx.Config().PrebuiltBuildTool(ctx, "m4")).
289 Text("--fatal-warnings -s").
Inseob Kimb554e592019-04-15 20:10:46 +0900290 FlagForEachArg("-D", ctx.DeviceConfig().SepolicyM4Defs()).
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900291 Flags(flagsToM4Macros(flags)).
Inseob Kim35e9d412023-01-04 15:27:32 +0900292 Inputs(inputsWithNewline).
Yuntao Xu42e732c2021-11-18 22:33:02 +0000293 FlagWithOutput("> ", builtContext)
Inseob Kimb554e592019-04-15 20:10:46 +0900294
295 if proptools.Bool(m.properties.Remove_comment) {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000296 rule.Temporary(builtContext)
Inseob Kimb554e592019-04-15 20:10:46 +0900297
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900298 remove_comment_output := pathForModuleOut(ctx, ctx.ModuleName()+"_remove_comment")
Inseob Kimb554e592019-04-15 20:10:46 +0900299
300 rule.Command().
301 Text("sed -e 's/#.*$//' -e '/^$/d'").
Yuntao Xu42e732c2021-11-18 22:33:02 +0000302 Input(builtContext).
Inseob Kimb554e592019-04-15 20:10:46 +0900303 FlagWithOutput("> ", remove_comment_output)
304
Yuntao Xu42e732c2021-11-18 22:33:02 +0000305 builtContext = remove_comment_output
Inseob Kimb554e592019-04-15 20:10:46 +0900306 }
307
308 if proptools.Bool(m.properties.Fc_sort) {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000309 rule.Temporary(builtContext)
Inseob Kimb554e592019-04-15 20:10:46 +0900310
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900311 sorted_output := pathForModuleOut(ctx, ctx.ModuleName()+"_sorted")
Inseob Kimb554e592019-04-15 20:10:46 +0900312
313 rule.Command().
314 Tool(ctx.Config().HostToolPath(ctx, "fc_sort")).
Yuntao Xu42e732c2021-11-18 22:33:02 +0000315 FlagWithInput("-i ", builtContext).
Inseob Kimb554e592019-04-15 20:10:46 +0900316 FlagWithOutput("-o ", sorted_output)
317
Yuntao Xu42e732c2021-11-18 22:33:02 +0000318 builtContext = sorted_output
Inseob Kimb554e592019-04-15 20:10:46 +0900319 }
320
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900321 ret := pathForModuleOut(ctx, m.stem())
Yuntao Xu42e732c2021-11-18 22:33:02 +0000322 rule.Temporary(builtContext)
323 rule.Command().Text("cp").Input(builtContext).Output(ret)
Inseob Kimb554e592019-04-15 20:10:46 +0900324
325 rule.DeleteTemporaryFiles()
Yuntao Xu42e732c2021-11-18 22:33:02 +0000326 rule.Build("selinux_contexts", "building contexts: "+m.Name())
Inseob Kimb554e592019-04-15 20:10:46 +0900327
Inseob Kimcd616492020-03-24 23:06:40 +0900328 return ret
Inseob Kimb554e592019-04-15 20:10:46 +0900329}
330
Inseob Kimcd616492020-03-24 23:06:40 +0900331func (m *selinuxContextsModule) buildFileContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kimdfa4a482023-11-01 17:58:18 +0900332 if m.properties.Remove_comment == nil {
333 m.properties.Remove_comment = proptools.BoolPtr(true)
Inseob Kimb554e592019-04-15 20:10:46 +0900334 }
Inseob Kimcd616492020-03-24 23:06:40 +0900335 return m.buildGeneralContexts(ctx, inputs)
Inseob Kimb554e592019-04-15 20:10:46 +0900336}
337
338func fileFactory() android.Module {
339 m := newModule()
Inseob Kimb554e592019-04-15 20:10:46 +0900340 m.build = m.buildFileContexts
341 return m
342}
343
Thiébaud Weksteen74482f52023-04-26 13:46:59 +1000344func (m *selinuxContextsModule) buildServiceContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kimb554e592019-04-15 20:10:46 +0900345 if m.properties.Remove_comment == nil {
346 m.properties.Remove_comment = proptools.BoolPtr(true)
347 }
348
Inseob Kimcd616492020-03-24 23:06:40 +0900349 return m.buildGeneralContexts(ctx, inputs)
350}
351
Inseob Kim085f22f2023-11-09 11:13:01 +0900352func (m *selinuxContextsModule) checkVendorPropertyNamespace(ctx android.ModuleContext, input android.Path) android.Path {
Inseob Kim2bcc0452020-12-21 13:16:44 +0900353 shippingApiLevel := ctx.DeviceConfig().ShippingApiLevel()
354 ApiLevelR := android.ApiLevelOrPanic(ctx, "R")
355
356 rule := android.NewRuleBuilder(pctx, ctx)
357
358 // This list is from vts_treble_sys_prop_test.
359 allowedPropertyPrefixes := []string{
360 "ctl.odm.",
361 "ctl.vendor.",
362 "ctl.start$odm.",
363 "ctl.start$vendor.",
364 "ctl.stop$odm.",
365 "ctl.stop$vendor.",
366 "init.svc.odm.",
367 "init.svc.vendor.",
368 "ro.boot.",
369 "ro.hardware.",
370 "ro.odm.",
371 "ro.vendor.",
372 "odm.",
373 "persist.odm.",
374 "persist.vendor.",
375 "vendor.",
376 }
377
378 // persist.camera is also allowed for devices launching with R or eariler
379 if shippingApiLevel.LessThanOrEqualTo(ApiLevelR) {
380 allowedPropertyPrefixes = append(allowedPropertyPrefixes, "persist.camera.")
381 }
382
383 var allowedContextPrefixes []string
384
385 if shippingApiLevel.GreaterThanOrEqualTo(ApiLevelR) {
386 // This list is from vts_treble_sys_prop_test.
387 allowedContextPrefixes = []string{
388 "vendor_",
389 "odm_",
390 }
391 }
392
Inseob Kim085f22f2023-11-09 11:13:01 +0900393 cmd := rule.Command().
394 BuiltTool("check_prop_prefix").
395 FlagWithInput("--property-contexts ", input).
396 FlagForEachArg("--allowed-property-prefix ", proptools.ShellEscapeList(allowedPropertyPrefixes)). // contains shell special character '$'
397 FlagForEachArg("--allowed-context-prefix ", allowedContextPrefixes)
Inseob Kim2bcc0452020-12-21 13:16:44 +0900398
Inseob Kim085f22f2023-11-09 11:13:01 +0900399 if !ctx.DeviceConfig().BuildBrokenVendorPropertyNamespace() {
400 cmd.Flag("--strict")
Inseob Kim2bcc0452020-12-21 13:16:44 +0900401 }
Inseob Kim085f22f2023-11-09 11:13:01 +0900402
Luca Stefani0b2d7112023-11-16 17:42:52 +0100403 out := pathForModuleOut(ctx, ctx.ModuleName()+"_namespace_checked")
Inseob Kim085f22f2023-11-09 11:13:01 +0900404 rule.Command().Text("cp -f").Input(input).Output(out)
Inseob Kim2bcc0452020-12-21 13:16:44 +0900405 rule.Build("check_namespace", "checking namespace of "+ctx.ModuleName())
Inseob Kim085f22f2023-11-09 11:13:01 +0900406 return out
Inseob Kim2bcc0452020-12-21 13:16:44 +0900407}
408
Inseob Kimcd616492020-03-24 23:06:40 +0900409func (m *selinuxContextsModule) buildPropertyContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kim2bcc0452020-12-21 13:16:44 +0900410 // vendor/odm properties are enforced for devices launching with Android Q or later. So, if
411 // vendor/odm, make sure that only vendor/odm properties exist.
Inseob Kim085f22f2023-11-09 11:13:01 +0900412 builtCtxFile := m.buildGeneralContexts(ctx, inputs)
413
Inseob Kim2bcc0452020-12-21 13:16:44 +0900414 shippingApiLevel := ctx.DeviceConfig().ShippingApiLevel()
415 ApiLevelQ := android.ApiLevelOrPanic(ctx, "Q")
416 if (ctx.SocSpecific() || ctx.DeviceSpecific()) && shippingApiLevel.GreaterThanOrEqualTo(ApiLevelQ) {
Inseob Kim085f22f2023-11-09 11:13:01 +0900417 builtCtxFile = m.checkVendorPropertyNamespace(ctx, builtCtxFile)
Inseob Kim2bcc0452020-12-21 13:16:44 +0900418 }
419
Inseob Kimcd616492020-03-24 23:06:40 +0900420 var apiFiles android.Paths
421 ctx.VisitDirectDepsWithTag(syspropLibraryDepTag, func(c android.Module) {
Inseob Kim3a3539a2021-01-15 18:10:29 +0900422 i, ok := c.(interface{ CurrentSyspropApiFile() android.OptionalPath })
Inseob Kimcd616492020-03-24 23:06:40 +0900423 if !ok {
424 panic(fmt.Errorf("unknown dependency %q for %q", ctx.OtherModuleName(c), ctx.ModuleName()))
425 }
Inseob Kim3a3539a2021-01-15 18:10:29 +0900426 if api := i.CurrentSyspropApiFile(); api.Valid() {
427 apiFiles = append(apiFiles, api.Path())
428 }
Inseob Kimcd616492020-03-24 23:06:40 +0900429 })
430
431 // check compatibility with sysprop_library
432 if len(apiFiles) > 0 {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900433 out := pathForModuleOut(ctx, ctx.ModuleName()+"_api_checked")
Colin Cross242c8bc2020-11-16 17:58:17 -0800434 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kimcd616492020-03-24 23:06:40 +0900435
436 msg := `\n******************************\n` +
437 `API of sysprop_library doesn't match with property_contexts\n` +
438 `Please fix the breakage and rebuild.\n` +
439 `******************************\n`
440
441 rule.Command().
442 Text("( ").
Colin Cross242c8bc2020-11-16 17:58:17 -0800443 BuiltTool("sysprop_type_checker").
Inseob Kimcd616492020-03-24 23:06:40 +0900444 FlagForEachInput("--api ", apiFiles).
445 FlagWithInput("--context ", builtCtxFile).
446 Text(" || ( echo").Flag("-e").
447 Flag(`"` + msg + `"`).
448 Text("; exit 38) )")
449
450 rule.Command().Text("cp -f").Input(builtCtxFile).Output(out)
Colin Cross242c8bc2020-11-16 17:58:17 -0800451 rule.Build("property_contexts_check_api", "checking API: "+m.Name())
Inseob Kimcd616492020-03-24 23:06:40 +0900452 builtCtxFile = out
453 }
454
455 return builtCtxFile
Inseob Kimb554e592019-04-15 20:10:46 +0900456}
457
Inseob Kim06518b12023-08-25 21:20:08 +0900458func (m *selinuxContextsModule) shouldCheckCoredomain(ctx android.ModuleContext) bool {
459 if !ctx.SocSpecific() && !ctx.DeviceSpecific() {
460 return false
461 }
462
463 return ctx.DeviceConfig().CheckVendorSeappViolations()
464}
465
Inseob Kim2dac2672021-12-29 17:54:57 +0900466func (m *selinuxContextsModule) buildSeappContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900467 neverallowFile := pathForModuleOut(ctx, "neverallow")
Inseob Kim085f22f2023-11-09 11:13:01 +0900468 ret := pathForModuleOut(ctx, "checkseapp", m.stem())
Inseob Kim2dac2672021-12-29 17:54:57 +0900469
Inseob Kim085f22f2023-11-09 11:13:01 +0900470 // Step 1. Generate a M4 processed neverallow file
471 flags := m.getBuildFlags(ctx)
472 m4NeverallowFile := pathForModuleOut(ctx, "neverallow.m4out")
Inseob Kim2dac2672021-12-29 17:54:57 +0900473 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kim085f22f2023-11-09 11:13:01 +0900474 rule.Command().
475 Tool(ctx.Config().PrebuiltBuildTool(ctx, "m4")).
476 Flag("--fatal-warnings").
477 FlagForEachArg("-D", ctx.DeviceConfig().SepolicyM4Defs()).
478 Flags(flagsToM4Macros(flags)).
479 Inputs(android.PathsForModuleSrc(ctx, m.seappProperties.Neverallow_files)).
480 FlagWithOutput("> ", m4NeverallowFile)
481
482 rule.Temporary(m4NeverallowFile)
483 rule.Command().
484 Text("( grep").
Inseob Kim2dac2672021-12-29 17:54:57 +0900485 Flag("-ihe").
486 Text("'^neverallow'").
Inseob Kim085f22f2023-11-09 11:13:01 +0900487 Input(m4NeverallowFile).
Inseob Kim2dac2672021-12-29 17:54:57 +0900488 Text(">").
489 Output(neverallowFile).
Inseob Kim085f22f2023-11-09 11:13:01 +0900490 Text("|| true )") // to make ninja happy even when result is empty
Inseob Kim2dac2672021-12-29 17:54:57 +0900491
Inseob Kim085f22f2023-11-09 11:13:01 +0900492 // Step 2. Generate a M4 processed contexts file
493 builtCtx := m.buildGeneralContexts(ctx, inputs)
494
495 // Step 3. checkseapp
Inseob Kim2dac2672021-12-29 17:54:57 +0900496 rule.Temporary(neverallowFile)
Inseob Kimd7d36092023-06-26 20:48:48 +0900497 checkCmd := rule.Command().BuiltTool("checkseapp").
Inseob Kim2dac2672021-12-29 17:54:57 +0900498 FlagWithInput("-p ", android.PathForModuleSrc(ctx, proptools.String(m.seappProperties.Sepolicy))).
499 FlagWithOutput("-o ", ret).
Inseob Kim085f22f2023-11-09 11:13:01 +0900500 Input(builtCtx).
Inseob Kim2dac2672021-12-29 17:54:57 +0900501 Input(neverallowFile)
502
Inseob Kim06518b12023-08-25 21:20:08 +0900503 if m.shouldCheckCoredomain(ctx) {
504 checkCmd.Flag("-c") // check coredomain for vendor contexts
Inseob Kimd7d36092023-06-26 20:48:48 +0900505 }
506
Inseob Kim2dac2672021-12-29 17:54:57 +0900507 rule.Build("seapp_contexts", "Building seapp_contexts: "+m.Name())
508 return ret
509}
510
Inseob Kimb554e592019-04-15 20:10:46 +0900511func hwServiceFactory() android.Module {
512 m := newModule()
Thiébaud Weksteen74482f52023-04-26 13:46:59 +1000513 m.build = m.buildServiceContexts
Inseob Kimb554e592019-04-15 20:10:46 +0900514 return m
515}
516
517func propertyFactory() android.Module {
518 m := newModule()
Inseob Kimcd616492020-03-24 23:06:40 +0900519 m.build = m.buildPropertyContexts
520 m.deps = m.propertyContextsDeps
Inseob Kimb554e592019-04-15 20:10:46 +0900521 return m
522}
523
524func serviceFactory() android.Module {
525 m := newModule()
Thiébaud Weksteen74482f52023-04-26 13:46:59 +1000526 m.build = m.buildServiceContexts
Inseob Kimb554e592019-04-15 20:10:46 +0900527 return m
528}
Janis Danisevskisc40681f2020-07-25 13:02:29 -0700529
530func keystoreKeyFactory() android.Module {
531 m := newModule()
532 m.build = m.buildGeneralContexts
533 return m
534}
Yuntao Xu42e732c2021-11-18 22:33:02 +0000535
Inseob Kim2dac2672021-12-29 17:54:57 +0900536func seappFactory() android.Module {
537 m := newModule()
538 m.build = m.buildSeappContexts
539 return m
540}
541
Inseob Kimc7596c42022-02-25 11:45:41 +0900542func vndServiceFactory() android.Module {
543 m := newModule()
544 m.build = m.buildGeneralContexts
545 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
546 if !ctx.SocSpecific() {
547 ctx.ModuleErrorf(m.Name(), "must set vendor: true")
548 return
549 }
550 })
551 return m
552}
553
Inseob Kimb5e23532022-02-16 02:26:11 +0000554type contextsTestProperties struct {
555 // Contexts files to be tested.
556 Srcs []string `android:"path"`
557
558 // Precompiled sepolicy binary to be tesed together.
559 Sepolicy *string `android:"path"`
560}
561
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100562type fileContextsTestProperties struct {
563 // Test data. File passed to `checkfc -t` to validate how contexts are resolved.
564 Test_data *string `android:"path"`
565}
566
Inseob Kimb5e23532022-02-16 02:26:11 +0000567type contextsTestModule struct {
568 android.ModuleBase
569
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100570 // The type of context.
571 context contextType
Inseob Kimb5e23532022-02-16 02:26:11 +0000572
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100573 properties contextsTestProperties
574 fileProperties fileContextsTestProperties
575 testTimestamp android.OutputPath
Inseob Kimb5e23532022-02-16 02:26:11 +0000576}
577
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100578type contextType int
579
580const (
581 FileContext contextType = iota
582 PropertyContext
583 ServiceContext
584 HwServiceContext
585 VndServiceContext
586)
587
Inseob Kimb5e23532022-02-16 02:26:11 +0000588// checkfc parses a context file and checks for syntax errors.
589// If -s is specified, the service backend is used to verify binder services.
590// If -l is specified, the service backend is used to verify hwbinder services.
591// Otherwise, context_file is assumed to be a file_contexts file
592// If -e is specified, then the context_file is allowed to be empty.
593
594// file_contexts_test tests given file_contexts files with checkfc.
595func fileContextsTestFactory() android.Module {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100596 m := &contextsTestModule{context: FileContext}
Inseob Kimb5e23532022-02-16 02:26:11 +0000597 m.AddProperties(&m.properties)
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100598 m.AddProperties(&m.fileProperties)
Inseob Kimb5e23532022-02-16 02:26:11 +0000599 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
600 return m
601}
602
603// property_contexts_test tests given property_contexts files with property_info_checker.
604func propertyContextsTestFactory() android.Module {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100605 m := &contextsTestModule{context: PropertyContext}
Inseob Kimb5e23532022-02-16 02:26:11 +0000606 m.AddProperties(&m.properties)
607 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
608 return m
609}
610
611// hwservice_contexts_test tests given hwservice_contexts files with checkfc.
612func hwserviceContextsTestFactory() android.Module {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100613 m := &contextsTestModule{context: HwServiceContext}
Inseob Kimb5e23532022-02-16 02:26:11 +0000614 m.AddProperties(&m.properties)
615 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
616 return m
617}
618
619// service_contexts_test tests given service_contexts files with checkfc.
620func serviceContextsTestFactory() android.Module {
621 // checkfc -s: service_contexts test
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100622 m := &contextsTestModule{context: ServiceContext}
Inseob Kimb5e23532022-02-16 02:26:11 +0000623 m.AddProperties(&m.properties)
624 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
625 return m
626}
627
Inseob Kimc7596c42022-02-25 11:45:41 +0900628// vndservice_contexts_test tests given vndservice_contexts files with checkfc.
629func vndServiceContextsTestFactory() android.Module {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100630 m := &contextsTestModule{context: VndServiceContext}
Inseob Kimc7596c42022-02-25 11:45:41 +0900631 m.AddProperties(&m.properties)
632 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
633 return m
634}
635
Inseob Kimb5e23532022-02-16 02:26:11 +0000636func (m *contextsTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100637 tool := "checkfc"
638 if m.context == PropertyContext {
639 tool = "property_info_checker"
Inseob Kimb5e23532022-02-16 02:26:11 +0000640 }
641
642 if len(m.properties.Srcs) == 0 {
643 ctx.PropertyErrorf("srcs", "can't be empty")
644 return
645 }
646
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100647 validateWithPolicy := true
Inseob Kimb5e23532022-02-16 02:26:11 +0000648 if proptools.String(m.properties.Sepolicy) == "" {
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100649 if m.context == FileContext {
650 if proptools.String(m.fileProperties.Test_data) == "" {
651 ctx.PropertyErrorf("test_data", "Either test_data or sepolicy should be provided")
652 return
653 }
654 validateWithPolicy = false
655 } else {
656 ctx.PropertyErrorf("sepolicy", "can't be empty")
657 return
658 }
Inseob Kimb5e23532022-02-16 02:26:11 +0000659 }
660
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100661 flags := []string(nil)
662 switch m.context {
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100663 case FileContext:
664 if !validateWithPolicy {
665 flags = []string{"-t"}
666 }
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100667 case ServiceContext:
668 flags = []string{"-s" /* binder services */}
669 case HwServiceContext:
670 flags = []string{"-e" /* allow empty */, "-l" /* hwbinder services */}
671 case VndServiceContext:
672 flags = []string{"-e" /* allow empty */, "-v" /* vnd service */}
673 }
674
Inseob Kimb5e23532022-02-16 02:26:11 +0000675 srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs)
Inseob Kimb5e23532022-02-16 02:26:11 +0000676 rule := android.NewRuleBuilder(pctx, ctx)
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100677
678 if validateWithPolicy {
679 sepolicy := android.PathForModuleSrc(ctx, proptools.String(m.properties.Sepolicy))
680 rule.Command().BuiltTool(tool).
681 Flags(flags).
682 Input(sepolicy).
683 Inputs(srcs)
684 } else {
685 test_data := android.PathForModuleSrc(ctx, proptools.String(m.fileProperties.Test_data))
686 rule.Command().BuiltTool(tool).
687 Flags(flags).
688 Inputs(srcs).
689 Input(test_data)
690 }
Inseob Kimb5e23532022-02-16 02:26:11 +0000691
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900692 m.testTimestamp = pathForModuleOut(ctx, "timestamp")
Inseob Kimb5e23532022-02-16 02:26:11 +0000693 rule.Command().Text("touch").Output(m.testTimestamp)
694 rule.Build("contexts_test", "running contexts test: "+ctx.ModuleName())
695}
696
697func (m *contextsTestModule) AndroidMkEntries() []android.AndroidMkEntries {
698 return []android.AndroidMkEntries{android.AndroidMkEntries{
699 Class: "FAKE",
700 // OutputFile is needed, even though BUILD_PHONY_PACKAGE doesn't use it.
701 // Without OutputFile this module won't be exported to Makefile.
702 OutputFile: android.OptionalPathForPath(m.testTimestamp),
703 Include: "$(BUILD_PHONY_PACKAGE)",
704 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
705 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
706 entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", m.testTimestamp.String())
707 },
708 },
709 }}
710}
711
712// contextsTestModule implements ImageInterface to be able to include recovery_available contexts
713// modules as its sources.
714func (m *contextsTestModule) ImageMutatorBegin(ctx android.BaseModuleContext) {
715}
716
Jihoon Kang03f4d9d2024-06-21 06:36:33 +0000717func (m *contextsTestModule) VendorVariantNeeded(ctx android.BaseModuleContext) bool {
718 return false
719}
720
721func (m *contextsTestModule) ProductVariantNeeded(ctx android.BaseModuleContext) bool {
722 return false
723}
724
Inseob Kimb5e23532022-02-16 02:26:11 +0000725func (m *contextsTestModule) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
726 return true
727}
728
729func (m *contextsTestModule) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
730 return false
731}
732
733func (m *contextsTestModule) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
734 return false
735}
736
737func (m *contextsTestModule) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
738 return false
739}
740
741func (m *contextsTestModule) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
742 return false
743}
744
745func (m *contextsTestModule) ExtraImageVariations(ctx android.BaseModuleContext) []string {
746 return nil
747}
748
Jihoon Kang8298ae52024-06-13 21:30:15 +0000749func (m *contextsTestModule) SetImageVariation(ctx android.BaseModuleContext, variation string) {
Inseob Kimb5e23532022-02-16 02:26:11 +0000750}
751
752var _ android.ImageInterface = (*contextsTestModule)(nil)