blob: 604014fc10d9a2e65ecf6777a93cb6e51abf9a52 [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 Kim7e8bd1e2021-03-17 18:59:43 +090037}
38
39type policyConfProperties struct {
40 // Name of the output. Default is {module_name}
41 Stem *string
42
43 // Policy files to be compiled to cil file.
44 Srcs []string `android:"path"`
45
46 // Target build variant (user / userdebug / eng). Default follows the current lunch target
47 Build_variant *string
48
49 // Whether to exclude build test or not. Default is false
50 Exclude_build_test *bool
51
52 // Whether to include asan specific policies or not. Default follows the current lunch target
53 With_asan *bool
54
55 // Whether to build CTS specific policy or not. Default is false
56 Cts *bool
57
58 // Whether this module is directly installable to one of the partitions. Default is true
59 Installable *bool
60}
61
62type policyConf struct {
63 android.ModuleBase
64
65 properties policyConfProperties
66
67 installSource android.Path
68 installPath android.InstallPath
69}
70
71// se_policy_conf merges collection of policy files into a policy.conf file to be processed by
72// checkpolicy.
73func policyConfFactory() android.Module {
74 c := &policyConf{}
75 c.AddProperties(&c.properties)
76 android.InitAndroidArchModule(c, android.DeviceSupported, android.MultilibCommon)
77 return c
78}
79
80func (c *policyConf) installable() bool {
81 return proptools.BoolDefault(c.properties.Installable, true)
82}
83
84func (c *policyConf) stem() string {
85 return proptools.StringDefault(c.properties.Stem, c.Name())
86}
87
88func (c *policyConf) buildVariant(ctx android.ModuleContext) string {
89 if variant := proptools.String(c.properties.Build_variant); variant != "" {
90 return variant
91 }
92 if ctx.Config().Eng() {
93 return "eng"
94 }
95 if ctx.Config().Debuggable() {
96 return "userdebug"
97 }
98 return "user"
99}
100
101func (c *policyConf) cts() bool {
102 return proptools.Bool(c.properties.Cts)
103}
104
105func (c *policyConf) withAsan(ctx android.ModuleContext) string {
106 isAsanDevice := android.InList("address", ctx.Config().SanitizeDevice())
107 return strconv.FormatBool(proptools.BoolDefault(c.properties.With_asan, isAsanDevice))
108}
109
110func (c *policyConf) sepolicySplit(ctx android.ModuleContext) string {
111 if c.cts() {
112 return "cts"
113 }
114 return strconv.FormatBool(ctx.DeviceConfig().SepolicySplit())
115}
116
117func (c *policyConf) compatibleProperty(ctx android.ModuleContext) string {
118 if c.cts() {
119 return "cts"
120 }
121 return "true"
122}
123
124func (c *policyConf) trebleSyspropNeverallow(ctx android.ModuleContext) string {
125 if c.cts() {
126 return "cts"
127 }
128 return strconv.FormatBool(!ctx.DeviceConfig().BuildBrokenTrebleSyspropNeverallow())
129}
130
131func (c *policyConf) enforceSyspropOwner(ctx android.ModuleContext) string {
132 if c.cts() {
133 return "cts"
134 }
135 return strconv.FormatBool(!ctx.DeviceConfig().BuildBrokenEnforceSyspropOwner())
136}
137
Hridya Valsarajua885dd82021-04-26 16:32:17 -0700138func (c *policyConf) enforceDebugfsRestrictions(ctx android.ModuleContext) string {
139 if c.cts() {
140 return "cts"
141 }
142 return strconv.FormatBool(ctx.DeviceConfig().BuildDebugfsRestrictionsEnabled())
143}
144
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900145func (c *policyConf) transformPolicyToConf(ctx android.ModuleContext) android.OutputPath {
146 conf := android.PathForModuleOut(ctx, "conf").OutputPath
147 rule := android.NewRuleBuilder(pctx, ctx)
148 rule.Command().Tool(ctx.Config().PrebuiltBuildTool(ctx, "m4")).
149 Flag("--fatal-warnings").
150 FlagForEachArg("-D ", ctx.DeviceConfig().SepolicyM4Defs()).
151 FlagWithArg("-D mls_num_sens=", strconv.Itoa(MlsSens)).
152 FlagWithArg("-D mls_num_cats=", strconv.Itoa(MlsCats)).
153 FlagWithArg("-D target_arch=", ctx.DeviceConfig().DeviceArch()).
154 FlagWithArg("-D target_with_asan=", c.withAsan(ctx)).
Inseob Kim4360c192021-03-23 20:52:53 +0900155 FlagWithArg("-D target_with_dexpreopt=", strconv.FormatBool(ctx.DeviceConfig().WithDexpreopt())).
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900156 FlagWithArg("-D target_with_native_coverage=", strconv.FormatBool(ctx.DeviceConfig().ClangCoverageEnabled() || ctx.DeviceConfig().GcovCoverageEnabled())).
157 FlagWithArg("-D target_build_variant=", c.buildVariant(ctx)).
158 FlagWithArg("-D target_full_treble=", c.sepolicySplit(ctx)).
159 FlagWithArg("-D target_compatible_property=", c.compatibleProperty(ctx)).
160 FlagWithArg("-D target_treble_sysprop_neverallow=", c.trebleSyspropNeverallow(ctx)).
161 FlagWithArg("-D target_enforce_sysprop_owner=", c.enforceSyspropOwner(ctx)).
162 FlagWithArg("-D target_exclude_build_test=", strconv.FormatBool(proptools.Bool(c.properties.Exclude_build_test))).
163 FlagWithArg("-D target_requires_insecure_execmem_for_swiftshader=", strconv.FormatBool(ctx.DeviceConfig().RequiresInsecureExecmemForSwiftshader())).
Hridya Valsarajua885dd82021-04-26 16:32:17 -0700164 FlagWithArg("-D target_enforce_debugfs_restriction=", c.enforceDebugfsRestrictions(ctx)).
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900165 Flag("-s").
166 Inputs(android.PathsForModuleSrc(ctx, c.properties.Srcs)).
167 Text("> ").Output(conf)
168
169 rule.Build("conf", "Transform policy to conf: "+ctx.ModuleName())
170 return conf
171}
172
173func (c *policyConf) DepsMutator(ctx android.BottomUpMutatorContext) {
174 // do nothing
175}
176
177func (c *policyConf) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900178 if !c.installable() {
179 c.SkipInstall()
180 }
Inseob Kim31db2742021-06-08 10:31:09 +0900181
182 c.installSource = c.transformPolicyToConf(ctx)
183 c.installPath = android.PathForModuleInstall(ctx, "etc")
184 ctx.InstallFile(c.installPath, c.stem(), c.installSource)
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900185}
186
187func (c *policyConf) AndroidMkEntries() []android.AndroidMkEntries {
188 return []android.AndroidMkEntries{android.AndroidMkEntries{
189 OutputFile: android.OptionalPathForPath(c.installSource),
190 Class: "ETC",
191 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
192 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
193 entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !c.installable())
194 entries.SetPath("LOCAL_MODULE_PATH", c.installPath.ToMakePath())
195 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", c.stem())
196 },
197 },
198 }}
199}
200
201func (c *policyConf) OutputFiles(tag string) (android.Paths, error) {
202 if tag == "" {
203 return android.Paths{c.installSource}, nil
204 }
205 return nil, fmt.Errorf("Unknown tag %q", tag)
206}
207
208var _ android.OutputFileProducer = (*policyConf)(nil)
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900209
210type policyCilProperties struct {
211 // Name of the output. Default is {module_name}
212 Stem *string
213
214 // Policy file to be compiled to cil file.
215 Src *string `android:"path"`
216
217 // Additional cil files to be added in the end of the output. This is to support workarounds
218 // which are not supported by the policy language.
219 Additional_cil_files []string `android:"path"`
220
221 // Cil files to be filtered out by the filter_out tool of "build_sepolicy". Used to build
222 // exported policies
223 Filter_out []string `android:"path"`
224
225 // Whether to remove line markers (denoted by ;;) out of compiled cil files. Defaults to false
226 Remove_line_marker *bool
227
228 // Whether to run secilc to check compiled policy or not. Defaults to true
229 Secilc_check *bool
230
231 // Whether to ignore neverallow when running secilc check. Defaults to
232 // SELINUX_IGNORE_NEVERALLOWS.
233 Ignore_neverallow *bool
234
235 // Whether this module is directly installable to one of the partitions. Default is true
236 Installable *bool
237}
238
239type policyCil struct {
240 android.ModuleBase
241
242 properties policyCilProperties
243
244 installSource android.Path
245 installPath android.InstallPath
246}
247
248// se_policy_cil compiles a policy.conf file to a cil file with checkpolicy, and optionally runs
249// secilc to check the output cil file. Affected by SELINUX_IGNORE_NEVERALLOWS.
250func policyCilFactory() android.Module {
251 c := &policyCil{}
252 c.AddProperties(&c.properties)
253 android.InitAndroidArchModule(c, android.DeviceSupported, android.MultilibCommon)
254 return c
255}
256
257func (c *policyCil) Installable() bool {
258 return proptools.BoolDefault(c.properties.Installable, true)
259}
260
261func (c *policyCil) stem() string {
262 return proptools.StringDefault(c.properties.Stem, c.Name())
263}
264
265func (c *policyCil) compileConfToCil(ctx android.ModuleContext, conf android.Path) android.OutputPath {
266 cil := android.PathForModuleOut(ctx, c.stem()).OutputPath
267 rule := android.NewRuleBuilder(pctx, ctx)
268 rule.Command().BuiltTool("checkpolicy").
269 Flag("-C"). // Write CIL
270 Flag("-M"). // Enable MLS
271 FlagWithArg("-c ", strconv.Itoa(PolicyVers)).
272 FlagWithOutput("-o ", cil).
273 Input(conf)
274
275 if len(c.properties.Additional_cil_files) > 0 {
276 rule.Command().Text("cat").
277 Inputs(android.PathsForModuleSrc(ctx, c.properties.Additional_cil_files)).
278 Text(">> ").Output(cil)
279 }
280
281 if len(c.properties.Filter_out) > 0 {
282 rule.Command().BuiltTool("build_sepolicy").
283 Text("filter_out").
284 Flag("-f").
285 Inputs(android.PathsForModuleSrc(ctx, c.properties.Filter_out)).
286 FlagWithOutput("-t ", cil)
287 }
288
289 if proptools.Bool(c.properties.Remove_line_marker) {
290 rule.Command().Text("grep -v").
291 Text(proptools.ShellEscape(";;")).
292 Text(cil.String()).
293 Text(">").
294 Text(cil.String() + ".tmp").
295 Text("&& mv").
296 Text(cil.String() + ".tmp").
297 Text(cil.String())
298 }
299
300 if proptools.BoolDefault(c.properties.Secilc_check, true) {
301 secilcCmd := rule.Command().BuiltTool("secilc").
302 Flag("-m"). // Multiple decls
303 FlagWithArg("-M ", "true"). // Enable MLS
304 Flag("-G"). // expand and remove auto generated attributes
305 FlagWithArg("-c ", strconv.Itoa(PolicyVers)).
306 Inputs(android.PathsForModuleSrc(ctx, c.properties.Filter_out)). // Also add cil files which are filtered out
307 Text(cil.String()).
308 FlagWithArg("-o ", os.DevNull).
309 FlagWithArg("-f ", os.DevNull)
310
311 if proptools.BoolDefault(c.properties.Ignore_neverallow, ctx.Config().SelinuxIgnoreNeverallows()) {
312 secilcCmd.Flag("-N")
313 }
314 }
315
316 rule.Build("cil", "Building cil for "+ctx.ModuleName())
317 return cil
318}
319
320func (c *policyCil) GenerateAndroidBuildActions(ctx android.ModuleContext) {
321 if proptools.String(c.properties.Src) == "" {
322 ctx.PropertyErrorf("src", "must be specified")
323 return
324 }
325 conf := android.PathForModuleSrc(ctx, *c.properties.Src)
326 cil := c.compileConfToCil(ctx, conf)
327
Inseob Kim31db2742021-06-08 10:31:09 +0900328 if !c.Installable() {
329 c.SkipInstall()
330 }
331
Inseob Kim6cc75f42021-04-29 13:53:20 +0000332 if c.InstallInDebugRamdisk() {
333 // for userdebug_plat_sepolicy.cil
334 c.installPath = android.PathForModuleInstall(ctx)
335 } else {
336 c.installPath = android.PathForModuleInstall(ctx, "etc", "selinux")
337 }
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900338 c.installSource = cil
339 ctx.InstallFile(c.installPath, c.stem(), c.installSource)
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900340}
341
342func (c *policyCil) AndroidMkEntries() []android.AndroidMkEntries {
343 return []android.AndroidMkEntries{android.AndroidMkEntries{
344 OutputFile: android.OptionalPathForPath(c.installSource),
345 Class: "ETC",
346 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
347 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
348 entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !c.Installable())
349 entries.SetPath("LOCAL_MODULE_PATH", c.installPath.ToMakePath())
350 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", c.stem())
351 },
352 },
353 }}
354}
355
356func (c *policyCil) OutputFiles(tag string) (android.Paths, error) {
357 if tag == "" {
358 return android.Paths{c.installSource}, nil
359 }
360 return nil, fmt.Errorf("Unknown tag %q", tag)
361}
362
363var _ android.OutputFileProducer = (*policyCil)(nil)