1// Copyright (C) 2023 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 17import ( 18 "maps" 19 20 "android/soong/android" 21 22 "github.com/google/blueprint" 23) 24 25var ( 26 flagsDepTag = dependencyTag{name: "flags"} 27 buildFlagsDepTag = dependencyTag{name: "build_flags"} 28) 29 30func init() { 31 ctx := android.InitRegistrationContext 32 ctx.RegisterModuleType("se_flags", flagsFactory) 33 ctx.RegisterModuleType("se_flags_collector", flagsCollectorFactory) 34} 35 36type flagsProperties struct { 37 // List of build time flags for flag-guarding. 38 Flags []string 39 40 // List of se_flags_collector modules to export flags to. 41 Export_to []string 42} 43 44type flagsModule struct { 45 android.ModuleBase 46 properties flagsProperties 47} 48 49type flagsInfo struct { 50 Flags []string 51} 52 53var flagsProviderKey = blueprint.NewProvider[flagsInfo]() 54 55// se_flags contains a list of build time flags for sepolicy. Build time flags are defined under 56// .scl files (e.g. build/release/build_flags.scl). By importing flags with se_flags modules, 57// sepolicy rules can be guarded by `is_flag_enabled` / `is_flag_disabled` macro. 58// 59// For example, an Android.bp file could have: 60// 61// se_flags { 62// name: "aosp_selinux_flags", 63// flags: ["RELEASE_AVF_ENABLE_DEVICE_ASSIGNMENT"], 64// export_to: ["all_selinux_flags"], 65// } 66// 67// And then one could flag-guard .te file rules: 68// 69// is_flag_enabled(RELEASE_AVF_ENABLE_DEVICE_ASSIGNMENT, ` 70// type vfio_handler, domain, coredomain; 71// binder_use(vfio_handler) 72// ') 73// 74// or contexts entries: 75// 76// is_flag_enabled(RELEASE_AVF_ENABLE_DEVICE_ASSIGNMENT, ` 77// android.system.virtualizationservice_internal.IVfioHandler u:object_r:vfio_handler_service:s0 78// ') 79func flagsFactory() android.Module { 80 module := &flagsModule{} 81 module.AddProperties(&module.properties) 82 android.InitAndroidModule(module) 83 return module 84} 85 86func (f *flagsModule) DepsMutator(ctx android.BottomUpMutatorContext) { 87 // dep se_flag_collector -> se_flags 88 for _, export := range f.properties.Export_to { 89 ctx.AddReverseDependency(ctx.Module(), flagsDepTag, export) 90 } 91} 92 93func (f *flagsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 94 android.SetProvider(ctx, flagsProviderKey, flagsInfo{ 95 Flags: f.properties.Flags, 96 }) 97} 98 99type buildFlagsInfo struct { 100 BuildFlags map[string]string 101} 102 103var buildFlagsProviderKey = blueprint.NewProvider[buildFlagsInfo]() 104 105type flagsCollectorModule struct { 106 android.ModuleBase 107 buildFlags map[string]string 108} 109 110// se_flags_collector module collects flags from exported se_flags modules (see export_to property 111// of se_flags modules), and then converts them into build-time flags. It will be used to generate 112// M4 macros to flag-guard sepolicy. 113func flagsCollectorFactory() android.Module { 114 module := &flagsCollectorModule{} 115 android.InitAndroidModule(module) 116 return module 117} 118 119func (f *flagsCollectorModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 120 var flags []string 121 ctx.VisitDirectDepsWithTag(flagsDepTag, func(m android.Module) { 122 if dep, ok := android.OtherModuleProvider(ctx, m, flagsProviderKey); ok { 123 flags = append(flags, dep.Flags...) 124 } else { 125 ctx.ModuleErrorf("unknown dependency %q", ctx.OtherModuleName(m)) 126 } 127 }) 128 buildFlags := make(map[string]string) 129 for _, flag := range android.SortedUniqueStrings(flags) { 130 if val, ok := ctx.Config().GetBuildFlag(flag); ok { 131 buildFlags[flag] = val 132 } 133 } 134 android.SetProvider(ctx, buildFlagsProviderKey, buildFlagsInfo{ 135 BuildFlags: buildFlags, 136 }) 137} 138 139type flaggableModuleProperties struct { 140 // List of se_flag_collector modules to be passed to M4 macro. 141 Build_flags []string 142} 143 144type flaggableModule interface { 145 android.Module 146 flagModuleBase() *flaggableModuleBase 147 flagDeps(ctx android.BottomUpMutatorContext) 148 getBuildFlags(ctx android.ModuleContext) map[string]string 149} 150 151type flaggableModuleBase struct { 152 properties flaggableModuleProperties 153} 154 155func initFlaggableModule(m flaggableModule) { 156 base := m.flagModuleBase() 157 m.AddProperties(&base.properties) 158} 159 160func (f *flaggableModuleBase) flagModuleBase() *flaggableModuleBase { 161 return f 162} 163 164func (f *flaggableModuleBase) flagDeps(ctx android.BottomUpMutatorContext) { 165 ctx.AddDependency(ctx.Module(), buildFlagsDepTag, f.properties.Build_flags...) 166} 167 168// getBuildFlags returns a map from flag names to flag values. 169func (f *flaggableModuleBase) getBuildFlags(ctx android.ModuleContext) map[string]string { 170 ret := make(map[string]string) 171 ctx.VisitDirectDepsWithTag(buildFlagsDepTag, func(m android.Module) { 172 if dep, ok := android.OtherModuleProvider(ctx, m, buildFlagsProviderKey); ok { 173 maps.Copy(ret, dep.BuildFlags) 174 } else { 175 ctx.PropertyErrorf("build_flags", "unknown dependency %q", ctx.OtherModuleName(m)) 176 } 177 }) 178 return ret 179} 180