• 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	"fmt"
23	"io"
24
25	"github.com/google/blueprint"
26	"github.com/google/blueprint/proptools"
27)
28
29var (
30	pctx = android.NewPackageContext("android/soong/selinux")
31
32	combine_maps    = pctx.HostBinToolVariable("combine_maps", "combine_maps")
33	combineMapsCmd  = "${combine_maps} -t ${topHalf} -b ${bottomHalf} -o $out"
34	combineMapsRule = pctx.StaticRule(
35		"combineMapsRule",
36		blueprint.RuleParams{
37			Command:     combineMapsCmd,
38			CommandDeps: []string{"${combine_maps}"},
39		},
40		"topHalf",
41		"bottomHalf",
42	)
43
44	String        = proptools.String
45	TopHalfDepTag = dependencyTag{name: "top"}
46)
47
48func init() {
49	android.RegisterModuleType("se_cil_compat_map", cilCompatMapFactory)
50	pctx.Import("android/soong/android")
51}
52
53func cilCompatMapFactory() android.Module {
54	c := &cilCompatMap{}
55	c.AddProperties(&c.properties)
56	android.InitAndroidModule(c)
57	return c
58}
59
60type cilCompatMapProperties struct {
61	// se_cil_compat_map module representing a compatibility mapping file for
62	// platform versions (x->y). Bottom half represents a mapping (y->z).
63	// Together the halves are used to generate a (x->z) mapping.
64	Top_half *string
65	// list of source (.cil) files used to build an the bottom half of sepolicy
66	// compatibility mapping file. bottom_half may reference the outputs of
67	// other modules that produce source files like genrule or filegroup using
68	// the syntax ":module". srcs has to be non-empty.
69	Bottom_half []string
70}
71
72type cilCompatMap struct {
73	android.ModuleBase
74	properties cilCompatMapProperties
75	// (.intermediate) module output path as installation source.
76	installSource android.Path
77}
78
79type CilCompatMapGenerator interface {
80	GeneratedMapFile() android.Path
81}
82
83type dependencyTag struct {
84	blueprint.BaseDependencyTag
85	name string
86}
87
88func expandTopHalf(ctx android.ModuleContext) android.OptionalPath {
89	var topHalf android.OptionalPath
90	ctx.VisitDirectDeps(func(dep android.Module) {
91		depTag := ctx.OtherModuleDependencyTag(dep)
92		switch depTag {
93		case TopHalfDepTag:
94			topHalf = android.OptionalPathForPath(dep.(CilCompatMapGenerator).GeneratedMapFile())
95		}
96	})
97	return topHalf
98}
99
100func expandSeSources(ctx android.ModuleContext, srcFiles []string) android.Paths {
101	expandedSrcFiles := make(android.Paths, 0, len(srcFiles))
102	for _, s := range srcFiles {
103		if m := android.SrcIsModule(s); m != "" {
104			module := ctx.GetDirectDepWithTag(m, android.SourceDepTag)
105			if module == nil {
106				// Error will have been handled by ExtractSourcesDeps
107				continue
108			}
109			if fg, ok := module.(*fileGroup); ok {
110				// Core compatibility mapping files are under system/sepolicy/private.
111				expandedSrcFiles = append(expandedSrcFiles, fg.SystemPrivateSrcs()...)
112				// Partner extensions to the compatibility mapping in must be located in
113				// BOARD_PLAT_PRIVATE_SEPOLICY_DIR
114				expandedSrcFiles = append(expandedSrcFiles, fg.SystemExtPrivateSrcs()...)
115			} else {
116				ctx.ModuleErrorf("srcs dependency %q is not an selinux filegroup", m)
117			}
118		} else {
119			p := android.PathForModuleSrc(ctx, s)
120			expandedSrcFiles = append(expandedSrcFiles, p)
121		}
122	}
123	return expandedSrcFiles
124}
125
126func (c *cilCompatMap) GenerateAndroidBuildActions(ctx android.ModuleContext) {
127	srcFiles := expandSeSources(ctx, c.properties.Bottom_half)
128
129	for _, src := range srcFiles {
130		if src.Ext() != ".cil" {
131			ctx.PropertyErrorf("bottom_half", "%s has to be a .cil file.", src.String())
132		}
133	}
134
135	bottomHalf := android.PathForModuleGen(ctx, "bottom_half")
136	ctx.Build(pctx, android.BuildParams{
137		Rule:   android.Cat,
138		Output: bottomHalf,
139		Inputs: srcFiles,
140	})
141
142	topHalf := expandTopHalf(ctx)
143	if topHalf.Valid() {
144		out := android.PathForModuleGen(ctx, c.Name())
145		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
146			Rule:   combineMapsRule,
147			Output: out,
148			Implicits: []android.Path{
149				topHalf.Path(),
150				bottomHalf,
151			},
152			Args: map[string]string{
153				"topHalf":    topHalf.String(),
154				"bottomHalf": bottomHalf.String(),
155			},
156		})
157		c.installSource = out
158	} else {
159		c.installSource = bottomHalf
160	}
161}
162
163func (c *cilCompatMap) DepsMutator(ctx android.BottomUpMutatorContext) {
164	android.ExtractSourcesDeps(ctx, c.properties.Bottom_half)
165	if c.properties.Top_half != nil {
166		ctx.AddDependency(c, TopHalfDepTag, String(c.properties.Top_half))
167	}
168}
169
170func (c *cilCompatMap) AndroidMk() android.AndroidMkData {
171	ret := android.AndroidMkData{
172		OutputFile: android.OptionalPathForPath(c.installSource),
173		Class:      "ETC",
174	}
175	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
176		fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/selinux/mapping")
177	})
178	return ret
179}
180
181var _ CilCompatMapGenerator = (*cilCompatMap)(nil)
182
183func (c *cilCompatMap) GeneratedMapFile() android.Path {
184	return c.installSource
185}
186