blob: 5611ed0665cd1946f786013e8270d510d9f42464 [file] [log] [blame]
Inseob Kim7e8bd1e2021-03-17 18:59:43 +09001// Copyright (C) 2021 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 (
Inseob Kim7e8bd1e2021-03-17 18:59:43 +090018 "os"
Inseob Kim0a707fa2021-12-09 23:35:11 +090019 "sort"
Inseob Kim7e8bd1e2021-03-17 18:59:43 +090020 "strconv"
Inseob Kim0a707fa2021-12-09 23:35:11 +090021 "strings"
Inseob Kim7e8bd1e2021-03-17 18:59:43 +090022
23 "github.com/google/blueprint/proptools"
24
25 "android/soong/android"
26)
27
28const (
Inseob Kim7e8bd1e2021-03-17 18:59:43 +090029 MlsSens = 1
30 MlsCats = 1024
31 PolicyVers = 30
32)
33
Inseob Kim0a707fa2021-12-09 23:35:11 +090034// This order should be kept. checkpolicy syntax requires it.
35var policyConfOrder = []string{
36 "security_classes",
37 "initial_sids",
38 "access_vectors",
39 "global_macros",
40 "neverallow_macros",
41 "mls_macros",
42 "mls_decl",
43 "mls",
44 "policy_capabilities",
45 "te_macros",
Inseob Kim0a707fa2021-12-09 23:35:11 +090046 "ioctl_defines",
47 "ioctl_macros",
Inseob Kim1e796342022-06-09 11:26:35 +090048 "attributes|*.te",
Inseob Kim0a707fa2021-12-09 23:35:11 +090049 "roles_decl",
50 "roles",
51 "users",
52 "initial_sid_contexts",
53 "fs_use",
54 "genfs_contexts",
55 "port_contexts",
56}
57
Inseob Kim7e8bd1e2021-03-17 18:59:43 +090058func init() {
59 android.RegisterModuleType("se_policy_conf", policyConfFactory)
Inseob Kim6cd0ddd2023-10-25 23:48:16 +090060 android.RegisterModuleType("se_policy_conf_defaults", policyConfDefaultFactory)
Inseob Kimdf1a0de2021-03-17 19:05:02 +090061 android.RegisterModuleType("se_policy_cil", policyCilFactory)
Inseob Kimb9d05112021-09-27 13:13:46 +000062 android.RegisterModuleType("se_policy_binary", policyBinaryFactory)
Inseob Kim7e8bd1e2021-03-17 18:59:43 +090063}
64
65type policyConfProperties struct {
66 // Name of the output. Default is {module_name}
67 Stem *string
68
69 // Policy files to be compiled to cil file.
70 Srcs []string `android:"path"`
71
72 // Target build variant (user / userdebug / eng). Default follows the current lunch target
73 Build_variant *string
74
75 // Whether to exclude build test or not. Default is false
76 Exclude_build_test *bool
77
78 // Whether to include asan specific policies or not. Default follows the current lunch target
79 With_asan *bool
80
81 // Whether to build CTS specific policy or not. Default is false
82 Cts *bool
83
Inseob Kim5bbcd682021-12-28 14:57:03 +090084 // Whether to build recovery specific policy or not. Default is false
85 Target_recovery *bool
86
Inseob Kim7e8bd1e2021-03-17 18:59:43 +090087 // Whether this module is directly installable to one of the partitions. Default is true
88 Installable *bool
Inseob Kim6e384f32022-03-10 13:15:05 +090089
90 // Desired number of MLS categories. Defaults to 1024
91 Mls_cats *int64
Inseob Kim8697fc82024-04-16 14:45:32 +090092
Inseob Kim007f0ae2024-07-18 10:29:52 +090093 // Board api level of policy files. Set "vendor" for RELEASE_BOARD_API_LEVEL, "system" for
94 // turning off the guard, or a direct version string (e.g. "202404"). Defaults to "system"
95 Board_api_level *string
Inseob Kim7e8bd1e2021-03-17 18:59:43 +090096}
97
98type policyConf struct {
99 android.ModuleBase
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900100 android.DefaultableModuleBase
101 flaggableModuleBase
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900102
103 properties policyConfProperties
104
105 installSource android.Path
106 installPath android.InstallPath
107}
108
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900109var _ flaggableModule = (*policyConf)(nil)
110
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900111// se_policy_conf merges collection of policy files into a policy.conf file to be processed by
112// checkpolicy.
113func policyConfFactory() android.Module {
114 c := &policyConf{}
115 c.AddProperties(&c.properties)
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900116 initFlaggableModule(c)
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900117 android.InitAndroidArchModule(c, android.DeviceSupported, android.MultilibCommon)
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900118 android.InitDefaultableModule(c)
119 return c
120}
121
122type policyConfDefaults struct {
123 android.ModuleBase
124 android.DefaultsModuleBase
125}
126
127// se_policy_conf_defaults provides a set of properties that can be inherited by other
128// se_policy_conf_defaults modules. A module can use the properties from a se_policy_conf_defaults
129// using `defaults: ["<:default_module_name>"]`. Properties of both modules are merged (when
130// possible) by prepending the default module's values to the depending module's values.
131func policyConfDefaultFactory() android.Module {
132 c := &policyConfDefaults{}
133 c.AddProperties(
134 &policyConfProperties{},
Inseob Kimbf7f4a42024-02-14 13:53:39 +0900135 &flaggableModuleProperties{},
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900136 )
137 android.InitDefaultsModule(c)
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900138 return c
139}
140
141func (c *policyConf) installable() bool {
142 return proptools.BoolDefault(c.properties.Installable, true)
143}
144
145func (c *policyConf) stem() string {
146 return proptools.StringDefault(c.properties.Stem, c.Name())
147}
148
149func (c *policyConf) buildVariant(ctx android.ModuleContext) string {
150 if variant := proptools.String(c.properties.Build_variant); variant != "" {
151 return variant
152 }
153 if ctx.Config().Eng() {
154 return "eng"
155 }
156 if ctx.Config().Debuggable() {
157 return "userdebug"
158 }
159 return "user"
160}
161
162func (c *policyConf) cts() bool {
163 return proptools.Bool(c.properties.Cts)
164}
165
Inseob Kim5bbcd682021-12-28 14:57:03 +0900166func (c *policyConf) isTargetRecovery() bool {
167 return proptools.Bool(c.properties.Target_recovery)
168}
169
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900170func (c *policyConf) withAsan(ctx android.ModuleContext) string {
171 isAsanDevice := android.InList("address", ctx.Config().SanitizeDevice())
172 return strconv.FormatBool(proptools.BoolDefault(c.properties.With_asan, isAsanDevice))
173}
174
175func (c *policyConf) sepolicySplit(ctx android.ModuleContext) string {
176 if c.cts() {
177 return "cts"
178 }
Inseob Kim5bbcd682021-12-28 14:57:03 +0900179 if c.isTargetRecovery() {
180 return "false"
181 }
Steven Moreland721f5af2023-05-31 21:54:51 +0000182 return strconv.FormatBool(true)
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900183}
184
185func (c *policyConf) compatibleProperty(ctx android.ModuleContext) string {
186 if c.cts() {
187 return "cts"
188 }
Inseob Kim5bbcd682021-12-28 14:57:03 +0900189 if c.isTargetRecovery() {
190 return "false"
191 }
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900192 return "true"
193}
194
195func (c *policyConf) trebleSyspropNeverallow(ctx android.ModuleContext) string {
196 if c.cts() {
197 return "cts"
198 }
Inseob Kim5bbcd682021-12-28 14:57:03 +0900199 if c.isTargetRecovery() {
200 return "false"
201 }
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900202 return strconv.FormatBool(!ctx.DeviceConfig().BuildBrokenTrebleSyspropNeverallow())
203}
204
205func (c *policyConf) enforceSyspropOwner(ctx android.ModuleContext) string {
206 if c.cts() {
207 return "cts"
208 }
Inseob Kim5bbcd682021-12-28 14:57:03 +0900209 if c.isTargetRecovery() {
210 return "false"
211 }
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900212 return strconv.FormatBool(!ctx.DeviceConfig().BuildBrokenEnforceSyspropOwner())
213}
214
Hridya Valsarajua885dd82021-04-26 16:32:17 -0700215func (c *policyConf) enforceDebugfsRestrictions(ctx android.ModuleContext) string {
216 if c.cts() {
217 return "cts"
218 }
219 return strconv.FormatBool(ctx.DeviceConfig().BuildDebugfsRestrictionsEnabled())
220}
221
Inseob Kim6e384f32022-03-10 13:15:05 +0900222func (c *policyConf) mlsCats() int {
223 return proptools.IntDefault(c.properties.Mls_cats, MlsCats)
224}
225
Inseob Kim8697fc82024-04-16 14:45:32 +0900226func (c *policyConf) boardApiLevel(ctx android.ModuleContext) string {
Inseob Kim007f0ae2024-07-18 10:29:52 +0900227 level := proptools.StringDefault(c.properties.Board_api_level, "system")
228
229 if level == "system" {
230 // aribtrary value greater than any other vendor API levels
231 return "1000000"
232 } else if level == "vendor" {
Inseob Kim8697fc82024-04-16 14:45:32 +0900233 return ctx.Config().VendorApiLevel()
Inseob Kim007f0ae2024-07-18 10:29:52 +0900234 } else {
235 return level
Inseob Kim8697fc82024-04-16 14:45:32 +0900236 }
Inseob Kim007f0ae2024-07-18 10:29:52 +0900237
Inseob Kim8697fc82024-04-16 14:45:32 +0900238}
239
Inseob Kim0a707fa2021-12-09 23:35:11 +0900240func findPolicyConfOrder(name string) int {
241 for idx, pattern := range policyConfOrder {
Inseob Kim1e796342022-06-09 11:26:35 +0900242 // We could use regexp but it seems like an overkill
243 if pattern == "attributes|*.te" && (name == "attributes" || strings.HasSuffix(name, ".te")) {
244 return idx
245 } else if pattern == name {
Inseob Kim0a707fa2021-12-09 23:35:11 +0900246 return idx
247 }
248 }
249 // name is not matched
250 return len(policyConfOrder)
251}
252
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900253func (c *policyConf) transformPolicyToConf(ctx android.ModuleContext) android.OutputPath {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900254 conf := pathForModuleOut(ctx, c.stem())
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900255 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kim0a707fa2021-12-09 23:35:11 +0900256
257 srcs := android.PathsForModuleSrc(ctx, c.properties.Srcs)
258 sort.SliceStable(srcs, func(x, y int) bool {
259 return findPolicyConfOrder(srcs[x].Base()) < findPolicyConfOrder(srcs[y].Base())
260 })
261
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900262 flags := c.getBuildFlags(ctx)
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900263 rule.Command().Tool(ctx.Config().PrebuiltBuildTool(ctx, "m4")).
264 Flag("--fatal-warnings").
265 FlagForEachArg("-D ", ctx.DeviceConfig().SepolicyM4Defs()).
266 FlagWithArg("-D mls_num_sens=", strconv.Itoa(MlsSens)).
Inseob Kim6e384f32022-03-10 13:15:05 +0900267 FlagWithArg("-D mls_num_cats=", strconv.Itoa(c.mlsCats())).
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900268 FlagWithArg("-D target_arch=", ctx.DeviceConfig().DeviceArch()).
269 FlagWithArg("-D target_with_asan=", c.withAsan(ctx)).
Inseob Kim4360c192021-03-23 20:52:53 +0900270 FlagWithArg("-D target_with_dexpreopt=", strconv.FormatBool(ctx.DeviceConfig().WithDexpreopt())).
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900271 FlagWithArg("-D target_with_native_coverage=", strconv.FormatBool(ctx.DeviceConfig().ClangCoverageEnabled() || ctx.DeviceConfig().GcovCoverageEnabled())).
272 FlagWithArg("-D target_build_variant=", c.buildVariant(ctx)).
273 FlagWithArg("-D target_full_treble=", c.sepolicySplit(ctx)).
274 FlagWithArg("-D target_compatible_property=", c.compatibleProperty(ctx)).
275 FlagWithArg("-D target_treble_sysprop_neverallow=", c.trebleSyspropNeverallow(ctx)).
276 FlagWithArg("-D target_enforce_sysprop_owner=", c.enforceSyspropOwner(ctx)).
277 FlagWithArg("-D target_exclude_build_test=", strconv.FormatBool(proptools.Bool(c.properties.Exclude_build_test))).
278 FlagWithArg("-D target_requires_insecure_execmem_for_swiftshader=", strconv.FormatBool(ctx.DeviceConfig().RequiresInsecureExecmemForSwiftshader())).
Hridya Valsarajua885dd82021-04-26 16:32:17 -0700279 FlagWithArg("-D target_enforce_debugfs_restriction=", c.enforceDebugfsRestrictions(ctx)).
Inseob Kim5bbcd682021-12-28 14:57:03 +0900280 FlagWithArg("-D target_recovery=", strconv.FormatBool(c.isTargetRecovery())).
Inseob Kim8697fc82024-04-16 14:45:32 +0900281 FlagWithArg("-D target_board_api_level=", c.boardApiLevel(ctx)).
Inseob Kim6cd0ddd2023-10-25 23:48:16 +0900282 Flags(flagsToM4Macros(flags)).
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900283 Flag("-s").
Inseob Kim0a707fa2021-12-09 23:35:11 +0900284 Inputs(srcs).
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900285 Text("> ").Output(conf)
286
287 rule.Build("conf", "Transform policy to conf: "+ctx.ModuleName())
288 return conf
289}
290
Inseob Kimbf7f4a42024-02-14 13:53:39 +0900291func (c *policyConf) DepsMutator(ctx android.BottomUpMutatorContext) {
292 c.flagDeps(ctx)
293}
294
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900295func (c *policyConf) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900296 if !c.installable() {
297 c.SkipInstall()
298 }
Inseob Kim31db2742021-06-08 10:31:09 +0900299
300 c.installSource = c.transformPolicyToConf(ctx)
301 c.installPath = android.PathForModuleInstall(ctx, "etc")
302 ctx.InstallFile(c.installPath, c.stem(), c.installSource)
mrziwangcb3f5502024-06-06 10:04:23 -0700303
304 ctx.SetOutputFiles(android.Paths{c.installSource}, "")
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900305}
306
307func (c *policyConf) AndroidMkEntries() []android.AndroidMkEntries {
308 return []android.AndroidMkEntries{android.AndroidMkEntries{
309 OutputFile: android.OptionalPathForPath(c.installSource),
310 Class: "ETC",
311 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
312 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
313 entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !c.installable())
Colin Cross6c7f9372022-01-11 19:35:43 -0800314 entries.SetPath("LOCAL_MODULE_PATH", c.installPath)
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900315 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", c.stem())
316 },
317 },
318 }}
319}
320
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900321type policyCilProperties struct {
322 // Name of the output. Default is {module_name}
323 Stem *string
324
325 // Policy file to be compiled to cil file.
326 Src *string `android:"path"`
327
Sandro143988d2022-08-05 11:38:56 +0000328 // If true, the input policy file is a binary policy that will be decompiled to a cil file.
329 // Defaults to false.
330 Decompile_binary *bool
331
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900332 // Additional cil files to be added in the end of the output. This is to support workarounds
333 // which are not supported by the policy language.
334 Additional_cil_files []string `android:"path"`
335
336 // Cil files to be filtered out by the filter_out tool of "build_sepolicy". Used to build
337 // exported policies
338 Filter_out []string `android:"path"`
339
340 // Whether to remove line markers (denoted by ;;) out of compiled cil files. Defaults to false
341 Remove_line_marker *bool
342
343 // Whether to run secilc to check compiled policy or not. Defaults to true
344 Secilc_check *bool
345
346 // Whether to ignore neverallow when running secilc check. Defaults to
347 // SELINUX_IGNORE_NEVERALLOWS.
348 Ignore_neverallow *bool
349
350 // Whether this module is directly installable to one of the partitions. Default is true
351 Installable *bool
352}
353
354type policyCil struct {
355 android.ModuleBase
356
357 properties policyCilProperties
358
359 installSource android.Path
360 installPath android.InstallPath
361}
362
363// se_policy_cil compiles a policy.conf file to a cil file with checkpolicy, and optionally runs
364// secilc to check the output cil file. Affected by SELINUX_IGNORE_NEVERALLOWS.
365func policyCilFactory() android.Module {
366 c := &policyCil{}
367 c.AddProperties(&c.properties)
368 android.InitAndroidArchModule(c, android.DeviceSupported, android.MultilibCommon)
369 return c
370}
371
372func (c *policyCil) Installable() bool {
373 return proptools.BoolDefault(c.properties.Installable, true)
374}
375
376func (c *policyCil) stem() string {
377 return proptools.StringDefault(c.properties.Stem, c.Name())
378}
379
380func (c *policyCil) compileConfToCil(ctx android.ModuleContext, conf android.Path) android.OutputPath {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900381 cil := pathForModuleOut(ctx, c.stem())
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900382 rule := android.NewRuleBuilder(pctx, ctx)
Sandro143988d2022-08-05 11:38:56 +0000383 checkpolicyCmd := rule.Command().BuiltTool("checkpolicy").
Lokesh Gidra1269a172022-08-01 17:20:38 +0000384 Flag("-C"). // Write CIL
385 Flag("-M"). // Enable MLS
386 FlagWithArg("-c ", strconv.Itoa(PolicyVers)).
387 FlagWithOutput("-o ", cil).
388 Input(conf)
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900389
Sandro143988d2022-08-05 11:38:56 +0000390 if proptools.Bool(c.properties.Decompile_binary) {
391 checkpolicyCmd.Flag("-b") // Read binary
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900392 }
393
394 if len(c.properties.Filter_out) > 0 {
395 rule.Command().BuiltTool("build_sepolicy").
396 Text("filter_out").
397 Flag("-f").
398 Inputs(android.PathsForModuleSrc(ctx, c.properties.Filter_out)).
399 FlagWithOutput("-t ", cil)
400 }
401
Sandro143988d2022-08-05 11:38:56 +0000402 if len(c.properties.Additional_cil_files) > 0 {
403 rule.Command().Text("cat").
404 Inputs(android.PathsForModuleSrc(ctx, c.properties.Additional_cil_files)).
405 Text(">> ").Output(cil)
406 }
407
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900408 if proptools.Bool(c.properties.Remove_line_marker) {
409 rule.Command().Text("grep -v").
410 Text(proptools.ShellEscape(";;")).
411 Text(cil.String()).
412 Text(">").
413 Text(cil.String() + ".tmp").
414 Text("&& mv").
415 Text(cil.String() + ".tmp").
416 Text(cil.String())
417 }
418
419 if proptools.BoolDefault(c.properties.Secilc_check, true) {
420 secilcCmd := rule.Command().BuiltTool("secilc").
421 Flag("-m"). // Multiple decls
422 FlagWithArg("-M ", "true"). // Enable MLS
423 Flag("-G"). // expand and remove auto generated attributes
424 FlagWithArg("-c ", strconv.Itoa(PolicyVers)).
425 Inputs(android.PathsForModuleSrc(ctx, c.properties.Filter_out)). // Also add cil files which are filtered out
426 Text(cil.String()).
427 FlagWithArg("-o ", os.DevNull).
428 FlagWithArg("-f ", os.DevNull)
429
430 if proptools.BoolDefault(c.properties.Ignore_neverallow, ctx.Config().SelinuxIgnoreNeverallows()) {
431 secilcCmd.Flag("-N")
432 }
433 }
434
435 rule.Build("cil", "Building cil for "+ctx.ModuleName())
436 return cil
437}
438
439func (c *policyCil) GenerateAndroidBuildActions(ctx android.ModuleContext) {
440 if proptools.String(c.properties.Src) == "" {
441 ctx.PropertyErrorf("src", "must be specified")
442 return
443 }
444 conf := android.PathForModuleSrc(ctx, *c.properties.Src)
445 cil := c.compileConfToCil(ctx, conf)
446
Inseob Kim31db2742021-06-08 10:31:09 +0900447 if !c.Installable() {
448 c.SkipInstall()
449 }
450
Inseob Kim6cc75f42021-04-29 13:53:20 +0000451 if c.InstallInDebugRamdisk() {
452 // for userdebug_plat_sepolicy.cil
453 c.installPath = android.PathForModuleInstall(ctx)
454 } else {
455 c.installPath = android.PathForModuleInstall(ctx, "etc", "selinux")
456 }
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900457 c.installSource = cil
458 ctx.InstallFile(c.installPath, c.stem(), c.installSource)
mrziwangcb3f5502024-06-06 10:04:23 -0700459
460 ctx.SetOutputFiles(android.Paths{c.installSource}, "")
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900461}
462
463func (c *policyCil) AndroidMkEntries() []android.AndroidMkEntries {
464 return []android.AndroidMkEntries{android.AndroidMkEntries{
465 OutputFile: android.OptionalPathForPath(c.installSource),
466 Class: "ETC",
467 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
468 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
469 entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !c.Installable())
Colin Cross6c7f9372022-01-11 19:35:43 -0800470 entries.SetPath("LOCAL_MODULE_PATH", c.installPath)
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900471 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", c.stem())
472 },
473 },
474 }}
475}
476
Inseob Kimb9d05112021-09-27 13:13:46 +0000477type policyBinaryProperties struct {
478 // Name of the output. Default is {module_name}
479 Stem *string
480
481 // Cil files to be compiled.
482 Srcs []string `android:"path"`
483
484 // Whether to ignore neverallow when running secilc check. Defaults to
485 // SELINUX_IGNORE_NEVERALLOWS.
486 Ignore_neverallow *bool
487
488 // Whether this module is directly installable to one of the partitions. Default is true
489 Installable *bool
Jiyong Parkef567212022-12-05 14:06:47 +0900490
491 // List of domains that are allowed to be in permissive mode on user builds.
492 Permissive_domains_on_user_builds []string
Inseob Kimb9d05112021-09-27 13:13:46 +0000493}
494
495type policyBinary struct {
496 android.ModuleBase
497
498 properties policyBinaryProperties
499
500 installSource android.Path
501 installPath android.InstallPath
502}
503
504// se_policy_binary compiles cil files to a binary sepolicy file with secilc. Usually sources of
505// se_policy_binary come from outputs of se_policy_cil modules.
506func policyBinaryFactory() android.Module {
507 c := &policyBinary{}
508 c.AddProperties(&c.properties)
509 android.InitAndroidArchModule(c, android.DeviceSupported, android.MultilibCommon)
510 return c
511}
512
Inseob Kim5bbcd682021-12-28 14:57:03 +0900513func (c *policyBinary) InstallInRoot() bool {
514 return c.InstallInRecovery()
515}
516
Inseob Kimb9d05112021-09-27 13:13:46 +0000517func (c *policyBinary) Installable() bool {
518 return proptools.BoolDefault(c.properties.Installable, true)
519}
520
521func (c *policyBinary) stem() string {
522 return proptools.StringDefault(c.properties.Stem, c.Name())
523}
524
525func (c *policyBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
526 if len(c.properties.Srcs) == 0 {
527 ctx.PropertyErrorf("srcs", "must be specified")
528 return
529 }
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900530 bin := pathForModuleOut(ctx, c.stem()+"_policy")
Inseob Kimb9d05112021-09-27 13:13:46 +0000531 rule := android.NewRuleBuilder(pctx, ctx)
532 secilcCmd := rule.Command().BuiltTool("secilc").
533 Flag("-m"). // Multiple decls
534 FlagWithArg("-M ", "true"). // Enable MLS
535 Flag("-G"). // expand and remove auto generated attributes
536 FlagWithArg("-c ", strconv.Itoa(PolicyVers)).
537 Inputs(android.PathsForModuleSrc(ctx, c.properties.Srcs)).
538 FlagWithOutput("-o ", bin).
539 FlagWithArg("-f ", os.DevNull)
540
541 if proptools.BoolDefault(c.properties.Ignore_neverallow, ctx.Config().SelinuxIgnoreNeverallows()) {
542 secilcCmd.Flag("-N")
543 }
Inseob Kim3d5f9252021-12-21 20:42:35 +0900544 rule.Temporary(bin)
Inseob Kimb9d05112021-09-27 13:13:46 +0000545
Inseob Kim3d5f9252021-12-21 20:42:35 +0900546 // permissive check is performed only in user build (not debuggable).
547 if !ctx.Config().Debuggable() {
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900548 permissiveDomains := pathForModuleOut(ctx, c.stem()+"_permissive")
Jiyong Parkef567212022-12-05 14:06:47 +0900549 cmd := rule.Command().BuiltTool("sepolicy-analyze").
Inseob Kim3d5f9252021-12-21 20:42:35 +0900550 Input(bin).
Jiyong Parkef567212022-12-05 14:06:47 +0900551 Text("permissive")
552 // Filter-out domains listed in permissive_domains_on_user_builds
553 allowedDomains := c.properties.Permissive_domains_on_user_builds
554 if len(allowedDomains) != 0 {
555 cmd.Text("| { grep -Fxv")
556 for _, d := range allowedDomains {
557 cmd.FlagWithArg("-e ", proptools.ShellEscape(d))
558 }
559 cmd.Text(" || true; }") // no match doesn't fail the cmd
560 }
561 cmd.Text(" > ").Output(permissiveDomains)
Inseob Kim3d5f9252021-12-21 20:42:35 +0900562 rule.Temporary(permissiveDomains)
563
564 msg := `==========\n` +
565 `ERROR: permissive domains not allowed in user builds\n` +
566 `List of invalid domains:`
567
568 rule.Command().Text("if test").
569 FlagWithInput("-s ", permissiveDomains).
570 Text("; then echo").
571 Flag("-e").
572 Text(`"` + msg + `"`).
573 Text("&& cat ").
574 Input(permissiveDomains).
575 Text("; exit 1; fi")
576 }
577
Inseob Kim6c6f53b2023-04-26 11:03:35 +0900578 out := pathForModuleOut(ctx, c.stem())
Inseob Kim3d5f9252021-12-21 20:42:35 +0900579 rule.Command().Text("cp").
580 Flag("-f").
581 Input(bin).
582 Output(out)
583
584 rule.DeleteTemporaryFiles()
Inseob Kimb9d05112021-09-27 13:13:46 +0000585 rule.Build("secilc", "Compiling cil files for "+ctx.ModuleName())
586
587 if !c.Installable() {
588 c.SkipInstall()
589 }
590
Inseob Kim5bbcd682021-12-28 14:57:03 +0900591 if c.InstallInRecovery() {
592 // install in root
593 c.installPath = android.PathForModuleInstall(ctx)
594 } else {
595 c.installPath = android.PathForModuleInstall(ctx, "etc", "selinux")
596 }
Inseob Kim3d5f9252021-12-21 20:42:35 +0900597 c.installSource = out
Inseob Kimb9d05112021-09-27 13:13:46 +0000598 ctx.InstallFile(c.installPath, c.stem(), c.installSource)
mrziwangcb3f5502024-06-06 10:04:23 -0700599
600 ctx.SetOutputFiles(android.Paths{c.installSource}, "")
Inseob Kimb9d05112021-09-27 13:13:46 +0000601}
602
603func (c *policyBinary) AndroidMkEntries() []android.AndroidMkEntries {
604 return []android.AndroidMkEntries{android.AndroidMkEntries{
605 OutputFile: android.OptionalPathForPath(c.installSource),
606 Class: "ETC",
607 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
608 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
609 entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !c.Installable())
Colin Cross6c7f9372022-01-11 19:35:43 -0800610 entries.SetPath("LOCAL_MODULE_PATH", c.installPath)
Inseob Kimb9d05112021-09-27 13:13:46 +0000611 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", c.stem())
612 },
613 },
614 }}
615}