blob: e07bbf019dc7ce091ea0de398fd87e3e5b6134bb [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"
20 "strings"
21
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
29const (
30 coreMode = "core"
31 recoveryMode = "recovery"
32)
33
34type selinuxContextsProperties struct {
35 // Filenames under sepolicy directories, which will be used to generate contexts file.
36 Srcs []string `android:"path"`
37
38 Product_variables struct {
39 Debuggable struct {
40 Srcs []string
41 }
42
43 Address_sanitize struct {
44 Srcs []string
45 }
46 }
47
48 // Whether reqd_mask directory is included to sepolicy directories or not.
49 Reqd_mask *bool
50
51 // Whether the comments in generated contexts file will be removed or not.
52 Remove_comment *bool
53
54 // Whether the result context file is sorted with fc_sort or not.
55 Fc_sort *bool
56
57 // Make this module available when building for recovery
58 Recovery_available *bool
59
60 InRecovery bool `blueprint:"mutated"`
61}
62
63type fileContextsProperties struct {
64 // flatten_apex can be used to specify additional sources of file_contexts.
65 // Apex paths, /system/apex/{apex_name}, will be amended to the paths of file_contexts
66 // entries.
67 Flatten_apex struct {
68 Srcs []string
69 }
70}
71
72type selinuxContextsModule struct {
73 android.ModuleBase
74
75 properties selinuxContextsProperties
76 fileContextsProperties fileContextsProperties
Inseob Kimcd616492020-03-24 23:06:40 +090077 build func(ctx android.ModuleContext, inputs android.Paths) android.Path
78 deps func(ctx android.BottomUpMutatorContext)
79 outputPath android.Path
Colin Cross040f1512019-10-02 10:36:09 -070080 installPath android.InstallPath
Inseob Kimb554e592019-04-15 20:10:46 +090081}
82
83var (
Inseob Kimcd616492020-03-24 23:06:40 +090084 reuseContextsDepTag = dependencyTag{name: "reuseContexts"}
85 syspropLibraryDepTag = dependencyTag{name: "sysprop_library"}
Inseob Kimb554e592019-04-15 20:10:46 +090086)
87
88func init() {
89 pctx.HostBinToolVariable("fc_sort", "fc_sort")
90
91 android.RegisterModuleType("file_contexts", fileFactory)
92 android.RegisterModuleType("hwservice_contexts", hwServiceFactory)
93 android.RegisterModuleType("property_contexts", propertyFactory)
94 android.RegisterModuleType("service_contexts", serviceFactory)
Janis Danisevskisc40681f2020-07-25 13:02:29 -070095 android.RegisterModuleType("keystore2_key_contexts", keystoreKeyFactory)
Inseob Kimb554e592019-04-15 20:10:46 +090096
97 android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
98 ctx.BottomUp("selinux_contexts", selinuxContextsMutator).Parallel()
99 })
100}
101
102func (m *selinuxContextsModule) inRecovery() bool {
103 return m.properties.InRecovery || m.ModuleBase.InstallInRecovery()
104}
105
106func (m *selinuxContextsModule) onlyInRecovery() bool {
107 return m.ModuleBase.InstallInRecovery()
108}
109
110func (m *selinuxContextsModule) InstallInRecovery() bool {
111 return m.inRecovery()
112}
113
Colin Cross040f1512019-10-02 10:36:09 -0700114func (m *selinuxContextsModule) InstallInRoot() bool {
115 return m.inRecovery()
116}
117
Inseob Kimcd616492020-03-24 23:06:40 +0900118func (m *selinuxContextsModule) DepsMutator(ctx android.BottomUpMutatorContext) {
119 if m.deps != nil {
120 m.deps(ctx)
121 }
122}
123
124func (m *selinuxContextsModule) propertyContextsDeps(ctx android.BottomUpMutatorContext) {
125 for _, lib := range sysprop.SyspropLibraries(ctx.Config()) {
126 ctx.AddFarVariationDependencies([]blueprint.Variation{}, syspropLibraryDepTag, lib)
127 }
128}
129
Inseob Kimb554e592019-04-15 20:10:46 +0900130func (m *selinuxContextsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross040f1512019-10-02 10:36:09 -0700131 if m.inRecovery() {
132 // 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
138 if m.inRecovery() && !m.onlyInRecovery() {
139 dep := ctx.GetDirectDepWithTag(m.Name(), reuseContextsDepTag)
140
141 if reuseDeps, ok := dep.(*selinuxContextsModule); ok {
142 m.outputPath = reuseDeps.outputPath
143 ctx.InstallFile(m.installPath, m.Name(), m.outputPath)
144 return
145 }
146 }
147
148 var inputs android.Paths
149
150 ctx.VisitDirectDepsWithTag(android.SourceDepTag, func(dep android.Module) {
151 segroup, ok := dep.(*fileGroup)
152 if !ok {
153 ctx.ModuleErrorf("srcs dependency %q is not an selinux filegroup",
154 ctx.OtherModuleName(dep))
155 return
156 }
157
158 if ctx.ProductSpecific() {
159 inputs = append(inputs, segroup.ProductPrivateSrcs()...)
160 } else if ctx.SocSpecific() {
Inseob Kim8ada8a72020-11-09 20:58:58 +0900161 if ctx.DeviceConfig().BoardSepolicyVers() == ctx.DeviceConfig().PlatformSepolicyVersion() {
162 inputs = append(inputs, segroup.SystemVendorSrcs()...)
163 }
Inseob Kimb554e592019-04-15 20:10:46 +0900164 inputs = append(inputs, segroup.VendorSrcs()...)
165 } else if ctx.DeviceSpecific() {
166 inputs = append(inputs, segroup.OdmSrcs()...)
Bowgo Tsai86a048d2019-09-09 22:04:06 +0800167 } else if ctx.SystemExtSpecific() {
168 inputs = append(inputs, segroup.SystemExtPrivateSrcs()...)
Inseob Kimb554e592019-04-15 20:10:46 +0900169 } else {
170 inputs = append(inputs, segroup.SystemPrivateSrcs()...)
Felix342b58a2020-03-02 16:13:12 +0100171 inputs = append(inputs, segroup.SystemPublicSrcs()...)
Inseob Kimb554e592019-04-15 20:10:46 +0900172 }
173
174 if proptools.Bool(m.properties.Reqd_mask) {
Inseob Kim8ada8a72020-11-09 20:58:58 +0900175 if ctx.SocSpecific() || ctx.DeviceSpecific() {
176 inputs = append(inputs, segroup.VendorReqdMaskSrcs()...)
177 } else {
178 inputs = append(inputs, segroup.SystemReqdMaskSrcs()...)
179 }
Inseob Kimb554e592019-04-15 20:10:46 +0900180 }
181 })
182
183 for _, src := range m.properties.Srcs {
184 // Module sources are handled above with VisitDirectDepsWithTag
185 if android.SrcIsModule(src) == "" {
186 inputs = append(inputs, android.PathForModuleSrc(ctx, src))
187 }
188 }
189
Inseob Kimcd616492020-03-24 23:06:40 +0900190 m.outputPath = m.build(ctx, inputs)
191 ctx.InstallFile(m.installPath, ctx.ModuleName(), m.outputPath)
Inseob Kimb554e592019-04-15 20:10:46 +0900192}
193
194func newModule() *selinuxContextsModule {
195 m := &selinuxContextsModule{}
196 m.AddProperties(
197 &m.properties,
198 )
199 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
200 android.AddLoadHook(m, func(ctx android.LoadHookContext) {
201 m.selinuxContextsHook(ctx)
202 })
203 return m
204}
205
206func (m *selinuxContextsModule) selinuxContextsHook(ctx android.LoadHookContext) {
207 // TODO: clean this up to use build/soong/android/variable.go after b/79249983
208 var srcs []string
209
210 if ctx.Config().Debuggable() {
211 srcs = append(srcs, m.properties.Product_variables.Debuggable.Srcs...)
212 }
213
214 for _, sanitize := range ctx.Config().SanitizeDevice() {
215 if sanitize == "address" {
216 srcs = append(srcs, m.properties.Product_variables.Address_sanitize.Srcs...)
217 break
218 }
219 }
220
221 m.properties.Srcs = append(m.properties.Srcs, srcs...)
222}
223
224func (m *selinuxContextsModule) AndroidMk() android.AndroidMkData {
225 return android.AndroidMkData{
226 Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
227 nameSuffix := ""
228 if m.inRecovery() && !m.onlyInRecovery() {
229 nameSuffix = ".recovery"
230 }
231 fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
232 fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
233 fmt.Fprintln(w, "LOCAL_MODULE :=", name+nameSuffix)
Bob Badour4eeb6a22021-01-07 03:34:31 +0000234 data.Entries.WriteLicenseVariables(w)
Inseob Kimb554e592019-04-15 20:10:46 +0900235 fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
236 if m.Owner() != "" {
237 fmt.Fprintln(w, "LOCAL_MODULE_OWNER :=", m.Owner())
238 }
239 fmt.Fprintln(w, "LOCAL_MODULE_TAGS := optional")
240 fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", m.outputPath.String())
Colin Cross040f1512019-10-02 10:36:09 -0700241 fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", m.installPath.ToMakePath().String())
Inseob Kimb554e592019-04-15 20:10:46 +0900242 fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", name)
243 fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
244 },
245 }
246}
247
248func selinuxContextsMutator(ctx android.BottomUpMutatorContext) {
249 m, ok := ctx.Module().(*selinuxContextsModule)
250 if !ok {
251 return
252 }
253
254 var coreVariantNeeded bool = true
255 var recoveryVariantNeeded bool = false
256 if proptools.Bool(m.properties.Recovery_available) {
257 recoveryVariantNeeded = true
258 }
259
260 if m.ModuleBase.InstallInRecovery() {
261 recoveryVariantNeeded = true
262 coreVariantNeeded = false
263 }
264
265 var variants []string
266 if coreVariantNeeded {
267 variants = append(variants, coreMode)
268 }
269 if recoveryVariantNeeded {
270 variants = append(variants, recoveryMode)
271 }
272 mod := ctx.CreateVariations(variants...)
273
274 for i, v := range variants {
275 if v == recoveryMode {
276 m := mod[i].(*selinuxContextsModule)
277 m.properties.InRecovery = true
278
279 if coreVariantNeeded {
280 ctx.AddInterVariantDependency(reuseContextsDepTag, m, mod[i-1])
281 }
282 }
283 }
284}
285
Inseob Kimcd616492020-03-24 23:06:40 +0900286func (m *selinuxContextsModule) buildGeneralContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
287 ret := android.PathForModuleGen(ctx, ctx.ModuleName()+"_m4out")
Inseob Kimb554e592019-04-15 20:10:46 +0900288
Colin Cross242c8bc2020-11-16 17:58:17 -0800289 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kimb554e592019-04-15 20:10:46 +0900290
291 rule.Command().
Dan Willemsen3c3e59b2019-06-19 10:52:50 -0700292 Tool(ctx.Config().PrebuiltBuildTool(ctx, "m4")).
293 Text("--fatal-warnings -s").
Inseob Kimb554e592019-04-15 20:10:46 +0900294 FlagForEachArg("-D", ctx.DeviceConfig().SepolicyM4Defs()).
295 Inputs(inputs).
Inseob Kimcd616492020-03-24 23:06:40 +0900296 FlagWithOutput("> ", ret)
Inseob Kimb554e592019-04-15 20:10:46 +0900297
298 if proptools.Bool(m.properties.Remove_comment) {
Inseob Kimcd616492020-03-24 23:06:40 +0900299 rule.Temporary(ret)
Inseob Kimb554e592019-04-15 20:10:46 +0900300
301 remove_comment_output := android.PathForModuleGen(ctx, ctx.ModuleName()+"_remove_comment")
302
303 rule.Command().
304 Text("sed -e 's/#.*$//' -e '/^$/d'").
Inseob Kimcd616492020-03-24 23:06:40 +0900305 Input(ret).
Inseob Kimb554e592019-04-15 20:10:46 +0900306 FlagWithOutput("> ", remove_comment_output)
307
Inseob Kimcd616492020-03-24 23:06:40 +0900308 ret = remove_comment_output
Inseob Kimb554e592019-04-15 20:10:46 +0900309 }
310
311 if proptools.Bool(m.properties.Fc_sort) {
Inseob Kimcd616492020-03-24 23:06:40 +0900312 rule.Temporary(ret)
Inseob Kimb554e592019-04-15 20:10:46 +0900313
314 sorted_output := android.PathForModuleGen(ctx, ctx.ModuleName()+"_sorted")
315
316 rule.Command().
317 Tool(ctx.Config().HostToolPath(ctx, "fc_sort")).
Inseob Kimcd616492020-03-24 23:06:40 +0900318 FlagWithInput("-i ", ret).
Inseob Kimb554e592019-04-15 20:10:46 +0900319 FlagWithOutput("-o ", sorted_output)
320
Inseob Kimcd616492020-03-24 23:06:40 +0900321 ret = sorted_output
Inseob Kimb554e592019-04-15 20:10:46 +0900322 }
323
Colin Cross242c8bc2020-11-16 17:58:17 -0800324 rule.Build("selinux_contexts", "building contexts: "+m.Name())
Inseob Kimb554e592019-04-15 20:10:46 +0900325
326 rule.DeleteTemporaryFiles()
327
Inseob Kimcd616492020-03-24 23:06:40 +0900328 return ret
Inseob Kimb554e592019-04-15 20:10:46 +0900329}
330
Inseob Kimcd616492020-03-24 23:06:40 +0900331func (m *selinuxContextsModule) buildFileContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kimb554e592019-04-15 20:10:46 +0900332 if m.properties.Fc_sort == nil {
333 m.properties.Fc_sort = proptools.BoolPtr(true)
334 }
335
Colin Cross242c8bc2020-11-16 17:58:17 -0800336 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kimb554e592019-04-15 20:10:46 +0900337
338 if ctx.Config().FlattenApex() {
339 for _, src := range m.fileContextsProperties.Flatten_apex.Srcs {
340 if m := android.SrcIsModule(src); m != "" {
341 ctx.ModuleErrorf(
342 "Module srcs dependency %q is not supported for flatten_apex.srcs", m)
Inseob Kimcd616492020-03-24 23:06:40 +0900343 return nil
Inseob Kimb554e592019-04-15 20:10:46 +0900344 }
345 for _, path := range android.PathsForModuleSrcExcludes(ctx, []string{src}, nil) {
346 out := android.PathForModuleGen(ctx, "flattened_apex", path.Rel())
347 apex_path := "/system/apex/" + strings.Replace(
348 strings.TrimSuffix(path.Base(), "-file_contexts"),
349 ".", "\\\\.", -1)
350
351 rule.Command().
352 Text("awk '/object_r/{printf(\""+apex_path+"%s\\n\",$0)}'").
353 Input(path).
354 FlagWithOutput("> ", out)
355
356 inputs = append(inputs, out)
357 }
358 }
359 }
360
Colin Cross242c8bc2020-11-16 17:58:17 -0800361 rule.Build(m.Name(), "flattened_apex_file_contexts")
Inseob Kimcd616492020-03-24 23:06:40 +0900362 return m.buildGeneralContexts(ctx, inputs)
Inseob Kimb554e592019-04-15 20:10:46 +0900363}
364
365func fileFactory() android.Module {
366 m := newModule()
367 m.AddProperties(&m.fileContextsProperties)
368 m.build = m.buildFileContexts
369 return m
370}
371
Inseob Kimcd616492020-03-24 23:06:40 +0900372func (m *selinuxContextsModule) buildHwServiceContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
Inseob Kimb554e592019-04-15 20:10:46 +0900373 if m.properties.Remove_comment == nil {
374 m.properties.Remove_comment = proptools.BoolPtr(true)
375 }
376
Inseob Kimcd616492020-03-24 23:06:40 +0900377 return m.buildGeneralContexts(ctx, inputs)
378}
379
380func (m *selinuxContextsModule) buildPropertyContexts(ctx android.ModuleContext, inputs android.Paths) android.Path {
381 builtCtxFile := m.buildGeneralContexts(ctx, inputs)
382
383 var apiFiles android.Paths
384 ctx.VisitDirectDepsWithTag(syspropLibraryDepTag, func(c android.Module) {
Inseob Kim3a3539a2021-01-15 18:10:29 +0900385 i, ok := c.(interface{ CurrentSyspropApiFile() android.OptionalPath })
Inseob Kimcd616492020-03-24 23:06:40 +0900386 if !ok {
387 panic(fmt.Errorf("unknown dependency %q for %q", ctx.OtherModuleName(c), ctx.ModuleName()))
388 }
Inseob Kim3a3539a2021-01-15 18:10:29 +0900389 if api := i.CurrentSyspropApiFile(); api.Valid() {
390 apiFiles = append(apiFiles, api.Path())
391 }
Inseob Kimcd616492020-03-24 23:06:40 +0900392 })
393
394 // check compatibility with sysprop_library
395 if len(apiFiles) > 0 {
396 out := android.PathForModuleGen(ctx, ctx.ModuleName()+"_api_checked")
Colin Cross242c8bc2020-11-16 17:58:17 -0800397 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kimcd616492020-03-24 23:06:40 +0900398
399 msg := `\n******************************\n` +
400 `API of sysprop_library doesn't match with property_contexts\n` +
401 `Please fix the breakage and rebuild.\n` +
402 `******************************\n`
403
404 rule.Command().
405 Text("( ").
Colin Cross242c8bc2020-11-16 17:58:17 -0800406 BuiltTool("sysprop_type_checker").
Inseob Kimcd616492020-03-24 23:06:40 +0900407 FlagForEachInput("--api ", apiFiles).
408 FlagWithInput("--context ", builtCtxFile).
409 Text(" || ( echo").Flag("-e").
410 Flag(`"` + msg + `"`).
411 Text("; exit 38) )")
412
413 rule.Command().Text("cp -f").Input(builtCtxFile).Output(out)
Colin Cross242c8bc2020-11-16 17:58:17 -0800414 rule.Build("property_contexts_check_api", "checking API: "+m.Name())
Inseob Kimcd616492020-03-24 23:06:40 +0900415 builtCtxFile = out
416 }
417
418 return builtCtxFile
Inseob Kimb554e592019-04-15 20:10:46 +0900419}
420
421func hwServiceFactory() android.Module {
422 m := newModule()
423 m.build = m.buildHwServiceContexts
424 return m
425}
426
427func propertyFactory() android.Module {
428 m := newModule()
Inseob Kimcd616492020-03-24 23:06:40 +0900429 m.build = m.buildPropertyContexts
430 m.deps = m.propertyContextsDeps
Inseob Kimb554e592019-04-15 20:10:46 +0900431 return m
432}
433
434func serviceFactory() android.Module {
435 m := newModule()
436 m.build = m.buildGeneralContexts
437 return m
438}
Janis Danisevskisc40681f2020-07-25 13:02:29 -0700439
440func keystoreKeyFactory() android.Module {
441 m := newModule()
442 m.build = m.buildGeneralContexts
443 return m
444}