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