blob: c96dda58bfc314305e03d336f56732652130466f [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
Thiébaud Weksteenfe008ad2024-09-17 12:06:12 +100049
50 // Board api level of policy files. Set "current" for RELEASE_BOARD_API_LEVEL, or a direct
51 // version string (e.g. "202404"). Defaults to "current"
52 Board_api_level *string
Inseob Kimb554e592019-04-15 20:10:46 +090053}
54
Inseob Kim2dac2672021-12-29 17:54:57 +090055type seappProperties struct {
56 // Files containing neverallow rules.
57 Neverallow_files []string `android:"path"`
58
59 // Precompiled sepolicy binary file which will be fed to checkseapp.
60 Sepolicy *string `android:"path"`
61}
62
Inseob Kimb554e592019-04-15 20:10:46 +090063type selinuxContextsModule struct {
64 android.ModuleBase
Inseob Kim6cd0ddd2023-10-25 23:48:16 +090065 android.DefaultableModuleBase
66 flaggableModuleBase
Inseob Kimb554e592019-04-15 20:10:46 +090067
Jooyung Han804e2342023-06-20 15:38:50 +090068 properties selinuxContextsProperties
69 seappProperties seappProperties
70 build func(ctx android.ModuleContext, inputs android.Paths) android.Path
71 deps func(ctx android.BottomUpMutatorContext)
72 outputPath android.Path
73 installPath android.InstallPath
Inseob Kimb554e592019-04-15 20:10:46 +090074}
75
Inseob Kim6cd0ddd2023-10-25 23:48:16 +090076var _ flaggableModule = (*selinuxContextsModule)(nil)
77
Inseob Kimb554e592019-04-15 20:10:46 +090078var (
Inseob Kimcd616492020-03-24 23:06:40 +090079 reuseContextsDepTag = dependencyTag{name: "reuseContexts"}
80 syspropLibraryDepTag = dependencyTag{name: "sysprop_library"}
Inseob Kimb554e592019-04-15 20:10:46 +090081)
82
83func init() {
84 pctx.HostBinToolVariable("fc_sort", "fc_sort")
85
Inseob Kim6cd0ddd2023-10-25 23:48:16 +090086 android.RegisterModuleType("contexts_defaults", contextsDefaultsFactory)
Inseob Kimb554e592019-04-15 20:10:46 +090087 android.RegisterModuleType("file_contexts", fileFactory)
88 android.RegisterModuleType("hwservice_contexts", hwServiceFactory)
89 android.RegisterModuleType("property_contexts", propertyFactory)
90 android.RegisterModuleType("service_contexts", serviceFactory)
Janis Danisevskisc40681f2020-07-25 13:02:29 -070091 android.RegisterModuleType("keystore2_key_contexts", keystoreKeyFactory)
Inseob Kim2dac2672021-12-29 17:54:57 +090092 android.RegisterModuleType("seapp_contexts", seappFactory)
Inseob Kimc7596c42022-02-25 11:45:41 +090093 android.RegisterModuleType("vndservice_contexts", vndServiceFactory)
Nikita Ioffe48966b62024-10-22 14:01:17 +000094 android.RegisterModuleType("tee_service_contexts", teeServiceFactory)
Inseob Kimb5e23532022-02-16 02:26:11 +000095
96 android.RegisterModuleType("file_contexts_test", fileContextsTestFactory)
97 android.RegisterModuleType("property_contexts_test", propertyContextsTestFactory)
98 android.RegisterModuleType("hwservice_contexts_test", hwserviceContextsTestFactory)
99 android.RegisterModuleType("service_contexts_test", serviceContextsTestFactory)
Inseob Kimc7596c42022-02-25 11:45:41 +0900100 android.RegisterModuleType("vndservice_contexts_test", vndServiceContextsTestFactory)
Inseob Kimb554e592019-04-15 20:10:46 +0900101}
102
Colin Cross040f1512019-10-02 10:36:09 -0700103func (m *selinuxContextsModule) InstallInRoot() bool {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900104 return m.InRecovery()
105}
106
107func (m *selinuxContextsModule) InstallInRecovery() bool {
108 // ModuleBase.InRecovery() checks the image variant
109 return m.InRecovery()
110}
111
112func (m *selinuxContextsModule) onlyInRecovery() bool {
113 // ModuleBase.InstallInRecovery() checks commonProperties.Recovery property
114 return m.ModuleBase.InstallInRecovery()
Colin Cross040f1512019-10-02 10:36:09 -0700115}
116
Inseob Kimcd616492020-03-24 23:06:40 +0900117func (m *selinuxContextsModule) DepsMutator(ctx android.BottomUpMutatorContext) {
Inseob Kimbf7f4a42024-02-14 13:53:39 +0900118 m.flagDeps(ctx)
119
Inseob Kimcd616492020-03-24 23:06:40 +0900120 if m.deps != nil {
121 m.deps(ctx)
122 }
Inseob Kimfa6fe472021-01-12 13:40:27 +0900123
124 if m.InRecovery() && !m.onlyInRecovery() {
125 ctx.AddFarVariationDependencies([]blueprint.Variation{
126 {Mutator: "image", Variation: android.CoreVariation},
127 }, reuseContextsDepTag, ctx.ModuleName())
128 }
Inseob Kimcd616492020-03-24 23:06:40 +0900129}
130
131func (m *selinuxContextsModule) propertyContextsDeps(ctx android.BottomUpMutatorContext) {
132 for _, lib := range sysprop.SyspropLibraries(ctx.Config()) {
133 ctx.AddFarVariationDependencies([]blueprint.Variation{}, syspropLibraryDepTag, lib)
134 }
135}
136
Yuntao Xu42e732c2021-11-18 22:33:02 +0000137func (m *selinuxContextsModule) stem() string {
138 return proptools.StringDefault(m.properties.Stem, m.Name())
139}
140
Inseob Kimb554e592019-04-15 20:10:46 +0900141func (m *selinuxContextsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900142 if m.InRecovery() {
Colin Cross040f1512019-10-02 10:36:09 -0700143 // Installing context files at the root of the recovery partition
144 m.installPath = android.PathForModuleInstall(ctx)
Inseob Kimb554e592019-04-15 20:10:46 +0900145 } else {
146 m.installPath = android.PathForModuleInstall(ctx, "etc", "selinux")
147 }
148
Inseob Kimfa6fe472021-01-12 13:40:27 +0900149 if m.InRecovery() && !m.onlyInRecovery() {
Inseob Kimb554e592019-04-15 20:10:46 +0900150 dep := ctx.GetDirectDepWithTag(m.Name(), reuseContextsDepTag)
151
152 if reuseDeps, ok := dep.(*selinuxContextsModule); ok {
153 m.outputPath = reuseDeps.outputPath
Yuntao Xu42e732c2021-11-18 22:33:02 +0000154 ctx.InstallFile(m.installPath, m.stem(), m.outputPath)
Inseob Kimb554e592019-04-15 20:10:46 +0900155 return
156 }
157 }
158
Inseob Kim6d3d5a62021-12-21 20:55:32 +0900159 m.outputPath = m.build(ctx, android.PathsForModuleSrc(ctx, m.properties.Srcs))
Yuntao Xu42e732c2021-11-18 22:33:02 +0000160 ctx.InstallFile(m.installPath, m.stem(), m.outputPath)
mrziwangdc268a72024-06-06 14:42:10 -0700161
162 ctx.SetOutputFiles([]android.Path{m.outputPath}, "")
Inseob Kimb554e592019-04-15 20:10:46 +0900163}
164
165func newModule() *selinuxContextsModule {
166 m := &selinuxContextsModule{}
167 m.AddProperties(
168 &m.properties,
Inseob Kim2dac2672021-12-29 17:54:57 +0900169 &m.seappProperties,
Inseob Kimb554e592019-04-15 20:10:46 +0900170 )
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900171 initFlaggableModule(m)
Inseob Kimb554e592019-04-15 20:10:46 +0900172 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900173 android.InitDefaultableModule(m)
Inseob Kimb554e592019-04-15 20:10:46 +0900174 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
175 m.selinuxContextsHook(ctx)
176 })
177 return m
178}
179
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900180type contextsDefaults struct {
181 android.ModuleBase
182 android.DefaultsModuleBase
183}
184
185// contexts_defaults provides a set of properties that can be inherited by other contexts modules.
186// (file_contexts, property_contexts, seapp_contexts, etc.) A module can use the properties from a
187// contexts_defaults using `defaults: ["<:default_module_name>"]`. Properties of both modules are
188// erged (when possible) by prepending the default module's values to the depending module's values.
189func contextsDefaultsFactory() android.Module {
190 m := &contextsDefaults{}
191 m.AddProperties(
192 &selinuxContextsProperties{},
193 &seappProperties{},
Inseob Kimbf7f4a42024-02-14 13:53:39 +0900194 &flaggableModuleProperties{},
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900195 )
196 android.InitDefaultsModule(m)
197 return m
198}
199
Inseob Kimb554e592019-04-15 20:10:46 +0900200func (m *selinuxContextsModule) selinuxContextsHook(ctx android.LoadHookContext) {
201 // TODO: clean this up to use build/soong/android/variable.go after b/79249983
202 var srcs []string
203
Inseob Kimb554e592019-04-15 20:10:46 +0900204 for _, sanitize := range ctx.Config().SanitizeDevice() {
205 if sanitize == "address" {
206 srcs = append(srcs, m.properties.Product_variables.Address_sanitize.Srcs...)
207 break
208 }
209 }
210
211 m.properties.Srcs = append(m.properties.Srcs, srcs...)
212}
213
214func (m *selinuxContextsModule) AndroidMk() android.AndroidMkData {
Colin Crossf82aed02021-11-04 17:25:55 -0700215 nameSuffix := ""
216 if m.InRecovery() && !m.onlyInRecovery() {
217 nameSuffix = ".recovery"
218 }
Inseob Kimb554e592019-04-15 20:10:46 +0900219 return android.AndroidMkData{
Colin Crossf82aed02021-11-04 17:25:55 -0700220 Class: "ETC",
221 OutputFile: android.OptionalPathForPath(m.outputPath),
222 SubName: nameSuffix,
223 Extra: []android.AndroidMkExtraFunc{
224 func(w io.Writer, outputFile android.Path) {
Colin Cross6c7f9372022-01-11 19:35:43 -0800225 fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", m.installPath.String())
Yuntao Xu42e732c2021-11-18 22:33:02 +0000226 fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.stem())
Colin Crossf82aed02021-11-04 17:25:55 -0700227 },
Inseob Kimb554e592019-04-15 20:10:46 +0900228 },
229 }
230}
231
Cole Faust05924482024-10-15 11:28:34 -0700232func (m *selinuxContextsModule) ImageMutatorBegin(ctx android.ImageInterfaceContext) {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000233 if proptools.Bool(m.properties.Recovery_available) && m.ModuleBase.InstallInRecovery() {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900234 ctx.PropertyErrorf("recovery_available",
235 "doesn't make sense at the same time as `recovery: true`")
Inseob Kimb554e592019-04-15 20:10:46 +0900236 }
237}
238
Cole Faust05924482024-10-15 11:28:34 -0700239func (m *selinuxContextsModule) VendorVariantNeeded(ctx android.ImageInterfaceContext) bool {
Jihoon Kang03f4d9d2024-06-21 06:36:33 +0000240 return false
241}
242
Cole Faust05924482024-10-15 11:28:34 -0700243func (m *selinuxContextsModule) ProductVariantNeeded(ctx android.ImageInterfaceContext) bool {
Jihoon Kang03f4d9d2024-06-21 06:36:33 +0000244 return false
245}
246
Cole Faust05924482024-10-15 11:28:34 -0700247func (m *selinuxContextsModule) CoreVariantNeeded(ctx android.ImageInterfaceContext) bool {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000248 return !m.ModuleBase.InstallInRecovery()
Inseob Kimfa6fe472021-01-12 13:40:27 +0900249}
250
Cole Faust05924482024-10-15 11:28:34 -0700251func (m *selinuxContextsModule) RamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900252 return false
253}
254
Cole Faust05924482024-10-15 11:28:34 -0700255func (m *selinuxContextsModule) VendorRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900256 return false
257}
258
Cole Faust05924482024-10-15 11:28:34 -0700259func (m *selinuxContextsModule) DebugRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
Inseob Kim6cc75f42021-04-29 13:53:20 +0000260 return false
261}
262
Cole Faust05924482024-10-15 11:28:34 -0700263func (m *selinuxContextsModule) RecoveryVariantNeeded(ctx android.ImageInterfaceContext) bool {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000264 return m.ModuleBase.InstallInRecovery() || proptools.Bool(m.properties.Recovery_available)
Inseob Kimfa6fe472021-01-12 13:40:27 +0900265}
266
Cole Faust05924482024-10-15 11:28:34 -0700267func (m *selinuxContextsModule) ExtraImageVariations(ctx android.ImageInterfaceContext) []string {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900268 return nil
269}
270
Cole Faust05924482024-10-15 11:28:34 -0700271func (m *selinuxContextsModule) SetImageVariation(ctx android.ImageInterfaceContext, variation string) {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900272}
273
274var _ android.ImageInterface = (*selinuxContextsModule)(nil)
275
Inseob Kimcd616492020-03-24 23:06:40 +0900276func (m *selinuxContextsModule) buildGeneralContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900277 builtContext := pathForModuleOut(ctx, ctx.ModuleName()+"_m4out")
Inseob Kimb554e592019-04-15 20:10:46 +0900278
Colin Cross242c8bc2020-11-16 17:58:17 -0800279 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kimb554e592019-04-15 20:10:46 +0900280
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900281 newlineFile := pathForModuleOut(ctx, "newline")
Inseob Kim35e9d412023-01-04 15:27:32 +0900282
283 rule.Command().Text("echo").FlagWithOutput("> ", newlineFile)
284 rule.Temporary(newlineFile)
285
286 var inputsWithNewline android.Paths
287 for _, input := range inputs {
288 inputsWithNewline = append(inputsWithNewline, input, newlineFile)
289 }
290
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900291 flags := m.getBuildFlags(ctx)
Inseob Kimb554e592019-04-15 20:10:46 +0900292 rule.Command().
Dan Willemsen3c3e59b2019-06-19 10:52:50 -0700293 Tool(ctx.Config().PrebuiltBuildTool(ctx, "m4")).
294 Text("--fatal-warnings -s").
Inseob Kimb554e592019-04-15 20:10:46 +0900295 FlagForEachArg("-D", ctx.DeviceConfig().SepolicyM4Defs()).
Thiébaud Weksteenfe008ad2024-09-17 12:06:12 +1000296 Flag(boardApiLevelToM4Macro(ctx, m.properties.Board_api_level)).
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900297 Flags(flagsToM4Macros(flags)).
Inseob Kim35e9d412023-01-04 15:27:32 +0900298 Inputs(inputsWithNewline).
Yuntao Xu42e732c2021-11-18 22:33:02 +0000299 FlagWithOutput("> ", builtContext)
Inseob Kimb554e592019-04-15 20:10:46 +0900300
301 if proptools.Bool(m.properties.Remove_comment) {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000302 rule.Temporary(builtContext)
Inseob Kimb554e592019-04-15 20:10:46 +0900303
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900304 remove_comment_output := pathForModuleOut(ctx, ctx.ModuleName()+"_remove_comment")
Inseob Kimb554e592019-04-15 20:10:46 +0900305
306 rule.Command().
307 Text("sed -e 's/#.*$//' -e '/^$/d'").
Yuntao Xu42e732c2021-11-18 22:33:02 +0000308 Input(builtContext).
Inseob Kimb554e592019-04-15 20:10:46 +0900309 FlagWithOutput("> ", remove_comment_output)
310
Yuntao Xu42e732c2021-11-18 22:33:02 +0000311 builtContext = remove_comment_output
Inseob Kimb554e592019-04-15 20:10:46 +0900312 }
313
314 if proptools.Bool(m.properties.Fc_sort) {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000315 rule.Temporary(builtContext)
Inseob Kimb554e592019-04-15 20:10:46 +0900316
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900317 sorted_output := pathForModuleOut(ctx, ctx.ModuleName()+"_sorted")
Inseob Kimb554e592019-04-15 20:10:46 +0900318
319 rule.Command().
320 Tool(ctx.Config().HostToolPath(ctx, "fc_sort")).
Yuntao Xu42e732c2021-11-18 22:33:02 +0000321 FlagWithInput("-i ", builtContext).
Inseob Kimb554e592019-04-15 20:10:46 +0900322 FlagWithOutput("-o ", sorted_output)
323
Yuntao Xu42e732c2021-11-18 22:33:02 +0000324 builtContext = sorted_output
Inseob Kimb554e592019-04-15 20:10:46 +0900325 }
326
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900327 ret := pathForModuleOut(ctx, m.stem())
Yuntao Xu42e732c2021-11-18 22:33:02 +0000328 rule.Temporary(builtContext)
329 rule.Command().Text("cp").Input(builtContext).Output(ret)
Inseob Kimb554e592019-04-15 20:10:46 +0900330
331 rule.DeleteTemporaryFiles()
Yuntao Xu42e732c2021-11-18 22:33:02 +0000332 rule.Build("selinux_contexts", "building contexts: "+m.Name())
Inseob Kimb554e592019-04-15 20:10:46 +0900333
Inseob Kimcd616492020-03-24 23:06:40 +0900334 return ret
Inseob Kimb554e592019-04-15 20:10:46 +0900335}
336
Inseob Kimcd616492020-03-24 23:06:40 +0900337func (m *selinuxContextsModule) buildFileContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kimdfa4a482023-11-01 17:58:18 +0900338 if m.properties.Remove_comment == nil {
339 m.properties.Remove_comment = proptools.BoolPtr(true)
Inseob Kimb554e592019-04-15 20:10:46 +0900340 }
Inseob Kimcd616492020-03-24 23:06:40 +0900341 return m.buildGeneralContexts(ctx, inputs)
Inseob Kimb554e592019-04-15 20:10:46 +0900342}
343
344func fileFactory() android.Module {
345 m := newModule()
Inseob Kimb554e592019-04-15 20:10:46 +0900346 m.build = m.buildFileContexts
347 return m
348}
349
Thiébaud Weksteen74482f52023-04-26 13:46:59 +1000350func (m *selinuxContextsModule) buildServiceContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kimb554e592019-04-15 20:10:46 +0900351 if m.properties.Remove_comment == nil {
352 m.properties.Remove_comment = proptools.BoolPtr(true)
353 }
354
Inseob Kimcd616492020-03-24 23:06:40 +0900355 return m.buildGeneralContexts(ctx, inputs)
356}
357
Inseob Kim085f22f2023-11-09 11:13:01 +0900358func (m *selinuxContextsModule) checkVendorPropertyNamespace(ctx android.ModuleContext, input android.Path) android.Path {
Inseob Kim2bcc0452020-12-21 13:16:44 +0900359 shippingApiLevel := ctx.DeviceConfig().ShippingApiLevel()
360 ApiLevelR := android.ApiLevelOrPanic(ctx, "R")
361
362 rule := android.NewRuleBuilder(pctx, ctx)
363
364 // This list is from vts_treble_sys_prop_test.
365 allowedPropertyPrefixes := []string{
366 "ctl.odm.",
367 "ctl.vendor.",
368 "ctl.start$odm.",
369 "ctl.start$vendor.",
370 "ctl.stop$odm.",
371 "ctl.stop$vendor.",
372 "init.svc.odm.",
373 "init.svc.vendor.",
374 "ro.boot.",
375 "ro.hardware.",
376 "ro.odm.",
377 "ro.vendor.",
378 "odm.",
379 "persist.odm.",
380 "persist.vendor.",
381 "vendor.",
382 }
383
384 // persist.camera is also allowed for devices launching with R or eariler
385 if shippingApiLevel.LessThanOrEqualTo(ApiLevelR) {
386 allowedPropertyPrefixes = append(allowedPropertyPrefixes, "persist.camera.")
387 }
388
389 var allowedContextPrefixes []string
390
391 if shippingApiLevel.GreaterThanOrEqualTo(ApiLevelR) {
392 // This list is from vts_treble_sys_prop_test.
393 allowedContextPrefixes = []string{
394 "vendor_",
395 "odm_",
396 }
397 }
398
Inseob Kim085f22f2023-11-09 11:13:01 +0900399 cmd := rule.Command().
400 BuiltTool("check_prop_prefix").
401 FlagWithInput("--property-contexts ", input).
402 FlagForEachArg("--allowed-property-prefix ", proptools.ShellEscapeList(allowedPropertyPrefixes)). // contains shell special character '$'
403 FlagForEachArg("--allowed-context-prefix ", allowedContextPrefixes)
Inseob Kim2bcc0452020-12-21 13:16:44 +0900404
Inseob Kim085f22f2023-11-09 11:13:01 +0900405 if !ctx.DeviceConfig().BuildBrokenVendorPropertyNamespace() {
406 cmd.Flag("--strict")
Inseob Kim2bcc0452020-12-21 13:16:44 +0900407 }
Inseob Kim085f22f2023-11-09 11:13:01 +0900408
Luca Stefani0b2d7112023-11-16 17:42:52 +0100409 out := pathForModuleOut(ctx, ctx.ModuleName()+"_namespace_checked")
Inseob Kim085f22f2023-11-09 11:13:01 +0900410 rule.Command().Text("cp -f").Input(input).Output(out)
Inseob Kim2bcc0452020-12-21 13:16:44 +0900411 rule.Build("check_namespace", "checking namespace of "+ctx.ModuleName())
Inseob Kim085f22f2023-11-09 11:13:01 +0900412 return out
Inseob Kim2bcc0452020-12-21 13:16:44 +0900413}
414
Inseob Kimcd616492020-03-24 23:06:40 +0900415func (m *selinuxContextsModule) buildPropertyContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kim2bcc0452020-12-21 13:16:44 +0900416 // vendor/odm properties are enforced for devices launching with Android Q or later. So, if
417 // vendor/odm, make sure that only vendor/odm properties exist.
Inseob Kim085f22f2023-11-09 11:13:01 +0900418 builtCtxFile := m.buildGeneralContexts(ctx, inputs)
419
Inseob Kim2bcc0452020-12-21 13:16:44 +0900420 shippingApiLevel := ctx.DeviceConfig().ShippingApiLevel()
421 ApiLevelQ := android.ApiLevelOrPanic(ctx, "Q")
422 if (ctx.SocSpecific() || ctx.DeviceSpecific()) && shippingApiLevel.GreaterThanOrEqualTo(ApiLevelQ) {
Inseob Kim085f22f2023-11-09 11:13:01 +0900423 builtCtxFile = m.checkVendorPropertyNamespace(ctx, builtCtxFile)
Inseob Kim2bcc0452020-12-21 13:16:44 +0900424 }
425
Inseob Kimcd616492020-03-24 23:06:40 +0900426 var apiFiles android.Paths
427 ctx.VisitDirectDepsWithTag(syspropLibraryDepTag, func(c android.Module) {
Inseob Kim3a3539a2021-01-15 18:10:29 +0900428 i, ok := c.(interface{ CurrentSyspropApiFile() android.OptionalPath })
Inseob Kimcd616492020-03-24 23:06:40 +0900429 if !ok {
430 panic(fmt.Errorf("unknown dependency %q for %q", ctx.OtherModuleName(c), ctx.ModuleName()))
431 }
Inseob Kim3a3539a2021-01-15 18:10:29 +0900432 if api := i.CurrentSyspropApiFile(); api.Valid() {
433 apiFiles = append(apiFiles, api.Path())
434 }
Inseob Kimcd616492020-03-24 23:06:40 +0900435 })
436
437 // check compatibility with sysprop_library
438 if len(apiFiles) > 0 {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900439 out := pathForModuleOut(ctx, ctx.ModuleName()+"_api_checked")
Colin Cross242c8bc2020-11-16 17:58:17 -0800440 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kimcd616492020-03-24 23:06:40 +0900441
442 msg := `\n******************************\n` +
443 `API of sysprop_library doesn't match with property_contexts\n` +
444 `Please fix the breakage and rebuild.\n` +
445 `******************************\n`
446
447 rule.Command().
448 Text("( ").
Colin Cross242c8bc2020-11-16 17:58:17 -0800449 BuiltTool("sysprop_type_checker").
Inseob Kimcd616492020-03-24 23:06:40 +0900450 FlagForEachInput("--api ", apiFiles).
451 FlagWithInput("--context ", builtCtxFile).
452 Text(" || ( echo").Flag("-e").
453 Flag(`"` + msg + `"`).
454 Text("; exit 38) )")
455
456 rule.Command().Text("cp -f").Input(builtCtxFile).Output(out)
Colin Cross242c8bc2020-11-16 17:58:17 -0800457 rule.Build("property_contexts_check_api", "checking API: "+m.Name())
Inseob Kimcd616492020-03-24 23:06:40 +0900458 builtCtxFile = out
459 }
460
461 return builtCtxFile
Inseob Kimb554e592019-04-15 20:10:46 +0900462}
463
Inseob Kim06518b12023-08-25 21:20:08 +0900464func (m *selinuxContextsModule) shouldCheckCoredomain(ctx android.ModuleContext) bool {
465 if !ctx.SocSpecific() && !ctx.DeviceSpecific() {
466 return false
467 }
468
469 return ctx.DeviceConfig().CheckVendorSeappViolations()
470}
471
Inseob Kim2dac2672021-12-29 17:54:57 +0900472func (m *selinuxContextsModule) buildSeappContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900473 neverallowFile := pathForModuleOut(ctx, "neverallow")
Inseob Kim085f22f2023-11-09 11:13:01 +0900474 ret := pathForModuleOut(ctx, "checkseapp", m.stem())
Inseob Kim2dac2672021-12-29 17:54:57 +0900475
Inseob Kim085f22f2023-11-09 11:13:01 +0900476 // Step 1. Generate a M4 processed neverallow file
477 flags := m.getBuildFlags(ctx)
478 m4NeverallowFile := pathForModuleOut(ctx, "neverallow.m4out")
Inseob Kim2dac2672021-12-29 17:54:57 +0900479 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kim085f22f2023-11-09 11:13:01 +0900480 rule.Command().
481 Tool(ctx.Config().PrebuiltBuildTool(ctx, "m4")).
482 Flag("--fatal-warnings").
483 FlagForEachArg("-D", ctx.DeviceConfig().SepolicyM4Defs()).
484 Flags(flagsToM4Macros(flags)).
485 Inputs(android.PathsForModuleSrc(ctx, m.seappProperties.Neverallow_files)).
486 FlagWithOutput("> ", m4NeverallowFile)
487
488 rule.Temporary(m4NeverallowFile)
489 rule.Command().
490 Text("( grep").
Inseob Kim2dac2672021-12-29 17:54:57 +0900491 Flag("-ihe").
492 Text("'^neverallow'").
Inseob Kim085f22f2023-11-09 11:13:01 +0900493 Input(m4NeverallowFile).
Inseob Kim2dac2672021-12-29 17:54:57 +0900494 Text(">").
495 Output(neverallowFile).
Inseob Kim085f22f2023-11-09 11:13:01 +0900496 Text("|| true )") // to make ninja happy even when result is empty
Inseob Kim2dac2672021-12-29 17:54:57 +0900497
Inseob Kim085f22f2023-11-09 11:13:01 +0900498 // Step 2. Generate a M4 processed contexts file
499 builtCtx := m.buildGeneralContexts(ctx, inputs)
500
501 // Step 3. checkseapp
Inseob Kim2dac2672021-12-29 17:54:57 +0900502 rule.Temporary(neverallowFile)
Inseob Kimd7d36092023-06-26 20:48:48 +0900503 checkCmd := rule.Command().BuiltTool("checkseapp").
Inseob Kim2dac2672021-12-29 17:54:57 +0900504 FlagWithInput("-p ", android.PathForModuleSrc(ctx, proptools.String(m.seappProperties.Sepolicy))).
505 FlagWithOutput("-o ", ret).
Inseob Kim085f22f2023-11-09 11:13:01 +0900506 Input(builtCtx).
Inseob Kim2dac2672021-12-29 17:54:57 +0900507 Input(neverallowFile)
508
Inseob Kim06518b12023-08-25 21:20:08 +0900509 if m.shouldCheckCoredomain(ctx) {
510 checkCmd.Flag("-c") // check coredomain for vendor contexts
Inseob Kimd7d36092023-06-26 20:48:48 +0900511 }
512
Inseob Kim2dac2672021-12-29 17:54:57 +0900513 rule.Build("seapp_contexts", "Building seapp_contexts: "+m.Name())
514 return ret
515}
516
Inseob Kimb554e592019-04-15 20:10:46 +0900517func hwServiceFactory() android.Module {
518 m := newModule()
Thiébaud Weksteen74482f52023-04-26 13:46:59 +1000519 m.build = m.buildServiceContexts
Inseob Kimb554e592019-04-15 20:10:46 +0900520 return m
521}
522
523func propertyFactory() android.Module {
524 m := newModule()
Inseob Kimcd616492020-03-24 23:06:40 +0900525 m.build = m.buildPropertyContexts
526 m.deps = m.propertyContextsDeps
Inseob Kimb554e592019-04-15 20:10:46 +0900527 return m
528}
529
530func serviceFactory() android.Module {
531 m := newModule()
Thiébaud Weksteen74482f52023-04-26 13:46:59 +1000532 m.build = m.buildServiceContexts
Inseob Kimb554e592019-04-15 20:10:46 +0900533 return m
534}
Janis Danisevskisc40681f2020-07-25 13:02:29 -0700535
536func keystoreKeyFactory() android.Module {
537 m := newModule()
538 m.build = m.buildGeneralContexts
539 return m
540}
Yuntao Xu42e732c2021-11-18 22:33:02 +0000541
Nikita Ioffe48966b62024-10-22 14:01:17 +0000542func teeServiceFactory() android.Module {
543 m := newModule()
544 m.build = m.buildGeneralContexts
545 return m
546}
547
Inseob Kim2dac2672021-12-29 17:54:57 +0900548func seappFactory() android.Module {
549 m := newModule()
550 m.build = m.buildSeappContexts
551 return m
552}
553
Inseob Kimc7596c42022-02-25 11:45:41 +0900554func vndServiceFactory() android.Module {
555 m := newModule()
556 m.build = m.buildGeneralContexts
557 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
558 if !ctx.SocSpecific() {
559 ctx.ModuleErrorf(m.Name(), "must set vendor: true")
560 return
561 }
562 })
563 return m
564}
565
Inseob Kimb5e23532022-02-16 02:26:11 +0000566type contextsTestProperties struct {
567 // Contexts files to be tested.
568 Srcs []string `android:"path"`
569
570 // Precompiled sepolicy binary to be tesed together.
571 Sepolicy *string `android:"path"`
572}
573
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100574type fileContextsTestProperties struct {
575 // Test data. File passed to `checkfc -t` to validate how contexts are resolved.
576 Test_data *string `android:"path"`
577}
578
Inseob Kimb5e23532022-02-16 02:26:11 +0000579type contextsTestModule struct {
580 android.ModuleBase
581
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100582 // The type of context.
583 context contextType
Inseob Kimb5e23532022-02-16 02:26:11 +0000584
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100585 properties contextsTestProperties
586 fileProperties fileContextsTestProperties
587 testTimestamp android.OutputPath
Inseob Kimb5e23532022-02-16 02:26:11 +0000588}
589
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100590type contextType int
591
592const (
593 FileContext contextType = iota
594 PropertyContext
595 ServiceContext
596 HwServiceContext
597 VndServiceContext
598)
599
Inseob Kimb5e23532022-02-16 02:26:11 +0000600// checkfc parses a context file and checks for syntax errors.
601// If -s is specified, the service backend is used to verify binder services.
602// If -l is specified, the service backend is used to verify hwbinder services.
603// Otherwise, context_file is assumed to be a file_contexts file
604// If -e is specified, then the context_file is allowed to be empty.
605
606// file_contexts_test tests given file_contexts files with checkfc.
607func fileContextsTestFactory() android.Module {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100608 m := &contextsTestModule{context: FileContext}
Inseob Kimb5e23532022-02-16 02:26:11 +0000609 m.AddProperties(&m.properties)
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100610 m.AddProperties(&m.fileProperties)
Inseob Kimb5e23532022-02-16 02:26:11 +0000611 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
612 return m
613}
614
615// property_contexts_test tests given property_contexts files with property_info_checker.
616func propertyContextsTestFactory() android.Module {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100617 m := &contextsTestModule{context: PropertyContext}
Inseob Kimb5e23532022-02-16 02:26:11 +0000618 m.AddProperties(&m.properties)
619 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
620 return m
621}
622
623// hwservice_contexts_test tests given hwservice_contexts files with checkfc.
624func hwserviceContextsTestFactory() android.Module {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100625 m := &contextsTestModule{context: HwServiceContext}
Inseob Kimb5e23532022-02-16 02:26:11 +0000626 m.AddProperties(&m.properties)
627 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
628 return m
629}
630
631// service_contexts_test tests given service_contexts files with checkfc.
632func serviceContextsTestFactory() android.Module {
633 // checkfc -s: service_contexts test
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100634 m := &contextsTestModule{context: ServiceContext}
Inseob Kimb5e23532022-02-16 02:26:11 +0000635 m.AddProperties(&m.properties)
636 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
637 return m
638}
639
Inseob Kimc7596c42022-02-25 11:45:41 +0900640// vndservice_contexts_test tests given vndservice_contexts files with checkfc.
641func vndServiceContextsTestFactory() android.Module {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100642 m := &contextsTestModule{context: VndServiceContext}
Inseob Kimc7596c42022-02-25 11:45:41 +0900643 m.AddProperties(&m.properties)
644 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
645 return m
646}
647
Inseob Kimb5e23532022-02-16 02:26:11 +0000648func (m *contextsTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100649 tool := "checkfc"
650 if m.context == PropertyContext {
651 tool = "property_info_checker"
Inseob Kimb5e23532022-02-16 02:26:11 +0000652 }
653
654 if len(m.properties.Srcs) == 0 {
655 ctx.PropertyErrorf("srcs", "can't be empty")
656 return
657 }
658
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100659 validateWithPolicy := true
Inseob Kimb5e23532022-02-16 02:26:11 +0000660 if proptools.String(m.properties.Sepolicy) == "" {
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100661 if m.context == FileContext {
662 if proptools.String(m.fileProperties.Test_data) == "" {
663 ctx.PropertyErrorf("test_data", "Either test_data or sepolicy should be provided")
664 return
665 }
666 validateWithPolicy = false
667 } else {
668 ctx.PropertyErrorf("sepolicy", "can't be empty")
669 return
670 }
Inseob Kimb5e23532022-02-16 02:26:11 +0000671 }
672
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100673 flags := []string(nil)
674 switch m.context {
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100675 case FileContext:
676 if !validateWithPolicy {
677 flags = []string{"-t"}
678 }
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100679 case ServiceContext:
680 flags = []string{"-s" /* binder services */}
681 case HwServiceContext:
682 flags = []string{"-e" /* allow empty */, "-l" /* hwbinder services */}
683 case VndServiceContext:
684 flags = []string{"-e" /* allow empty */, "-v" /* vnd service */}
685 }
686
Inseob Kimb5e23532022-02-16 02:26:11 +0000687 srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs)
Inseob Kimb5e23532022-02-16 02:26:11 +0000688 rule := android.NewRuleBuilder(pctx, ctx)
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100689
690 if validateWithPolicy {
691 sepolicy := android.PathForModuleSrc(ctx, proptools.String(m.properties.Sepolicy))
692 rule.Command().BuiltTool(tool).
693 Flags(flags).
694 Input(sepolicy).
695 Inputs(srcs)
696 } else {
697 test_data := android.PathForModuleSrc(ctx, proptools.String(m.fileProperties.Test_data))
698 rule.Command().BuiltTool(tool).
699 Flags(flags).
700 Inputs(srcs).
701 Input(test_data)
702 }
Inseob Kimb5e23532022-02-16 02:26:11 +0000703
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900704 m.testTimestamp = pathForModuleOut(ctx, "timestamp")
Inseob Kimb5e23532022-02-16 02:26:11 +0000705 rule.Command().Text("touch").Output(m.testTimestamp)
706 rule.Build("contexts_test", "running contexts test: "+ctx.ModuleName())
707}
708
709func (m *contextsTestModule) AndroidMkEntries() []android.AndroidMkEntries {
710 return []android.AndroidMkEntries{android.AndroidMkEntries{
711 Class: "FAKE",
712 // OutputFile is needed, even though BUILD_PHONY_PACKAGE doesn't use it.
713 // Without OutputFile this module won't be exported to Makefile.
714 OutputFile: android.OptionalPathForPath(m.testTimestamp),
715 Include: "$(BUILD_PHONY_PACKAGE)",
716 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
717 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
718 entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", m.testTimestamp.String())
719 },
720 },
721 }}
722}
723
724// contextsTestModule implements ImageInterface to be able to include recovery_available contexts
725// modules as its sources.
Cole Faust05924482024-10-15 11:28:34 -0700726func (m *contextsTestModule) ImageMutatorBegin(ctx android.ImageInterfaceContext) {
Inseob Kimb5e23532022-02-16 02:26:11 +0000727}
728
Cole Faust05924482024-10-15 11:28:34 -0700729func (m *contextsTestModule) VendorVariantNeeded(ctx android.ImageInterfaceContext) bool {
Jihoon Kang03f4d9d2024-06-21 06:36:33 +0000730 return false
731}
732
Cole Faust05924482024-10-15 11:28:34 -0700733func (m *contextsTestModule) ProductVariantNeeded(ctx android.ImageInterfaceContext) bool {
Jihoon Kang03f4d9d2024-06-21 06:36:33 +0000734 return false
735}
736
Cole Faust05924482024-10-15 11:28:34 -0700737func (m *contextsTestModule) CoreVariantNeeded(ctx android.ImageInterfaceContext) bool {
Inseob Kimb5e23532022-02-16 02:26:11 +0000738 return true
739}
740
Cole Faust05924482024-10-15 11:28:34 -0700741func (m *contextsTestModule) RamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
Inseob Kimb5e23532022-02-16 02:26:11 +0000742 return false
743}
744
Cole Faust05924482024-10-15 11:28:34 -0700745func (m *contextsTestModule) VendorRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
Inseob Kimb5e23532022-02-16 02:26:11 +0000746 return false
747}
748
Cole Faust05924482024-10-15 11:28:34 -0700749func (m *contextsTestModule) DebugRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
Inseob Kimb5e23532022-02-16 02:26:11 +0000750 return false
751}
752
Cole Faust05924482024-10-15 11:28:34 -0700753func (m *contextsTestModule) RecoveryVariantNeeded(ctx android.ImageInterfaceContext) bool {
Inseob Kimb5e23532022-02-16 02:26:11 +0000754 return false
755}
756
Cole Faust05924482024-10-15 11:28:34 -0700757func (m *contextsTestModule) ExtraImageVariations(ctx android.ImageInterfaceContext) []string {
Inseob Kimb5e23532022-02-16 02:26:11 +0000758 return nil
759}
760
Cole Faust05924482024-10-15 11:28:34 -0700761func (m *contextsTestModule) SetImageVariation(ctx android.ImageInterfaceContext, variation string) {
Inseob Kimb5e23532022-02-16 02:26:11 +0000762}
763
764var _ android.ImageInterface = (*contextsTestModule)(nil)