blob: 1f7901b6c4961ab9feaea8c5ddcb5430da389b4c [file] [log] [blame]
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +08001// Copyright 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 Kim16d3be32022-01-07 09:15:27 +090018 "fmt"
19
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080020 "github.com/google/blueprint/proptools"
21
22 "android/soong/android"
23)
24
Inseob Kim16d3be32022-01-07 09:15:27 +090025var (
26 compatTestDepTag = dependencyTag{name: "compat_test"}
27)
28
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080029func init() {
Inseob Kim16d3be32022-01-07 09:15:27 +090030 ctx := android.InitRegistrationContext
31 ctx.RegisterModuleType("se_compat_cil", compatCilFactory)
LaMont Jones3ee89842023-05-16 16:59:17 +000032 ctx.RegisterParallelSingletonModuleType("se_compat_test", compatTestFactory)
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080033}
34
35// se_compat_cil collects and installs backwards compatibility cil files.
36func compatCilFactory() android.Module {
37 c := &compatCil{}
38 c.AddProperties(&c.properties)
39 android.InitAndroidArchModule(c, android.DeviceSupported, android.MultilibCommon)
40 return c
41}
42
43type compatCil struct {
44 android.ModuleBase
45 properties compatCilProperties
Inseob Kim61d6beb2023-08-23 08:37:20 +000046 installSource android.OptionalPath
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080047 installPath android.InstallPath
48}
49
50type compatCilProperties struct {
Inseob Kim41964032022-04-22 07:50:22 +090051 // List of source files. Can reference se_build_files type modules with the ":module" syntax.
Paul Duffin532bde12021-07-09 22:53:03 +010052 Srcs []string `android:"path"`
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080053
54 // Output file name. Defaults to module name if unspecified.
55 Stem *string
Inseob Kim61d6beb2023-08-23 08:37:20 +000056
57 // Target version that this module supports. This module will be ignored if platform sepolicy
58 // version is same as this module's version.
59 Version *string
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080060}
61
62func (c *compatCil) stem() string {
63 return proptools.StringDefault(c.properties.Stem, c.Name())
64}
65
66func (c *compatCil) expandSeSources(ctx android.ModuleContext) android.Paths {
Inseob Kim41964032022-04-22 07:50:22 +090067 return android.PathsForModuleSrc(ctx, c.properties.Srcs)
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080068}
69
Inseob Kim61d6beb2023-08-23 08:37:20 +000070func (c *compatCil) shouldSkipBuild(ctx android.ModuleContext) bool {
71 return proptools.String(c.properties.Version) == ctx.DeviceConfig().PlatformSepolicyVersion()
72}
73
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080074func (c *compatCil) GenerateAndroidBuildActions(ctx android.ModuleContext) {
75 if c.ProductSpecific() || c.SocSpecific() || c.DeviceSpecific() {
76 ctx.ModuleErrorf("Compat cil files only support system and system_ext partitions")
77 }
78
Inseob Kim61d6beb2023-08-23 08:37:20 +000079 if c.shouldSkipBuild(ctx) {
80 return
81 }
82
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080083 srcPaths := c.expandSeSources(ctx)
84 out := android.PathForModuleGen(ctx, c.Name())
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080085 ctx.Build(pctx, android.BuildParams{
86 Rule: android.Cat,
87 Inputs: srcPaths,
88 Output: out,
89 Description: "Combining compat cil for " + c.Name(),
90 })
91
92 c.installPath = android.PathForModuleInstall(ctx, "etc", "selinux", "mapping")
Inseob Kim61d6beb2023-08-23 08:37:20 +000093 c.installSource = android.OptionalPathForPath(out)
94 ctx.InstallFile(c.installPath, c.stem(), out)
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +080095}
96
97func (c *compatCil) AndroidMkEntries() []android.AndroidMkEntries {
Inseob Kim61d6beb2023-08-23 08:37:20 +000098 if !c.installSource.Valid() {
99 return nil
100 }
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +0800101 return []android.AndroidMkEntries{android.AndroidMkEntries{
102 Class: "ETC",
Inseob Kim61d6beb2023-08-23 08:37:20 +0000103 OutputFile: c.installSource,
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +0800104 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
105 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
Colin Cross6c7f9372022-01-11 19:35:43 -0800106 entries.SetPath("LOCAL_MODULE_PATH", c.installPath)
Yi-Yo Chiang41c34d62021-04-13 02:44:41 +0800107 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", c.stem())
108 },
109 },
110 }}
111}
Inseob Kim16d3be32022-01-07 09:15:27 +0900112
113func (c *compatCil) OutputFiles(tag string) (android.Paths, error) {
114 switch tag {
115 case "":
Inseob Kim61d6beb2023-08-23 08:37:20 +0000116 if c.installSource.Valid() {
117 return android.Paths{c.installSource.Path()}, nil
118 } else {
119 return nil, nil
120 }
Inseob Kim16d3be32022-01-07 09:15:27 +0900121 default:
122 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
123 }
124}
125
126var _ android.OutputFileProducer = (*compatCil)(nil)
127
128// se_compat_test checks if compat files ({ver}.cil, {ver}.compat.cil) files are compatible with
129// current policy.
130func compatTestFactory() android.SingletonModule {
131 f := &compatTestModule{}
132 android.InitAndroidModule(f)
133 android.AddLoadHook(f, func(ctx android.LoadHookContext) {
134 f.loadHook(ctx)
135 })
136 return f
137}
138
139type compatTestModule struct {
140 android.SingletonModuleBase
141
142 compatTestTimestamp android.ModuleOutPath
143}
144
145func (f *compatTestModule) createPlatPubVersionedModule(ctx android.LoadHookContext, ver string) {
146 confName := fmt.Sprintf("pub_policy_%s.conf", ver)
147 cilName := fmt.Sprintf("pub_policy_%s.cil", ver)
148 platPubVersionedName := fmt.Sprintf("plat_pub_versioned_%s.cil", ver)
149
150 ctx.CreateModule(policyConfFactory, &nameProperties{
151 Name: proptools.StringPtr(confName),
152 }, &policyConfProperties{
153 Srcs: []string{
154 fmt.Sprintf(":se_build_files{.plat_public_%s}", ver),
Inseob Kim73f43ff2022-02-14 23:01:04 +0900155 fmt.Sprintf(":se_build_files{.system_ext_public_%s}", ver),
156 fmt.Sprintf(":se_build_files{.product_public_%s}", ver),
Inseob Kim16d3be32022-01-07 09:15:27 +0900157 ":se_build_files{.reqd_mask}",
158 },
159 Installable: proptools.BoolPtr(false),
160 })
161
162 ctx.CreateModule(policyCilFactory, &nameProperties{
163 Name: proptools.StringPtr(cilName),
164 }, &policyCilProperties{
165 Src: proptools.StringPtr(":" + confName),
166 Filter_out: []string{":reqd_policy_mask.cil"},
167 Secilc_check: proptools.BoolPtr(false),
168 Installable: proptools.BoolPtr(false),
169 })
170
171 ctx.CreateModule(versionedPolicyFactory, &nameProperties{
172 Name: proptools.StringPtr(platPubVersionedName),
173 }, &versionedPolicyProperties{
174 Base: proptools.StringPtr(":" + cilName),
175 Target_policy: proptools.StringPtr(":" + cilName),
176 Version: proptools.StringPtr(ver),
177 Installable: proptools.BoolPtr(false),
178 })
179}
180
181func (f *compatTestModule) createCompatTestModule(ctx android.LoadHookContext, ver string) {
182 srcs := []string{
183 ":plat_sepolicy.cil",
184 ":system_ext_sepolicy.cil",
185 ":product_sepolicy.cil",
186 fmt.Sprintf(":plat_%s.cil", ver),
187 fmt.Sprintf(":%s.compat.cil", ver),
188 fmt.Sprintf(":system_ext_%s.cil", ver),
189 fmt.Sprintf(":system_ext_%s.compat.cil", ver),
190 fmt.Sprintf(":product_%s.cil", ver),
191 }
192
193 if ver == ctx.DeviceConfig().BoardSepolicyVers() {
194 srcs = append(srcs,
195 ":plat_pub_versioned.cil",
196 ":vendor_sepolicy.cil",
197 ":odm_sepolicy.cil",
198 )
199 } else {
200 srcs = append(srcs, fmt.Sprintf(":plat_pub_versioned_%s.cil", ver))
201 }
202
203 compatTestName := fmt.Sprintf("%s_compat_test", ver)
204 ctx.CreateModule(policyBinaryFactory, &nameProperties{
205 Name: proptools.StringPtr(compatTestName),
206 }, &policyBinaryProperties{
207 Srcs: srcs,
208 Ignore_neverallow: proptools.BoolPtr(true),
209 Installable: proptools.BoolPtr(false),
210 })
211}
212
213func (f *compatTestModule) loadHook(ctx android.LoadHookContext) {
214 for _, ver := range ctx.DeviceConfig().PlatformSepolicyCompatVersions() {
215 f.createPlatPubVersionedModule(ctx, ver)
216 f.createCompatTestModule(ctx, ver)
217 }
218}
219
220func (f *compatTestModule) DepsMutator(ctx android.BottomUpMutatorContext) {
221 for _, ver := range ctx.DeviceConfig().PlatformSepolicyCompatVersions() {
222 ctx.AddDependency(f, compatTestDepTag, fmt.Sprintf("%s_compat_test", ver))
223 }
224}
225
226func (f *compatTestModule) GenerateSingletonBuildActions(ctx android.SingletonContext) {
227 // does nothing; se_compat_test is a singeton because two compat test modules don't make sense.
228}
229
230func (f *compatTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
231 var inputs android.Paths
232 ctx.VisitDirectDepsWithTag(compatTestDepTag, func(child android.Module) {
233 o, ok := child.(android.OutputFileProducer)
234 if !ok {
235 panic(fmt.Errorf("Module %q should be an OutputFileProducer but it isn't", ctx.OtherModuleName(child)))
236 }
237
238 outputs, err := o.OutputFiles("")
239 if err != nil {
240 panic(fmt.Errorf("Module %q error while producing output: %v", ctx.OtherModuleName(child), err))
241 }
242 if len(outputs) != 1 {
243 panic(fmt.Errorf("Module %q should produce exactly one output, but did %q", ctx.OtherModuleName(child), outputs.Strings()))
244 }
245
246 inputs = append(inputs, outputs[0])
247 })
248
249 f.compatTestTimestamp = android.PathForModuleOut(ctx, "timestamp")
250 rule := android.NewRuleBuilder(pctx, ctx)
251 rule.Command().Text("touch").Output(f.compatTestTimestamp).Implicits(inputs)
252 rule.Build("compat", "compat test timestamp for: "+f.Name())
253}
254
255func (f *compatTestModule) AndroidMkEntries() []android.AndroidMkEntries {
256 return []android.AndroidMkEntries{android.AndroidMkEntries{
257 Class: "FAKE",
258 // OutputFile is needed, even though BUILD_PHONY_PACKAGE doesn't use it.
259 // Without OutputFile this module won't be exported to Makefile.
260 OutputFile: android.OptionalPathForPath(f.compatTestTimestamp),
261 Include: "$(BUILD_PHONY_PACKAGE)",
262 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
263 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
264 entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", f.compatTestTimestamp.String())
265 },
266 },
267 }}
268}