blob: 390c4399c0ab9bd7a2a3e0964ad2b02ca88ca8f3 [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"
Inseob Kim0a707fa2021-12-09 23:35:11 +090020 "sort"
Inseob Kim7e8bd1e2021-03-17 18:59:43 +090021 "strconv"
Inseob Kim0a707fa2021-12-09 23:35:11 +090022 "strings"
Inseob Kim7e8bd1e2021-03-17 18:59:43 +090023
24 "github.com/google/blueprint/proptools"
25
26 "android/soong/android"
27)
28
29const (
30 // TODO: sync with Android.mk
31 MlsSens = 1
32 MlsCats = 1024
33 PolicyVers = 30
34)
35
Inseob Kim0a707fa2021-12-09 23:35:11 +090036// This order should be kept. checkpolicy syntax requires it.
37var policyConfOrder = []string{
38 "security_classes",
39 "initial_sids",
40 "access_vectors",
41 "global_macros",
42 "neverallow_macros",
43 "mls_macros",
44 "mls_decl",
45 "mls",
46 "policy_capabilities",
47 "te_macros",
48 "attributes",
49 "ioctl_defines",
50 "ioctl_macros",
51 "*.te",
52 "roles_decl",
53 "roles",
54 "users",
55 "initial_sid_contexts",
56 "fs_use",
57 "genfs_contexts",
58 "port_contexts",
59}
60
Inseob Kim7e8bd1e2021-03-17 18:59:43 +090061func init() {
62 android.RegisterModuleType("se_policy_conf", policyConfFactory)
Inseob Kimdf1a0de2021-03-17 19:05:02 +090063 android.RegisterModuleType("se_policy_cil", policyCilFactory)
Inseob Kimb9d05112021-09-27 13:13:46 +000064 android.RegisterModuleType("se_policy_binary", policyBinaryFactory)
Inseob Kim7e8bd1e2021-03-17 18:59:43 +090065}
66
67type policyConfProperties struct {
68 // Name of the output. Default is {module_name}
69 Stem *string
70
71 // Policy files to be compiled to cil file.
72 Srcs []string `android:"path"`
73
74 // Target build variant (user / userdebug / eng). Default follows the current lunch target
75 Build_variant *string
76
77 // Whether to exclude build test or not. Default is false
78 Exclude_build_test *bool
79
80 // Whether to include asan specific policies or not. Default follows the current lunch target
81 With_asan *bool
82
83 // Whether to build CTS specific policy or not. Default is false
84 Cts *bool
85
Inseob Kim5bbcd682021-12-28 14:57:03 +090086 // Whether to build recovery specific policy or not. Default is false
87 Target_recovery *bool
88
Inseob Kim7e8bd1e2021-03-17 18:59:43 +090089 // Whether this module is directly installable to one of the partitions. Default is true
90 Installable *bool
91}
92
93type policyConf struct {
94 android.ModuleBase
95
96 properties policyConfProperties
97
98 installSource android.Path
99 installPath android.InstallPath
100}
101
102// se_policy_conf merges collection of policy files into a policy.conf file to be processed by
103// checkpolicy.
104func policyConfFactory() android.Module {
105 c := &policyConf{}
106 c.AddProperties(&c.properties)
107 android.InitAndroidArchModule(c, android.DeviceSupported, android.MultilibCommon)
108 return c
109}
110
111func (c *policyConf) installable() bool {
112 return proptools.BoolDefault(c.properties.Installable, true)
113}
114
115func (c *policyConf) stem() string {
116 return proptools.StringDefault(c.properties.Stem, c.Name())
117}
118
119func (c *policyConf) buildVariant(ctx android.ModuleContext) string {
120 if variant := proptools.String(c.properties.Build_variant); variant != "" {
121 return variant
122 }
123 if ctx.Config().Eng() {
124 return "eng"
125 }
126 if ctx.Config().Debuggable() {
127 return "userdebug"
128 }
129 return "user"
130}
131
132func (c *policyConf) cts() bool {
133 return proptools.Bool(c.properties.Cts)
134}
135
Inseob Kim5bbcd682021-12-28 14:57:03 +0900136func (c *policyConf) isTargetRecovery() bool {
137 return proptools.Bool(c.properties.Target_recovery)
138}
139
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900140func (c *policyConf) withAsan(ctx android.ModuleContext) string {
141 isAsanDevice := android.InList("address", ctx.Config().SanitizeDevice())
142 return strconv.FormatBool(proptools.BoolDefault(c.properties.With_asan, isAsanDevice))
143}
144
145func (c *policyConf) sepolicySplit(ctx android.ModuleContext) string {
146 if c.cts() {
147 return "cts"
148 }
Inseob Kim5bbcd682021-12-28 14:57:03 +0900149 if c.isTargetRecovery() {
150 return "false"
151 }
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900152 return strconv.FormatBool(ctx.DeviceConfig().SepolicySplit())
153}
154
155func (c *policyConf) compatibleProperty(ctx android.ModuleContext) string {
156 if c.cts() {
157 return "cts"
158 }
Inseob Kim5bbcd682021-12-28 14:57:03 +0900159 if c.isTargetRecovery() {
160 return "false"
161 }
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900162 return "true"
163}
164
165func (c *policyConf) trebleSyspropNeverallow(ctx android.ModuleContext) string {
166 if c.cts() {
167 return "cts"
168 }
Inseob Kim5bbcd682021-12-28 14:57:03 +0900169 if c.isTargetRecovery() {
170 return "false"
171 }
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900172 return strconv.FormatBool(!ctx.DeviceConfig().BuildBrokenTrebleSyspropNeverallow())
173}
174
175func (c *policyConf) enforceSyspropOwner(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 }
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900182 return strconv.FormatBool(!ctx.DeviceConfig().BuildBrokenEnforceSyspropOwner())
183}
184
Hridya Valsarajua885dd82021-04-26 16:32:17 -0700185func (c *policyConf) enforceDebugfsRestrictions(ctx android.ModuleContext) string {
186 if c.cts() {
187 return "cts"
188 }
189 return strconv.FormatBool(ctx.DeviceConfig().BuildDebugfsRestrictionsEnabled())
190}
191
Inseob Kim0a707fa2021-12-09 23:35:11 +0900192func findPolicyConfOrder(name string) int {
193 for idx, pattern := range policyConfOrder {
194 if pattern == name || (pattern == "*.te" && strings.HasSuffix(name, ".te")) {
195 return idx
196 }
197 }
198 // name is not matched
199 return len(policyConfOrder)
200}
201
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900202func (c *policyConf) transformPolicyToConf(ctx android.ModuleContext) android.OutputPath {
Inseob Kim6c5fa542022-02-09 23:27:04 +0900203 conf := android.PathForModuleOut(ctx, c.stem()).OutputPath
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900204 rule := android.NewRuleBuilder(pctx, ctx)
Inseob Kim0a707fa2021-12-09 23:35:11 +0900205
206 srcs := android.PathsForModuleSrc(ctx, c.properties.Srcs)
207 sort.SliceStable(srcs, func(x, y int) bool {
208 return findPolicyConfOrder(srcs[x].Base()) < findPolicyConfOrder(srcs[y].Base())
209 })
210
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900211 rule.Command().Tool(ctx.Config().PrebuiltBuildTool(ctx, "m4")).
212 Flag("--fatal-warnings").
213 FlagForEachArg("-D ", ctx.DeviceConfig().SepolicyM4Defs()).
214 FlagWithArg("-D mls_num_sens=", strconv.Itoa(MlsSens)).
215 FlagWithArg("-D mls_num_cats=", strconv.Itoa(MlsCats)).
216 FlagWithArg("-D target_arch=", ctx.DeviceConfig().DeviceArch()).
217 FlagWithArg("-D target_with_asan=", c.withAsan(ctx)).
Inseob Kim4360c192021-03-23 20:52:53 +0900218 FlagWithArg("-D target_with_dexpreopt=", strconv.FormatBool(ctx.DeviceConfig().WithDexpreopt())).
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900219 FlagWithArg("-D target_with_native_coverage=", strconv.FormatBool(ctx.DeviceConfig().ClangCoverageEnabled() || ctx.DeviceConfig().GcovCoverageEnabled())).
220 FlagWithArg("-D target_build_variant=", c.buildVariant(ctx)).
221 FlagWithArg("-D target_full_treble=", c.sepolicySplit(ctx)).
222 FlagWithArg("-D target_compatible_property=", c.compatibleProperty(ctx)).
223 FlagWithArg("-D target_treble_sysprop_neverallow=", c.trebleSyspropNeverallow(ctx)).
224 FlagWithArg("-D target_enforce_sysprop_owner=", c.enforceSyspropOwner(ctx)).
225 FlagWithArg("-D target_exclude_build_test=", strconv.FormatBool(proptools.Bool(c.properties.Exclude_build_test))).
226 FlagWithArg("-D target_requires_insecure_execmem_for_swiftshader=", strconv.FormatBool(ctx.DeviceConfig().RequiresInsecureExecmemForSwiftshader())).
Hridya Valsarajua885dd82021-04-26 16:32:17 -0700227 FlagWithArg("-D target_enforce_debugfs_restriction=", c.enforceDebugfsRestrictions(ctx)).
Inseob Kim5bbcd682021-12-28 14:57:03 +0900228 FlagWithArg("-D target_recovery=", strconv.FormatBool(c.isTargetRecovery())).
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900229 Flag("-s").
Inseob Kim0a707fa2021-12-09 23:35:11 +0900230 Inputs(srcs).
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900231 Text("> ").Output(conf)
232
233 rule.Build("conf", "Transform policy to conf: "+ctx.ModuleName())
234 return conf
235}
236
237func (c *policyConf) DepsMutator(ctx android.BottomUpMutatorContext) {
238 // do nothing
239}
240
241func (c *policyConf) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900242 if !c.installable() {
243 c.SkipInstall()
244 }
Inseob Kim31db2742021-06-08 10:31:09 +0900245
246 c.installSource = c.transformPolicyToConf(ctx)
247 c.installPath = android.PathForModuleInstall(ctx, "etc")
248 ctx.InstallFile(c.installPath, c.stem(), c.installSource)
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900249}
250
251func (c *policyConf) AndroidMkEntries() []android.AndroidMkEntries {
252 return []android.AndroidMkEntries{android.AndroidMkEntries{
253 OutputFile: android.OptionalPathForPath(c.installSource),
254 Class: "ETC",
255 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
256 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
257 entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !c.installable())
Colin Cross6c7f9372022-01-11 19:35:43 -0800258 entries.SetPath("LOCAL_MODULE_PATH", c.installPath)
Inseob Kim7e8bd1e2021-03-17 18:59:43 +0900259 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", c.stem())
260 },
261 },
262 }}
263}
264
265func (c *policyConf) OutputFiles(tag string) (android.Paths, error) {
266 if tag == "" {
267 return android.Paths{c.installSource}, nil
268 }
269 return nil, fmt.Errorf("Unknown tag %q", tag)
270}
271
272var _ android.OutputFileProducer = (*policyConf)(nil)
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900273
274type policyCilProperties struct {
275 // Name of the output. Default is {module_name}
276 Stem *string
277
278 // Policy file to be compiled to cil file.
279 Src *string `android:"path"`
280
281 // Additional cil files to be added in the end of the output. This is to support workarounds
282 // which are not supported by the policy language.
283 Additional_cil_files []string `android:"path"`
284
285 // Cil files to be filtered out by the filter_out tool of "build_sepolicy". Used to build
286 // exported policies
287 Filter_out []string `android:"path"`
288
289 // Whether to remove line markers (denoted by ;;) out of compiled cil files. Defaults to false
290 Remove_line_marker *bool
291
292 // Whether to run secilc to check compiled policy or not. Defaults to true
293 Secilc_check *bool
294
295 // Whether to ignore neverallow when running secilc check. Defaults to
296 // SELINUX_IGNORE_NEVERALLOWS.
297 Ignore_neverallow *bool
298
299 // Whether this module is directly installable to one of the partitions. Default is true
300 Installable *bool
301}
302
303type policyCil struct {
304 android.ModuleBase
305
306 properties policyCilProperties
307
308 installSource android.Path
309 installPath android.InstallPath
310}
311
312// se_policy_cil compiles a policy.conf file to a cil file with checkpolicy, and optionally runs
313// secilc to check the output cil file. Affected by SELINUX_IGNORE_NEVERALLOWS.
314func policyCilFactory() android.Module {
315 c := &policyCil{}
316 c.AddProperties(&c.properties)
317 android.InitAndroidArchModule(c, android.DeviceSupported, android.MultilibCommon)
318 return c
319}
320
321func (c *policyCil) Installable() bool {
322 return proptools.BoolDefault(c.properties.Installable, true)
323}
324
325func (c *policyCil) stem() string {
326 return proptools.StringDefault(c.properties.Stem, c.Name())
327}
328
329func (c *policyCil) compileConfToCil(ctx android.ModuleContext, conf android.Path) android.OutputPath {
330 cil := android.PathForModuleOut(ctx, c.stem()).OutputPath
331 rule := android.NewRuleBuilder(pctx, ctx)
332 rule.Command().BuiltTool("checkpolicy").
333 Flag("-C"). // Write CIL
334 Flag("-M"). // Enable MLS
335 FlagWithArg("-c ", strconv.Itoa(PolicyVers)).
336 FlagWithOutput("-o ", cil).
337 Input(conf)
338
339 if len(c.properties.Additional_cil_files) > 0 {
340 rule.Command().Text("cat").
341 Inputs(android.PathsForModuleSrc(ctx, c.properties.Additional_cil_files)).
342 Text(">> ").Output(cil)
343 }
344
345 if len(c.properties.Filter_out) > 0 {
346 rule.Command().BuiltTool("build_sepolicy").
347 Text("filter_out").
348 Flag("-f").
349 Inputs(android.PathsForModuleSrc(ctx, c.properties.Filter_out)).
350 FlagWithOutput("-t ", cil)
351 }
352
353 if proptools.Bool(c.properties.Remove_line_marker) {
354 rule.Command().Text("grep -v").
355 Text(proptools.ShellEscape(";;")).
356 Text(cil.String()).
357 Text(">").
358 Text(cil.String() + ".tmp").
359 Text("&& mv").
360 Text(cil.String() + ".tmp").
361 Text(cil.String())
362 }
363
364 if proptools.BoolDefault(c.properties.Secilc_check, true) {
365 secilcCmd := rule.Command().BuiltTool("secilc").
366 Flag("-m"). // Multiple decls
367 FlagWithArg("-M ", "true"). // Enable MLS
368 Flag("-G"). // expand and remove auto generated attributes
369 FlagWithArg("-c ", strconv.Itoa(PolicyVers)).
370 Inputs(android.PathsForModuleSrc(ctx, c.properties.Filter_out)). // Also add cil files which are filtered out
371 Text(cil.String()).
372 FlagWithArg("-o ", os.DevNull).
373 FlagWithArg("-f ", os.DevNull)
374
375 if proptools.BoolDefault(c.properties.Ignore_neverallow, ctx.Config().SelinuxIgnoreNeverallows()) {
376 secilcCmd.Flag("-N")
377 }
378 }
379
380 rule.Build("cil", "Building cil for "+ctx.ModuleName())
381 return cil
382}
383
384func (c *policyCil) GenerateAndroidBuildActions(ctx android.ModuleContext) {
385 if proptools.String(c.properties.Src) == "" {
386 ctx.PropertyErrorf("src", "must be specified")
387 return
388 }
389 conf := android.PathForModuleSrc(ctx, *c.properties.Src)
390 cil := c.compileConfToCil(ctx, conf)
391
Inseob Kim31db2742021-06-08 10:31:09 +0900392 if !c.Installable() {
393 c.SkipInstall()
394 }
395
Inseob Kim6cc75f42021-04-29 13:53:20 +0000396 if c.InstallInDebugRamdisk() {
397 // for userdebug_plat_sepolicy.cil
398 c.installPath = android.PathForModuleInstall(ctx)
399 } else {
400 c.installPath = android.PathForModuleInstall(ctx, "etc", "selinux")
401 }
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900402 c.installSource = cil
403 ctx.InstallFile(c.installPath, c.stem(), c.installSource)
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900404}
405
406func (c *policyCil) AndroidMkEntries() []android.AndroidMkEntries {
407 return []android.AndroidMkEntries{android.AndroidMkEntries{
408 OutputFile: android.OptionalPathForPath(c.installSource),
409 Class: "ETC",
410 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
411 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
412 entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !c.Installable())
Colin Cross6c7f9372022-01-11 19:35:43 -0800413 entries.SetPath("LOCAL_MODULE_PATH", c.installPath)
Inseob Kimdf1a0de2021-03-17 19:05:02 +0900414 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", c.stem())
415 },
416 },
417 }}
418}
419
420func (c *policyCil) OutputFiles(tag string) (android.Paths, error) {
421 if tag == "" {
422 return android.Paths{c.installSource}, nil
423 }
424 return nil, fmt.Errorf("Unknown tag %q", tag)
425}
426
427var _ android.OutputFileProducer = (*policyCil)(nil)
Inseob Kimb9d05112021-09-27 13:13:46 +0000428
429type policyBinaryProperties struct {
430 // Name of the output. Default is {module_name}
431 Stem *string
432
433 // Cil files to be compiled.
434 Srcs []string `android:"path"`
435
436 // Whether to ignore neverallow when running secilc check. Defaults to
437 // SELINUX_IGNORE_NEVERALLOWS.
438 Ignore_neverallow *bool
439
440 // Whether this module is directly installable to one of the partitions. Default is true
441 Installable *bool
442}
443
444type policyBinary struct {
445 android.ModuleBase
446
447 properties policyBinaryProperties
448
449 installSource android.Path
450 installPath android.InstallPath
451}
452
453// se_policy_binary compiles cil files to a binary sepolicy file with secilc. Usually sources of
454// se_policy_binary come from outputs of se_policy_cil modules.
455func policyBinaryFactory() android.Module {
456 c := &policyBinary{}
457 c.AddProperties(&c.properties)
458 android.InitAndroidArchModule(c, android.DeviceSupported, android.MultilibCommon)
459 return c
460}
461
Inseob Kim5bbcd682021-12-28 14:57:03 +0900462func (c *policyBinary) InstallInRoot() bool {
463 return c.InstallInRecovery()
464}
465
Inseob Kimb9d05112021-09-27 13:13:46 +0000466func (c *policyBinary) Installable() bool {
467 return proptools.BoolDefault(c.properties.Installable, true)
468}
469
470func (c *policyBinary) stem() string {
471 return proptools.StringDefault(c.properties.Stem, c.Name())
472}
473
474func (c *policyBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
475 if len(c.properties.Srcs) == 0 {
476 ctx.PropertyErrorf("srcs", "must be specified")
477 return
478 }
Inseob Kim3d5f9252021-12-21 20:42:35 +0900479 bin := android.PathForModuleOut(ctx, c.stem()+"_policy")
Inseob Kimb9d05112021-09-27 13:13:46 +0000480 rule := android.NewRuleBuilder(pctx, ctx)
481 secilcCmd := rule.Command().BuiltTool("secilc").
482 Flag("-m"). // Multiple decls
483 FlagWithArg("-M ", "true"). // Enable MLS
484 Flag("-G"). // expand and remove auto generated attributes
485 FlagWithArg("-c ", strconv.Itoa(PolicyVers)).
486 Inputs(android.PathsForModuleSrc(ctx, c.properties.Srcs)).
487 FlagWithOutput("-o ", bin).
488 FlagWithArg("-f ", os.DevNull)
489
490 if proptools.BoolDefault(c.properties.Ignore_neverallow, ctx.Config().SelinuxIgnoreNeverallows()) {
491 secilcCmd.Flag("-N")
492 }
Inseob Kim3d5f9252021-12-21 20:42:35 +0900493 rule.Temporary(bin)
Inseob Kimb9d05112021-09-27 13:13:46 +0000494
Inseob Kim3d5f9252021-12-21 20:42:35 +0900495 // permissive check is performed only in user build (not debuggable).
496 if !ctx.Config().Debuggable() {
497 permissiveDomains := android.PathForModuleOut(ctx, c.stem()+"_permissive")
498 rule.Command().BuiltTool("sepolicy-analyze").
499 Input(bin).
500 Text("permissive").
501 Text(" > ").
502 Output(permissiveDomains)
503 rule.Temporary(permissiveDomains)
504
505 msg := `==========\n` +
506 `ERROR: permissive domains not allowed in user builds\n` +
507 `List of invalid domains:`
508
509 rule.Command().Text("if test").
510 FlagWithInput("-s ", permissiveDomains).
511 Text("; then echo").
512 Flag("-e").
513 Text(`"` + msg + `"`).
514 Text("&& cat ").
515 Input(permissiveDomains).
516 Text("; exit 1; fi")
517 }
518
519 out := android.PathForModuleOut(ctx, c.stem())
520 rule.Command().Text("cp").
521 Flag("-f").
522 Input(bin).
523 Output(out)
524
525 rule.DeleteTemporaryFiles()
Inseob Kimb9d05112021-09-27 13:13:46 +0000526 rule.Build("secilc", "Compiling cil files for "+ctx.ModuleName())
527
528 if !c.Installable() {
529 c.SkipInstall()
530 }
531
Inseob Kim5bbcd682021-12-28 14:57:03 +0900532 if c.InstallInRecovery() {
533 // install in root
534 c.installPath = android.PathForModuleInstall(ctx)
535 } else {
536 c.installPath = android.PathForModuleInstall(ctx, "etc", "selinux")
537 }
Inseob Kim3d5f9252021-12-21 20:42:35 +0900538 c.installSource = out
Inseob Kimb9d05112021-09-27 13:13:46 +0000539 ctx.InstallFile(c.installPath, c.stem(), c.installSource)
540}
541
542func (c *policyBinary) AndroidMkEntries() []android.AndroidMkEntries {
543 return []android.AndroidMkEntries{android.AndroidMkEntries{
544 OutputFile: android.OptionalPathForPath(c.installSource),
545 Class: "ETC",
546 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
547 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
548 entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !c.Installable())
Colin Cross6c7f9372022-01-11 19:35:43 -0800549 entries.SetPath("LOCAL_MODULE_PATH", c.installPath)
Inseob Kimb9d05112021-09-27 13:13:46 +0000550 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", c.stem())
551 },
552 },
553 }}
554}
555
556func (c *policyBinary) OutputFiles(tag string) (android.Paths, error) {
557 if tag == "" {
558 return android.Paths{c.installSource}, nil
559 }
560 return nil, fmt.Errorf("Unknown tag %q", tag)
561}
562
563var _ android.OutputFileProducer = (*policyBinary)(nil)