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