Revert "Revert "Restrict plugins to an existing allowlist""
This reverts commit b20a12553ef65a6401dfe0f67ab8b882da0f89db.
Reason for revert: Rollforward with fix
soong-ca-certificates-apex was missing from allowlist
Test: verify fixes CI breakages
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dfe4a9e4dd088f42ba5e0a3c4f7777c253d378d3)
Merged-In: I00687bd2962dbdaaf55189ca4aa82183264eb8d7
Change-Id: I00687bd2962dbdaaf55189ca4aa82183264eb8d7
diff --git a/android/Android.bp b/android/Android.bp
index 118087d..94d2c04 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -77,6 +77,7 @@
"path_properties.go",
"paths.go",
"phony.go",
+ "plugin.go",
"prebuilt.go",
"prebuilt_build_tool.go",
"proto.go",
diff --git a/android/config.go b/android/config.go
index acadb3f..01b8cfa 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1850,6 +1850,10 @@
return uncheckedFinalApiLevel(apiLevel)
}
+func (c *deviceConfig) BuildBrokenPluginValidation() []string {
+ return c.config.productVariables.BuildBrokenPluginValidation
+}
+
func (c *deviceConfig) BuildBrokenClangAsFlags() bool {
return c.config.productVariables.BuildBrokenClangAsFlags
}
diff --git a/android/plugin.go b/android/plugin.go
new file mode 100644
index 0000000..c9d1338
--- /dev/null
+++ b/android/plugin.go
@@ -0,0 +1,140 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// 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 android
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "strings"
+
+ "github.com/google/blueprint"
+)
+
+func init() {
+ RegisterPluginSingletonBuildComponents(InitRegistrationContext)
+}
+
+func RegisterPluginSingletonBuildComponents(ctx RegistrationContext) {
+ ctx.RegisterSingletonType("plugins", pluginSingletonFactory)
+}
+
+// pluginSingleton is a singleton to handle allowlisting of the final Android-<product_name>.mk file
+// output.
+func pluginSingletonFactory() Singleton {
+ return &pluginSingleton{}
+}
+
+type pluginSingleton struct{}
+
+var allowedPluginsByName = map[string]bool{
+ "aidl-soong-rules": true,
+ "arm_compute_library_nn_driver": true,
+ "cuttlefish-soong-rules": true,
+ "gki-soong-rules": true,
+ "hidl-soong-rules": true,
+ "kernel-config-soong-rules": true,
+ "soong-angle-codegen": true,
+ "soong-api": true,
+ "soong-art": true,
+ "soong-ca-certificates": true,
+ "soong-ca-certificates-apex": true,
+ "soong-clang": true,
+ "soong-clang-prebuilts": true,
+ "soong-csuite": true,
+ "soong-fluoride": true,
+ "soong-fs_config": true,
+ "soong-icu": true,
+ "soong-java-config-error_prone": true,
+ "soong-libchrome": true,
+ "soong-llvm": true,
+ "soong-robolectric": true,
+ "soong-rust-prebuilts": true,
+ "soong-selinux": true,
+ "soong-wayland-protocol-codegen": true,
+ "treble_report_app": true,
+ "treble_report_local": true,
+ "treble_report_module": true,
+ "vintf-compatibility-matrix-soong-rules": true,
+ "xsdc-soong-rules": true,
+}
+
+const (
+ internalPluginsPath = "vendor/google/build/soong/internal_plugins.json"
+)
+
+type pluginProvider interface {
+ IsPluginFor(string) bool
+}
+
+func maybeAddInternalPluginsToAllowlist(ctx SingletonContext) {
+ if path := ExistentPathForSource(ctx, internalPluginsPath); path.Valid() {
+ ctx.AddNinjaFileDeps(path.String())
+ absPath := absolutePath(path.String())
+ var moreAllowed map[string]bool
+ data, err := ioutil.ReadFile(absPath)
+ if err != nil {
+ ctx.Errorf("Failed to open internal plugins path %q %q", internalPluginsPath, err)
+ }
+ if err := json.Unmarshal(data, &moreAllowed); err != nil {
+ fmt.Fprintf(os.Stderr, "Internal plugins file %q did not parse correctly: %q", data, err)
+ }
+ for k, v := range moreAllowed {
+ allowedPluginsByName[k] = v
+ }
+ }
+}
+
+func (p *pluginSingleton) GenerateBuildActions(ctx SingletonContext) {
+ for _, p := range ctx.DeviceConfig().BuildBrokenPluginValidation() {
+ allowedPluginsByName[p] = true
+ }
+ maybeAddInternalPluginsToAllowlist(ctx)
+
+ disallowedPlugins := map[string]bool{}
+ ctx.VisitAllModulesBlueprint(func(module blueprint.Module) {
+ if ctx.ModuleType(module) != "bootstrap_go_package" {
+ return
+ }
+
+ p, ok := module.(pluginProvider)
+ if !ok || !p.IsPluginFor("soong_build") {
+ return
+ }
+
+ name := ctx.ModuleName(module)
+ if _, ok := allowedPluginsByName[name]; ok {
+ return
+ }
+
+ dir := ctx.ModuleDir(module)
+
+ // allow use of plugins within Soong to not allowlist everything
+ if strings.HasPrefix(dir, "build/soong") {
+ return
+ }
+
+ // allow third party users outside of external to create new plugins, i.e. non-google paths
+ // under vendor or hardware
+ if !strings.HasPrefix(dir, "external/") && IsThirdPartyPath(dir) {
+ return
+ }
+ disallowedPlugins[name] = true
+ })
+ if len(disallowedPlugins) > 0 {
+ ctx.Errorf("New plugins are not supported; however %q were found. Please reach out to the build team or use BUILD_BROKEN_PLUGIN_VALIDATION (see Changes.md for more info).", SortedStringKeys(disallowedPlugins))
+ }
+}
diff --git a/android/variable.go b/android/variable.go
index 97171e7..40eb006 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -440,6 +440,7 @@
ShippingApiLevel *string `json:",omitempty"`
+ BuildBrokenPluginValidation []string `json:",omitempty"`
BuildBrokenClangAsFlags bool `json:",omitempty"`
BuildBrokenClangCFlags bool `json:",omitempty"`
BuildBrokenClangProperty bool `json:",omitempty"`
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index 5935247..5fc05f8 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -207,8 +207,8 @@
function test_soong_build_rerun_iff_environment_changes() {
setup
- mkdir -p cherry
- cat > cherry/Android.bp <<'EOF'
+ mkdir -p build/soong/cherry
+ cat > build/soong/cherry/Android.bp <<'EOF'
bootstrap_go_package {
name: "cherry",
pkgPath: "android/soong/cherry",
@@ -224,7 +224,7 @@
}
EOF
- cat > cherry/cherry.go <<'EOF'
+ cat > build/soong/cherry/cherry.go <<'EOF'
package cherry
import (
@@ -317,8 +317,8 @@
run_soong
local -r mtime1=$(stat -c "%y" out/soong/build.ninja)
- mkdir -p a
- cat > a/Android.bp <<'EOF'
+ mkdir -p vendor/foo/picard
+ cat > vendor/foo/picard/Android.bp <<'EOF'
bootstrap_go_package {
name: "picard-soong-rules",
pkgPath: "android/soong/picard",
@@ -334,7 +334,7 @@
}
EOF
- cat > a/picard.go <<'EOF'
+ cat > vendor/foo/picard/picard.go <<'EOF'
package picard
import (
@@ -390,11 +390,11 @@
function test_glob_during_bootstrapping() {
setup
- mkdir -p a
- cat > a/Android.bp <<'EOF'
+ mkdir -p build/soong/picard
+ cat > build/soong/picard/Android.bp <<'EOF'
build=["foo*.bp"]
EOF
- cat > a/fooa.bp <<'EOF'
+ cat > build/soong/picard/fooa.bp <<'EOF'
bootstrap_go_package {
name: "picard-soong-rules",
pkgPath: "android/soong/picard",
@@ -410,7 +410,7 @@
}
EOF
- cat > a/picard.go <<'EOF'
+ cat > build/soong/picard/picard.go <<'EOF'
package picard
import (
@@ -459,7 +459,7 @@
grep -q "Make it so" out/soong/build.ninja || fail "Original action not present"
- cat > a/foob.bp <<'EOF'
+ cat > build/soong/picard/foob.bp <<'EOF'
bootstrap_go_package {
name: "worf-soong-rules",
pkgPath: "android/soong/worf",
@@ -476,7 +476,7 @@
}
EOF
- cat > a/worf.go <<'EOF'
+ cat > build/soong/picard/worf.go <<'EOF'
package worf
import "android/soong/picard"