1// Copyright (C) 2022 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 "encoding/json" 19 "fmt" 20 21 "android/soong/android" 22) 23 24func init() { 25 android.RegisterModuleType("fuzzer_bindings_test", fuzzerBindingsTestFactory) 26 android.PreArchMutators(registerFuzzerMutators) 27} 28 29func registerFuzzerMutators(ctx android.RegisterMutatorsContext) { 30 ctx.BottomUp("addFuzzerConfigDeps", addFuzzerConfigDeps).Parallel() 31} 32 33func addFuzzerConfigDeps(ctx android.BottomUpMutatorContext) { 34 if _, ok := ctx.Module().(*fuzzerBindingsTestModule); ok { 35 for _, fuzzers := range ServiceFuzzerBindings { 36 for _, fuzzer := range fuzzers { 37 if !ctx.OtherModuleExists(fuzzer) && !ctx.Config().AllowMissingDependencies() { 38 panic(fmt.Errorf("Fuzzer doesn't exist : %s", fuzzer)) 39 } 40 } 41 } 42 } 43} 44 45type bindingsTestProperties struct { 46 // Contexts files to be tested. 47 Srcs []string `android:"path"` 48} 49 50type fuzzerBindingsTestModule struct { 51 android.ModuleBase 52 tool string 53 properties bindingsTestProperties 54 testTimestamp android.ModuleOutPath 55} 56 57// fuzzer_bindings_test checks if a fuzzer is implemented for every service in service_contexts 58func fuzzerBindingsTestFactory() android.Module { 59 m := &fuzzerBindingsTestModule{tool: "fuzzer_bindings_check"} 60 m.AddProperties(&m.properties) 61 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) 62 return m 63} 64 65func (m *fuzzerBindingsTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 66 tool := m.tool 67 if tool != "fuzzer_bindings_check" { 68 panic(fmt.Errorf("%q: unknown tool name: %q", ctx.ModuleName(), tool)) 69 } 70 71 if len(m.properties.Srcs) == 0 { 72 ctx.PropertyErrorf("srcs", "can't be empty") 73 return 74 } 75 76 // Generate a json file which contains existing bindings 77 rootPath := android.PathForIntermediates(ctx, "bindings.json") 78 jsonString, parseError := json.Marshal(ServiceFuzzerBindings) 79 if parseError != nil { 80 panic(fmt.Errorf("Error while marshalling ServiceFuzzerBindings dict. Check Format")) 81 } 82 android.WriteFileRule(ctx, rootPath, string(jsonString)) 83 84 //input module json, service context and binding files here 85 srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs) 86 rule := android.NewRuleBuilder(pctx, ctx) 87 88 rule.Command().BuiltTool(tool).Flag("-s").Inputs(srcs).Flag("-b").Input(rootPath) 89 90 // Every Soong module needs to generate an output even if it doesn't require it 91 m.testTimestamp = android.PathForModuleOut(ctx, "timestamp") 92 rule.Command().Text("touch").Output(m.testTimestamp) 93 rule.Build("fuzzer_bindings_test", "running service:fuzzer bindings test: "+ctx.ModuleName()) 94} 95 96func (m *fuzzerBindingsTestModule) AndroidMkEntries() []android.AndroidMkEntries { 97 return []android.AndroidMkEntries{android.AndroidMkEntries{ 98 Class: "FAKE", 99 // OutputFile is needed, even though BUILD_PHONY_PACKAGE doesn't use it. 100 // Without OutputFile this module won't be exported to Makefile. 101 OutputFile: android.OptionalPathForPath(m.testTimestamp), 102 Include: "$(BUILD_PHONY_PACKAGE)", 103 ExtraEntries: []android.AndroidMkExtraEntriesFunc{ 104 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { 105 entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", m.testTimestamp.String()) 106 }, 107 }, 108 }} 109} 110