blob: 7424001b8f06504d00668f1e4ce9c74b2108a8c7 [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 Kimb5e23532022-02-16 02:26:11 +000096
97 android.RegisterModuleType("file_contexts_test", fileContextsTestFactory)
98 android.RegisterModuleType("property_contexts_test", propertyContextsTestFactory)
99 android.RegisterModuleType("hwservice_contexts_test", hwserviceContextsTestFactory)
100 android.RegisterModuleType("service_contexts_test", serviceContextsTestFactory)
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) {
118 if m.deps != nil {
119 m.deps(ctx)
120 }
Inseob Kimfa6fe472021-01-12 13:40:27 +0900121
122 if m.InRecovery() && !m.onlyInRecovery() {
123 ctx.AddFarVariationDependencies([]blueprint.Variation{
124 {Mutator: "image", Variation: android.CoreVariation},
125 }, reuseContextsDepTag, ctx.ModuleName())
126 }
Inseob Kimcd616492020-03-24 23:06:40 +0900127}
128
129func (m *selinuxContextsModule) propertyContextsDeps(ctx android.BottomUpMutatorContext) {
130 for _, lib := range sysprop.SyspropLibraries(ctx.Config()) {
131 ctx.AddFarVariationDependencies([]blueprint.Variation{}, syspropLibraryDepTag, lib)
132 }
133}
134
Yuntao Xu42e732c2021-11-18 22:33:02 +0000135func (m *selinuxContextsModule) stem() string {
136 return proptools.StringDefault(m.properties.Stem, m.Name())
137}
138
Inseob Kimb554e592019-04-15 20:10:46 +0900139func (m *selinuxContextsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900140 if m.InRecovery() {
Colin Cross040f1512019-10-02 10:36:09 -0700141 // Installing context files at the root of the recovery partition
142 m.installPath = android.PathForModuleInstall(ctx)
Inseob Kimb554e592019-04-15 20:10:46 +0900143 } else {
144 m.installPath = android.PathForModuleInstall(ctx, "etc", "selinux")
145 }
146
Inseob Kimfa6fe472021-01-12 13:40:27 +0900147 if m.InRecovery() && !m.onlyInRecovery() {
Inseob Kimb554e592019-04-15 20:10:46 +0900148 dep := ctx.GetDirectDepWithTag(m.Name(), reuseContextsDepTag)
149
150 if reuseDeps, ok := dep.(*selinuxContextsModule); ok {
151 m.outputPath = reuseDeps.outputPath
Yuntao Xu42e732c2021-11-18 22:33:02 +0000152 ctx.InstallFile(m.installPath, m.stem(), m.outputPath)
Inseob Kimb554e592019-04-15 20:10:46 +0900153 return
154 }
155 }
156
Inseob Kim6d3d5a62021-12-21 20:55:32 +0900157 m.outputPath = m.build(ctx, android.PathsForModuleSrc(ctx, m.properties.Srcs))
Yuntao Xu42e732c2021-11-18 22:33:02 +0000158 ctx.InstallFile(m.installPath, m.stem(), m.outputPath)
Inseob Kimb554e592019-04-15 20:10:46 +0900159}
160
161func newModule() *selinuxContextsModule {
162 m := &selinuxContextsModule{}
163 m.AddProperties(
164 &m.properties,
Inseob Kim6d3d5a62021-12-21 20:55:32 +0900165 &m.fileContextsProperties,
Inseob Kim2dac2672021-12-29 17:54:57 +0900166 &m.seappProperties,
Inseob Kimb554e592019-04-15 20:10:46 +0900167 )
168 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
169 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
170 m.selinuxContextsHook(ctx)
171 })
172 return m
173}
174
175func (m *selinuxContextsModule) selinuxContextsHook(ctx android.LoadHookContext) {
176 // TODO: clean this up to use build/soong/android/variable.go after b/79249983
177 var srcs []string
178
Inseob Kimb554e592019-04-15 20:10:46 +0900179 for _, sanitize := range ctx.Config().SanitizeDevice() {
180 if sanitize == "address" {
181 srcs = append(srcs, m.properties.Product_variables.Address_sanitize.Srcs...)
182 break
183 }
184 }
185
186 m.properties.Srcs = append(m.properties.Srcs, srcs...)
187}
188
189func (m *selinuxContextsModule) AndroidMk() android.AndroidMkData {
Colin Crossf82aed02021-11-04 17:25:55 -0700190 nameSuffix := ""
191 if m.InRecovery() && !m.onlyInRecovery() {
192 nameSuffix = ".recovery"
193 }
Inseob Kimb554e592019-04-15 20:10:46 +0900194 return android.AndroidMkData{
Colin Crossf82aed02021-11-04 17:25:55 -0700195 Class: "ETC",
196 OutputFile: android.OptionalPathForPath(m.outputPath),
197 SubName: nameSuffix,
198 Extra: []android.AndroidMkExtraFunc{
199 func(w io.Writer, outputFile android.Path) {
200 fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", m.installPath.ToMakePath().String())
Yuntao Xu42e732c2021-11-18 22:33:02 +0000201 fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.stem())
Colin Crossf82aed02021-11-04 17:25:55 -0700202 },
Inseob Kimb554e592019-04-15 20:10:46 +0900203 },
204 }
205}
206
Inseob Kimfa6fe472021-01-12 13:40:27 +0900207func (m *selinuxContextsModule) ImageMutatorBegin(ctx android.BaseModuleContext) {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000208 if proptools.Bool(m.properties.Recovery_available) && m.ModuleBase.InstallInRecovery() {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900209 ctx.PropertyErrorf("recovery_available",
210 "doesn't make sense at the same time as `recovery: true`")
Inseob Kimb554e592019-04-15 20:10:46 +0900211 }
212}
213
Inseob Kimfa6fe472021-01-12 13:40:27 +0900214func (m *selinuxContextsModule) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000215 return !m.ModuleBase.InstallInRecovery()
Inseob Kimfa6fe472021-01-12 13:40:27 +0900216}
217
218func (m *selinuxContextsModule) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
219 return false
220}
221
222func (m *selinuxContextsModule) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
223 return false
224}
225
Inseob Kim6cc75f42021-04-29 13:53:20 +0000226func (m *selinuxContextsModule) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
227 return false
228}
229
Inseob Kimfa6fe472021-01-12 13:40:27 +0900230func (m *selinuxContextsModule) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000231 return m.ModuleBase.InstallInRecovery() || proptools.Bool(m.properties.Recovery_available)
Inseob Kimfa6fe472021-01-12 13:40:27 +0900232}
233
234func (m *selinuxContextsModule) ExtraImageVariations(ctx android.BaseModuleContext) []string {
235 return nil
236}
237
238func (m *selinuxContextsModule) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
239}
240
241var _ android.ImageInterface = (*selinuxContextsModule)(nil)
242
Inseob Kimcd616492020-03-24 23:06:40 +0900243func (m *selinuxContextsModule) buildGeneralContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000244 builtContext := android.PathForModuleGen(ctx, ctx.ModuleName()+"_m4out")
Inseob Kimb554e592019-04-15 20:10:46 +0900245
Colin Cross242c8bc2020-11-16 17:58:17 -0800246 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kimb554e592019-04-15 20:10:46 +0900247
248 rule.Command().
Dan Willemsen3c3e59b2019-06-19 10:52:50 -0700249 Tool(ctx.Config().PrebuiltBuildTool(ctx, "m4")).
250 Text("--fatal-warnings -s").
Inseob Kimb554e592019-04-15 20:10:46 +0900251 FlagForEachArg("-D", ctx.DeviceConfig().SepolicyM4Defs()).
252 Inputs(inputs).
Yuntao Xu42e732c2021-11-18 22:33:02 +0000253 FlagWithOutput("> ", builtContext)
Inseob Kimb554e592019-04-15 20:10:46 +0900254
255 if proptools.Bool(m.properties.Remove_comment) {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000256 rule.Temporary(builtContext)
Inseob Kimb554e592019-04-15 20:10:46 +0900257
258 remove_comment_output := android.PathForModuleGen(ctx, ctx.ModuleName()+"_remove_comment")
259
260 rule.Command().
261 Text("sed -e 's/#.*$//' -e '/^$/d'").
Yuntao Xu42e732c2021-11-18 22:33:02 +0000262 Input(builtContext).
Inseob Kimb554e592019-04-15 20:10:46 +0900263 FlagWithOutput("> ", remove_comment_output)
264
Yuntao Xu42e732c2021-11-18 22:33:02 +0000265 builtContext = remove_comment_output
Inseob Kimb554e592019-04-15 20:10:46 +0900266 }
267
268 if proptools.Bool(m.properties.Fc_sort) {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000269 rule.Temporary(builtContext)
Inseob Kimb554e592019-04-15 20:10:46 +0900270
271 sorted_output := android.PathForModuleGen(ctx, ctx.ModuleName()+"_sorted")
272
273 rule.Command().
274 Tool(ctx.Config().HostToolPath(ctx, "fc_sort")).
Yuntao Xu42e732c2021-11-18 22:33:02 +0000275 FlagWithInput("-i ", builtContext).
Inseob Kimb554e592019-04-15 20:10:46 +0900276 FlagWithOutput("-o ", sorted_output)
277
Yuntao Xu42e732c2021-11-18 22:33:02 +0000278 builtContext = sorted_output
Inseob Kimb554e592019-04-15 20:10:46 +0900279 }
280
Yuntao Xu42e732c2021-11-18 22:33:02 +0000281 ret := android.PathForModuleGen(ctx, m.stem())
282 rule.Temporary(builtContext)
283 rule.Command().Text("cp").Input(builtContext).Output(ret)
Inseob Kimb554e592019-04-15 20:10:46 +0900284
285 rule.DeleteTemporaryFiles()
Yuntao Xu42e732c2021-11-18 22:33:02 +0000286 rule.Build("selinux_contexts", "building contexts: "+m.Name())
Inseob Kimb554e592019-04-15 20:10:46 +0900287
Inseob Kimcd616492020-03-24 23:06:40 +0900288 return ret
Inseob Kimb554e592019-04-15 20:10:46 +0900289}
290
Inseob Kimcd616492020-03-24 23:06:40 +0900291func (m *selinuxContextsModule) buildFileContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kimb554e592019-04-15 20:10:46 +0900292 if m.properties.Fc_sort == nil {
293 m.properties.Fc_sort = proptools.BoolPtr(true)
294 }
295
Colin Cross242c8bc2020-11-16 17:58:17 -0800296 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kimb554e592019-04-15 20:10:46 +0900297
298 if ctx.Config().FlattenApex() {
Inseob Kim6d3d5a62021-12-21 20:55:32 +0900299 for _, path := range android.PathsForModuleSrc(ctx, m.fileContextsProperties.Flatten_apex.Srcs) {
300 out := android.PathForModuleGen(ctx, "flattened_apex", path.Rel())
301 apex_path := "/system/apex/" + strings.Replace(
302 strings.TrimSuffix(path.Base(), "-file_contexts"),
303 ".", "\\\\.", -1)
Inseob Kimb554e592019-04-15 20:10:46 +0900304
Inseob Kim6d3d5a62021-12-21 20:55:32 +0900305 rule.Command().
306 Text("awk '/object_r/{printf(\""+apex_path+"%s\\n\",$0)}'").
307 Input(path).
308 FlagWithOutput("> ", out)
Inseob Kimb554e592019-04-15 20:10:46 +0900309
Inseob Kim6d3d5a62021-12-21 20:55:32 +0900310 inputs = append(inputs, out)
Inseob Kimb554e592019-04-15 20:10:46 +0900311 }
312 }
313
Colin Cross242c8bc2020-11-16 17:58:17 -0800314 rule.Build(m.Name(), "flattened_apex_file_contexts")
Inseob Kimcd616492020-03-24 23:06:40 +0900315 return m.buildGeneralContexts(ctx, inputs)
Inseob Kimb554e592019-04-15 20:10:46 +0900316}
317
318func fileFactory() android.Module {
319 m := newModule()
Inseob Kimb554e592019-04-15 20:10:46 +0900320 m.build = m.buildFileContexts
321 return m
322}
323
Inseob Kimcd616492020-03-24 23:06:40 +0900324func (m *selinuxContextsModule) buildHwServiceContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kimb554e592019-04-15 20:10:46 +0900325 if m.properties.Remove_comment == nil {
326 m.properties.Remove_comment = proptools.BoolPtr(true)
327 }
328
Inseob Kimcd616492020-03-24 23:06:40 +0900329 return m.buildGeneralContexts(ctx, inputs)
330}
331
Inseob Kim2bcc0452020-12-21 13:16:44 +0900332func (m *selinuxContextsModule) checkVendorPropertyNamespace(ctx android.ModuleContext, inputs android.Paths) android.Paths {
333 shippingApiLevel := ctx.DeviceConfig().ShippingApiLevel()
334 ApiLevelR := android.ApiLevelOrPanic(ctx, "R")
335
336 rule := android.NewRuleBuilder(pctx, ctx)
337
338 // This list is from vts_treble_sys_prop_test.
339 allowedPropertyPrefixes := []string{
340 "ctl.odm.",
341 "ctl.vendor.",
342 "ctl.start$odm.",
343 "ctl.start$vendor.",
344 "ctl.stop$odm.",
345 "ctl.stop$vendor.",
346 "init.svc.odm.",
347 "init.svc.vendor.",
348 "ro.boot.",
349 "ro.hardware.",
350 "ro.odm.",
351 "ro.vendor.",
352 "odm.",
353 "persist.odm.",
354 "persist.vendor.",
355 "vendor.",
356 }
357
358 // persist.camera is also allowed for devices launching with R or eariler
359 if shippingApiLevel.LessThanOrEqualTo(ApiLevelR) {
360 allowedPropertyPrefixes = append(allowedPropertyPrefixes, "persist.camera.")
361 }
362
363 var allowedContextPrefixes []string
364
365 if shippingApiLevel.GreaterThanOrEqualTo(ApiLevelR) {
366 // This list is from vts_treble_sys_prop_test.
367 allowedContextPrefixes = []string{
368 "vendor_",
369 "odm_",
370 }
371 }
372
373 var ret android.Paths
374 for _, input := range inputs {
375 cmd := rule.Command().
376 BuiltTool("check_prop_prefix").
377 FlagWithInput("--property-contexts ", input).
378 FlagForEachArg("--allowed-property-prefix ", proptools.ShellEscapeList(allowedPropertyPrefixes)). // contains shell special character '$'
379 FlagForEachArg("--allowed-context-prefix ", allowedContextPrefixes)
380
381 if !ctx.DeviceConfig().BuildBrokenVendorPropertyNamespace() {
382 cmd.Flag("--strict")
383 }
384
385 out := android.PathForModuleGen(ctx, "namespace_checked").Join(ctx, input.String())
386 rule.Command().Text("cp -f").Input(input).Output(out)
387 ret = append(ret, out)
388 }
389 rule.Build("check_namespace", "checking namespace of "+ctx.ModuleName())
390 return ret
391}
392
Inseob Kimcd616492020-03-24 23:06:40 +0900393func (m *selinuxContextsModule) buildPropertyContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kim2bcc0452020-12-21 13:16:44 +0900394 // vendor/odm properties are enforced for devices launching with Android Q or later. So, if
395 // vendor/odm, make sure that only vendor/odm properties exist.
396 shippingApiLevel := ctx.DeviceConfig().ShippingApiLevel()
397 ApiLevelQ := android.ApiLevelOrPanic(ctx, "Q")
398 if (ctx.SocSpecific() || ctx.DeviceSpecific()) && shippingApiLevel.GreaterThanOrEqualTo(ApiLevelQ) {
399 inputs = m.checkVendorPropertyNamespace(ctx, inputs)
400 }
401
Inseob Kimcd616492020-03-24 23:06:40 +0900402 builtCtxFile := m.buildGeneralContexts(ctx, inputs)
403
404 var apiFiles android.Paths
405 ctx.VisitDirectDepsWithTag(syspropLibraryDepTag, func(c android.Module) {
Inseob Kim3a3539a2021-01-15 18:10:29 +0900406 i, ok := c.(interface{ CurrentSyspropApiFile() android.OptionalPath })
Inseob Kimcd616492020-03-24 23:06:40 +0900407 if !ok {
408 panic(fmt.Errorf("unknown dependency %q for %q", ctx.OtherModuleName(c), ctx.ModuleName()))
409 }
Inseob Kim3a3539a2021-01-15 18:10:29 +0900410 if api := i.CurrentSyspropApiFile(); api.Valid() {
411 apiFiles = append(apiFiles, api.Path())
412 }
Inseob Kimcd616492020-03-24 23:06:40 +0900413 })
414
415 // check compatibility with sysprop_library
416 if len(apiFiles) > 0 {
417 out := android.PathForModuleGen(ctx, ctx.ModuleName()+"_api_checked")
Colin Cross242c8bc2020-11-16 17:58:17 -0800418 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kimcd616492020-03-24 23:06:40 +0900419
420 msg := `\n******************************\n` +
421 `API of sysprop_library doesn't match with property_contexts\n` +
422 `Please fix the breakage and rebuild.\n` +
423 `******************************\n`
424
425 rule.Command().
426 Text("( ").
Colin Cross242c8bc2020-11-16 17:58:17 -0800427 BuiltTool("sysprop_type_checker").
Inseob Kimcd616492020-03-24 23:06:40 +0900428 FlagForEachInput("--api ", apiFiles).
429 FlagWithInput("--context ", builtCtxFile).
430 Text(" || ( echo").Flag("-e").
431 Flag(`"` + msg + `"`).
432 Text("; exit 38) )")
433
434 rule.Command().Text("cp -f").Input(builtCtxFile).Output(out)
Colin Cross242c8bc2020-11-16 17:58:17 -0800435 rule.Build("property_contexts_check_api", "checking API: "+m.Name())
Inseob Kimcd616492020-03-24 23:06:40 +0900436 builtCtxFile = out
437 }
438
439 return builtCtxFile
Inseob Kimb554e592019-04-15 20:10:46 +0900440}
441
Inseob Kim2dac2672021-12-29 17:54:57 +0900442func (m *selinuxContextsModule) buildSeappContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
443 neverallowFile := android.PathForModuleGen(ctx, "neverallow")
444 ret := android.PathForModuleGen(ctx, m.stem())
445
446 rule := android.NewRuleBuilder(pctx, ctx)
447 rule.Command().Text("(grep").
448 Flag("-ihe").
449 Text("'^neverallow'").
450 Inputs(android.PathsForModuleSrc(ctx, m.seappProperties.Neverallow_files)).
451 Text(os.DevNull). // to make grep happy even when Neverallow_files is empty
452 Text(">").
453 Output(neverallowFile).
454 Text("|| true)") // to make ninja happy even when result is empty
455
456 rule.Temporary(neverallowFile)
457 rule.Command().BuiltTool("checkseapp").
458 FlagWithInput("-p ", android.PathForModuleSrc(ctx, proptools.String(m.seappProperties.Sepolicy))).
459 FlagWithOutput("-o ", ret).
460 Inputs(inputs).
461 Input(neverallowFile)
462
463 rule.Build("seapp_contexts", "Building seapp_contexts: "+m.Name())
464 return ret
465}
466
Inseob Kimb554e592019-04-15 20:10:46 +0900467func hwServiceFactory() android.Module {
468 m := newModule()
469 m.build = m.buildHwServiceContexts
470 return m
471}
472
473func propertyFactory() android.Module {
474 m := newModule()
Inseob Kimcd616492020-03-24 23:06:40 +0900475 m.build = m.buildPropertyContexts
476 m.deps = m.propertyContextsDeps
Inseob Kimb554e592019-04-15 20:10:46 +0900477 return m
478}
479
480func serviceFactory() android.Module {
481 m := newModule()
482 m.build = m.buildGeneralContexts
483 return m
484}
Janis Danisevskisc40681f2020-07-25 13:02:29 -0700485
486func keystoreKeyFactory() android.Module {
487 m := newModule()
488 m.build = m.buildGeneralContexts
489 return m
490}
Yuntao Xu42e732c2021-11-18 22:33:02 +0000491
Inseob Kim2dac2672021-12-29 17:54:57 +0900492func seappFactory() android.Module {
493 m := newModule()
494 m.build = m.buildSeappContexts
495 return m
496}
497
Yuntao Xu42e732c2021-11-18 22:33:02 +0000498var _ android.OutputFileProducer = (*selinuxContextsModule)(nil)
499
500// Implements android.OutputFileProducer
501func (m *selinuxContextsModule) OutputFiles(tag string) (android.Paths, error) {
502 if tag == "" {
503 return []android.Path{m.outputPath}, nil
504 }
505 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
506}
Inseob Kimb5e23532022-02-16 02:26:11 +0000507
508type contextsTestProperties struct {
509 // Contexts files to be tested.
510 Srcs []string `android:"path"`
511
512 // Precompiled sepolicy binary to be tesed together.
513 Sepolicy *string `android:"path"`
514}
515
516type contextsTestModule struct {
517 android.ModuleBase
518
519 // Name of the test tool. "checkfc" or "property_info_checker"
520 tool string
521
522 // Additional flags to be passed to the tool.
523 flags []string
524
525 properties contextsTestProperties
526 testTimestamp android.ModuleOutPath
527}
528
529// checkfc parses a context file and checks for syntax errors.
530// If -s is specified, the service backend is used to verify binder services.
531// If -l is specified, the service backend is used to verify hwbinder services.
532// Otherwise, context_file is assumed to be a file_contexts file
533// If -e is specified, then the context_file is allowed to be empty.
534
535// file_contexts_test tests given file_contexts files with checkfc.
536func fileContextsTestFactory() android.Module {
537 m := &contextsTestModule{tool: "checkfc" /* no flags: file_contexts file check */}
538 m.AddProperties(&m.properties)
539 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
540 return m
541}
542
543// property_contexts_test tests given property_contexts files with property_info_checker.
544func propertyContextsTestFactory() android.Module {
545 m := &contextsTestModule{tool: "property_info_checker"}
546 m.AddProperties(&m.properties)
547 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
548 return m
549}
550
551// hwservice_contexts_test tests given hwservice_contexts files with checkfc.
552func hwserviceContextsTestFactory() android.Module {
553 m := &contextsTestModule{tool: "checkfc", flags: []string{"-e" /* allow empty */, "-l" /* hwbinder services */}}
554 m.AddProperties(&m.properties)
555 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
556 return m
557}
558
559// service_contexts_test tests given service_contexts files with checkfc.
560func serviceContextsTestFactory() android.Module {
561 // checkfc -s: service_contexts test
562 m := &contextsTestModule{tool: "checkfc", flags: []string{"-s" /* binder services */}}
563 m.AddProperties(&m.properties)
564 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
565 return m
566}
567
568func (m *contextsTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
569 tool := m.tool
570 if tool != "checkfc" && tool != "property_info_checker" {
571 panic(fmt.Errorf("%q: unknown tool name: %q", ctx.ModuleName(), tool))
572 }
573
574 if len(m.properties.Srcs) == 0 {
575 ctx.PropertyErrorf("srcs", "can't be empty")
576 return
577 }
578
579 if proptools.String(m.properties.Sepolicy) == "" {
580 ctx.PropertyErrorf("sepolicy", "can't be empty")
581 return
582 }
583
584 srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs)
585 sepolicy := android.PathForModuleSrc(ctx, proptools.String(m.properties.Sepolicy))
586
587 rule := android.NewRuleBuilder(pctx, ctx)
588 rule.Command().BuiltTool(tool).
589 Flags(m.flags).
590 Input(sepolicy).
591 Inputs(srcs)
592
593 m.testTimestamp = android.PathForModuleOut(ctx, "timestamp")
594 rule.Command().Text("touch").Output(m.testTimestamp)
595 rule.Build("contexts_test", "running contexts test: "+ctx.ModuleName())
596}
597
598func (m *contextsTestModule) AndroidMkEntries() []android.AndroidMkEntries {
599 return []android.AndroidMkEntries{android.AndroidMkEntries{
600 Class: "FAKE",
601 // OutputFile is needed, even though BUILD_PHONY_PACKAGE doesn't use it.
602 // Without OutputFile this module won't be exported to Makefile.
603 OutputFile: android.OptionalPathForPath(m.testTimestamp),
604 Include: "$(BUILD_PHONY_PACKAGE)",
605 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
606 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
607 entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", m.testTimestamp.String())
608 },
609 },
610 }}
611}
612
613// contextsTestModule implements ImageInterface to be able to include recovery_available contexts
614// modules as its sources.
615func (m *contextsTestModule) ImageMutatorBegin(ctx android.BaseModuleContext) {
616}
617
618func (m *contextsTestModule) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
619 return true
620}
621
622func (m *contextsTestModule) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
623 return false
624}
625
626func (m *contextsTestModule) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
627 return false
628}
629
630func (m *contextsTestModule) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
631 return false
632}
633
634func (m *contextsTestModule) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
635 return false
636}
637
638func (m *contextsTestModule) ExtraImageVariations(ctx android.BaseModuleContext) []string {
639 return nil
640}
641
642func (m *contextsTestModule) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
643}
644
645var _ android.ImageInterface = (*contextsTestModule)(nil)