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