blob: 82fabe371878b22f1d390557939a68f3181f5d87 [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 (
18 "fmt"
19 "os"
20 "strconv"
21
22 "github.com/google/blueprint/proptools"
23
24 "android/soong/android"
25)
26
27const (
28 // TODO: sync with Android.mk
29 MlsSens = 1
30 MlsCats = 1024
31 PolicyVers = 30
32)
33
34func init() {
35 android.RegisterModuleType("se_policy_conf", policyConfFactory)
Inseob Kimdf1a0de2021-03-17 19:05:02 +090036 android.RegisterModuleType("se_policy_cil", policyCilFactory)
Inseob Kimb9d05112021-09-27 13:13:46 +000037 android.RegisterModuleType("se_policy_binary", policyBinaryFactory)
Inseob Kim7e8bd1e2021-03-17 18:59:43 +090038}
39
40type policyConfProperties struct {
41 // Name of the output. Default is {module_name}
42 Stem *string
43
44 // Policy files to be compiled to cil file.
45 Srcs []string `android:"path"`
46
47 // Target build variant (user / userdebug / eng). Default follows the current lunch target
48 Build_variant *string
49
50 // Whether to exclude build test or not. Default is false
51 Exclude_build_test *bool
52
53 // Whether to include asan specific policies or not. Default follows the current lunch target
54 With_asan *bool
55
56 // Whether to build CTS specific policy or not. Default is false
57 Cts *bool
58
59 // Whether this module is directly installable to one of the partitions. Default is true
60 Installable *bool
61}
62
63type policyConf struct {
64 android.ModuleBase
65
66 properties policyConfProperties
67
68 installSource android.Path
69 installPath android.InstallPath
70}
71
72// se_policy_conf merges collection of policy files into a policy.conf file to be processed by
73// checkpolicy.
74func policyConfFactory() android.Module {
75 c := &policyConf{}
76 c.AddProperties(&c.properties)
77 android.InitAndroidArchModule(c, android.DeviceSupported, android.MultilibCommon)
78 return c
79}
80
81func (c *policyConf) installable() bool {
82 return proptools.BoolDefault(c.properties.Installable, true)
83}
84
85func (c *policyConf) stem() string {
86 return proptools.StringDefault(c.properties.Stem, c.Name())
87}
88
89func (c *policyConf) buildVariant(ctx android.ModuleContext) string {
90 if variant := proptools.String(c.properties.Build_variant); variant != "" {
91 return variant
92 }
93 if ctx.Config().Eng() {
94 return "eng"
95 }
96 if ctx.Config().Debuggable() {
97 return "userdebug"
98 }
99 return "user"
100}
101
102func (c *policyConf) cts() bool {
103 return proptools.Bool(c.properties.Cts)
104}
105
106func (c *policyConf) withAsan(ctx android.ModuleContext) string {
107 isAsanDevice := android.InList("address", ctx.Config().SanitizeDevice())
108 return strconv.FormatBool(proptools.BoolDefault(c.properties.With_asan, isAsanDevice))
109}
110
111func (c *policyConf) sepolicySplit(ctx android.ModuleContext) string {
112 if c.cts() {
113 return "cts"
114 }
115 return strconv.FormatBool(ctx.DeviceConfig().SepolicySplit())
116}
117
118func (c *policyConf) compatibleProperty(ctx android.ModuleContext) string {
119 if c.cts() {
120 return "cts"
121 }
122 return "true"
123}
124
125func (c *policyConf) trebleSyspropNeverallow(ctx android.ModuleContext) string {
126 if c.cts() {
127 return "cts"
128 }
129 return strconv.FormatBool(!ctx.DeviceConfig().BuildBrokenTrebleSyspropNeverallow())
130}
131
132func (c *policyConf) enforceSyspropOwner(ctx android.ModuleContext) string {
133 if c.cts() {
134 return "cts"
135 }
136 return strconv.FormatBool(!ctx.DeviceConfig().BuildBrokenEnforceSyspropOwner())
137}
138
Hridya Valsarajua885dd82021-04-26 16:32:17 -0700139func (c *policyConf) enforceDebugfsRestrictions(ctx android.ModuleContext) string {
140 if c.cts() {
141 return "cts"
142 }
143 return strconv.FormatBool(ctx.DeviceConfig().BuildDebugfsRestrictionsEnabled())
144}
145
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900146func (c *policyConf) transformPolicyToConf(ctx android.ModuleContext) android.OutputPath {
147 conf := android.PathForModuleOut(ctx, "conf").OutputPath
148 rule := android.NewRuleBuilder(pctx, ctx)
149 rule.Command().Tool(ctx.Config().PrebuiltBuildTool(ctx, "m4")).
150 Flag("--fatal-warnings").
151 FlagForEachArg("-D ", ctx.DeviceConfig().SepolicyM4Defs()).
152 FlagWithArg("-D mls_num_sens=", strconv.Itoa(MlsSens)).
153 FlagWithArg("-D mls_num_cats=", strconv.Itoa(MlsCats)).
154 FlagWithArg("-D target_arch=", ctx.DeviceConfig().DeviceArch()).
155 FlagWithArg("-D target_with_asan=", c.withAsan(ctx)).
Inseob Kim4360c192021-03-23 20:52:53 +0900156 FlagWithArg("-D target_with_dexpreopt=", strconv.FormatBool(ctx.DeviceConfig().WithDexpreopt())).
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900157 FlagWithArg("-D target_with_native_coverage=", strconv.FormatBool(ctx.DeviceConfig().ClangCoverageEnabled() || ctx.DeviceConfig().GcovCoverageEnabled())).
158 FlagWithArg("-D target_build_variant=", c.buildVariant(ctx)).
159 FlagWithArg("-D target_full_treble=", c.sepolicySplit(ctx)).
160 FlagWithArg("-D target_compatible_property=", c.compatibleProperty(ctx)).
161 FlagWithArg("-D target_treble_sysprop_neverallow=", c.trebleSyspropNeverallow(ctx)).
162 FlagWithArg("-D target_enforce_sysprop_owner=", c.enforceSyspropOwner(ctx)).
163 FlagWithArg("-D target_exclude_build_test=", strconv.FormatBool(proptools.Bool(c.properties.Exclude_build_test))).
164 FlagWithArg("-D target_requires_insecure_execmem_for_swiftshader=", strconv.FormatBool(ctx.DeviceConfig().RequiresInsecureExecmemForSwiftshader())).
Hridya Valsarajua885dd82021-04-26 16:32:17 -0700165 FlagWithArg("-D target_enforce_debugfs_restriction=", c.enforceDebugfsRestrictions(ctx)).
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900166 Flag("-s").
167 Inputs(android.PathsForModuleSrc(ctx, c.properties.Srcs)).
168 Text("> ").Output(conf)
169
170 rule.Build("conf", "Transform policy to conf: "+ctx.ModuleName())
171 return conf
172}
173
174func (c *policyConf) DepsMutator(ctx android.BottomUpMutatorContext) {
175 // do nothing
176}
177
178func (c *policyConf) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900179 if !c.installable() {
180 c.SkipInstall()
181 }
Inseob Kim31db2742021-06-08 10:31:09 +0900182
183 c.installSource = c.transformPolicyToConf(ctx)
184 c.installPath = android.PathForModuleInstall(ctx, "etc")
185 ctx.InstallFile(c.installPath, c.stem(), c.installSource)
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900186}
187
188func (c *policyConf) AndroidMkEntries() []android.AndroidMkEntries {
189 return []android.AndroidMkEntries{android.AndroidMkEntries{
190 OutputFile: android.OptionalPathForPath(c.installSource),
191 Class: "ETC",
192 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
193 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
194 entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !c.installable())
195 entries.SetPath("LOCAL_MODULE_PATH", c.installPath.ToMakePath())
196 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", c.stem())
197 },
198 },
199 }}
200}
201
202func (c *policyConf) OutputFiles(tag string) (android.Paths, error) {
203 if tag == "" {
204 return android.Paths{c.installSource}, nil
205 }
206 return nil, fmt.Errorf("Unknown tag %q", tag)
207}
208
209var _ android.OutputFileProducer = (*policyConf)(nil)
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900210
211type policyCilProperties struct {
212 // Name of the output. Default is {module_name}
213 Stem *string
214
215 // Policy file to be compiled to cil file.
216 Src *string `android:"path"`
217
218 // Additional cil files to be added in the end of the output. This is to support workarounds
219 // which are not supported by the policy language.
220 Additional_cil_files []string `android:"path"`
221
222 // Cil files to be filtered out by the filter_out tool of "build_sepolicy". Used to build
223 // exported policies
224 Filter_out []string `android:"path"`
225
226 // Whether to remove line markers (denoted by ;;) out of compiled cil files. Defaults to false
227 Remove_line_marker *bool
228
229 // Whether to run secilc to check compiled policy or not. Defaults to true
230 Secilc_check *bool
231
232 // Whether to ignore neverallow when running secilc check. Defaults to
233 // SELINUX_IGNORE_NEVERALLOWS.
234 Ignore_neverallow *bool
235
236 // Whether this module is directly installable to one of the partitions. Default is true
237 Installable *bool
238}
239
240type policyCil struct {
241 android.ModuleBase
242
243 properties policyCilProperties
244
245 installSource android.Path
246 installPath android.InstallPath
247}
248
249// se_policy_cil compiles a policy.conf file to a cil file with checkpolicy, and optionally runs
250// secilc to check the output cil file. Affected by SELINUX_IGNORE_NEVERALLOWS.
251func policyCilFactory() android.Module {
252 c := &policyCil{}
253 c.AddProperties(&c.properties)
254 android.InitAndroidArchModule(c, android.DeviceSupported, android.MultilibCommon)
255 return c
256}
257
258func (c *policyCil) Installable() bool {
259 return proptools.BoolDefault(c.properties.Installable, true)
260}
261
262func (c *policyCil) stem() string {
263 return proptools.StringDefault(c.properties.Stem, c.Name())
264}
265
266func (c *policyCil) compileConfToCil(ctx android.ModuleContext, conf android.Path) android.OutputPath {
267 cil := android.PathForModuleOut(ctx, c.stem()).OutputPath
268 rule := android.NewRuleBuilder(pctx, ctx)
269 rule.Command().BuiltTool("checkpolicy").
270 Flag("-C"). // Write CIL
271 Flag("-M"). // Enable MLS
272 FlagWithArg("-c ", strconv.Itoa(PolicyVers)).
273 FlagWithOutput("-o ", cil).
274 Input(conf)
275
276 if len(c.properties.Additional_cil_files) > 0 {
277 rule.Command().Text("cat").
278 Inputs(android.PathsForModuleSrc(ctx, c.properties.Additional_cil_files)).
279 Text(">> ").Output(cil)
280 }
281
282 if len(c.properties.Filter_out) > 0 {
283 rule.Command().BuiltTool("build_sepolicy").
284 Text("filter_out").
285 Flag("-f").
286 Inputs(android.PathsForModuleSrc(ctx, c.properties.Filter_out)).
287 FlagWithOutput("-t ", cil)
288 }
289
290 if proptools.Bool(c.properties.Remove_line_marker) {
291 rule.Command().Text("grep -v").
292 Text(proptools.ShellEscape(";;")).
293 Text(cil.String()).
294 Text(">").
295 Text(cil.String() + ".tmp").
296 Text("&& mv").
297 Text(cil.String() + ".tmp").
298 Text(cil.String())
299 }
300
301 if proptools.BoolDefault(c.properties.Secilc_check, true) {
302 secilcCmd := rule.Command().BuiltTool("secilc").
303 Flag("-m"). // Multiple decls
304 FlagWithArg("-M ", "true"). // Enable MLS
305 Flag("-G"). // expand and remove auto generated attributes
306 FlagWithArg("-c ", strconv.Itoa(PolicyVers)).
307 Inputs(android.PathsForModuleSrc(ctx, c.properties.Filter_out)). // Also add cil files which are filtered out
308 Text(cil.String()).
309 FlagWithArg("-o ", os.DevNull).
310 FlagWithArg("-f ", os.DevNull)
311
312 if proptools.BoolDefault(c.properties.Ignore_neverallow, ctx.Config().SelinuxIgnoreNeverallows()) {
313 secilcCmd.Flag("-N")
314 }
315 }
316
317 rule.Build("cil", "Building cil for "+ctx.ModuleName())
318 return cil
319}
320
321func (c *policyCil) GenerateAndroidBuildActions(ctx android.ModuleContext) {
322 if proptools.String(c.properties.Src) == "" {
323 ctx.PropertyErrorf("src", "must be specified")
324 return
325 }
326 conf := android.PathForModuleSrc(ctx, *c.properties.Src)
327 cil := c.compileConfToCil(ctx, conf)
328
Inseob Kim31db2742021-06-08 10:31:09 +0900329 if !c.Installable() {
330 c.SkipInstall()
331 }
332
Inseob Kim6cc75f42021-04-29 13:53:20 +0000333 if c.InstallInDebugRamdisk() {
334 // for userdebug_plat_sepolicy.cil
335 c.installPath = android.PathForModuleInstall(ctx)
336 } else {
337 c.installPath = android.PathForModuleInstall(ctx, "etc", "selinux")
338 }
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900339 c.installSource = cil
340 ctx.InstallFile(c.installPath, c.stem(), c.installSource)
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900341}
342
343func (c *policyCil) AndroidMkEntries() []android.AndroidMkEntries {
344 return []android.AndroidMkEntries{android.AndroidMkEntries{
345 OutputFile: android.OptionalPathForPath(c.installSource),
346 Class: "ETC",
347 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
348 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
349 entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !c.Installable())
350 entries.SetPath("LOCAL_MODULE_PATH", c.installPath.ToMakePath())
351 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", c.stem())
352 },
353 },
354 }}
355}
356
357func (c *policyCil) OutputFiles(tag string) (android.Paths, error) {
358 if tag == "" {
359 return android.Paths{c.installSource}, nil
360 }
361 return nil, fmt.Errorf("Unknown tag %q", tag)
362}
363
364var _ android.OutputFileProducer = (*policyCil)(nil)
Inseob Kimb9d05112021-09-27 13:13:46 +0000365
366type policyBinaryProperties struct {
367 // Name of the output. Default is {module_name}
368 Stem *string
369
370 // Cil files to be compiled.
371 Srcs []string `android:"path"`
372
373 // Whether to ignore neverallow when running secilc check. Defaults to
374 // SELINUX_IGNORE_NEVERALLOWS.
375 Ignore_neverallow *bool
376
377 // Whether this module is directly installable to one of the partitions. Default is true
378 Installable *bool
379}
380
381type policyBinary struct {
382 android.ModuleBase
383
384 properties policyBinaryProperties
385
386 installSource android.Path
387 installPath android.InstallPath
388}
389
390// se_policy_binary compiles cil files to a binary sepolicy file with secilc. Usually sources of
391// se_policy_binary come from outputs of se_policy_cil modules.
392func policyBinaryFactory() android.Module {
393 c := &policyBinary{}
394 c.AddProperties(&c.properties)
395 android.InitAndroidArchModule(c, android.DeviceSupported, android.MultilibCommon)
396 return c
397}
398
399func (c *policyBinary) Installable() bool {
400 return proptools.BoolDefault(c.properties.Installable, true)
401}
402
403func (c *policyBinary) stem() string {
404 return proptools.StringDefault(c.properties.Stem, c.Name())
405}
406
407func (c *policyBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
408 if len(c.properties.Srcs) == 0 {
409 ctx.PropertyErrorf("srcs", "must be specified")
410 return
411 }
412 bin := android.PathForModuleOut(ctx, c.stem()).OutputPath
413 rule := android.NewRuleBuilder(pctx, ctx)
414 secilcCmd := rule.Command().BuiltTool("secilc").
415 Flag("-m"). // Multiple decls
416 FlagWithArg("-M ", "true"). // Enable MLS
417 Flag("-G"). // expand and remove auto generated attributes
418 FlagWithArg("-c ", strconv.Itoa(PolicyVers)).
419 Inputs(android.PathsForModuleSrc(ctx, c.properties.Srcs)).
420 FlagWithOutput("-o ", bin).
421 FlagWithArg("-f ", os.DevNull)
422
423 if proptools.BoolDefault(c.properties.Ignore_neverallow, ctx.Config().SelinuxIgnoreNeverallows()) {
424 secilcCmd.Flag("-N")
425 }
426
427 rule.Build("secilc", "Compiling cil files for "+ctx.ModuleName())
428
429 if !c.Installable() {
430 c.SkipInstall()
431 }
432
433 c.installPath = android.PathForModuleInstall(ctx, "etc", "selinux")
434 c.installSource = bin
435 ctx.InstallFile(c.installPath, c.stem(), c.installSource)
436}
437
438func (c *policyBinary) AndroidMkEntries() []android.AndroidMkEntries {
439 return []android.AndroidMkEntries{android.AndroidMkEntries{
440 OutputFile: android.OptionalPathForPath(c.installSource),
441 Class: "ETC",
442 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
443 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
444 entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !c.Installable())
445 entries.SetPath("LOCAL_MODULE_PATH", c.installPath.ToMakePath())
446 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", c.stem())
447 },
448 },
449 }}
450}
451
452func (c *policyBinary) OutputFiles(tag string) (android.Paths, error) {
453 if tag == "" {
454 return android.Paths{c.installSource}, nil
455 }
456 return nil, fmt.Errorf("Unknown tag %q", tag)
457}
458
459var _ android.OutputFileProducer = (*policyBinary)(nil)