| // Copyright (C) 2021 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package selinux |
| |
| import ( |
| "fmt" |
| "os" |
| "strconv" |
| |
| "github.com/google/blueprint/proptools" |
| |
| "android/soong/android" |
| ) |
| |
| func init() { |
| android.RegisterModuleType("se_versioned_policy", versionedPolicyFactory) |
| } |
| |
| type versionedPolicyProperties struct { |
| // Base cil file for versioning. |
| Base *string `android:"path"` |
| |
| // Output file name. Defaults to {name} if target_policy is set, {version}.cil if mapping is set |
| Stem *string |
| |
| // Target sepolicy version. Can be a specific version number (e.g. "30.0" for R), "current" |
| // (PLATFORM_SEPOLICY_VERSION), or "vendor" (BOARD_SEPOLICY_VERS). Defaults to "current" |
| Version *string |
| |
| // If true, generate mapping file from given base cil file. Cannot be set with target_policy. |
| Mapping *bool |
| |
| // If given, version target policy file according to base policy. Cannot be set with mapping. |
| Target_policy *string `android:"path"` |
| |
| // Cil files to be filtered out by the filter_out tool of "build_sepolicy". |
| Filter_out []string `android:"path"` |
| |
| // Cil files to which this mapping file depends. If specified, secilc checks whether the output |
| // file can be merged with specified cil files or not. |
| Dependent_cils []string `android:"path"` |
| |
| // Whether this module is directly installable to one of the partitions. Default is true |
| Installable *bool |
| |
| // install to a subdirectory of the default install path for the module |
| Relative_install_path *string |
| } |
| |
| type versionedPolicy struct { |
| android.ModuleBase |
| |
| properties versionedPolicyProperties |
| |
| installSource android.Path |
| installPath android.InstallPath |
| } |
| |
| // se_versioned_policy generates versioned cil file with "version_policy". This can generate either |
| // mapping file for public plat policies, or associate a target policy file with the version that |
| // non-platform policy targets. |
| func versionedPolicyFactory() android.Module { |
| m := &versionedPolicy{} |
| m.AddProperties(&m.properties) |
| android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) |
| return m |
| } |
| |
| func (m *versionedPolicy) installable() bool { |
| return proptools.BoolDefault(m.properties.Installable, true) |
| } |
| |
| func (m *versionedPolicy) DepsMutator(ctx android.BottomUpMutatorContext) { |
| // do nothing |
| } |
| |
| func (m *versionedPolicy) GenerateAndroidBuildActions(ctx android.ModuleContext) { |
| version := proptools.StringDefault(m.properties.Version, "current") |
| if version == "current" { |
| version = ctx.DeviceConfig().PlatformSepolicyVersion() |
| } else if version == "vendor" { |
| version = ctx.DeviceConfig().BoardSepolicyVers() |
| } |
| |
| var stem string |
| if s := proptools.String(m.properties.Stem); s != "" { |
| stem = s |
| } else if proptools.Bool(m.properties.Mapping) { |
| stem = version + ".cil" |
| } else { |
| stem = ctx.ModuleName() |
| } |
| |
| out := pathForModuleOut(ctx, stem) |
| rule := android.NewRuleBuilder(pctx, ctx) |
| |
| if proptools.String(m.properties.Base) == "" { |
| ctx.PropertyErrorf("base", "must be specified") |
| return |
| } |
| |
| versionCmd := rule.Command().BuiltTool("version_policy"). |
| FlagWithInput("-b ", android.PathForModuleSrc(ctx, *m.properties.Base)). |
| FlagWithArg("-n ", version). |
| FlagWithOutput("-o ", out) |
| |
| if proptools.Bool(m.properties.Mapping) && proptools.String(m.properties.Target_policy) != "" { |
| ctx.ModuleErrorf("Can't set both mapping and target_policy") |
| return |
| } |
| |
| if proptools.Bool(m.properties.Mapping) { |
| versionCmd.Flag("-m") |
| } else if target := proptools.String(m.properties.Target_policy); target != "" { |
| versionCmd.FlagWithInput("-t ", android.PathForModuleSrc(ctx, target)) |
| } else { |
| ctx.ModuleErrorf("Either mapping or target_policy must be set") |
| return |
| } |
| |
| if len(m.properties.Filter_out) > 0 { |
| rule.Command().BuiltTool("build_sepolicy"). |
| Text("filter_out"). |
| Flag("-f"). |
| Inputs(android.PathsForModuleSrc(ctx, m.properties.Filter_out)). |
| FlagWithOutput("-t ", out) |
| } |
| |
| if len(m.properties.Dependent_cils) > 0 { |
| rule.Command().BuiltTool("secilc"). |
| Flag("-m"). |
| FlagWithArg("-M ", "true"). |
| Flag("-G"). |
| Flag("-N"). |
| FlagWithArg("-c ", strconv.Itoa(PolicyVers)). |
| Inputs(android.PathsForModuleSrc(ctx, m.properties.Dependent_cils)). |
| Text(out.String()). |
| FlagWithArg("-o ", os.DevNull). |
| FlagWithArg("-f ", os.DevNull) |
| } |
| |
| rule.Build("mapping", "Versioning mapping file "+ctx.ModuleName()) |
| |
| if !m.installable() { |
| m.SkipInstall() |
| } |
| |
| m.installSource = out |
| m.installPath = android.PathForModuleInstall(ctx, "etc", "selinux") |
| if subdir := proptools.String(m.properties.Relative_install_path); subdir != "" { |
| m.installPath = m.installPath.Join(ctx, subdir) |
| } |
| ctx.InstallFile(m.installPath, m.installSource.Base(), m.installSource) |
| } |
| |
| func (m *versionedPolicy) AndroidMkEntries() []android.AndroidMkEntries { |
| return []android.AndroidMkEntries{android.AndroidMkEntries{ |
| OutputFile: android.OptionalPathForPath(m.installSource), |
| Class: "ETC", |
| ExtraEntries: []android.AndroidMkExtraEntriesFunc{ |
| func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { |
| entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !m.installable()) |
| entries.SetPath("LOCAL_MODULE_PATH", m.installPath) |
| entries.SetString("LOCAL_INSTALLED_MODULE_STEM", m.installSource.Base()) |
| }, |
| }, |
| }} |
| } |
| |
| func (m *versionedPolicy) OutputFiles(tag string) (android.Paths, error) { |
| if tag == "" { |
| return android.Paths{m.installSource}, nil |
| } |
| return nil, fmt.Errorf("Unknown tag %q", tag) |
| } |
| |
| var _ android.OutputFileProducer = (*policyConf)(nil) |