blob: 5f7d525a6173d00ba1d7601e820e4c4d2ac939c9 [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 Kim2dac2672021-12-29 17:54:57 +090020 "os"
Inseob Kimb554e592019-04-15 20:10:46 +090021
Inseob Kimcd616492020-03-24 23:06:40 +090022 "github.com/google/blueprint"
Inseob Kimb554e592019-04-15 20:10:46 +090023 "github.com/google/blueprint/proptools"
24
25 "android/soong/android"
Inseob Kimcd616492020-03-24 23:06:40 +090026 "android/soong/sysprop"
Inseob Kimb554e592019-04-15 20:10:46 +090027)
28
Inseob Kimb554e592019-04-15 20:10:46 +090029type selinuxContextsProperties struct {
30 // Filenames under sepolicy directories, which will be used to generate contexts file.
31 Srcs []string `android:"path"`
32
Yuntao Xu42e732c2021-11-18 22:33:02 +000033 // Output file name. Defaults to module name
34 Stem *string
35
Inseob Kimb554e592019-04-15 20:10:46 +090036 Product_variables struct {
Inseob Kimb554e592019-04-15 20:10:46 +090037 Address_sanitize struct {
Inseob Kim6d3d5a62021-12-21 20:55:32 +090038 Srcs []string `android:"path"`
Inseob Kimb554e592019-04-15 20:10:46 +090039 }
40 }
41
Inseob Kimb554e592019-04-15 20:10:46 +090042 // Whether the comments in generated contexts file will be removed or not.
43 Remove_comment *bool
44
45 // Whether the result context file is sorted with fc_sort or not.
46 Fc_sort *bool
47
48 // Make this module available when building for recovery
49 Recovery_available *bool
Inseob Kimb554e592019-04-15 20:10:46 +090050}
51
Inseob Kim2dac2672021-12-29 17:54:57 +090052type seappProperties struct {
53 // Files containing neverallow rules.
54 Neverallow_files []string `android:"path"`
55
56 // Precompiled sepolicy binary file which will be fed to checkseapp.
57 Sepolicy *string `android:"path"`
58}
59
Inseob Kimb554e592019-04-15 20:10:46 +090060type selinuxContextsModule struct {
61 android.ModuleBase
Inseob Kim6cd0ddd2023-10-25 23:48:16 +090062 android.DefaultableModuleBase
63 flaggableModuleBase
Inseob Kimb554e592019-04-15 20:10:46 +090064
Jooyung Han804e2342023-06-20 15:38:50 +090065 properties selinuxContextsProperties
66 seappProperties seappProperties
67 build func(ctx android.ModuleContext, inputs android.Paths) android.Path
68 deps func(ctx android.BottomUpMutatorContext)
69 outputPath android.Path
70 installPath android.InstallPath
Inseob Kimb554e592019-04-15 20:10:46 +090071}
72
Inseob Kim6cd0ddd2023-10-25 23:48:16 +090073var _ flaggableModule = (*selinuxContextsModule)(nil)
74
Inseob Kimb554e592019-04-15 20:10:46 +090075var (
Inseob Kimcd616492020-03-24 23:06:40 +090076 reuseContextsDepTag = dependencyTag{name: "reuseContexts"}
77 syspropLibraryDepTag = dependencyTag{name: "sysprop_library"}
Inseob Kimb554e592019-04-15 20:10:46 +090078)
79
80func init() {
81 pctx.HostBinToolVariable("fc_sort", "fc_sort")
82
Inseob Kim6cd0ddd2023-10-25 23:48:16 +090083 android.RegisterModuleType("contexts_defaults", contextsDefaultsFactory)
Inseob Kimb554e592019-04-15 20:10:46 +090084 android.RegisterModuleType("file_contexts", fileFactory)
85 android.RegisterModuleType("hwservice_contexts", hwServiceFactory)
86 android.RegisterModuleType("property_contexts", propertyFactory)
87 android.RegisterModuleType("service_contexts", serviceFactory)
Janis Danisevskisc40681f2020-07-25 13:02:29 -070088 android.RegisterModuleType("keystore2_key_contexts", keystoreKeyFactory)
Inseob Kim2dac2672021-12-29 17:54:57 +090089 android.RegisterModuleType("seapp_contexts", seappFactory)
Inseob Kimc7596c42022-02-25 11:45:41 +090090 android.RegisterModuleType("vndservice_contexts", vndServiceFactory)
Inseob Kimb5e23532022-02-16 02:26:11 +000091
92 android.RegisterModuleType("file_contexts_test", fileContextsTestFactory)
93 android.RegisterModuleType("property_contexts_test", propertyContextsTestFactory)
94 android.RegisterModuleType("hwservice_contexts_test", hwserviceContextsTestFactory)
95 android.RegisterModuleType("service_contexts_test", serviceContextsTestFactory)
Inseob Kimc7596c42022-02-25 11:45:41 +090096 android.RegisterModuleType("vndservice_contexts_test", vndServiceContextsTestFactory)
Inseob Kimb554e592019-04-15 20:10:46 +090097}
98
Colin Cross040f1512019-10-02 10:36:09 -070099func (m *selinuxContextsModule) InstallInRoot() bool {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900100 return m.InRecovery()
101}
102
103func (m *selinuxContextsModule) InstallInRecovery() bool {
104 // ModuleBase.InRecovery() checks the image variant
105 return m.InRecovery()
106}
107
108func (m *selinuxContextsModule) onlyInRecovery() bool {
109 // ModuleBase.InstallInRecovery() checks commonProperties.Recovery property
110 return m.ModuleBase.InstallInRecovery()
Colin Cross040f1512019-10-02 10:36:09 -0700111}
112
Inseob Kimcd616492020-03-24 23:06:40 +0900113func (m *selinuxContextsModule) DepsMutator(ctx android.BottomUpMutatorContext) {
114 if m.deps != nil {
115 m.deps(ctx)
116 }
Inseob Kimfa6fe472021-01-12 13:40:27 +0900117
118 if m.InRecovery() && !m.onlyInRecovery() {
119 ctx.AddFarVariationDependencies([]blueprint.Variation{
120 {Mutator: "image", Variation: android.CoreVariation},
121 }, reuseContextsDepTag, ctx.ModuleName())
122 }
Inseob Kimcd616492020-03-24 23:06:40 +0900123}
124
125func (m *selinuxContextsModule) propertyContextsDeps(ctx android.BottomUpMutatorContext) {
126 for _, lib := range sysprop.SyspropLibraries(ctx.Config()) {
127 ctx.AddFarVariationDependencies([]blueprint.Variation{}, syspropLibraryDepTag, lib)
128 }
129}
130
Yuntao Xu42e732c2021-11-18 22:33:02 +0000131func (m *selinuxContextsModule) stem() string {
132 return proptools.StringDefault(m.properties.Stem, m.Name())
133}
134
Inseob Kimb554e592019-04-15 20:10:46 +0900135func (m *selinuxContextsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900136 if m.InRecovery() {
Colin Cross040f1512019-10-02 10:36:09 -0700137 // Installing context files at the root of the recovery partition
138 m.installPath = android.PathForModuleInstall(ctx)
Inseob Kimb554e592019-04-15 20:10:46 +0900139 } else {
140 m.installPath = android.PathForModuleInstall(ctx, "etc", "selinux")
141 }
142
Inseob Kimfa6fe472021-01-12 13:40:27 +0900143 if m.InRecovery() && !m.onlyInRecovery() {
Inseob Kimb554e592019-04-15 20:10:46 +0900144 dep := ctx.GetDirectDepWithTag(m.Name(), reuseContextsDepTag)
145
146 if reuseDeps, ok := dep.(*selinuxContextsModule); ok {
147 m.outputPath = reuseDeps.outputPath
Yuntao Xu42e732c2021-11-18 22:33:02 +0000148 ctx.InstallFile(m.installPath, m.stem(), m.outputPath)
Inseob Kimb554e592019-04-15 20:10:46 +0900149 return
150 }
151 }
152
Inseob Kim6d3d5a62021-12-21 20:55:32 +0900153 m.outputPath = m.build(ctx, android.PathsForModuleSrc(ctx, m.properties.Srcs))
Yuntao Xu42e732c2021-11-18 22:33:02 +0000154 ctx.InstallFile(m.installPath, m.stem(), m.outputPath)
Inseob Kimb554e592019-04-15 20:10:46 +0900155}
156
157func newModule() *selinuxContextsModule {
158 m := &selinuxContextsModule{}
159 m.AddProperties(
160 &m.properties,
Inseob Kim2dac2672021-12-29 17:54:57 +0900161 &m.seappProperties,
Inseob Kimb554e592019-04-15 20:10:46 +0900162 )
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900163 initFlaggableModule(m)
Inseob Kimb554e592019-04-15 20:10:46 +0900164 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900165 android.InitDefaultableModule(m)
Inseob Kimb554e592019-04-15 20:10:46 +0900166 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
167 m.selinuxContextsHook(ctx)
168 })
169 return m
170}
171
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900172type contextsDefaults struct {
173 android.ModuleBase
174 android.DefaultsModuleBase
175}
176
177// contexts_defaults provides a set of properties that can be inherited by other contexts modules.
178// (file_contexts, property_contexts, seapp_contexts, etc.) A module can use the properties from a
179// contexts_defaults using `defaults: ["<:default_module_name>"]`. Properties of both modules are
180// erged (when possible) by prepending the default module's values to the depending module's values.
181func contextsDefaultsFactory() android.Module {
182 m := &contextsDefaults{}
183 m.AddProperties(
184 &selinuxContextsProperties{},
185 &seappProperties{},
186 &flagsProperties{},
187 )
188 android.InitDefaultsModule(m)
189 return m
190}
191
Inseob Kimb554e592019-04-15 20:10:46 +0900192func (m *selinuxContextsModule) selinuxContextsHook(ctx android.LoadHookContext) {
193 // TODO: clean this up to use build/soong/android/variable.go after b/79249983
194 var srcs []string
195
Inseob Kimb554e592019-04-15 20:10:46 +0900196 for _, sanitize := range ctx.Config().SanitizeDevice() {
197 if sanitize == "address" {
198 srcs = append(srcs, m.properties.Product_variables.Address_sanitize.Srcs...)
199 break
200 }
201 }
202
203 m.properties.Srcs = append(m.properties.Srcs, srcs...)
204}
205
206func (m *selinuxContextsModule) AndroidMk() android.AndroidMkData {
Colin Crossf82aed02021-11-04 17:25:55 -0700207 nameSuffix := ""
208 if m.InRecovery() && !m.onlyInRecovery() {
209 nameSuffix = ".recovery"
210 }
Inseob Kimb554e592019-04-15 20:10:46 +0900211 return android.AndroidMkData{
Colin Crossf82aed02021-11-04 17:25:55 -0700212 Class: "ETC",
213 OutputFile: android.OptionalPathForPath(m.outputPath),
214 SubName: nameSuffix,
215 Extra: []android.AndroidMkExtraFunc{
216 func(w io.Writer, outputFile android.Path) {
Colin Cross6c7f9372022-01-11 19:35:43 -0800217 fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", m.installPath.String())
Yuntao Xu42e732c2021-11-18 22:33:02 +0000218 fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.stem())
Colin Crossf82aed02021-11-04 17:25:55 -0700219 },
Inseob Kimb554e592019-04-15 20:10:46 +0900220 },
221 }
222}
223
Inseob Kimfa6fe472021-01-12 13:40:27 +0900224func (m *selinuxContextsModule) ImageMutatorBegin(ctx android.BaseModuleContext) {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000225 if proptools.Bool(m.properties.Recovery_available) && m.ModuleBase.InstallInRecovery() {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900226 ctx.PropertyErrorf("recovery_available",
227 "doesn't make sense at the same time as `recovery: true`")
Inseob Kimb554e592019-04-15 20:10:46 +0900228 }
229}
230
Inseob Kimfa6fe472021-01-12 13:40:27 +0900231func (m *selinuxContextsModule) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000232 return !m.ModuleBase.InstallInRecovery()
Inseob Kimfa6fe472021-01-12 13:40:27 +0900233}
234
235func (m *selinuxContextsModule) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
236 return false
237}
238
239func (m *selinuxContextsModule) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
240 return false
241}
242
Inseob Kim6cc75f42021-04-29 13:53:20 +0000243func (m *selinuxContextsModule) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
244 return false
245}
246
Inseob Kimfa6fe472021-01-12 13:40:27 +0900247func (m *selinuxContextsModule) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000248 return m.ModuleBase.InstallInRecovery() || proptools.Bool(m.properties.Recovery_available)
Inseob Kimfa6fe472021-01-12 13:40:27 +0900249}
250
251func (m *selinuxContextsModule) ExtraImageVariations(ctx android.BaseModuleContext) []string {
252 return nil
253}
254
255func (m *selinuxContextsModule) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
256}
257
258var _ android.ImageInterface = (*selinuxContextsModule)(nil)
259
Inseob Kimcd616492020-03-24 23:06:40 +0900260func (m *selinuxContextsModule) buildGeneralContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900261 builtContext := pathForModuleOut(ctx, ctx.ModuleName()+"_m4out")
Inseob Kimb554e592019-04-15 20:10:46 +0900262
Colin Cross242c8bc2020-11-16 17:58:17 -0800263 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kimb554e592019-04-15 20:10:46 +0900264
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900265 newlineFile := pathForModuleOut(ctx, "newline")
Inseob Kim35e9d412023-01-04 15:27:32 +0900266
267 rule.Command().Text("echo").FlagWithOutput("> ", newlineFile)
268 rule.Temporary(newlineFile)
269
270 var inputsWithNewline android.Paths
271 for _, input := range inputs {
272 inputsWithNewline = append(inputsWithNewline, input, newlineFile)
273 }
274
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900275 flags := m.getBuildFlags(ctx)
Inseob Kimb554e592019-04-15 20:10:46 +0900276 rule.Command().
Dan Willemsen3c3e59b2019-06-19 10:52:50 -0700277 Tool(ctx.Config().PrebuiltBuildTool(ctx, "m4")).
278 Text("--fatal-warnings -s").
Inseob Kimb554e592019-04-15 20:10:46 +0900279 FlagForEachArg("-D", ctx.DeviceConfig().SepolicyM4Defs()).
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900280 Flags(flagsToM4Macros(flags)).
Inseob Kim35e9d412023-01-04 15:27:32 +0900281 Inputs(inputsWithNewline).
Yuntao Xu42e732c2021-11-18 22:33:02 +0000282 FlagWithOutput("> ", builtContext)
Inseob Kimb554e592019-04-15 20:10:46 +0900283
284 if proptools.Bool(m.properties.Remove_comment) {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000285 rule.Temporary(builtContext)
Inseob Kimb554e592019-04-15 20:10:46 +0900286
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900287 remove_comment_output := pathForModuleOut(ctx, ctx.ModuleName()+"_remove_comment")
Inseob Kimb554e592019-04-15 20:10:46 +0900288
289 rule.Command().
290 Text("sed -e 's/#.*$//' -e '/^$/d'").
Yuntao Xu42e732c2021-11-18 22:33:02 +0000291 Input(builtContext).
Inseob Kimb554e592019-04-15 20:10:46 +0900292 FlagWithOutput("> ", remove_comment_output)
293
Yuntao Xu42e732c2021-11-18 22:33:02 +0000294 builtContext = remove_comment_output
Inseob Kimb554e592019-04-15 20:10:46 +0900295 }
296
297 if proptools.Bool(m.properties.Fc_sort) {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000298 rule.Temporary(builtContext)
Inseob Kimb554e592019-04-15 20:10:46 +0900299
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900300 sorted_output := pathForModuleOut(ctx, ctx.ModuleName()+"_sorted")
Inseob Kimb554e592019-04-15 20:10:46 +0900301
302 rule.Command().
303 Tool(ctx.Config().HostToolPath(ctx, "fc_sort")).
Yuntao Xu42e732c2021-11-18 22:33:02 +0000304 FlagWithInput("-i ", builtContext).
Inseob Kimb554e592019-04-15 20:10:46 +0900305 FlagWithOutput("-o ", sorted_output)
306
Yuntao Xu42e732c2021-11-18 22:33:02 +0000307 builtContext = sorted_output
Inseob Kimb554e592019-04-15 20:10:46 +0900308 }
309
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900310 ret := pathForModuleOut(ctx, m.stem())
Yuntao Xu42e732c2021-11-18 22:33:02 +0000311 rule.Temporary(builtContext)
312 rule.Command().Text("cp").Input(builtContext).Output(ret)
Inseob Kimb554e592019-04-15 20:10:46 +0900313
314 rule.DeleteTemporaryFiles()
Yuntao Xu42e732c2021-11-18 22:33:02 +0000315 rule.Build("selinux_contexts", "building contexts: "+m.Name())
Inseob Kimb554e592019-04-15 20:10:46 +0900316
Inseob Kimcd616492020-03-24 23:06:40 +0900317 return ret
Inseob Kimb554e592019-04-15 20:10:46 +0900318}
319
Inseob Kimcd616492020-03-24 23:06:40 +0900320func (m *selinuxContextsModule) buildFileContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kimdfa4a482023-11-01 17:58:18 +0900321 if m.properties.Remove_comment == nil {
322 m.properties.Remove_comment = proptools.BoolPtr(true)
Inseob Kimb554e592019-04-15 20:10:46 +0900323 }
Inseob Kimcd616492020-03-24 23:06:40 +0900324 return m.buildGeneralContexts(ctx, inputs)
Inseob Kimb554e592019-04-15 20:10:46 +0900325}
326
327func fileFactory() android.Module {
328 m := newModule()
Inseob Kimb554e592019-04-15 20:10:46 +0900329 m.build = m.buildFileContexts
330 return m
331}
332
Thiébaud Weksteen74482f52023-04-26 13:46:59 +1000333func (m *selinuxContextsModule) buildServiceContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kimb554e592019-04-15 20:10:46 +0900334 if m.properties.Remove_comment == nil {
335 m.properties.Remove_comment = proptools.BoolPtr(true)
336 }
337
Inseob Kimcd616492020-03-24 23:06:40 +0900338 return m.buildGeneralContexts(ctx, inputs)
339}
340
Inseob Kim2bcc0452020-12-21 13:16:44 +0900341func (m *selinuxContextsModule) checkVendorPropertyNamespace(ctx android.ModuleContext, inputs android.Paths) android.Paths {
342 shippingApiLevel := ctx.DeviceConfig().ShippingApiLevel()
343 ApiLevelR := android.ApiLevelOrPanic(ctx, "R")
344
345 rule := android.NewRuleBuilder(pctx, ctx)
346
347 // This list is from vts_treble_sys_prop_test.
348 allowedPropertyPrefixes := []string{
349 "ctl.odm.",
350 "ctl.vendor.",
351 "ctl.start$odm.",
352 "ctl.start$vendor.",
353 "ctl.stop$odm.",
354 "ctl.stop$vendor.",
355 "init.svc.odm.",
356 "init.svc.vendor.",
357 "ro.boot.",
358 "ro.hardware.",
359 "ro.odm.",
360 "ro.vendor.",
361 "odm.",
362 "persist.odm.",
363 "persist.vendor.",
364 "vendor.",
365 }
366
367 // persist.camera is also allowed for devices launching with R or eariler
368 if shippingApiLevel.LessThanOrEqualTo(ApiLevelR) {
369 allowedPropertyPrefixes = append(allowedPropertyPrefixes, "persist.camera.")
370 }
371
372 var allowedContextPrefixes []string
373
374 if shippingApiLevel.GreaterThanOrEqualTo(ApiLevelR) {
375 // This list is from vts_treble_sys_prop_test.
376 allowedContextPrefixes = []string{
377 "vendor_",
378 "odm_",
379 }
380 }
381
382 var ret android.Paths
383 for _, input := range inputs {
384 cmd := rule.Command().
385 BuiltTool("check_prop_prefix").
386 FlagWithInput("--property-contexts ", input).
387 FlagForEachArg("--allowed-property-prefix ", proptools.ShellEscapeList(allowedPropertyPrefixes)). // contains shell special character '$'
388 FlagForEachArg("--allowed-context-prefix ", allowedContextPrefixes)
389
390 if !ctx.DeviceConfig().BuildBrokenVendorPropertyNamespace() {
391 cmd.Flag("--strict")
392 }
393
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900394 out := pathForModuleOut(ctx, "namespace_checked").Join(ctx, input.String())
Inseob Kim2bcc0452020-12-21 13:16:44 +0900395 rule.Command().Text("cp -f").Input(input).Output(out)
396 ret = append(ret, out)
397 }
398 rule.Build("check_namespace", "checking namespace of "+ctx.ModuleName())
399 return ret
400}
401
Inseob Kimcd616492020-03-24 23:06:40 +0900402func (m *selinuxContextsModule) buildPropertyContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kim2bcc0452020-12-21 13:16:44 +0900403 // vendor/odm properties are enforced for devices launching with Android Q or later. So, if
404 // vendor/odm, make sure that only vendor/odm properties exist.
405 shippingApiLevel := ctx.DeviceConfig().ShippingApiLevel()
406 ApiLevelQ := android.ApiLevelOrPanic(ctx, "Q")
407 if (ctx.SocSpecific() || ctx.DeviceSpecific()) && shippingApiLevel.GreaterThanOrEqualTo(ApiLevelQ) {
408 inputs = m.checkVendorPropertyNamespace(ctx, inputs)
409 }
410
Inseob Kimcd616492020-03-24 23:06:40 +0900411 builtCtxFile := m.buildGeneralContexts(ctx, inputs)
412
413 var apiFiles android.Paths
414 ctx.VisitDirectDepsWithTag(syspropLibraryDepTag, func(c android.Module) {
Inseob Kim3a3539a2021-01-15 18:10:29 +0900415 i, ok := c.(interface{ CurrentSyspropApiFile() android.OptionalPath })
Inseob Kimcd616492020-03-24 23:06:40 +0900416 if !ok {
417 panic(fmt.Errorf("unknown dependency %q for %q", ctx.OtherModuleName(c), ctx.ModuleName()))
418 }
Inseob Kim3a3539a2021-01-15 18:10:29 +0900419 if api := i.CurrentSyspropApiFile(); api.Valid() {
420 apiFiles = append(apiFiles, api.Path())
421 }
Inseob Kimcd616492020-03-24 23:06:40 +0900422 })
423
424 // check compatibility with sysprop_library
425 if len(apiFiles) > 0 {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900426 out := pathForModuleOut(ctx, ctx.ModuleName()+"_api_checked")
Colin Cross242c8bc2020-11-16 17:58:17 -0800427 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kimcd616492020-03-24 23:06:40 +0900428
429 msg := `\n******************************\n` +
430 `API of sysprop_library doesn't match with property_contexts\n` +
431 `Please fix the breakage and rebuild.\n` +
432 `******************************\n`
433
434 rule.Command().
435 Text("( ").
Colin Cross242c8bc2020-11-16 17:58:17 -0800436 BuiltTool("sysprop_type_checker").
Inseob Kimcd616492020-03-24 23:06:40 +0900437 FlagForEachInput("--api ", apiFiles).
438 FlagWithInput("--context ", builtCtxFile).
439 Text(" || ( echo").Flag("-e").
440 Flag(`"` + msg + `"`).
441 Text("; exit 38) )")
442
443 rule.Command().Text("cp -f").Input(builtCtxFile).Output(out)
Colin Cross242c8bc2020-11-16 17:58:17 -0800444 rule.Build("property_contexts_check_api", "checking API: "+m.Name())
Inseob Kimcd616492020-03-24 23:06:40 +0900445 builtCtxFile = out
446 }
447
448 return builtCtxFile
Inseob Kimb554e592019-04-15 20:10:46 +0900449}
450
Inseob Kim06518b12023-08-25 21:20:08 +0900451func (m *selinuxContextsModule) shouldCheckCoredomain(ctx android.ModuleContext) bool {
452 if !ctx.SocSpecific() && !ctx.DeviceSpecific() {
453 return false
454 }
455
456 return ctx.DeviceConfig().CheckVendorSeappViolations()
457}
458
Inseob Kim2dac2672021-12-29 17:54:57 +0900459func (m *selinuxContextsModule) buildSeappContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900460 neverallowFile := pathForModuleOut(ctx, "neverallow")
461 ret := pathForModuleOut(ctx, m.stem())
Inseob Kim2dac2672021-12-29 17:54:57 +0900462
463 rule := android.NewRuleBuilder(pctx, ctx)
464 rule.Command().Text("(grep").
465 Flag("-ihe").
466 Text("'^neverallow'").
467 Inputs(android.PathsForModuleSrc(ctx, m.seappProperties.Neverallow_files)).
468 Text(os.DevNull). // to make grep happy even when Neverallow_files is empty
469 Text(">").
470 Output(neverallowFile).
471 Text("|| true)") // to make ninja happy even when result is empty
472
473 rule.Temporary(neverallowFile)
Inseob Kimd7d36092023-06-26 20:48:48 +0900474 checkCmd := rule.Command().BuiltTool("checkseapp").
Inseob Kim2dac2672021-12-29 17:54:57 +0900475 FlagWithInput("-p ", android.PathForModuleSrc(ctx, proptools.String(m.seappProperties.Sepolicy))).
476 FlagWithOutput("-o ", ret).
477 Inputs(inputs).
478 Input(neverallowFile)
479
Inseob Kim06518b12023-08-25 21:20:08 +0900480 if m.shouldCheckCoredomain(ctx) {
481 checkCmd.Flag("-c") // check coredomain for vendor contexts
Inseob Kimd7d36092023-06-26 20:48:48 +0900482 }
483
Inseob Kim2dac2672021-12-29 17:54:57 +0900484 rule.Build("seapp_contexts", "Building seapp_contexts: "+m.Name())
485 return ret
486}
487
Inseob Kimb554e592019-04-15 20:10:46 +0900488func hwServiceFactory() android.Module {
489 m := newModule()
Thiébaud Weksteen74482f52023-04-26 13:46:59 +1000490 m.build = m.buildServiceContexts
Inseob Kimb554e592019-04-15 20:10:46 +0900491 return m
492}
493
494func propertyFactory() android.Module {
495 m := newModule()
Inseob Kimcd616492020-03-24 23:06:40 +0900496 m.build = m.buildPropertyContexts
497 m.deps = m.propertyContextsDeps
Inseob Kimb554e592019-04-15 20:10:46 +0900498 return m
499}
500
501func serviceFactory() android.Module {
502 m := newModule()
Thiébaud Weksteen74482f52023-04-26 13:46:59 +1000503 m.build = m.buildServiceContexts
Inseob Kimb554e592019-04-15 20:10:46 +0900504 return m
505}
Janis Danisevskisc40681f2020-07-25 13:02:29 -0700506
507func keystoreKeyFactory() android.Module {
508 m := newModule()
509 m.build = m.buildGeneralContexts
510 return m
511}
Yuntao Xu42e732c2021-11-18 22:33:02 +0000512
Inseob Kim2dac2672021-12-29 17:54:57 +0900513func seappFactory() android.Module {
514 m := newModule()
515 m.build = m.buildSeappContexts
516 return m
517}
518
Inseob Kimc7596c42022-02-25 11:45:41 +0900519func vndServiceFactory() android.Module {
520 m := newModule()
521 m.build = m.buildGeneralContexts
522 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
523 if !ctx.SocSpecific() {
524 ctx.ModuleErrorf(m.Name(), "must set vendor: true")
525 return
526 }
527 })
528 return m
529}
530
Yuntao Xu42e732c2021-11-18 22:33:02 +0000531var _ android.OutputFileProducer = (*selinuxContextsModule)(nil)
532
533// Implements android.OutputFileProducer
534func (m *selinuxContextsModule) OutputFiles(tag string) (android.Paths, error) {
535 if tag == "" {
536 return []android.Path{m.outputPath}, nil
537 }
538 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
539}
Inseob Kimb5e23532022-02-16 02:26:11 +0000540
541type contextsTestProperties struct {
542 // Contexts files to be tested.
543 Srcs []string `android:"path"`
544
545 // Precompiled sepolicy binary to be tesed together.
546 Sepolicy *string `android:"path"`
547}
548
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100549type fileContextsTestProperties struct {
550 // Test data. File passed to `checkfc -t` to validate how contexts are resolved.
551 Test_data *string `android:"path"`
552}
553
Inseob Kimb5e23532022-02-16 02:26:11 +0000554type contextsTestModule struct {
555 android.ModuleBase
556
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100557 // The type of context.
558 context contextType
Inseob Kimb5e23532022-02-16 02:26:11 +0000559
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100560 properties contextsTestProperties
561 fileProperties fileContextsTestProperties
562 testTimestamp android.OutputPath
Inseob Kimb5e23532022-02-16 02:26:11 +0000563}
564
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100565type contextType int
566
567const (
568 FileContext contextType = iota
569 PropertyContext
570 ServiceContext
571 HwServiceContext
572 VndServiceContext
573)
574
Inseob Kimb5e23532022-02-16 02:26:11 +0000575// checkfc parses a context file and checks for syntax errors.
576// If -s is specified, the service backend is used to verify binder services.
577// If -l is specified, the service backend is used to verify hwbinder services.
578// Otherwise, context_file is assumed to be a file_contexts file
579// If -e is specified, then the context_file is allowed to be empty.
580
581// file_contexts_test tests given file_contexts files with checkfc.
582func fileContextsTestFactory() android.Module {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100583 m := &contextsTestModule{context: FileContext}
Inseob Kimb5e23532022-02-16 02:26:11 +0000584 m.AddProperties(&m.properties)
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100585 m.AddProperties(&m.fileProperties)
Inseob Kimb5e23532022-02-16 02:26:11 +0000586 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
587 return m
588}
589
590// property_contexts_test tests given property_contexts files with property_info_checker.
591func propertyContextsTestFactory() android.Module {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100592 m := &contextsTestModule{context: PropertyContext}
Inseob Kimb5e23532022-02-16 02:26:11 +0000593 m.AddProperties(&m.properties)
594 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
595 return m
596}
597
598// hwservice_contexts_test tests given hwservice_contexts files with checkfc.
599func hwserviceContextsTestFactory() android.Module {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100600 m := &contextsTestModule{context: HwServiceContext}
Inseob Kimb5e23532022-02-16 02:26:11 +0000601 m.AddProperties(&m.properties)
602 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
603 return m
604}
605
606// service_contexts_test tests given service_contexts files with checkfc.
607func serviceContextsTestFactory() android.Module {
608 // checkfc -s: service_contexts test
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100609 m := &contextsTestModule{context: ServiceContext}
Inseob Kimb5e23532022-02-16 02:26:11 +0000610 m.AddProperties(&m.properties)
611 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
612 return m
613}
614
Inseob Kimc7596c42022-02-25 11:45:41 +0900615// vndservice_contexts_test tests given vndservice_contexts files with checkfc.
616func vndServiceContextsTestFactory() android.Module {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100617 m := &contextsTestModule{context: VndServiceContext}
Inseob Kimc7596c42022-02-25 11:45:41 +0900618 m.AddProperties(&m.properties)
619 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
620 return m
621}
622
Inseob Kimb5e23532022-02-16 02:26:11 +0000623func (m *contextsTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100624 tool := "checkfc"
625 if m.context == PropertyContext {
626 tool = "property_info_checker"
Inseob Kimb5e23532022-02-16 02:26:11 +0000627 }
628
629 if len(m.properties.Srcs) == 0 {
630 ctx.PropertyErrorf("srcs", "can't be empty")
631 return
632 }
633
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100634 validateWithPolicy := true
Inseob Kimb5e23532022-02-16 02:26:11 +0000635 if proptools.String(m.properties.Sepolicy) == "" {
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100636 if m.context == FileContext {
637 if proptools.String(m.fileProperties.Test_data) == "" {
638 ctx.PropertyErrorf("test_data", "Either test_data or sepolicy should be provided")
639 return
640 }
641 validateWithPolicy = false
642 } else {
643 ctx.PropertyErrorf("sepolicy", "can't be empty")
644 return
645 }
Inseob Kimb5e23532022-02-16 02:26:11 +0000646 }
647
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100648 flags := []string(nil)
649 switch m.context {
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100650 case FileContext:
651 if !validateWithPolicy {
652 flags = []string{"-t"}
653 }
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100654 case ServiceContext:
655 flags = []string{"-s" /* binder services */}
656 case HwServiceContext:
657 flags = []string{"-e" /* allow empty */, "-l" /* hwbinder services */}
658 case VndServiceContext:
659 flags = []string{"-e" /* allow empty */, "-v" /* vnd service */}
660 }
661
Inseob Kimb5e23532022-02-16 02:26:11 +0000662 srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs)
Inseob Kimb5e23532022-02-16 02:26:11 +0000663 rule := android.NewRuleBuilder(pctx, ctx)
Thiébaud Weksteenb6e74302023-10-20 15:36:15 +1100664
665 if validateWithPolicy {
666 sepolicy := android.PathForModuleSrc(ctx, proptools.String(m.properties.Sepolicy))
667 rule.Command().BuiltTool(tool).
668 Flags(flags).
669 Input(sepolicy).
670 Inputs(srcs)
671 } else {
672 test_data := android.PathForModuleSrc(ctx, proptools.String(m.fileProperties.Test_data))
673 rule.Command().BuiltTool(tool).
674 Flags(flags).
675 Inputs(srcs).
676 Input(test_data)
677 }
Inseob Kimb5e23532022-02-16 02:26:11 +0000678
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900679 m.testTimestamp = pathForModuleOut(ctx, "timestamp")
Inseob Kimb5e23532022-02-16 02:26:11 +0000680 rule.Command().Text("touch").Output(m.testTimestamp)
681 rule.Build("contexts_test", "running contexts test: "+ctx.ModuleName())
682}
683
684func (m *contextsTestModule) AndroidMkEntries() []android.AndroidMkEntries {
685 return []android.AndroidMkEntries{android.AndroidMkEntries{
686 Class: "FAKE",
687 // OutputFile is needed, even though BUILD_PHONY_PACKAGE doesn't use it.
688 // Without OutputFile this module won't be exported to Makefile.
689 OutputFile: android.OptionalPathForPath(m.testTimestamp),
690 Include: "$(BUILD_PHONY_PACKAGE)",
691 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
692 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
693 entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", m.testTimestamp.String())
694 },
695 },
696 }}
697}
698
699// contextsTestModule implements ImageInterface to be able to include recovery_available contexts
700// modules as its sources.
701func (m *contextsTestModule) ImageMutatorBegin(ctx android.BaseModuleContext) {
702}
703
704func (m *contextsTestModule) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
705 return true
706}
707
708func (m *contextsTestModule) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
709 return false
710}
711
712func (m *contextsTestModule) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
713 return false
714}
715
716func (m *contextsTestModule) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
717 return false
718}
719
720func (m *contextsTestModule) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
721 return false
722}
723
724func (m *contextsTestModule) ExtraImageVariations(ctx android.BaseModuleContext) []string {
725 return nil
726}
727
728func (m *contextsTestModule) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
729}
730
731var _ android.ImageInterface = (*contextsTestModule)(nil)