• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2018 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
17// This file contains "se_cil_compat_map" module type used to build and install
18// sepolicy backwards compatibility mapping files.
19
20import (
21	"android/soong/android"
22
23	"github.com/google/blueprint"
24	"github.com/google/blueprint/proptools"
25)
26
27var (
28	combine_maps    = pctx.HostBinToolVariable("combine_maps", "combine_maps")
29	combineMapsCmd  = "${combine_maps} -t ${topHalf} -b ${bottomHalf} -o $out"
30	combineMapsRule = pctx.StaticRule(
31		"combineMapsRule",
32		blueprint.RuleParams{
33			Command:     combineMapsCmd,
34			CommandDeps: []string{"${combine_maps}"},
35		},
36		"topHalf",
37		"bottomHalf",
38	)
39
40	String        = proptools.String
41	TopHalfDepTag = dependencyTag{name: "top"}
42)
43
44func init() {
45	android.RegisterModuleType("se_cil_compat_map", cilCompatMapFactory)
46	pctx.Import("android/soong/android")
47}
48
49func cilCompatMapFactory() android.Module {
50	c := &cilCompatMap{}
51	c.AddProperties(&c.properties)
52	android.InitAndroidArchModule(c, android.DeviceSupported, android.MultilibCommon)
53	return c
54}
55
56type cilCompatMapProperties struct {
57	// se_cil_compat_map module representing a compatibility mapping file for
58	// platform versions (x->y). Bottom half represents a mapping (y->z).
59	// Together the halves are used to generate a (x->z) mapping.
60	Top_half *string `android:"path"`
61	// list of source (.cil) files used to build an the bottom half of sepolicy
62	// compatibility mapping file. bottom_half may reference the outputs of
63	// other modules that produce source files like genrule or filegroup using
64	// the syntax ":module". srcs has to be non-empty.
65	Bottom_half []string `android:"path"`
66	// name of the output
67	Stem *string
68	// Target version that this module supports. This module will be ignored if platform sepolicy
69	// version is same as this module's version.
70	Version *string
71}
72
73type cilCompatMap struct {
74	android.ModuleBase
75	properties cilCompatMapProperties
76	// (.intermediate) module output path as installation source.
77	installSource android.OptionalPath
78	installPath   android.InstallPath
79}
80
81type CilCompatMapGenerator interface {
82	GeneratedMapFile() android.OptionalPath
83}
84
85func expandTopHalf(ctx android.ModuleContext) android.OptionalPath {
86	var topHalf android.OptionalPath
87	ctx.VisitDirectDeps(func(dep android.Module) {
88		depTag := ctx.OtherModuleDependencyTag(dep)
89		switch depTag {
90		case TopHalfDepTag:
91			topHalf = dep.(CilCompatMapGenerator).GeneratedMapFile()
92		}
93	})
94	return topHalf
95}
96
97func expandSeSources(ctx android.ModuleContext, srcFiles []string) android.Paths {
98	return android.PathsForModuleSrc(ctx, srcFiles)
99}
100
101func (c *cilCompatMap) shouldSkipBuild(ctx android.ModuleContext) bool {
102	return proptools.String(c.properties.Version) == ctx.DeviceConfig().PlatformSepolicyVersion()
103}
104
105func (c *cilCompatMap) stem() string {
106	return proptools.StringDefault(c.properties.Stem, c.Name())
107}
108
109func (c *cilCompatMap) GenerateAndroidBuildActions(ctx android.ModuleContext) {
110	if c.shouldSkipBuild(ctx) {
111		return
112	}
113
114	c.installPath = android.PathForModuleInstall(ctx, "etc", "selinux", "mapping")
115
116	srcFiles := expandSeSources(ctx, c.properties.Bottom_half)
117
118	for _, src := range srcFiles {
119		if src.Ext() != ".cil" {
120			ctx.PropertyErrorf("bottom_half", "%s has to be a .cil file.", src.String())
121		}
122	}
123
124	bottomHalf := android.PathForModuleGen(ctx, "bottom_half")
125	ctx.Build(pctx, android.BuildParams{
126		Rule:   android.Cat,
127		Output: bottomHalf,
128		Inputs: srcFiles,
129	})
130
131	topHalf := expandTopHalf(ctx)
132	if topHalf.Valid() {
133		out := android.PathForModuleGen(ctx, c.Name())
134		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
135			Rule:   combineMapsRule,
136			Output: out,
137			Implicits: []android.Path{
138				topHalf.Path(),
139				bottomHalf,
140			},
141			Args: map[string]string{
142				"topHalf":    topHalf.String(),
143				"bottomHalf": bottomHalf.String(),
144			},
145		})
146		c.installSource = android.OptionalPathForPath(out)
147	} else {
148		c.installSource = android.OptionalPathForPath(bottomHalf)
149	}
150	ctx.InstallFile(c.installPath, c.stem(), c.installSource.Path())
151
152	if c.installSource.Valid() {
153		ctx.SetOutputFiles(android.Paths{c.installSource.Path()}, "")
154	}
155}
156
157func (c *cilCompatMap) DepsMutator(ctx android.BottomUpMutatorContext) {
158	if c.properties.Top_half != nil {
159		ctx.AddDependency(c, TopHalfDepTag, String(c.properties.Top_half))
160	}
161}
162
163func (c *cilCompatMap) AndroidMkEntries() []android.AndroidMkEntries {
164	if !c.installSource.Valid() {
165		return nil
166	}
167	return []android.AndroidMkEntries{android.AndroidMkEntries{
168		Class:      "ETC",
169		OutputFile: c.installSource,
170		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
171			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
172				entries.SetPath("LOCAL_MODULE_PATH", c.installPath)
173				if c.properties.Stem != nil {
174					entries.SetString("LOCAL_INSTALLED_MODULE_STEM", String(c.properties.Stem))
175				}
176			},
177		},
178	}}
179}
180
181var _ CilCompatMapGenerator = (*cilCompatMap)(nil)
182
183func (c *cilCompatMap) GeneratedMapFile() android.OptionalPath {
184	return c.installSource
185}
186