blob: 47a63d023a4983acb623b0f080871a81a9fb893e [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
62
Jooyung Han804e2342023-06-20 15:38:50 +090063 properties selinuxContextsProperties
64 seappProperties seappProperties
65 build func(ctx android.ModuleContext, inputs android.Paths) android.Path
66 deps func(ctx android.BottomUpMutatorContext)
67 outputPath android.Path
68 installPath android.InstallPath
Inseob Kimb554e592019-04-15 20:10:46 +090069}
70
71var (
Inseob Kimcd616492020-03-24 23:06:40 +090072 reuseContextsDepTag = dependencyTag{name: "reuseContexts"}
73 syspropLibraryDepTag = dependencyTag{name: "sysprop_library"}
Inseob Kimb554e592019-04-15 20:10:46 +090074)
75
76func init() {
77 pctx.HostBinToolVariable("fc_sort", "fc_sort")
78
79 android.RegisterModuleType("file_contexts", fileFactory)
80 android.RegisterModuleType("hwservice_contexts", hwServiceFactory)
81 android.RegisterModuleType("property_contexts", propertyFactory)
82 android.RegisterModuleType("service_contexts", serviceFactory)
Janis Danisevskisc40681f2020-07-25 13:02:29 -070083 android.RegisterModuleType("keystore2_key_contexts", keystoreKeyFactory)
Inseob Kim2dac2672021-12-29 17:54:57 +090084 android.RegisterModuleType("seapp_contexts", seappFactory)
Inseob Kimc7596c42022-02-25 11:45:41 +090085 android.RegisterModuleType("vndservice_contexts", vndServiceFactory)
Inseob Kimb5e23532022-02-16 02:26:11 +000086
87 android.RegisterModuleType("file_contexts_test", fileContextsTestFactory)
88 android.RegisterModuleType("property_contexts_test", propertyContextsTestFactory)
89 android.RegisterModuleType("hwservice_contexts_test", hwserviceContextsTestFactory)
90 android.RegisterModuleType("service_contexts_test", serviceContextsTestFactory)
Inseob Kimc7596c42022-02-25 11:45:41 +090091 android.RegisterModuleType("vndservice_contexts_test", vndServiceContextsTestFactory)
Inseob Kimb554e592019-04-15 20:10:46 +090092}
93
Colin Cross040f1512019-10-02 10:36:09 -070094func (m *selinuxContextsModule) InstallInRoot() bool {
Inseob Kimfa6fe472021-01-12 13:40:27 +090095 return m.InRecovery()
96}
97
98func (m *selinuxContextsModule) InstallInRecovery() bool {
99 // ModuleBase.InRecovery() checks the image variant
100 return m.InRecovery()
101}
102
103func (m *selinuxContextsModule) onlyInRecovery() bool {
104 // ModuleBase.InstallInRecovery() checks commonProperties.Recovery property
105 return m.ModuleBase.InstallInRecovery()
Colin Cross040f1512019-10-02 10:36:09 -0700106}
107
Inseob Kimcd616492020-03-24 23:06:40 +0900108func (m *selinuxContextsModule) DepsMutator(ctx android.BottomUpMutatorContext) {
109 if m.deps != nil {
110 m.deps(ctx)
111 }
Inseob Kimfa6fe472021-01-12 13:40:27 +0900112
113 if m.InRecovery() && !m.onlyInRecovery() {
114 ctx.AddFarVariationDependencies([]blueprint.Variation{
115 {Mutator: "image", Variation: android.CoreVariation},
116 }, reuseContextsDepTag, ctx.ModuleName())
117 }
Inseob Kimcd616492020-03-24 23:06:40 +0900118}
119
120func (m *selinuxContextsModule) propertyContextsDeps(ctx android.BottomUpMutatorContext) {
121 for _, lib := range sysprop.SyspropLibraries(ctx.Config()) {
122 ctx.AddFarVariationDependencies([]blueprint.Variation{}, syspropLibraryDepTag, lib)
123 }
124}
125
Yuntao Xu42e732c2021-11-18 22:33:02 +0000126func (m *selinuxContextsModule) stem() string {
127 return proptools.StringDefault(m.properties.Stem, m.Name())
128}
129
Inseob Kimb554e592019-04-15 20:10:46 +0900130func (m *selinuxContextsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900131 if m.InRecovery() {
Colin Cross040f1512019-10-02 10:36:09 -0700132 // Installing context files at the root of the recovery partition
133 m.installPath = android.PathForModuleInstall(ctx)
Inseob Kimb554e592019-04-15 20:10:46 +0900134 } else {
135 m.installPath = android.PathForModuleInstall(ctx, "etc", "selinux")
136 }
137
Inseob Kimfa6fe472021-01-12 13:40:27 +0900138 if m.InRecovery() && !m.onlyInRecovery() {
Inseob Kimb554e592019-04-15 20:10:46 +0900139 dep := ctx.GetDirectDepWithTag(m.Name(), reuseContextsDepTag)
140
141 if reuseDeps, ok := dep.(*selinuxContextsModule); ok {
142 m.outputPath = reuseDeps.outputPath
Yuntao Xu42e732c2021-11-18 22:33:02 +0000143 ctx.InstallFile(m.installPath, m.stem(), m.outputPath)
Inseob Kimb554e592019-04-15 20:10:46 +0900144 return
145 }
146 }
147
Inseob Kim6d3d5a62021-12-21 20:55:32 +0900148 m.outputPath = m.build(ctx, android.PathsForModuleSrc(ctx, m.properties.Srcs))
Yuntao Xu42e732c2021-11-18 22:33:02 +0000149 ctx.InstallFile(m.installPath, m.stem(), m.outputPath)
Inseob Kimb554e592019-04-15 20:10:46 +0900150}
151
152func newModule() *selinuxContextsModule {
153 m := &selinuxContextsModule{}
154 m.AddProperties(
155 &m.properties,
Inseob Kim2dac2672021-12-29 17:54:57 +0900156 &m.seappProperties,
Inseob Kimb554e592019-04-15 20:10:46 +0900157 )
158 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
159 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
160 m.selinuxContextsHook(ctx)
161 })
162 return m
163}
164
165func (m *selinuxContextsModule) selinuxContextsHook(ctx android.LoadHookContext) {
166 // TODO: clean this up to use build/soong/android/variable.go after b/79249983
167 var srcs []string
168
Inseob Kimb554e592019-04-15 20:10:46 +0900169 for _, sanitize := range ctx.Config().SanitizeDevice() {
170 if sanitize == "address" {
171 srcs = append(srcs, m.properties.Product_variables.Address_sanitize.Srcs...)
172 break
173 }
174 }
175
176 m.properties.Srcs = append(m.properties.Srcs, srcs...)
177}
178
179func (m *selinuxContextsModule) AndroidMk() android.AndroidMkData {
Colin Crossf82aed02021-11-04 17:25:55 -0700180 nameSuffix := ""
181 if m.InRecovery() && !m.onlyInRecovery() {
182 nameSuffix = ".recovery"
183 }
Inseob Kimb554e592019-04-15 20:10:46 +0900184 return android.AndroidMkData{
Colin Crossf82aed02021-11-04 17:25:55 -0700185 Class: "ETC",
186 OutputFile: android.OptionalPathForPath(m.outputPath),
187 SubName: nameSuffix,
188 Extra: []android.AndroidMkExtraFunc{
189 func(w io.Writer, outputFile android.Path) {
Colin Cross6c7f9372022-01-11 19:35:43 -0800190 fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", m.installPath.String())
Yuntao Xu42e732c2021-11-18 22:33:02 +0000191 fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.stem())
Colin Crossf82aed02021-11-04 17:25:55 -0700192 },
Inseob Kimb554e592019-04-15 20:10:46 +0900193 },
194 }
195}
196
Inseob Kimfa6fe472021-01-12 13:40:27 +0900197func (m *selinuxContextsModule) ImageMutatorBegin(ctx android.BaseModuleContext) {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000198 if proptools.Bool(m.properties.Recovery_available) && m.ModuleBase.InstallInRecovery() {
Inseob Kimfa6fe472021-01-12 13:40:27 +0900199 ctx.PropertyErrorf("recovery_available",
200 "doesn't make sense at the same time as `recovery: true`")
Inseob Kimb554e592019-04-15 20:10:46 +0900201 }
202}
203
Inseob Kimfa6fe472021-01-12 13:40:27 +0900204func (m *selinuxContextsModule) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000205 return !m.ModuleBase.InstallInRecovery()
Inseob Kimfa6fe472021-01-12 13:40:27 +0900206}
207
208func (m *selinuxContextsModule) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
209 return false
210}
211
212func (m *selinuxContextsModule) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
213 return false
214}
215
Inseob Kim6cc75f42021-04-29 13:53:20 +0000216func (m *selinuxContextsModule) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
217 return false
218}
219
Inseob Kimfa6fe472021-01-12 13:40:27 +0900220func (m *selinuxContextsModule) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
Yuntao Xu42e732c2021-11-18 22:33:02 +0000221 return m.ModuleBase.InstallInRecovery() || proptools.Bool(m.properties.Recovery_available)
Inseob Kimfa6fe472021-01-12 13:40:27 +0900222}
223
224func (m *selinuxContextsModule) ExtraImageVariations(ctx android.BaseModuleContext) []string {
225 return nil
226}
227
228func (m *selinuxContextsModule) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
229}
230
231var _ android.ImageInterface = (*selinuxContextsModule)(nil)
232
Inseob Kimcd616492020-03-24 23:06:40 +0900233func (m *selinuxContextsModule) buildGeneralContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900234 builtContext := pathForModuleOut(ctx, ctx.ModuleName()+"_m4out")
Inseob Kimb554e592019-04-15 20:10:46 +0900235
Colin Cross242c8bc2020-11-16 17:58:17 -0800236 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kimb554e592019-04-15 20:10:46 +0900237
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900238 newlineFile := pathForModuleOut(ctx, "newline")
Inseob Kim35e9d412023-01-04 15:27:32 +0900239
240 rule.Command().Text("echo").FlagWithOutput("> ", newlineFile)
241 rule.Temporary(newlineFile)
242
243 var inputsWithNewline android.Paths
244 for _, input := range inputs {
245 inputsWithNewline = append(inputsWithNewline, input, newlineFile)
246 }
247
Inseob Kimb554e592019-04-15 20:10:46 +0900248 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()).
Inseob Kim35e9d412023-01-04 15:27:32 +0900252 Inputs(inputsWithNewline).
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
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900258 remove_comment_output := pathForModuleOut(ctx, ctx.ModuleName()+"_remove_comment")
Inseob Kimb554e592019-04-15 20:10:46 +0900259
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
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900271 sorted_output := pathForModuleOut(ctx, ctx.ModuleName()+"_sorted")
Inseob Kimb554e592019-04-15 20:10:46 +0900272
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
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900281 ret := pathForModuleOut(ctx, m.stem())
Yuntao Xu42e732c2021-11-18 22:33:02 +0000282 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 }
Inseob Kimcd616492020-03-24 23:06:40 +0900295 return m.buildGeneralContexts(ctx, inputs)
Inseob Kimb554e592019-04-15 20:10:46 +0900296}
297
298func fileFactory() android.Module {
299 m := newModule()
Inseob Kimb554e592019-04-15 20:10:46 +0900300 m.build = m.buildFileContexts
301 return m
302}
303
Thiébaud Weksteen74482f52023-04-26 13:46:59 +1000304func (m *selinuxContextsModule) buildServiceContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kimb554e592019-04-15 20:10:46 +0900305 if m.properties.Remove_comment == nil {
306 m.properties.Remove_comment = proptools.BoolPtr(true)
307 }
308
Inseob Kimcd616492020-03-24 23:06:40 +0900309 return m.buildGeneralContexts(ctx, inputs)
310}
311
Inseob Kim2bcc0452020-12-21 13:16:44 +0900312func (m *selinuxContextsModule) checkVendorPropertyNamespace(ctx android.ModuleContext, inputs android.Paths) android.Paths {
313 shippingApiLevel := ctx.DeviceConfig().ShippingApiLevel()
314 ApiLevelR := android.ApiLevelOrPanic(ctx, "R")
315
316 rule := android.NewRuleBuilder(pctx, ctx)
317
318 // This list is from vts_treble_sys_prop_test.
319 allowedPropertyPrefixes := []string{
320 "ctl.odm.",
321 "ctl.vendor.",
322 "ctl.start$odm.",
323 "ctl.start$vendor.",
324 "ctl.stop$odm.",
325 "ctl.stop$vendor.",
326 "init.svc.odm.",
327 "init.svc.vendor.",
328 "ro.boot.",
329 "ro.hardware.",
330 "ro.odm.",
331 "ro.vendor.",
332 "odm.",
333 "persist.odm.",
334 "persist.vendor.",
335 "vendor.",
336 }
337
338 // persist.camera is also allowed for devices launching with R or eariler
339 if shippingApiLevel.LessThanOrEqualTo(ApiLevelR) {
340 allowedPropertyPrefixes = append(allowedPropertyPrefixes, "persist.camera.")
341 }
342
343 var allowedContextPrefixes []string
344
345 if shippingApiLevel.GreaterThanOrEqualTo(ApiLevelR) {
346 // This list is from vts_treble_sys_prop_test.
347 allowedContextPrefixes = []string{
348 "vendor_",
349 "odm_",
350 }
351 }
352
353 var ret android.Paths
354 for _, input := range inputs {
355 cmd := rule.Command().
356 BuiltTool("check_prop_prefix").
357 FlagWithInput("--property-contexts ", input).
358 FlagForEachArg("--allowed-property-prefix ", proptools.ShellEscapeList(allowedPropertyPrefixes)). // contains shell special character '$'
359 FlagForEachArg("--allowed-context-prefix ", allowedContextPrefixes)
360
361 if !ctx.DeviceConfig().BuildBrokenVendorPropertyNamespace() {
362 cmd.Flag("--strict")
363 }
364
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900365 out := pathForModuleOut(ctx, "namespace_checked").Join(ctx, input.String())
Inseob Kim2bcc0452020-12-21 13:16:44 +0900366 rule.Command().Text("cp -f").Input(input).Output(out)
367 ret = append(ret, out)
368 }
369 rule.Build("check_namespace", "checking namespace of "+ctx.ModuleName())
370 return ret
371}
372
Inseob Kimcd616492020-03-24 23:06:40 +0900373func (m *selinuxContextsModule) buildPropertyContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kim2bcc0452020-12-21 13:16:44 +0900374 // vendor/odm properties are enforced for devices launching with Android Q or later. So, if
375 // vendor/odm, make sure that only vendor/odm properties exist.
376 shippingApiLevel := ctx.DeviceConfig().ShippingApiLevel()
377 ApiLevelQ := android.ApiLevelOrPanic(ctx, "Q")
378 if (ctx.SocSpecific() || ctx.DeviceSpecific()) && shippingApiLevel.GreaterThanOrEqualTo(ApiLevelQ) {
379 inputs = m.checkVendorPropertyNamespace(ctx, inputs)
380 }
381
Inseob Kimcd616492020-03-24 23:06:40 +0900382 builtCtxFile := m.buildGeneralContexts(ctx, inputs)
383
384 var apiFiles android.Paths
385 ctx.VisitDirectDepsWithTag(syspropLibraryDepTag, func(c android.Module) {
Inseob Kim3a3539a2021-01-15 18:10:29 +0900386 i, ok := c.(interface{ CurrentSyspropApiFile() android.OptionalPath })
Inseob Kimcd616492020-03-24 23:06:40 +0900387 if !ok {
388 panic(fmt.Errorf("unknown dependency %q for %q", ctx.OtherModuleName(c), ctx.ModuleName()))
389 }
Inseob Kim3a3539a2021-01-15 18:10:29 +0900390 if api := i.CurrentSyspropApiFile(); api.Valid() {
391 apiFiles = append(apiFiles, api.Path())
392 }
Inseob Kimcd616492020-03-24 23:06:40 +0900393 })
394
395 // check compatibility with sysprop_library
396 if len(apiFiles) > 0 {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900397 out := pathForModuleOut(ctx, ctx.ModuleName()+"_api_checked")
Colin Cross242c8bc2020-11-16 17:58:17 -0800398 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kimcd616492020-03-24 23:06:40 +0900399
400 msg := `\n******************************\n` +
401 `API of sysprop_library doesn't match with property_contexts\n` +
402 `Please fix the breakage and rebuild.\n` +
403 `******************************\n`
404
405 rule.Command().
406 Text("( ").
Colin Cross242c8bc2020-11-16 17:58:17 -0800407 BuiltTool("sysprop_type_checker").
Inseob Kimcd616492020-03-24 23:06:40 +0900408 FlagForEachInput("--api ", apiFiles).
409 FlagWithInput("--context ", builtCtxFile).
410 Text(" || ( echo").Flag("-e").
411 Flag(`"` + msg + `"`).
412 Text("; exit 38) )")
413
414 rule.Command().Text("cp -f").Input(builtCtxFile).Output(out)
Colin Cross242c8bc2020-11-16 17:58:17 -0800415 rule.Build("property_contexts_check_api", "checking API: "+m.Name())
Inseob Kimcd616492020-03-24 23:06:40 +0900416 builtCtxFile = out
417 }
418
419 return builtCtxFile
Inseob Kimb554e592019-04-15 20:10:46 +0900420}
421
Inseob Kim06518b12023-08-25 21:20:08 +0900422func (m *selinuxContextsModule) shouldCheckCoredomain(ctx android.ModuleContext) bool {
423 if !ctx.SocSpecific() && !ctx.DeviceSpecific() {
424 return false
425 }
426
427 return ctx.DeviceConfig().CheckVendorSeappViolations()
428}
429
Inseob Kim2dac2672021-12-29 17:54:57 +0900430func (m *selinuxContextsModule) buildSeappContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900431 neverallowFile := pathForModuleOut(ctx, "neverallow")
432 ret := pathForModuleOut(ctx, m.stem())
Inseob Kim2dac2672021-12-29 17:54:57 +0900433
434 rule := android.NewRuleBuilder(pctx, ctx)
435 rule.Command().Text("(grep").
436 Flag("-ihe").
437 Text("'^neverallow'").
438 Inputs(android.PathsForModuleSrc(ctx, m.seappProperties.Neverallow_files)).
439 Text(os.DevNull). // to make grep happy even when Neverallow_files is empty
440 Text(">").
441 Output(neverallowFile).
442 Text("|| true)") // to make ninja happy even when result is empty
443
444 rule.Temporary(neverallowFile)
Inseob Kimd7d36092023-06-26 20:48:48 +0900445 checkCmd := rule.Command().BuiltTool("checkseapp").
Inseob Kim2dac2672021-12-29 17:54:57 +0900446 FlagWithInput("-p ", android.PathForModuleSrc(ctx, proptools.String(m.seappProperties.Sepolicy))).
447 FlagWithOutput("-o ", ret).
448 Inputs(inputs).
449 Input(neverallowFile)
450
Inseob Kim06518b12023-08-25 21:20:08 +0900451 if m.shouldCheckCoredomain(ctx) {
452 checkCmd.Flag("-c") // check coredomain for vendor contexts
Inseob Kimd7d36092023-06-26 20:48:48 +0900453 }
454
Inseob Kim2dac2672021-12-29 17:54:57 +0900455 rule.Build("seapp_contexts", "Building seapp_contexts: "+m.Name())
456 return ret
457}
458
Inseob Kimb554e592019-04-15 20:10:46 +0900459func hwServiceFactory() android.Module {
460 m := newModule()
Thiébaud Weksteen74482f52023-04-26 13:46:59 +1000461 m.build = m.buildServiceContexts
Inseob Kimb554e592019-04-15 20:10:46 +0900462 return m
463}
464
465func propertyFactory() android.Module {
466 m := newModule()
Inseob Kimcd616492020-03-24 23:06:40 +0900467 m.build = m.buildPropertyContexts
468 m.deps = m.propertyContextsDeps
Inseob Kimb554e592019-04-15 20:10:46 +0900469 return m
470}
471
472func serviceFactory() android.Module {
473 m := newModule()
Thiébaud Weksteen74482f52023-04-26 13:46:59 +1000474 m.build = m.buildServiceContexts
Inseob Kimb554e592019-04-15 20:10:46 +0900475 return m
476}
Janis Danisevskisc40681f2020-07-25 13:02:29 -0700477
478func keystoreKeyFactory() android.Module {
479 m := newModule()
480 m.build = m.buildGeneralContexts
481 return m
482}
Yuntao Xu42e732c2021-11-18 22:33:02 +0000483
Inseob Kim2dac2672021-12-29 17:54:57 +0900484func seappFactory() android.Module {
485 m := newModule()
486 m.build = m.buildSeappContexts
487 return m
488}
489
Inseob Kimc7596c42022-02-25 11:45:41 +0900490func vndServiceFactory() android.Module {
491 m := newModule()
492 m.build = m.buildGeneralContexts
493 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
494 if !ctx.SocSpecific() {
495 ctx.ModuleErrorf(m.Name(), "must set vendor: true")
496 return
497 }
498 })
499 return m
500}
501
Yuntao Xu42e732c2021-11-18 22:33:02 +0000502var _ android.OutputFileProducer = (*selinuxContextsModule)(nil)
503
504// Implements android.OutputFileProducer
505func (m *selinuxContextsModule) OutputFiles(tag string) (android.Paths, error) {
506 if tag == "" {
507 return []android.Path{m.outputPath}, nil
508 }
509 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
510}
Inseob Kimb5e23532022-02-16 02:26:11 +0000511
512type contextsTestProperties struct {
513 // Contexts files to be tested.
514 Srcs []string `android:"path"`
515
516 // Precompiled sepolicy binary to be tesed together.
517 Sepolicy *string `android:"path"`
518}
519
520type contextsTestModule struct {
521 android.ModuleBase
522
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100523 // The type of context.
524 context contextType
Inseob Kimb5e23532022-02-16 02:26:11 +0000525
526 properties contextsTestProperties
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900527 testTimestamp android.OutputPath
Inseob Kimb5e23532022-02-16 02:26:11 +0000528}
529
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100530type contextType int
531
532const (
533 FileContext contextType = iota
534 PropertyContext
535 ServiceContext
536 HwServiceContext
537 VndServiceContext
538)
539
Inseob Kimb5e23532022-02-16 02:26:11 +0000540// checkfc parses a context file and checks for syntax errors.
541// If -s is specified, the service backend is used to verify binder services.
542// If -l is specified, the service backend is used to verify hwbinder services.
543// Otherwise, context_file is assumed to be a file_contexts file
544// If -e is specified, then the context_file is allowed to be empty.
545
546// file_contexts_test tests given file_contexts files with checkfc.
547func fileContextsTestFactory() android.Module {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100548 m := &contextsTestModule{context: FileContext}
Inseob Kimb5e23532022-02-16 02:26:11 +0000549 m.AddProperties(&m.properties)
550 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
551 return m
552}
553
554// property_contexts_test tests given property_contexts files with property_info_checker.
555func propertyContextsTestFactory() android.Module {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100556 m := &contextsTestModule{context: PropertyContext}
Inseob Kimb5e23532022-02-16 02:26:11 +0000557 m.AddProperties(&m.properties)
558 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
559 return m
560}
561
562// hwservice_contexts_test tests given hwservice_contexts files with checkfc.
563func hwserviceContextsTestFactory() android.Module {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100564 m := &contextsTestModule{context: HwServiceContext}
Inseob Kimb5e23532022-02-16 02:26:11 +0000565 m.AddProperties(&m.properties)
566 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
567 return m
568}
569
570// service_contexts_test tests given service_contexts files with checkfc.
571func serviceContextsTestFactory() android.Module {
572 // checkfc -s: service_contexts test
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100573 m := &contextsTestModule{context: ServiceContext}
Inseob Kimb5e23532022-02-16 02:26:11 +0000574 m.AddProperties(&m.properties)
575 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
576 return m
577}
578
Inseob Kimc7596c42022-02-25 11:45:41 +0900579// vndservice_contexts_test tests given vndservice_contexts files with checkfc.
580func vndServiceContextsTestFactory() android.Module {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100581 m := &contextsTestModule{context: VndServiceContext}
Inseob Kimc7596c42022-02-25 11:45:41 +0900582 m.AddProperties(&m.properties)
583 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
584 return m
585}
586
Inseob Kimb5e23532022-02-16 02:26:11 +0000587func (m *contextsTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100588 tool := "checkfc"
589 if m.context == PropertyContext {
590 tool = "property_info_checker"
Inseob Kimb5e23532022-02-16 02:26:11 +0000591 }
592
593 if len(m.properties.Srcs) == 0 {
594 ctx.PropertyErrorf("srcs", "can't be empty")
595 return
596 }
597
598 if proptools.String(m.properties.Sepolicy) == "" {
599 ctx.PropertyErrorf("sepolicy", "can't be empty")
600 return
601 }
602
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100603 flags := []string(nil)
604 switch m.context {
605 case ServiceContext:
606 flags = []string{"-s" /* binder services */}
607 case HwServiceContext:
608 flags = []string{"-e" /* allow empty */, "-l" /* hwbinder services */}
609 case VndServiceContext:
610 flags = []string{"-e" /* allow empty */, "-v" /* vnd service */}
611 }
612
Inseob Kimb5e23532022-02-16 02:26:11 +0000613 srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs)
614 sepolicy := android.PathForModuleSrc(ctx, proptools.String(m.properties.Sepolicy))
615
616 rule := android.NewRuleBuilder(pctx, ctx)
617 rule.Command().BuiltTool(tool).
Thiébaud Weksteena69e14f2023-10-20 13:31:19 +1100618 Flags(flags).
Inseob Kimb5e23532022-02-16 02:26:11 +0000619 Input(sepolicy).
620 Inputs(srcs)
621
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900622 m.testTimestamp = pathForModuleOut(ctx, "timestamp")
Inseob Kimb5e23532022-02-16 02:26:11 +0000623 rule.Command().Text("touch").Output(m.testTimestamp)
624 rule.Build("contexts_test", "running contexts test: "+ctx.ModuleName())
625}
626
627func (m *contextsTestModule) AndroidMkEntries() []android.AndroidMkEntries {
628 return []android.AndroidMkEntries{android.AndroidMkEntries{
629 Class: "FAKE",
630 // OutputFile is needed, even though BUILD_PHONY_PACKAGE doesn't use it.
631 // Without OutputFile this module won't be exported to Makefile.
632 OutputFile: android.OptionalPathForPath(m.testTimestamp),
633 Include: "$(BUILD_PHONY_PACKAGE)",
634 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
635 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
636 entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", m.testTimestamp.String())
637 },
638 },
639 }}
640}
641
642// contextsTestModule implements ImageInterface to be able to include recovery_available contexts
643// modules as its sources.
644func (m *contextsTestModule) ImageMutatorBegin(ctx android.BaseModuleContext) {
645}
646
647func (m *contextsTestModule) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
648 return true
649}
650
651func (m *contextsTestModule) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
652 return false
653}
654
655func (m *contextsTestModule) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
656 return false
657}
658
659func (m *contextsTestModule) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
660 return false
661}
662
663func (m *contextsTestModule) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
664 return false
665}
666
667func (m *contextsTestModule) ExtraImageVariations(ctx android.BaseModuleContext) []string {
668 return nil
669}
670
671func (m *contextsTestModule) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
672}
673
674var _ android.ImageInterface = (*contextsTestModule)(nil)