• 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	combine_maps    = pctx.HostBinToolVariable("combine_maps", "combine_maps")
31	combineMapsCmd  = "${combine_maps} -t ${topHalf} -b ${bottomHalf} -o $out"
32	combineMapsRule = pctx.StaticRule(
33		"combineMapsRule",
34		blueprint.RuleParams{
35			Command:     combineMapsCmd,
36			CommandDeps: []string{"${combine_maps}"},
37		},
38		"topHalf",
39		"bottomHalf",
40	)
41
42	String        = proptools.String
43	TopHalfDepTag = dependencyTag{name: "top"}
44)
45
46func init() {
47	android.RegisterModuleType("se_cil_compat_map", cilCompatMapFactory)
48	pctx.Import("android/soong/android")
49}
50
51func cilCompatMapFactory() android.Module {
52	c := &cilCompatMap{}
53	c.AddProperties(&c.properties)
54	android.InitAndroidArchModule(c, android.DeviceSupported, android.MultilibCommon)
55	return c
56}
57
58type cilCompatMapProperties struct {
59	// se_cil_compat_map module representing a compatibility mapping file for
60	// platform versions (x->y). Bottom half represents a mapping (y->z).
61	// Together the halves are used to generate a (x->z) mapping.
62	Top_half *string `android:"path"`
63	// list of source (.cil) files used to build an the bottom half of sepolicy
64	// compatibility mapping file. bottom_half may reference the outputs of
65	// other modules that produce source files like genrule or filegroup using
66	// the syntax ":module". srcs has to be non-empty.
67	Bottom_half []string `android:"path"`
68	// name of the output
69	Stem *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	installPath   android.InstallPath
78}
79
80type CilCompatMapGenerator interface {
81	GeneratedMapFile() android.Path
82}
83
84func expandTopHalf(ctx android.ModuleContext) android.OptionalPath {
85	var topHalf android.OptionalPath
86	ctx.VisitDirectDeps(func(dep android.Module) {
87		depTag := ctx.OtherModuleDependencyTag(dep)
88		switch depTag {
89		case TopHalfDepTag:
90			topHalf = android.OptionalPathForPath(dep.(CilCompatMapGenerator).GeneratedMapFile())
91		}
92	})
93	return topHalf
94}
95
96func expandSeSources(ctx android.ModuleContext, srcFiles []string) android.Paths {
97	return android.PathsForModuleSrc(ctx, srcFiles)
98}
99
100func (c *cilCompatMap) GenerateAndroidBuildActions(ctx android.ModuleContext) {
101	c.installPath = android.PathForModuleInstall(ctx, "etc", "selinux", "mapping")
102
103	srcFiles := expandSeSources(ctx, c.properties.Bottom_half)
104
105	for _, src := range srcFiles {
106		if src.Ext() != ".cil" {
107			ctx.PropertyErrorf("bottom_half", "%s has to be a .cil file.", src.String())
108		}
109	}
110
111	bottomHalf := android.PathForModuleGen(ctx, "bottom_half")
112	ctx.Build(pctx, android.BuildParams{
113		Rule:   android.Cat,
114		Output: bottomHalf,
115		Inputs: srcFiles,
116	})
117
118	topHalf := expandTopHalf(ctx)
119	if topHalf.Valid() {
120		out := android.PathForModuleGen(ctx, c.Name())
121		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
122			Rule:   combineMapsRule,
123			Output: out,
124			Implicits: []android.Path{
125				topHalf.Path(),
126				bottomHalf,
127			},
128			Args: map[string]string{
129				"topHalf":    topHalf.String(),
130				"bottomHalf": bottomHalf.String(),
131			},
132		})
133		c.installSource = out
134	} else {
135		c.installSource = bottomHalf
136	}
137}
138
139func (c *cilCompatMap) DepsMutator(ctx android.BottomUpMutatorContext) {
140	if c.properties.Top_half != nil {
141		ctx.AddDependency(c, TopHalfDepTag, String(c.properties.Top_half))
142	}
143}
144
145func (c *cilCompatMap) AndroidMk() android.AndroidMkData {
146	ret := android.AndroidMkData{
147		OutputFile: android.OptionalPathForPath(c.installSource),
148		Class:      "ETC",
149	}
150	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
151		fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", c.installPath.String())
152		if c.properties.Stem != nil {
153			fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", String(c.properties.Stem))
154		}
155	})
156	return ret
157}
158
159var _ CilCompatMapGenerator = (*cilCompatMap)(nil)
160var _ android.OutputFileProducer = (*cilCompatMap)(nil)
161
162func (c *cilCompatMap) GeneratedMapFile() android.Path {
163	return c.installSource
164}
165
166func (c *cilCompatMap) OutputFiles(tag string) (android.Paths, error) {
167	if tag == "" {
168		return android.Paths{c.installSource}, nil
169	}
170	return nil, fmt.Errorf("Unknown tag %q", tag)
171}
172