blob: 587fe9192e3fa6bbc425df6de9d518ee7f26338f [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 "strings"
22
Inseob Kimcd616492020-03-24 23:06:40 +090023 "github.com/google/blueprint"
Inseob Kimb554e592019-04-15 20:10:46 +090024 "github.com/google/blueprint/proptools"
25
26 "android/soong/android"
Inseob Kimcd616492020-03-24 23:06:40 +090027 "android/soong/sysprop"
Inseob Kimb554e592019-04-15 20:10:46 +090028)
29
Inseob Kimb554e592019-04-15 20:10:46 +090030type selinuxContextsProperties struct {
31 // Filenames under sepolicy directories, which will be used to generate contexts file.
32 Srcs []string `android:"path"`
33
Yuntao Xu42e732c2021-11-18 22:33:02 +000034 // Output file name. Defaults to module name
35 Stem *string
36
Inseob Kimb554e592019-04-15 20:10:46 +090037 Product_variables struct {
Inseob Kimb554e592019-04-15 20:10:46 +090038 Address_sanitize struct {
Inseob Kim6d3d5a62021-12-21 20:55:32 +090039 Srcs []string `android:"path"`
Inseob Kimb554e592019-04-15 20:10:46 +090040 }
41 }
42
Inseob Kimb554e592019-04-15 20:10:46 +090043 // Whether the comments in generated contexts file will be removed or not.
44 Remove_comment *bool
45
46 // Whether the result context file is sorted with fc_sort or not.
47 Fc_sort *bool
48
49 // Make this module available when building for recovery
50 Recovery_available *bool
Inseob Kimb554e592019-04-15 20:10:46 +090051}
52
53type fileContextsProperties struct {
54 // flatten_apex can be used to specify additional sources of file_contexts.
55 // Apex paths, /system/apex/{apex_name}, will be amended to the paths of file_contexts
56 // entries.
57 Flatten_apex struct {
Inseob Kim6d3d5a62021-12-21 20:55:32 +090058 Srcs []string `android:"path"`
Inseob Kimb554e592019-04-15 20:10:46 +090059 }
60}
61
Inseob Kim2dac2672021-12-29 17:54:57 +090062type seappProperties struct {
63 // Files containing neverallow rules.
64 Neverallow_files []string `android:"path"`
65
66 // Precompiled sepolicy binary file which will be fed to checkseapp.
67 Sepolicy *string `android:"path"`
68}
69
Inseob Kimb554e592019-04-15 20:10:46 +090070type selinuxContextsModule struct {
71 android.ModuleBase
72
73 properties selinuxContextsProperties
74 fileContextsProperties fileContextsProperties
Inseob Kim2dac2672021-12-29 17:54:57 +090075 seappProperties seappProperties
Inseob Kimcd616492020-03-24 23:06:40 +090076 build func(ctx android.ModuleContext, inputs android.Paths) android.Path
77 deps func(ctx android.BottomUpMutatorContext)
78 outputPath android.Path
Colin Cross040f1512019-10-02 10:36:09 -070079 installPath android.InstallPath
Inseob Kimb554e592019-04-15 20:10:46 +090080}
81
82var (
Inseob Kimcd616492020-03-24 23:06:40 +090083 reuseContextsDepTag = dependencyTag{name: "reuseContexts"}
84 syspropLibraryDepTag = dependencyTag{name: "sysprop_library"}
Inseob Kimb554e592019-04-15 20:10:46 +090085)
86
87func init() {
88 pctx.HostBinToolVariable("fc_sort", "fc_sort")
89
90 android.RegisterModuleType("file_contexts", fileFactory)
91 android.RegisterModuleType("hwservice_contexts", hwServiceFactory)
92 android.RegisterModuleType("property_contexts", propertyFactory)
93 android.RegisterModuleType("service_contexts", serviceFactory)
Janis Danisevskisc40681f2020-07-25 13:02:29 -070094 android.RegisterModuleType("keystore2_key_contexts", keystoreKeyFactory)
Inseob Kim2dac2672021-12-29 17:54:57 +090095 android.RegisterModuleType("seapp_contexts", seappFactory)
Inseob Kimc7596c42022-02-25 11:45:41 +090096 android.RegisterModuleType("vndservice_contexts", vndServiceFactory)
Inseob Kimb5e23532022-02-16 02:26:11 +000097
98 android.RegisterModuleType("file_contexts_test", fileContextsTestFactory)
99 android.RegisterModuleType("property_contexts_test", propertyContextsTestFactory)
100 android.RegisterModuleType("hwservice_contexts_test", hwserviceContextsTestFactory)
101 android.RegisterModuleType("service_contexts_test", serviceContextsTestFactory)
Inseob Kimc7596c42022-02-25 11:45:41 +0900102 android.RegisterModuleType("vndservice_contexts_test", vndServiceContextsTestFactory)
Inseob Kimb554e592019-04-15 20:10:46 +0900103}
104
Colin Cross040f1512019-10-02 10:36:09 -0700105func (m *selinuxContextsModule) InstallInRoot() bool {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900106 return m.InRecovery()
107}
108
109func (m *selinuxContextsModule) InstallInRecovery() bool {
110 // ModuleBase.InRecovery() checks the image variant
111 return m.InRecovery()
112}
113
114func (m *selinuxContextsModule) onlyInRecovery() bool {
115 // ModuleBase.InstallInRecovery() checks commonProperties.Recovery property
116 return m.ModuleBase.InstallInRecovery()
Colin Cross040f1512019-10-02 10:36:09 -0700117}
118
Inseob Kimcd616492020-03-24 23:06:40 +0900119func (m *selinuxContextsModule) DepsMutator(ctx android.BottomUpMutatorContext) {
120 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)
Inseob Kimb554e592019-04-15 20:10:46 +0900161}
162
163func newModule() *selinuxContextsModule {
164 m := &selinuxContextsModule{}
165 m.AddProperties(
166 &m.properties,
Inseob Kim6d3d5a62021-12-21 20:55:32 +0900167 &m.fileContextsProperties,
Inseob Kim2dac2672021-12-29 17:54:57 +0900168 &m.seappProperties,
Inseob Kimb554e592019-04-15 20:10:46 +0900169 )
170 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
171 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
172 m.selinuxContextsHook(ctx)
173 })
174 return m
175}
176
177func (m *selinuxContextsModule) selinuxContextsHook(ctx android.LoadHookContext) {
178 // TODO: clean this up to use build/soong/android/variable.go after b/79249983
179 var srcs []string
180
Inseob Kimb554e592019-04-15 20:10:46 +0900181 for _, sanitize := range ctx.Config().SanitizeDevice() {
182 if sanitize == "address" {
183 srcs = append(srcs, m.properties.Product_variables.Address_sanitize.Srcs...)
184 break
185 }
186 }
187
188 m.properties.Srcs = append(m.properties.Srcs, srcs...)
189}
190
191func (m *selinuxContextsModule) AndroidMk() android.AndroidMkData {
Colin Crossf82aed02021-11-04 17:25:55 -0700192 nameSuffix := ""
193 if m.InRecovery() && !m.onlyInRecovery() {
194 nameSuffix = ".recovery"
195 }
Inseob Kimb554e592019-04-15 20:10:46 +0900196 return android.AndroidMkData{
Colin Crossf82aed02021-11-04 17:25:55 -0700197 Class: "ETC",
198 OutputFile: android.OptionalPathForPath(m.outputPath),
199 SubName: nameSuffix,
200 Extra: []android.AndroidMkExtraFunc{
201 func(w io.Writer, outputFile android.Path) {
Colin Cross6c7f9372022-01-11 19:35:43 -0800202 fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", m.installPath.String())
Yuntao Xu42e732c2021-11-18 22:33:02 +0000203 fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.stem())
Colin Crossf82aed02021-11-04 17:25:55 -0700204 },
Inseob Kimb554e592019-04-15 20:10:46 +0900205 },
206 }
207}
208
Inseob Kimfa6fe472021-01-12 13:40:27 +0900209func (m *selinuxContextsModule) ImageMutatorBegin(ctx android.BaseModuleContext) {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000210 if proptools.Bool(m.properties.Recovery_available) && m.ModuleBase.InstallInRecovery() {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900211 ctx.PropertyErrorf("recovery_available",
212 "doesn't make sense at the same time as `recovery: true`")
Inseob Kimb554e592019-04-15 20:10:46 +0900213 }
214}
215
Inseob Kimfa6fe472021-01-12 13:40:27 +0900216func (m *selinuxContextsModule) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000217 return !m.ModuleBase.InstallInRecovery()
Inseob Kimfa6fe472021-01-12 13:40:27 +0900218}
219
220func (m *selinuxContextsModule) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
221 return false
222}
223
224func (m *selinuxContextsModule) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
225 return false
226}
227
Inseob Kim6cc75f42021-04-29 13:53:20 +0000228func (m *selinuxContextsModule) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
229 return false
230}
231
Inseob Kimfa6fe472021-01-12 13:40:27 +0900232func (m *selinuxContextsModule) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000233 return m.ModuleBase.InstallInRecovery() || proptools.Bool(m.properties.Recovery_available)
Inseob Kimfa6fe472021-01-12 13:40:27 +0900234}
235
236func (m *selinuxContextsModule) ExtraImageVariations(ctx android.BaseModuleContext) []string {
237 return nil
238}
239
240func (m *selinuxContextsModule) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
241}
242
243var _ android.ImageInterface = (*selinuxContextsModule)(nil)
244
Inseob Kimcd616492020-03-24 23:06:40 +0900245func (m *selinuxContextsModule) buildGeneralContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900246 builtContext := pathForModuleOut(ctx, ctx.ModuleName()+"_m4out")
Inseob Kimb554e592019-04-15 20:10:46 +0900247
Colin Cross242c8bc2020-11-16 17:58:17 -0800248 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kimb554e592019-04-15 20:10:46 +0900249
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900250 newlineFile := pathForModuleOut(ctx, "newline")
Inseob Kim35e9d412023-01-04 15:27:32 +0900251
252 rule.Command().Text("echo").FlagWithOutput("> ", newlineFile)
253 rule.Temporary(newlineFile)
254
255 var inputsWithNewline android.Paths
256 for _, input := range inputs {
257 inputsWithNewline = append(inputsWithNewline, input, newlineFile)
258 }
259
Inseob Kimb554e592019-04-15 20:10:46 +0900260 rule.Command().
Dan Willemsen3c3e59b2019-06-19 10:52:50 -0700261 Tool(ctx.Config().PrebuiltBuildTool(ctx, "m4")).
262 Text("--fatal-warnings -s").
Inseob Kimb554e592019-04-15 20:10:46 +0900263 FlagForEachArg("-D", ctx.DeviceConfig().SepolicyM4Defs()).
Inseob Kim35e9d412023-01-04 15:27:32 +0900264 Inputs(inputsWithNewline).
Yuntao Xu42e732c2021-11-18 22:33:02 +0000265 FlagWithOutput("> ", builtContext)
Inseob Kimb554e592019-04-15 20:10:46 +0900266
267 if proptools.Bool(m.properties.Remove_comment) {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000268 rule.Temporary(builtContext)
Inseob Kimb554e592019-04-15 20:10:46 +0900269
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900270 remove_comment_output := pathForModuleOut(ctx, ctx.ModuleName()+"_remove_comment")
Inseob Kimb554e592019-04-15 20:10:46 +0900271
272 rule.Command().
273 Text("sed -e 's/#.*$//' -e '/^$/d'").
Yuntao Xu42e732c2021-11-18 22:33:02 +0000274 Input(builtContext).
Inseob Kimb554e592019-04-15 20:10:46 +0900275 FlagWithOutput("> ", remove_comment_output)
276
Yuntao Xu42e732c2021-11-18 22:33:02 +0000277 builtContext = remove_comment_output
Inseob Kimb554e592019-04-15 20:10:46 +0900278 }
279
280 if proptools.Bool(m.properties.Fc_sort) {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000281 rule.Temporary(builtContext)
Inseob Kimb554e592019-04-15 20:10:46 +0900282
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900283 sorted_output := pathForModuleOut(ctx, ctx.ModuleName()+"_sorted")
Inseob Kimb554e592019-04-15 20:10:46 +0900284
285 rule.Command().
286 Tool(ctx.Config().HostToolPath(ctx, "fc_sort")).
Yuntao Xu42e732c2021-11-18 22:33:02 +0000287 FlagWithInput("-i ", builtContext).
Inseob Kimb554e592019-04-15 20:10:46 +0900288 FlagWithOutput("-o ", sorted_output)
289
Yuntao Xu42e732c2021-11-18 22:33:02 +0000290 builtContext = sorted_output
Inseob Kimb554e592019-04-15 20:10:46 +0900291 }
292
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900293 ret := pathForModuleOut(ctx, m.stem())
Yuntao Xu42e732c2021-11-18 22:33:02 +0000294 rule.Temporary(builtContext)
295 rule.Command().Text("cp").Input(builtContext).Output(ret)
Inseob Kimb554e592019-04-15 20:10:46 +0900296
297 rule.DeleteTemporaryFiles()
Yuntao Xu42e732c2021-11-18 22:33:02 +0000298 rule.Build("selinux_contexts", "building contexts: "+m.Name())
Inseob Kimb554e592019-04-15 20:10:46 +0900299
Inseob Kimcd616492020-03-24 23:06:40 +0900300 return ret
Inseob Kimb554e592019-04-15 20:10:46 +0900301}
302
Inseob Kimcd616492020-03-24 23:06:40 +0900303func (m *selinuxContextsModule) buildFileContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kimb554e592019-04-15 20:10:46 +0900304 if m.properties.Fc_sort == nil {
305 m.properties.Fc_sort = proptools.BoolPtr(true)
306 }
307
Colin Cross242c8bc2020-11-16 17:58:17 -0800308 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kimb554e592019-04-15 20:10:46 +0900309
310 if ctx.Config().FlattenApex() {
Inseob Kim6d3d5a62021-12-21 20:55:32 +0900311 for _, path := range android.PathsForModuleSrc(ctx, m.fileContextsProperties.Flatten_apex.Srcs) {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900312 out := pathForModuleOut(ctx, "flattened_apex", path.Rel())
Inseob Kim6d3d5a62021-12-21 20:55:32 +0900313 apex_path := "/system/apex/" + strings.Replace(
314 strings.TrimSuffix(path.Base(), "-file_contexts"),
315 ".", "\\\\.", -1)
Inseob Kimb554e592019-04-15 20:10:46 +0900316
Inseob Kim6d3d5a62021-12-21 20:55:32 +0900317 rule.Command().
318 Text("awk '/object_r/{printf(\""+apex_path+"%s\\n\",$0)}'").
319 Input(path).
320 FlagWithOutput("> ", out)
Inseob Kimb554e592019-04-15 20:10:46 +0900321
Inseob Kim6d3d5a62021-12-21 20:55:32 +0900322 inputs = append(inputs, out)
Inseob Kimb554e592019-04-15 20:10:46 +0900323 }
324 }
325
Colin Cross242c8bc2020-11-16 17:58:17 -0800326 rule.Build(m.Name(), "flattened_apex_file_contexts")
Inseob Kimcd616492020-03-24 23:06:40 +0900327 return m.buildGeneralContexts(ctx, inputs)
Inseob Kimb554e592019-04-15 20:10:46 +0900328}
329
330func fileFactory() android.Module {
331 m := newModule()
Inseob Kimb554e592019-04-15 20:10:46 +0900332 m.build = m.buildFileContexts
333 return m
334}
335
ThiƩbaud Weksteen74482f52023-04-26 13:46:59 +1000336func (m *selinuxContextsModule) buildServiceContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kimb554e592019-04-15 20:10:46 +0900337 if m.properties.Remove_comment == nil {
338 m.properties.Remove_comment = proptools.BoolPtr(true)
339 }
340
Inseob Kimcd616492020-03-24 23:06:40 +0900341 return m.buildGeneralContexts(ctx, inputs)
342}
343
Inseob Kim2bcc0452020-12-21 13:16:44 +0900344func (m *selinuxContextsModule) checkVendorPropertyNamespace(ctx android.ModuleContext, inputs android.Paths) android.Paths {
345 shippingApiLevel := ctx.DeviceConfig().ShippingApiLevel()
346 ApiLevelR := android.ApiLevelOrPanic(ctx, "R")
347
348 rule := android.NewRuleBuilder(pctx, ctx)
349
350 // This list is from vts_treble_sys_prop_test.
351 allowedPropertyPrefixes := []string{
352 "ctl.odm.",
353 "ctl.vendor.",
354 "ctl.start$odm.",
355 "ctl.start$vendor.",
356 "ctl.stop$odm.",
357 "ctl.stop$vendor.",
358 "init.svc.odm.",
359 "init.svc.vendor.",
360 "ro.boot.",
361 "ro.hardware.",
362 "ro.odm.",
363 "ro.vendor.",
364 "odm.",
365 "persist.odm.",
366 "persist.vendor.",
367 "vendor.",
368 }
369
370 // persist.camera is also allowed for devices launching with R or eariler
371 if shippingApiLevel.LessThanOrEqualTo(ApiLevelR) {
372 allowedPropertyPrefixes = append(allowedPropertyPrefixes, "persist.camera.")
373 }
374
375 var allowedContextPrefixes []string
376
377 if shippingApiLevel.GreaterThanOrEqualTo(ApiLevelR) {
378 // This list is from vts_treble_sys_prop_test.
379 allowedContextPrefixes = []string{
380 "vendor_",
381 "odm_",
382 }
383 }
384
385 var ret android.Paths
386 for _, input := range inputs {
387 cmd := rule.Command().
388 BuiltTool("check_prop_prefix").
389 FlagWithInput("--property-contexts ", input).
390 FlagForEachArg("--allowed-property-prefix ", proptools.ShellEscapeList(allowedPropertyPrefixes)). // contains shell special character '$'
391 FlagForEachArg("--allowed-context-prefix ", allowedContextPrefixes)
392
393 if !ctx.DeviceConfig().BuildBrokenVendorPropertyNamespace() {
394 cmd.Flag("--strict")
395 }
396
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900397 out := pathForModuleOut(ctx, "namespace_checked").Join(ctx, input.String())
Inseob Kim2bcc0452020-12-21 13:16:44 +0900398 rule.Command().Text("cp -f").Input(input).Output(out)
399 ret = append(ret, out)
400 }
401 rule.Build("check_namespace", "checking namespace of "+ctx.ModuleName())
402 return ret
403}
404
Inseob Kimcd616492020-03-24 23:06:40 +0900405func (m *selinuxContextsModule) buildPropertyContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kim2bcc0452020-12-21 13:16:44 +0900406 // vendor/odm properties are enforced for devices launching with Android Q or later. So, if
407 // vendor/odm, make sure that only vendor/odm properties exist.
408 shippingApiLevel := ctx.DeviceConfig().ShippingApiLevel()
409 ApiLevelQ := android.ApiLevelOrPanic(ctx, "Q")
410 if (ctx.SocSpecific() || ctx.DeviceSpecific()) && shippingApiLevel.GreaterThanOrEqualTo(ApiLevelQ) {
411 inputs = m.checkVendorPropertyNamespace(ctx, inputs)
412 }
413
Inseob Kimcd616492020-03-24 23:06:40 +0900414 builtCtxFile := m.buildGeneralContexts(ctx, inputs)
415
416 var apiFiles android.Paths
417 ctx.VisitDirectDepsWithTag(syspropLibraryDepTag, func(c android.Module) {
Inseob Kim3a3539a2021-01-15 18:10:29 +0900418 i, ok := c.(interface{ CurrentSyspropApiFile() android.OptionalPath })
Inseob Kimcd616492020-03-24 23:06:40 +0900419 if !ok {
420 panic(fmt.Errorf("unknown dependency %q for %q", ctx.OtherModuleName(c), ctx.ModuleName()))
421 }
Inseob Kim3a3539a2021-01-15 18:10:29 +0900422 if api := i.CurrentSyspropApiFile(); api.Valid() {
423 apiFiles = append(apiFiles, api.Path())
424 }
Inseob Kimcd616492020-03-24 23:06:40 +0900425 })
426
427 // check compatibility with sysprop_library
428 if len(apiFiles) > 0 {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900429 out := pathForModuleOut(ctx, ctx.ModuleName()+"_api_checked")
Colin Cross242c8bc2020-11-16 17:58:17 -0800430 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kimcd616492020-03-24 23:06:40 +0900431
432 msg := `\n******************************\n` +
433 `API of sysprop_library doesn't match with property_contexts\n` +
434 `Please fix the breakage and rebuild.\n` +
435 `******************************\n`
436
437 rule.Command().
438 Text("( ").
Colin Cross242c8bc2020-11-16 17:58:17 -0800439 BuiltTool("sysprop_type_checker").
Inseob Kimcd616492020-03-24 23:06:40 +0900440 FlagForEachInput("--api ", apiFiles).
441 FlagWithInput("--context ", builtCtxFile).
442 Text(" || ( echo").Flag("-e").
443 Flag(`"` + msg + `"`).
444 Text("; exit 38) )")
445
446 rule.Command().Text("cp -f").Input(builtCtxFile).Output(out)
Colin Cross242c8bc2020-11-16 17:58:17 -0800447 rule.Build("property_contexts_check_api", "checking API: "+m.Name())
Inseob Kimcd616492020-03-24 23:06:40 +0900448 builtCtxFile = out
449 }
450
451 return builtCtxFile
Inseob Kimb554e592019-04-15 20:10:46 +0900452}
453
Inseob Kim2dac2672021-12-29 17:54:57 +0900454func (m *selinuxContextsModule) buildSeappContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900455 neverallowFile := pathForModuleOut(ctx, "neverallow")
456 ret := pathForModuleOut(ctx, m.stem())
Inseob Kim2dac2672021-12-29 17:54:57 +0900457
458 rule := android.NewRuleBuilder(pctx, ctx)
459 rule.Command().Text("(grep").
460 Flag("-ihe").
461 Text("'^neverallow'").
462 Inputs(android.PathsForModuleSrc(ctx, m.seappProperties.Neverallow_files)).
463 Text(os.DevNull). // to make grep happy even when Neverallow_files is empty
464 Text(">").
465 Output(neverallowFile).
466 Text("|| true)") // to make ninja happy even when result is empty
467
468 rule.Temporary(neverallowFile)
469 rule.Command().BuiltTool("checkseapp").
470 FlagWithInput("-p ", android.PathForModuleSrc(ctx, proptools.String(m.seappProperties.Sepolicy))).
471 FlagWithOutput("-o ", ret).
472 Inputs(inputs).
473 Input(neverallowFile)
474
475 rule.Build("seapp_contexts", "Building seapp_contexts: "+m.Name())
476 return ret
477}
478
Inseob Kimb554e592019-04-15 20:10:46 +0900479func hwServiceFactory() android.Module {
480 m := newModule()
ThiƩbaud Weksteen74482f52023-04-26 13:46:59 +1000481 m.build = m.buildServiceContexts
Inseob Kimb554e592019-04-15 20:10:46 +0900482 return m
483}
484
485func propertyFactory() android.Module {
486 m := newModule()
Inseob Kimcd616492020-03-24 23:06:40 +0900487 m.build = m.buildPropertyContexts
488 m.deps = m.propertyContextsDeps
Inseob Kimb554e592019-04-15 20:10:46 +0900489 return m
490}
491
492func serviceFactory() android.Module {
493 m := newModule()
ThiƩbaud Weksteen74482f52023-04-26 13:46:59 +1000494 m.build = m.buildServiceContexts
Inseob Kimb554e592019-04-15 20:10:46 +0900495 return m
496}
Janis Danisevskisc40681f2020-07-25 13:02:29 -0700497
498func keystoreKeyFactory() android.Module {
499 m := newModule()
500 m.build = m.buildGeneralContexts
501 return m
502}
Yuntao Xu42e732c2021-11-18 22:33:02 +0000503
Inseob Kim2dac2672021-12-29 17:54:57 +0900504func seappFactory() android.Module {
505 m := newModule()
506 m.build = m.buildSeappContexts
507 return m
508}
509
Inseob Kimc7596c42022-02-25 11:45:41 +0900510func vndServiceFactory() android.Module {
511 m := newModule()
512 m.build = m.buildGeneralContexts
513 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
514 if !ctx.SocSpecific() {
515 ctx.ModuleErrorf(m.Name(), "must set vendor: true")
516 return
517 }
518 })
519 return m
520}
521
Yuntao Xu42e732c2021-11-18 22:33:02 +0000522var _ android.OutputFileProducer = (*selinuxContextsModule)(nil)
523
524// Implements android.OutputFileProducer
525func (m *selinuxContextsModule) OutputFiles(tag string) (android.Paths, error) {
526 if tag == "" {
527 return []android.Path{m.outputPath}, nil
528 }
529 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
530}
Inseob Kimb5e23532022-02-16 02:26:11 +0000531
532type contextsTestProperties struct {
533 // Contexts files to be tested.
534 Srcs []string `android:"path"`
535
536 // Precompiled sepolicy binary to be tesed together.
537 Sepolicy *string `android:"path"`
538}
539
540type contextsTestModule struct {
541 android.ModuleBase
542
543 // Name of the test tool. "checkfc" or "property_info_checker"
544 tool string
545
546 // Additional flags to be passed to the tool.
547 flags []string
548
549 properties contextsTestProperties
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900550 testTimestamp android.OutputPath
Inseob Kimb5e23532022-02-16 02:26:11 +0000551}
552
553// checkfc parses a context file and checks for syntax errors.
554// If -s is specified, the service backend is used to verify binder services.
555// If -l is specified, the service backend is used to verify hwbinder services.
556// Otherwise, context_file is assumed to be a file_contexts file
557// If -e is specified, then the context_file is allowed to be empty.
558
559// file_contexts_test tests given file_contexts files with checkfc.
560func fileContextsTestFactory() android.Module {
561 m := &contextsTestModule{tool: "checkfc" /* no flags: file_contexts file check */}
562 m.AddProperties(&m.properties)
563 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
564 return m
565}
566
567// property_contexts_test tests given property_contexts files with property_info_checker.
568func propertyContextsTestFactory() android.Module {
569 m := &contextsTestModule{tool: "property_info_checker"}
570 m.AddProperties(&m.properties)
571 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
572 return m
573}
574
575// hwservice_contexts_test tests given hwservice_contexts files with checkfc.
576func hwserviceContextsTestFactory() android.Module {
577 m := &contextsTestModule{tool: "checkfc", flags: []string{"-e" /* allow empty */, "-l" /* hwbinder services */}}
578 m.AddProperties(&m.properties)
579 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
580 return m
581}
582
583// service_contexts_test tests given service_contexts files with checkfc.
584func serviceContextsTestFactory() android.Module {
585 // checkfc -s: service_contexts test
586 m := &contextsTestModule{tool: "checkfc", flags: []string{"-s" /* binder services */}}
587 m.AddProperties(&m.properties)
588 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
589 return m
590}
591
Inseob Kimc7596c42022-02-25 11:45:41 +0900592// vndservice_contexts_test tests given vndservice_contexts files with checkfc.
593func vndServiceContextsTestFactory() android.Module {
594 m := &contextsTestModule{tool: "checkfc", flags: []string{"-e" /* allow empty */, "-v" /* vnd service */}}
595 m.AddProperties(&m.properties)
596 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
597 return m
598}
599
Inseob Kimb5e23532022-02-16 02:26:11 +0000600func (m *contextsTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
601 tool := m.tool
602 if tool != "checkfc" && tool != "property_info_checker" {
603 panic(fmt.Errorf("%q: unknown tool name: %q", ctx.ModuleName(), tool))
604 }
605
606 if len(m.properties.Srcs) == 0 {
607 ctx.PropertyErrorf("srcs", "can't be empty")
608 return
609 }
610
611 if proptools.String(m.properties.Sepolicy) == "" {
612 ctx.PropertyErrorf("sepolicy", "can't be empty")
613 return
614 }
615
616 srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs)
617 sepolicy := android.PathForModuleSrc(ctx, proptools.String(m.properties.Sepolicy))
618
619 rule := android.NewRuleBuilder(pctx, ctx)
620 rule.Command().BuiltTool(tool).
621 Flags(m.flags).
622 Input(sepolicy).
623 Inputs(srcs)
624
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900625 m.testTimestamp = pathForModuleOut(ctx, "timestamp")
Inseob Kimb5e23532022-02-16 02:26:11 +0000626 rule.Command().Text("touch").Output(m.testTimestamp)
627 rule.Build("contexts_test", "running contexts test: "+ctx.ModuleName())
628}
629
630func (m *contextsTestModule) AndroidMkEntries() []android.AndroidMkEntries {
631 return []android.AndroidMkEntries{android.AndroidMkEntries{
632 Class: "FAKE",
633 // OutputFile is needed, even though BUILD_PHONY_PACKAGE doesn't use it.
634 // Without OutputFile this module won't be exported to Makefile.
635 OutputFile: android.OptionalPathForPath(m.testTimestamp),
636 Include: "$(BUILD_PHONY_PACKAGE)",
637 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
638 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
639 entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", m.testTimestamp.String())
640 },
641 },
642 }}
643}
644
645// contextsTestModule implements ImageInterface to be able to include recovery_available contexts
646// modules as its sources.
647func (m *contextsTestModule) ImageMutatorBegin(ctx android.BaseModuleContext) {
648}
649
650func (m *contextsTestModule) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
651 return true
652}
653
654func (m *contextsTestModule) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
655 return false
656}
657
658func (m *contextsTestModule) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
659 return false
660}
661
662func (m *contextsTestModule) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
663 return false
664}
665
666func (m *contextsTestModule) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
667 return false
668}
669
670func (m *contextsTestModule) ExtraImageVariations(ctx android.BaseModuleContext) []string {
671 return nil
672}
673
674func (m *contextsTestModule) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
675}
676
677var _ android.ImageInterface = (*contextsTestModule)(nil)