xref: /aosp_15_r20/build/soong/android/neverallow.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2017 Google Inc. All rights reserved.
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerpackage android
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"fmt"
19*333d2b36SAndroid Build Coastguard Worker	"path/filepath"
20*333d2b36SAndroid Build Coastguard Worker	"reflect"
21*333d2b36SAndroid Build Coastguard Worker	"regexp"
22*333d2b36SAndroid Build Coastguard Worker	"strconv"
23*333d2b36SAndroid Build Coastguard Worker	"strings"
24*333d2b36SAndroid Build Coastguard Worker
25*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint/proptools"
26*333d2b36SAndroid Build Coastguard Worker)
27*333d2b36SAndroid Build Coastguard Worker
28*333d2b36SAndroid Build Coastguard Worker// "neverallow" rules for the build system.
29*333d2b36SAndroid Build Coastguard Worker//
30*333d2b36SAndroid Build Coastguard Worker// This allows things which aren't related to the build system and are enforced
31*333d2b36SAndroid Build Coastguard Worker// against assumptions, in progress code refactors, or policy to be expressed in a
32*333d2b36SAndroid Build Coastguard Worker// straightforward away disjoint from implementations and tests which should
33*333d2b36SAndroid Build Coastguard Worker// work regardless of these restrictions.
34*333d2b36SAndroid Build Coastguard Worker//
35*333d2b36SAndroid Build Coastguard Worker// A module is disallowed if all of the following are true:
36*333d2b36SAndroid Build Coastguard Worker// - it is in one of the "In" paths
37*333d2b36SAndroid Build Coastguard Worker// - it is not in one of the "NotIn" paths
38*333d2b36SAndroid Build Coastguard Worker// - it has all "With" properties matched
39*333d2b36SAndroid Build Coastguard Worker// - - values are matched in their entirety
40*333d2b36SAndroid Build Coastguard Worker// - - nil is interpreted as an empty string
41*333d2b36SAndroid Build Coastguard Worker// - - nested properties are separated with a '.'
42*333d2b36SAndroid Build Coastguard Worker// - - if the property is a list, any of the values in the list being matches
43*333d2b36SAndroid Build Coastguard Worker//     counts as a match
44*333d2b36SAndroid Build Coastguard Worker// - it has none of the "Without" properties matched (same rules as above)
45*333d2b36SAndroid Build Coastguard Worker
46*333d2b36SAndroid Build Coastguard Workerfunc registerNeverallowMutator(ctx RegisterMutatorsContext) {
47*333d2b36SAndroid Build Coastguard Worker	ctx.BottomUp("neverallow", neverallowMutator)
48*333d2b36SAndroid Build Coastguard Worker}
49*333d2b36SAndroid Build Coastguard Worker
50*333d2b36SAndroid Build Coastguard Workervar neverallows = []Rule{}
51*333d2b36SAndroid Build Coastguard Worker
52*333d2b36SAndroid Build Coastguard Workerfunc init() {
53*333d2b36SAndroid Build Coastguard Worker	AddNeverAllowRules(createIncludeDirsRules()...)
54*333d2b36SAndroid Build Coastguard Worker	AddNeverAllowRules(createTrebleRules()...)
55*333d2b36SAndroid Build Coastguard Worker	AddNeverAllowRules(createJavaDeviceForHostRules()...)
56*333d2b36SAndroid Build Coastguard Worker	AddNeverAllowRules(createCcSdkVariantRules()...)
57*333d2b36SAndroid Build Coastguard Worker	AddNeverAllowRules(createUncompressDexRules()...)
58*333d2b36SAndroid Build Coastguard Worker	AddNeverAllowRules(createInstallInRootAllowingRules()...)
59*333d2b36SAndroid Build Coastguard Worker	AddNeverAllowRules(createProhibitFrameworkAccessRules()...)
60*333d2b36SAndroid Build Coastguard Worker	AddNeverAllowRules(createCcStubsRule())
61*333d2b36SAndroid Build Coastguard Worker	AddNeverAllowRules(createProhibitHeaderOnlyRule())
62*333d2b36SAndroid Build Coastguard Worker	AddNeverAllowRules(createLimitNdkExportRule()...)
63*333d2b36SAndroid Build Coastguard Worker	AddNeverAllowRules(createLimitDirgroupRule()...)
64*333d2b36SAndroid Build Coastguard Worker	AddNeverAllowRules(createFilesystemIsAutoGeneratedRule())
65*333d2b36SAndroid Build Coastguard Worker	AddNeverAllowRules(createKotlinPluginRule()...)
66*333d2b36SAndroid Build Coastguard Worker	AddNeverAllowRules(createPrebuiltEtcBpDefineRule())
67*333d2b36SAndroid Build Coastguard Worker	AddNeverAllowRules(createAutogenRroBpDefineRule())
68*333d2b36SAndroid Build Coastguard Worker}
69*333d2b36SAndroid Build Coastguard Worker
70*333d2b36SAndroid Build Coastguard Worker// Add a NeverAllow rule to the set of rules to apply.
71*333d2b36SAndroid Build Coastguard Workerfunc AddNeverAllowRules(rules ...Rule) {
72*333d2b36SAndroid Build Coastguard Worker	neverallows = append(neverallows, rules...)
73*333d2b36SAndroid Build Coastguard Worker}
74*333d2b36SAndroid Build Coastguard Worker
75*333d2b36SAndroid Build Coastguard Workervar (
76*333d2b36SAndroid Build Coastguard Worker	neverallowNotInIncludeDir = []string{
77*333d2b36SAndroid Build Coastguard Worker		"art",
78*333d2b36SAndroid Build Coastguard Worker		"art/libnativebridge",
79*333d2b36SAndroid Build Coastguard Worker		"art/libnativeloader",
80*333d2b36SAndroid Build Coastguard Worker		"libcore",
81*333d2b36SAndroid Build Coastguard Worker		"libnativehelper",
82*333d2b36SAndroid Build Coastguard Worker		"external/apache-harmony",
83*333d2b36SAndroid Build Coastguard Worker		"external/apache-xml",
84*333d2b36SAndroid Build Coastguard Worker		"external/boringssl",
85*333d2b36SAndroid Build Coastguard Worker		"external/bouncycastle",
86*333d2b36SAndroid Build Coastguard Worker		"external/conscrypt",
87*333d2b36SAndroid Build Coastguard Worker		"external/icu",
88*333d2b36SAndroid Build Coastguard Worker		"external/okhttp",
89*333d2b36SAndroid Build Coastguard Worker		"external/vixl",
90*333d2b36SAndroid Build Coastguard Worker		"external/wycheproof",
91*333d2b36SAndroid Build Coastguard Worker	}
92*333d2b36SAndroid Build Coastguard Worker	neverallowNoUseIncludeDir = []string{
93*333d2b36SAndroid Build Coastguard Worker		"frameworks/av/apex",
94*333d2b36SAndroid Build Coastguard Worker		"frameworks/av/tools",
95*333d2b36SAndroid Build Coastguard Worker		"frameworks/native/cmds",
96*333d2b36SAndroid Build Coastguard Worker		"system/apex",
97*333d2b36SAndroid Build Coastguard Worker		"system/bpf",
98*333d2b36SAndroid Build Coastguard Worker		"system/gatekeeper",
99*333d2b36SAndroid Build Coastguard Worker		"system/hwservicemanager",
100*333d2b36SAndroid Build Coastguard Worker		"system/libbase",
101*333d2b36SAndroid Build Coastguard Worker		"system/libfmq",
102*333d2b36SAndroid Build Coastguard Worker		"system/libvintf",
103*333d2b36SAndroid Build Coastguard Worker	}
104*333d2b36SAndroid Build Coastguard Worker)
105*333d2b36SAndroid Build Coastguard Worker
106*333d2b36SAndroid Build Coastguard Workerfunc createIncludeDirsRules() []Rule {
107*333d2b36SAndroid Build Coastguard Worker	rules := make([]Rule, 0, len(neverallowNotInIncludeDir)+len(neverallowNoUseIncludeDir))
108*333d2b36SAndroid Build Coastguard Worker
109*333d2b36SAndroid Build Coastguard Worker	for _, path := range neverallowNotInIncludeDir {
110*333d2b36SAndroid Build Coastguard Worker		rule :=
111*333d2b36SAndroid Build Coastguard Worker			NeverAllow().
112*333d2b36SAndroid Build Coastguard Worker				WithMatcher("include_dirs", StartsWith(path+"/")).
113*333d2b36SAndroid Build Coastguard Worker				Because("include_dirs is deprecated, all usages of '" + path + "' have been migrated" +
114*333d2b36SAndroid Build Coastguard Worker					" to use alternate mechanisms and so can no longer be used.")
115*333d2b36SAndroid Build Coastguard Worker
116*333d2b36SAndroid Build Coastguard Worker		rules = append(rules, rule)
117*333d2b36SAndroid Build Coastguard Worker	}
118*333d2b36SAndroid Build Coastguard Worker
119*333d2b36SAndroid Build Coastguard Worker	for _, path := range neverallowNoUseIncludeDir {
120*333d2b36SAndroid Build Coastguard Worker		rule := NeverAllow().In(path+"/").WithMatcher("include_dirs", isSetMatcherInstance).
121*333d2b36SAndroid Build Coastguard Worker			Because("include_dirs is deprecated, all usages of them in '" + path + "' have been migrated" +
122*333d2b36SAndroid Build Coastguard Worker				" to use alternate mechanisms and so can no longer be used.")
123*333d2b36SAndroid Build Coastguard Worker		rules = append(rules, rule)
124*333d2b36SAndroid Build Coastguard Worker	}
125*333d2b36SAndroid Build Coastguard Worker
126*333d2b36SAndroid Build Coastguard Worker	return rules
127*333d2b36SAndroid Build Coastguard Worker}
128*333d2b36SAndroid Build Coastguard Worker
129*333d2b36SAndroid Build Coastguard Workerfunc createTrebleRules() []Rule {
130*333d2b36SAndroid Build Coastguard Worker	return []Rule{
131*333d2b36SAndroid Build Coastguard Worker		NeverAllow().
132*333d2b36SAndroid Build Coastguard Worker			In("vendor", "device").
133*333d2b36SAndroid Build Coastguard Worker			With("vndk.enabled", "true").
134*333d2b36SAndroid Build Coastguard Worker			Without("vendor", "true").
135*333d2b36SAndroid Build Coastguard Worker			Without("product_specific", "true").
136*333d2b36SAndroid Build Coastguard Worker			Because("the VNDK can never contain a library that is device dependent."),
137*333d2b36SAndroid Build Coastguard Worker		NeverAllow().
138*333d2b36SAndroid Build Coastguard Worker			With("vndk.enabled", "true").
139*333d2b36SAndroid Build Coastguard Worker			Without("vendor", "true").
140*333d2b36SAndroid Build Coastguard Worker			Without("owner", "").
141*333d2b36SAndroid Build Coastguard Worker			Because("a VNDK module can never have an owner."),
142*333d2b36SAndroid Build Coastguard Worker
143*333d2b36SAndroid Build Coastguard Worker		// TODO(b/67974785): always enforce the manifest
144*333d2b36SAndroid Build Coastguard Worker		NeverAllow().
145*333d2b36SAndroid Build Coastguard Worker			Without("name", "libhidlbase-combined-impl").
146*333d2b36SAndroid Build Coastguard Worker			Without("name", "libhidlbase").
147*333d2b36SAndroid Build Coastguard Worker			With("product_variables.enforce_vintf_manifest.cflags", "*").
148*333d2b36SAndroid Build Coastguard Worker			Because("manifest enforcement should be independent of ."),
149*333d2b36SAndroid Build Coastguard Worker
150*333d2b36SAndroid Build Coastguard Worker		// TODO(b/67975799): vendor code should always use /vendor/bin/sh
151*333d2b36SAndroid Build Coastguard Worker		NeverAllow().
152*333d2b36SAndroid Build Coastguard Worker			Without("name", "libc_bionic_ndk").
153*333d2b36SAndroid Build Coastguard Worker			With("product_variables.treble_linker_namespaces.cflags", "*").
154*333d2b36SAndroid Build Coastguard Worker			Because("nothing should care if linker namespaces are enabled or not"),
155*333d2b36SAndroid Build Coastguard Worker
156*333d2b36SAndroid Build Coastguard Worker		// Example:
157*333d2b36SAndroid Build Coastguard Worker		// *NeverAllow().with("Srcs", "main.cpp"))
158*333d2b36SAndroid Build Coastguard Worker	}
159*333d2b36SAndroid Build Coastguard Worker}
160*333d2b36SAndroid Build Coastguard Worker
161*333d2b36SAndroid Build Coastguard Workerfunc createJavaDeviceForHostRules() []Rule {
162*333d2b36SAndroid Build Coastguard Worker	javaDeviceForHostProjectsAllowedList := []string{
163*333d2b36SAndroid Build Coastguard Worker		"development/build",
164*333d2b36SAndroid Build Coastguard Worker		"external/guava",
165*333d2b36SAndroid Build Coastguard Worker		"external/kotlinx.coroutines",
166*333d2b36SAndroid Build Coastguard Worker		"external/robolectric-shadows",
167*333d2b36SAndroid Build Coastguard Worker		"external/robolectric",
168*333d2b36SAndroid Build Coastguard Worker		"frameworks/base/ravenwood",
169*333d2b36SAndroid Build Coastguard Worker		"frameworks/base/tools/hoststubgen",
170*333d2b36SAndroid Build Coastguard Worker		"frameworks/layoutlib",
171*333d2b36SAndroid Build Coastguard Worker	}
172*333d2b36SAndroid Build Coastguard Worker
173*333d2b36SAndroid Build Coastguard Worker	return []Rule{
174*333d2b36SAndroid Build Coastguard Worker		NeverAllow().
175*333d2b36SAndroid Build Coastguard Worker			NotIn(javaDeviceForHostProjectsAllowedList...).
176*333d2b36SAndroid Build Coastguard Worker			ModuleType("java_device_for_host", "java_host_for_device").
177*333d2b36SAndroid Build Coastguard Worker			Because("java_device_for_host can only be used in allowed projects"),
178*333d2b36SAndroid Build Coastguard Worker	}
179*333d2b36SAndroid Build Coastguard Worker}
180*333d2b36SAndroid Build Coastguard Worker
181*333d2b36SAndroid Build Coastguard Workerfunc createCcSdkVariantRules() []Rule {
182*333d2b36SAndroid Build Coastguard Worker	sdkVersionOnlyAllowedList := []string{
183*333d2b36SAndroid Build Coastguard Worker		// derive_sdk_prefer32 has stem: "derive_sdk" which conflicts with the derive_sdk.
184*333d2b36SAndroid Build Coastguard Worker		// This sometimes works because the APEX modules that contain derive_sdk and
185*333d2b36SAndroid Build Coastguard Worker		// derive_sdk_prefer32 suppress the platform installation rules, but fails when
186*333d2b36SAndroid Build Coastguard Worker		// the APEX modules contain the SDK variant and the platform variant still exists.
187*333d2b36SAndroid Build Coastguard Worker		"packages/modules/SdkExtensions/derive_sdk",
188*333d2b36SAndroid Build Coastguard Worker		// These are for apps and shouldn't be used by non-SDK variant modules.
189*333d2b36SAndroid Build Coastguard Worker		"prebuilts/ndk",
190*333d2b36SAndroid Build Coastguard Worker		"frameworks/native/libs/binder/ndk",
191*333d2b36SAndroid Build Coastguard Worker		"tools/test/graphicsbenchmark/apps/sample_app",
192*333d2b36SAndroid Build Coastguard Worker		"tools/test/graphicsbenchmark/functional_tests/java",
193*333d2b36SAndroid Build Coastguard Worker		"vendor/xts/gts-tests/hostsidetests/gamedevicecert/apps/javatests",
194*333d2b36SAndroid Build Coastguard Worker		"external/libtextclassifier/native",
195*333d2b36SAndroid Build Coastguard Worker	}
196*333d2b36SAndroid Build Coastguard Worker
197*333d2b36SAndroid Build Coastguard Worker	platformVariantPropertiesAllowedList := []string{
198*333d2b36SAndroid Build Coastguard Worker		// android_native_app_glue and libRSSupport use native_window.h but target old
199*333d2b36SAndroid Build Coastguard Worker		// sdk versions (minimum and 9 respectively) where libnativewindow didn't exist,
200*333d2b36SAndroid Build Coastguard Worker		// so they can't add libnativewindow to shared_libs to get the header directory
201*333d2b36SAndroid Build Coastguard Worker		// for the platform variant.  Allow them to use the platform variant
202*333d2b36SAndroid Build Coastguard Worker		// property to set shared_libs.
203*333d2b36SAndroid Build Coastguard Worker		"prebuilts/ndk",
204*333d2b36SAndroid Build Coastguard Worker		"frameworks/rs",
205*333d2b36SAndroid Build Coastguard Worker	}
206*333d2b36SAndroid Build Coastguard Worker
207*333d2b36SAndroid Build Coastguard Worker	return []Rule{
208*333d2b36SAndroid Build Coastguard Worker		NeverAllow().
209*333d2b36SAndroid Build Coastguard Worker			NotIn(sdkVersionOnlyAllowedList...).
210*333d2b36SAndroid Build Coastguard Worker			WithMatcher("sdk_variant_only", isSetMatcherInstance).
211*333d2b36SAndroid Build Coastguard Worker			Because("sdk_variant_only can only be used in allowed projects"),
212*333d2b36SAndroid Build Coastguard Worker		NeverAllow().
213*333d2b36SAndroid Build Coastguard Worker			NotIn(platformVariantPropertiesAllowedList...).
214*333d2b36SAndroid Build Coastguard Worker			WithMatcher("platform.shared_libs", isSetMatcherInstance).
215*333d2b36SAndroid Build Coastguard Worker			Because("platform variant properties can only be used in allowed projects"),
216*333d2b36SAndroid Build Coastguard Worker	}
217*333d2b36SAndroid Build Coastguard Worker}
218*333d2b36SAndroid Build Coastguard Worker
219*333d2b36SAndroid Build Coastguard Workerfunc createCcStubsRule() Rule {
220*333d2b36SAndroid Build Coastguard Worker	ccStubsImplementationInstallableProjectsAllowedList := []string{
221*333d2b36SAndroid Build Coastguard Worker		"packages/modules/Virtualization/libs/libvm_payload",
222*333d2b36SAndroid Build Coastguard Worker	}
223*333d2b36SAndroid Build Coastguard Worker
224*333d2b36SAndroid Build Coastguard Worker	return NeverAllow().
225*333d2b36SAndroid Build Coastguard Worker		NotIn(ccStubsImplementationInstallableProjectsAllowedList...).
226*333d2b36SAndroid Build Coastguard Worker		WithMatcher("stubs.implementation_installable", isSetMatcherInstance).
227*333d2b36SAndroid Build Coastguard Worker		Because("implementation_installable can only be used in allowed projects.")
228*333d2b36SAndroid Build Coastguard Worker}
229*333d2b36SAndroid Build Coastguard Worker
230*333d2b36SAndroid Build Coastguard Workerfunc createUncompressDexRules() []Rule {
231*333d2b36SAndroid Build Coastguard Worker	return []Rule{
232*333d2b36SAndroid Build Coastguard Worker		NeverAllow().
233*333d2b36SAndroid Build Coastguard Worker			NotIn("art").
234*333d2b36SAndroid Build Coastguard Worker			WithMatcher("uncompress_dex", isSetMatcherInstance).
235*333d2b36SAndroid Build Coastguard Worker			Because("uncompress_dex is only allowed for certain jars for test in art."),
236*333d2b36SAndroid Build Coastguard Worker	}
237*333d2b36SAndroid Build Coastguard Worker}
238*333d2b36SAndroid Build Coastguard Worker
239*333d2b36SAndroid Build Coastguard Workerfunc createInstallInRootAllowingRules() []Rule {
240*333d2b36SAndroid Build Coastguard Worker	return []Rule{
241*333d2b36SAndroid Build Coastguard Worker		NeverAllow().
242*333d2b36SAndroid Build Coastguard Worker			Without("name", "init_first_stage_defaults").
243*333d2b36SAndroid Build Coastguard Worker			Without("name", "init_first_stage").
244*333d2b36SAndroid Build Coastguard Worker			Without("name", "init_first_stage.microdroid").
245*333d2b36SAndroid Build Coastguard Worker			Without("name", "librecovery_ui_ext").
246*333d2b36SAndroid Build Coastguard Worker			With("install_in_root", "true").
247*333d2b36SAndroid Build Coastguard Worker			NotModuleType("prebuilt_root").
248*333d2b36SAndroid Build Coastguard Worker			NotModuleType("prebuilt_vendor").
249*333d2b36SAndroid Build Coastguard Worker			NotModuleType("prebuilt_sbin").
250*333d2b36SAndroid Build Coastguard Worker			NotModuleType("prebuilt_system").
251*333d2b36SAndroid Build Coastguard Worker			NotModuleType("prebuilt_first_stage_ramdisk").
252*333d2b36SAndroid Build Coastguard Worker			NotModuleType("prebuilt_res").
253*333d2b36SAndroid Build Coastguard Worker			Because("install_in_root is only for init_first_stage or librecovery_ui_ext."),
254*333d2b36SAndroid Build Coastguard Worker	}
255*333d2b36SAndroid Build Coastguard Worker}
256*333d2b36SAndroid Build Coastguard Worker
257*333d2b36SAndroid Build Coastguard Workerfunc createProhibitFrameworkAccessRules() []Rule {
258*333d2b36SAndroid Build Coastguard Worker	return []Rule{
259*333d2b36SAndroid Build Coastguard Worker		NeverAllow().
260*333d2b36SAndroid Build Coastguard Worker			With("libs", "framework").
261*333d2b36SAndroid Build Coastguard Worker			WithoutMatcher("sdk_version", Regexp("(core_.*|^$)")).
262*333d2b36SAndroid Build Coastguard Worker			Because("framework can't be used when building against SDK"),
263*333d2b36SAndroid Build Coastguard Worker	}
264*333d2b36SAndroid Build Coastguard Worker}
265*333d2b36SAndroid Build Coastguard Worker
266*333d2b36SAndroid Build Coastguard Workerfunc createProhibitHeaderOnlyRule() Rule {
267*333d2b36SAndroid Build Coastguard Worker	return NeverAllow().
268*333d2b36SAndroid Build Coastguard Worker		Without("name", "framework-minus-apex-headers").
269*333d2b36SAndroid Build Coastguard Worker		With("headers_only", "true").
270*333d2b36SAndroid Build Coastguard Worker		Because("headers_only can only be used for generating framework-minus-apex headers for non-updatable modules")
271*333d2b36SAndroid Build Coastguard Worker}
272*333d2b36SAndroid Build Coastguard Worker
273*333d2b36SAndroid Build Coastguard Workerfunc createLimitNdkExportRule() []Rule {
274*333d2b36SAndroid Build Coastguard Worker	reason := "If the headers you're trying to export are meant to be a part of the NDK, they should be exposed by an ndk_headers module. If the headers shouldn't be a part of the NDK, the headers should instead be exposed from a separate `cc_library_headers` which consumers depend on."
275*333d2b36SAndroid Build Coastguard Worker	// DO NOT ADD HERE - please consult danalbert@
276*333d2b36SAndroid Build Coastguard Worker	// b/357711733
277*333d2b36SAndroid Build Coastguard Worker	return []Rule{
278*333d2b36SAndroid Build Coastguard Worker		NeverAllow().
279*333d2b36SAndroid Build Coastguard Worker			NotIn("frameworks/native/libs/binder/ndk").
280*333d2b36SAndroid Build Coastguard Worker			ModuleType("ndk_library").
281*333d2b36SAndroid Build Coastguard Worker			WithMatcher("export_header_libs", isSetMatcherInstance).Because(reason),
282*333d2b36SAndroid Build Coastguard Worker		NeverAllow().ModuleType("ndk_library").WithMatcher("export_generated_headers", isSetMatcherInstance).Because(reason),
283*333d2b36SAndroid Build Coastguard Worker		NeverAllow().ModuleType("ndk_library").WithMatcher("export_include_dirs", isSetMatcherInstance).Because(reason),
284*333d2b36SAndroid Build Coastguard Worker		NeverAllow().ModuleType("ndk_library").WithMatcher("export_shared_lib_headers", isSetMatcherInstance).Because(reason),
285*333d2b36SAndroid Build Coastguard Worker		NeverAllow().ModuleType("ndk_library").WithMatcher("export_static_lib_headers", isSetMatcherInstance).Because(reason),
286*333d2b36SAndroid Build Coastguard Worker	}
287*333d2b36SAndroid Build Coastguard Worker}
288*333d2b36SAndroid Build Coastguard Worker
289*333d2b36SAndroid Build Coastguard Workerfunc createLimitDirgroupRule() []Rule {
290*333d2b36SAndroid Build Coastguard Worker	reason := "dirgroup module and dir_srcs / keep_gendir property of genrule is allowed only to Trusty build rule."
291*333d2b36SAndroid Build Coastguard Worker	return []Rule{
292*333d2b36SAndroid Build Coastguard Worker		NeverAllow().
293*333d2b36SAndroid Build Coastguard Worker			ModuleType("dirgroup").
294*333d2b36SAndroid Build Coastguard Worker			WithMatcher("visibility", NotInList([]string{"//trusty/vendor/google/aosp/scripts"})).Because(reason),
295*333d2b36SAndroid Build Coastguard Worker		NeverAllow().
296*333d2b36SAndroid Build Coastguard Worker			ModuleType("dirgroup").
297*333d2b36SAndroid Build Coastguard Worker			Without("visibility", "//trusty/vendor/google/aosp/scripts").Because(reason),
298*333d2b36SAndroid Build Coastguard Worker		NeverAllow().
299*333d2b36SAndroid Build Coastguard Worker			ModuleType("genrule").
300*333d2b36SAndroid Build Coastguard Worker			Without("name", "trusty-arm64.lk.elf.gen").
301*333d2b36SAndroid Build Coastguard Worker			Without("name", "trusty-arm64-virt-test-debug.lk.elf.gen").
302*333d2b36SAndroid Build Coastguard Worker			Without("name", "trusty-x86_64.lk.elf.gen").
303*333d2b36SAndroid Build Coastguard Worker			Without("name", "trusty-x86_64-test.lk.elf.gen").
304*333d2b36SAndroid Build Coastguard Worker			WithMatcher("dir_srcs", isSetMatcherInstance).Because(reason),
305*333d2b36SAndroid Build Coastguard Worker		NeverAllow().
306*333d2b36SAndroid Build Coastguard Worker			ModuleType("genrule").
307*333d2b36SAndroid Build Coastguard Worker			Without("name", "trusty-arm64.lk.elf.gen").
308*333d2b36SAndroid Build Coastguard Worker			Without("name", "trusty-arm64-virt-test-debug.lk.elf.gen").
309*333d2b36SAndroid Build Coastguard Worker			Without("name", "trusty-x86_64.lk.elf.gen").
310*333d2b36SAndroid Build Coastguard Worker			Without("name", "trusty-x86_64-test.lk.elf.gen").
311*333d2b36SAndroid Build Coastguard Worker			With("keep_gendir", "true").Because(reason),
312*333d2b36SAndroid Build Coastguard Worker	}
313*333d2b36SAndroid Build Coastguard Worker}
314*333d2b36SAndroid Build Coastguard Worker
315*333d2b36SAndroid Build Coastguard Workerfunc createFilesystemIsAutoGeneratedRule() Rule {
316*333d2b36SAndroid Build Coastguard Worker	return NeverAllow().
317*333d2b36SAndroid Build Coastguard Worker		NotIn("build/soong/fsgen").
318*333d2b36SAndroid Build Coastguard Worker		ModuleType("filesystem", "android_system_image").
319*333d2b36SAndroid Build Coastguard Worker		WithMatcher("is_auto_generated", isSetMatcherInstance).
320*333d2b36SAndroid Build Coastguard Worker		Because("is_auto_generated property is only allowed for filesystem modules in build/soong/fsgen directory")
321*333d2b36SAndroid Build Coastguard Worker}
322*333d2b36SAndroid Build Coastguard Worker
323*333d2b36SAndroid Build Coastguard Workerfunc createKotlinPluginRule() []Rule {
324*333d2b36SAndroid Build Coastguard Worker	kotlinPluginProjectsAllowedList := []string{
325*333d2b36SAndroid Build Coastguard Worker		// TODO: Migrate compose plugin to the bundled compiler plugin
326*333d2b36SAndroid Build Coastguard Worker		// Actual path prebuilts/sdk/current/androidx/m2repository/androidx/compose/compiler/compiler-hosted
327*333d2b36SAndroid Build Coastguard Worker		"prebuilts/sdk/current/androidx",
328*333d2b36SAndroid Build Coastguard Worker		"external/kotlinc",
329*333d2b36SAndroid Build Coastguard Worker	}
330*333d2b36SAndroid Build Coastguard Worker
331*333d2b36SAndroid Build Coastguard Worker	return []Rule{
332*333d2b36SAndroid Build Coastguard Worker		NeverAllow().
333*333d2b36SAndroid Build Coastguard Worker			NotIn(kotlinPluginProjectsAllowedList...).
334*333d2b36SAndroid Build Coastguard Worker			ModuleType("kotlin_plugin").
335*333d2b36SAndroid Build Coastguard Worker			Because("kotlin_plugin can only be used in allowed projects"),
336*333d2b36SAndroid Build Coastguard Worker	}
337*333d2b36SAndroid Build Coastguard Worker}
338*333d2b36SAndroid Build Coastguard Worker
339*333d2b36SAndroid Build Coastguard Worker// These module types are introduced to convert PRODUCT_COPY_FILES to Soong,
340*333d2b36SAndroid Build Coastguard Worker// and is only intended to be used by filesystem_creator.
341*333d2b36SAndroid Build Coastguard Workerfunc createPrebuiltEtcBpDefineRule() Rule {
342*333d2b36SAndroid Build Coastguard Worker	return NeverAllow().
343*333d2b36SAndroid Build Coastguard Worker		ModuleType(
344*333d2b36SAndroid Build Coastguard Worker			"prebuilt_usr_srec",
345*333d2b36SAndroid Build Coastguard Worker			"prebuilt_priv_app",
346*333d2b36SAndroid Build Coastguard Worker			"prebuilt_rfs",
347*333d2b36SAndroid Build Coastguard Worker			"prebuilt_framework",
348*333d2b36SAndroid Build Coastguard Worker			"prebuilt_wlc_upt",
349*333d2b36SAndroid Build Coastguard Worker			"prebuilt_odm",
350*333d2b36SAndroid Build Coastguard Worker			"prebuilt_vendor_dlkm",
351*333d2b36SAndroid Build Coastguard Worker			"prebuilt_bt_firmware",
352*333d2b36SAndroid Build Coastguard Worker			"prebuilt_tvservice",
353*333d2b36SAndroid Build Coastguard Worker			"prebuilt_optee",
354*333d2b36SAndroid Build Coastguard Worker			"prebuilt_tvconfig",
355*333d2b36SAndroid Build Coastguard Worker			"prebuilt_vendor",
356*333d2b36SAndroid Build Coastguard Worker			"prebuilt_sbin",
357*333d2b36SAndroid Build Coastguard Worker			"prebuilt_system",
358*333d2b36SAndroid Build Coastguard Worker			"prebuilt_first_stage_ramdisk",
359*333d2b36SAndroid Build Coastguard Worker		).
360*333d2b36SAndroid Build Coastguard Worker		DefinedInBpFile().
361*333d2b36SAndroid Build Coastguard Worker		Because("module type not allowed to be defined in bp file")
362*333d2b36SAndroid Build Coastguard Worker}
363*333d2b36SAndroid Build Coastguard Worker
364*333d2b36SAndroid Build Coastguard Workerfunc createAutogenRroBpDefineRule() Rule {
365*333d2b36SAndroid Build Coastguard Worker	return NeverAllow().
366*333d2b36SAndroid Build Coastguard Worker		ModuleType(
367*333d2b36SAndroid Build Coastguard Worker			"autogen_runtime_resource_overlay",
368*333d2b36SAndroid Build Coastguard Worker		).
369*333d2b36SAndroid Build Coastguard Worker		DefinedInBpFile().
370*333d2b36SAndroid Build Coastguard Worker		Because("Module type will be autogenerated by soong. Use runtime_resource_overlay instead")
371*333d2b36SAndroid Build Coastguard Worker}
372*333d2b36SAndroid Build Coastguard Worker
373*333d2b36SAndroid Build Coastguard Workerfunc neverallowMutator(ctx BottomUpMutatorContext) {
374*333d2b36SAndroid Build Coastguard Worker	m, ok := ctx.Module().(Module)
375*333d2b36SAndroid Build Coastguard Worker	if !ok {
376*333d2b36SAndroid Build Coastguard Worker		return
377*333d2b36SAndroid Build Coastguard Worker	}
378*333d2b36SAndroid Build Coastguard Worker
379*333d2b36SAndroid Build Coastguard Worker	dir := ctx.ModuleDir() + "/"
380*333d2b36SAndroid Build Coastguard Worker	properties := m.GetProperties()
381*333d2b36SAndroid Build Coastguard Worker
382*333d2b36SAndroid Build Coastguard Worker	osClass := ctx.Module().Target().Os.Class
383*333d2b36SAndroid Build Coastguard Worker
384*333d2b36SAndroid Build Coastguard Worker	for _, r := range neverallowRules(ctx.Config()) {
385*333d2b36SAndroid Build Coastguard Worker		n := r.(*rule)
386*333d2b36SAndroid Build Coastguard Worker		if !n.appliesToPath(dir) {
387*333d2b36SAndroid Build Coastguard Worker			continue
388*333d2b36SAndroid Build Coastguard Worker		}
389*333d2b36SAndroid Build Coastguard Worker
390*333d2b36SAndroid Build Coastguard Worker		if !n.appliesToModuleType(ctx.ModuleType()) {
391*333d2b36SAndroid Build Coastguard Worker			continue
392*333d2b36SAndroid Build Coastguard Worker		}
393*333d2b36SAndroid Build Coastguard Worker
394*333d2b36SAndroid Build Coastguard Worker		if !n.appliesToProperties(ctx, properties) {
395*333d2b36SAndroid Build Coastguard Worker			continue
396*333d2b36SAndroid Build Coastguard Worker		}
397*333d2b36SAndroid Build Coastguard Worker
398*333d2b36SAndroid Build Coastguard Worker		if !n.appliesToOsClass(osClass) {
399*333d2b36SAndroid Build Coastguard Worker			continue
400*333d2b36SAndroid Build Coastguard Worker		}
401*333d2b36SAndroid Build Coastguard Worker
402*333d2b36SAndroid Build Coastguard Worker		if !n.appliesToDirectDeps(ctx) {
403*333d2b36SAndroid Build Coastguard Worker			continue
404*333d2b36SAndroid Build Coastguard Worker		}
405*333d2b36SAndroid Build Coastguard Worker
406*333d2b36SAndroid Build Coastguard Worker		if !n.appliesToBpDefinedModule(ctx) {
407*333d2b36SAndroid Build Coastguard Worker			continue
408*333d2b36SAndroid Build Coastguard Worker		}
409*333d2b36SAndroid Build Coastguard Worker
410*333d2b36SAndroid Build Coastguard Worker		ctx.ModuleErrorf("violates " + n.String())
411*333d2b36SAndroid Build Coastguard Worker	}
412*333d2b36SAndroid Build Coastguard Worker}
413*333d2b36SAndroid Build Coastguard Worker
414*333d2b36SAndroid Build Coastguard Workertype ValueMatcher interface {
415*333d2b36SAndroid Build Coastguard Worker	Test(string) bool
416*333d2b36SAndroid Build Coastguard Worker	String() string
417*333d2b36SAndroid Build Coastguard Worker}
418*333d2b36SAndroid Build Coastguard Worker
419*333d2b36SAndroid Build Coastguard Workertype equalMatcher struct {
420*333d2b36SAndroid Build Coastguard Worker	expected string
421*333d2b36SAndroid Build Coastguard Worker}
422*333d2b36SAndroid Build Coastguard Worker
423*333d2b36SAndroid Build Coastguard Workerfunc (m *equalMatcher) Test(value string) bool {
424*333d2b36SAndroid Build Coastguard Worker	return m.expected == value
425*333d2b36SAndroid Build Coastguard Worker}
426*333d2b36SAndroid Build Coastguard Worker
427*333d2b36SAndroid Build Coastguard Workerfunc (m *equalMatcher) String() string {
428*333d2b36SAndroid Build Coastguard Worker	return "=" + m.expected
429*333d2b36SAndroid Build Coastguard Worker}
430*333d2b36SAndroid Build Coastguard Worker
431*333d2b36SAndroid Build Coastguard Workertype anyMatcher struct {
432*333d2b36SAndroid Build Coastguard Worker}
433*333d2b36SAndroid Build Coastguard Worker
434*333d2b36SAndroid Build Coastguard Workerfunc (m *anyMatcher) Test(value string) bool {
435*333d2b36SAndroid Build Coastguard Worker	return true
436*333d2b36SAndroid Build Coastguard Worker}
437*333d2b36SAndroid Build Coastguard Worker
438*333d2b36SAndroid Build Coastguard Workerfunc (m *anyMatcher) String() string {
439*333d2b36SAndroid Build Coastguard Worker	return "=*"
440*333d2b36SAndroid Build Coastguard Worker}
441*333d2b36SAndroid Build Coastguard Worker
442*333d2b36SAndroid Build Coastguard Workervar anyMatcherInstance = &anyMatcher{}
443*333d2b36SAndroid Build Coastguard Worker
444*333d2b36SAndroid Build Coastguard Workertype startsWithMatcher struct {
445*333d2b36SAndroid Build Coastguard Worker	prefix string
446*333d2b36SAndroid Build Coastguard Worker}
447*333d2b36SAndroid Build Coastguard Worker
448*333d2b36SAndroid Build Coastguard Workerfunc (m *startsWithMatcher) Test(value string) bool {
449*333d2b36SAndroid Build Coastguard Worker	return strings.HasPrefix(value, m.prefix)
450*333d2b36SAndroid Build Coastguard Worker}
451*333d2b36SAndroid Build Coastguard Worker
452*333d2b36SAndroid Build Coastguard Workerfunc (m *startsWithMatcher) String() string {
453*333d2b36SAndroid Build Coastguard Worker	return ".starts-with(" + m.prefix + ")"
454*333d2b36SAndroid Build Coastguard Worker}
455*333d2b36SAndroid Build Coastguard Worker
456*333d2b36SAndroid Build Coastguard Workertype regexMatcher struct {
457*333d2b36SAndroid Build Coastguard Worker	re *regexp.Regexp
458*333d2b36SAndroid Build Coastguard Worker}
459*333d2b36SAndroid Build Coastguard Worker
460*333d2b36SAndroid Build Coastguard Workerfunc (m *regexMatcher) Test(value string) bool {
461*333d2b36SAndroid Build Coastguard Worker	return m.re.MatchString(value)
462*333d2b36SAndroid Build Coastguard Worker}
463*333d2b36SAndroid Build Coastguard Worker
464*333d2b36SAndroid Build Coastguard Workerfunc (m *regexMatcher) String() string {
465*333d2b36SAndroid Build Coastguard Worker	return ".regexp(" + m.re.String() + ")"
466*333d2b36SAndroid Build Coastguard Worker}
467*333d2b36SAndroid Build Coastguard Worker
468*333d2b36SAndroid Build Coastguard Workertype notInListMatcher struct {
469*333d2b36SAndroid Build Coastguard Worker	allowed []string
470*333d2b36SAndroid Build Coastguard Worker}
471*333d2b36SAndroid Build Coastguard Worker
472*333d2b36SAndroid Build Coastguard Workerfunc (m *notInListMatcher) Test(value string) bool {
473*333d2b36SAndroid Build Coastguard Worker	return !InList(value, m.allowed)
474*333d2b36SAndroid Build Coastguard Worker}
475*333d2b36SAndroid Build Coastguard Worker
476*333d2b36SAndroid Build Coastguard Workerfunc (m *notInListMatcher) String() string {
477*333d2b36SAndroid Build Coastguard Worker	return ".not-in-list(" + strings.Join(m.allowed, ",") + ")"
478*333d2b36SAndroid Build Coastguard Worker}
479*333d2b36SAndroid Build Coastguard Worker
480*333d2b36SAndroid Build Coastguard Workertype isSetMatcher struct{}
481*333d2b36SAndroid Build Coastguard Worker
482*333d2b36SAndroid Build Coastguard Workerfunc (m *isSetMatcher) Test(value string) bool {
483*333d2b36SAndroid Build Coastguard Worker	return value != ""
484*333d2b36SAndroid Build Coastguard Worker}
485*333d2b36SAndroid Build Coastguard Worker
486*333d2b36SAndroid Build Coastguard Workerfunc (m *isSetMatcher) String() string {
487*333d2b36SAndroid Build Coastguard Worker	return ".is-set"
488*333d2b36SAndroid Build Coastguard Worker}
489*333d2b36SAndroid Build Coastguard Worker
490*333d2b36SAndroid Build Coastguard Workervar isSetMatcherInstance = &isSetMatcher{}
491*333d2b36SAndroid Build Coastguard Worker
492*333d2b36SAndroid Build Coastguard Workertype ruleProperty struct {
493*333d2b36SAndroid Build Coastguard Worker	fields  []string // e.x.: Vndk.Enabled
494*333d2b36SAndroid Build Coastguard Worker	matcher ValueMatcher
495*333d2b36SAndroid Build Coastguard Worker}
496*333d2b36SAndroid Build Coastguard Worker
497*333d2b36SAndroid Build Coastguard Workerfunc (r *ruleProperty) String() string {
498*333d2b36SAndroid Build Coastguard Worker	return fmt.Sprintf("%q matches: %s", strings.Join(r.fields, "."), r.matcher)
499*333d2b36SAndroid Build Coastguard Worker}
500*333d2b36SAndroid Build Coastguard Worker
501*333d2b36SAndroid Build Coastguard Workertype ruleProperties []ruleProperty
502*333d2b36SAndroid Build Coastguard Worker
503*333d2b36SAndroid Build Coastguard Workerfunc (r ruleProperties) String() string {
504*333d2b36SAndroid Build Coastguard Worker	var s []string
505*333d2b36SAndroid Build Coastguard Worker	for _, r := range r {
506*333d2b36SAndroid Build Coastguard Worker		s = append(s, r.String())
507*333d2b36SAndroid Build Coastguard Worker	}
508*333d2b36SAndroid Build Coastguard Worker	return strings.Join(s, " ")
509*333d2b36SAndroid Build Coastguard Worker}
510*333d2b36SAndroid Build Coastguard Worker
511*333d2b36SAndroid Build Coastguard Worker// A NeverAllow rule.
512*333d2b36SAndroid Build Coastguard Workertype Rule interface {
513*333d2b36SAndroid Build Coastguard Worker	In(path ...string) Rule
514*333d2b36SAndroid Build Coastguard Worker
515*333d2b36SAndroid Build Coastguard Worker	NotIn(path ...string) Rule
516*333d2b36SAndroid Build Coastguard Worker
517*333d2b36SAndroid Build Coastguard Worker	InDirectDeps(deps ...string) Rule
518*333d2b36SAndroid Build Coastguard Worker
519*333d2b36SAndroid Build Coastguard Worker	WithOsClass(osClasses ...OsClass) Rule
520*333d2b36SAndroid Build Coastguard Worker
521*333d2b36SAndroid Build Coastguard Worker	ModuleType(types ...string) Rule
522*333d2b36SAndroid Build Coastguard Worker
523*333d2b36SAndroid Build Coastguard Worker	NotModuleType(types ...string) Rule
524*333d2b36SAndroid Build Coastguard Worker
525*333d2b36SAndroid Build Coastguard Worker	With(properties, value string) Rule
526*333d2b36SAndroid Build Coastguard Worker
527*333d2b36SAndroid Build Coastguard Worker	WithMatcher(properties string, matcher ValueMatcher) Rule
528*333d2b36SAndroid Build Coastguard Worker
529*333d2b36SAndroid Build Coastguard Worker	Without(properties, value string) Rule
530*333d2b36SAndroid Build Coastguard Worker
531*333d2b36SAndroid Build Coastguard Worker	WithoutMatcher(properties string, matcher ValueMatcher) Rule
532*333d2b36SAndroid Build Coastguard Worker
533*333d2b36SAndroid Build Coastguard Worker	DefinedInBpFile() Rule
534*333d2b36SAndroid Build Coastguard Worker
535*333d2b36SAndroid Build Coastguard Worker	Because(reason string) Rule
536*333d2b36SAndroid Build Coastguard Worker}
537*333d2b36SAndroid Build Coastguard Worker
538*333d2b36SAndroid Build Coastguard Workertype rule struct {
539*333d2b36SAndroid Build Coastguard Worker	// User string for why this is a thing.
540*333d2b36SAndroid Build Coastguard Worker	reason string
541*333d2b36SAndroid Build Coastguard Worker
542*333d2b36SAndroid Build Coastguard Worker	paths       []string
543*333d2b36SAndroid Build Coastguard Worker	unlessPaths []string
544*333d2b36SAndroid Build Coastguard Worker
545*333d2b36SAndroid Build Coastguard Worker	directDeps map[string]bool
546*333d2b36SAndroid Build Coastguard Worker
547*333d2b36SAndroid Build Coastguard Worker	osClasses []OsClass
548*333d2b36SAndroid Build Coastguard Worker
549*333d2b36SAndroid Build Coastguard Worker	moduleTypes       []string
550*333d2b36SAndroid Build Coastguard Worker	unlessModuleTypes []string
551*333d2b36SAndroid Build Coastguard Worker
552*333d2b36SAndroid Build Coastguard Worker	props       ruleProperties
553*333d2b36SAndroid Build Coastguard Worker	unlessProps ruleProperties
554*333d2b36SAndroid Build Coastguard Worker
555*333d2b36SAndroid Build Coastguard Worker	onlyBootclasspathJar bool
556*333d2b36SAndroid Build Coastguard Worker
557*333d2b36SAndroid Build Coastguard Worker	definedInBp bool
558*333d2b36SAndroid Build Coastguard Worker}
559*333d2b36SAndroid Build Coastguard Worker
560*333d2b36SAndroid Build Coastguard Worker// Create a new NeverAllow rule.
561*333d2b36SAndroid Build Coastguard Workerfunc NeverAllow() Rule {
562*333d2b36SAndroid Build Coastguard Worker	return &rule{directDeps: make(map[string]bool)}
563*333d2b36SAndroid Build Coastguard Worker}
564*333d2b36SAndroid Build Coastguard Worker
565*333d2b36SAndroid Build Coastguard Worker// In adds path(s) where this rule applies.
566*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) In(path ...string) Rule {
567*333d2b36SAndroid Build Coastguard Worker	r.paths = append(r.paths, cleanPaths(path)...)
568*333d2b36SAndroid Build Coastguard Worker	return r
569*333d2b36SAndroid Build Coastguard Worker}
570*333d2b36SAndroid Build Coastguard Worker
571*333d2b36SAndroid Build Coastguard Worker// NotIn adds path(s) to that this rule does not apply to.
572*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) NotIn(path ...string) Rule {
573*333d2b36SAndroid Build Coastguard Worker	r.unlessPaths = append(r.unlessPaths, cleanPaths(path)...)
574*333d2b36SAndroid Build Coastguard Worker	return r
575*333d2b36SAndroid Build Coastguard Worker}
576*333d2b36SAndroid Build Coastguard Worker
577*333d2b36SAndroid Build Coastguard Worker// InDirectDeps adds dep(s) that are not allowed with this rule.
578*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) InDirectDeps(deps ...string) Rule {
579*333d2b36SAndroid Build Coastguard Worker	for _, d := range deps {
580*333d2b36SAndroid Build Coastguard Worker		r.directDeps[d] = true
581*333d2b36SAndroid Build Coastguard Worker	}
582*333d2b36SAndroid Build Coastguard Worker	return r
583*333d2b36SAndroid Build Coastguard Worker}
584*333d2b36SAndroid Build Coastguard Worker
585*333d2b36SAndroid Build Coastguard Worker// WithOsClass adds osClass(es) that this rule applies to.
586*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) WithOsClass(osClasses ...OsClass) Rule {
587*333d2b36SAndroid Build Coastguard Worker	r.osClasses = append(r.osClasses, osClasses...)
588*333d2b36SAndroid Build Coastguard Worker	return r
589*333d2b36SAndroid Build Coastguard Worker}
590*333d2b36SAndroid Build Coastguard Worker
591*333d2b36SAndroid Build Coastguard Worker// ModuleType adds type(s) that this rule applies to.
592*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) ModuleType(types ...string) Rule {
593*333d2b36SAndroid Build Coastguard Worker	r.moduleTypes = append(r.moduleTypes, types...)
594*333d2b36SAndroid Build Coastguard Worker	return r
595*333d2b36SAndroid Build Coastguard Worker}
596*333d2b36SAndroid Build Coastguard Worker
597*333d2b36SAndroid Build Coastguard Worker// NotModuleType adds type(s) that this rule does not apply to..
598*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) NotModuleType(types ...string) Rule {
599*333d2b36SAndroid Build Coastguard Worker	r.unlessModuleTypes = append(r.unlessModuleTypes, types...)
600*333d2b36SAndroid Build Coastguard Worker	return r
601*333d2b36SAndroid Build Coastguard Worker}
602*333d2b36SAndroid Build Coastguard Worker
603*333d2b36SAndroid Build Coastguard Worker// With specifies property/value combinations that are restricted for this rule.
604*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) With(properties, value string) Rule {
605*333d2b36SAndroid Build Coastguard Worker	return r.WithMatcher(properties, selectMatcher(value))
606*333d2b36SAndroid Build Coastguard Worker}
607*333d2b36SAndroid Build Coastguard Worker
608*333d2b36SAndroid Build Coastguard Worker// WithMatcher specifies property/matcher combinations that are restricted for this rule.
609*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) WithMatcher(properties string, matcher ValueMatcher) Rule {
610*333d2b36SAndroid Build Coastguard Worker	r.props = append(r.props, ruleProperty{
611*333d2b36SAndroid Build Coastguard Worker		fields:  fieldNamesForProperties(properties),
612*333d2b36SAndroid Build Coastguard Worker		matcher: matcher,
613*333d2b36SAndroid Build Coastguard Worker	})
614*333d2b36SAndroid Build Coastguard Worker	return r
615*333d2b36SAndroid Build Coastguard Worker}
616*333d2b36SAndroid Build Coastguard Worker
617*333d2b36SAndroid Build Coastguard Worker// Without specifies property/value combinations that this rule does not apply to.
618*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) Without(properties, value string) Rule {
619*333d2b36SAndroid Build Coastguard Worker	return r.WithoutMatcher(properties, selectMatcher(value))
620*333d2b36SAndroid Build Coastguard Worker}
621*333d2b36SAndroid Build Coastguard Worker
622*333d2b36SAndroid Build Coastguard Worker// Without specifies property/matcher combinations that this rule does not apply to.
623*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) WithoutMatcher(properties string, matcher ValueMatcher) Rule {
624*333d2b36SAndroid Build Coastguard Worker	r.unlessProps = append(r.unlessProps, ruleProperty{
625*333d2b36SAndroid Build Coastguard Worker		fields:  fieldNamesForProperties(properties),
626*333d2b36SAndroid Build Coastguard Worker		matcher: matcher,
627*333d2b36SAndroid Build Coastguard Worker	})
628*333d2b36SAndroid Build Coastguard Worker	return r
629*333d2b36SAndroid Build Coastguard Worker}
630*333d2b36SAndroid Build Coastguard Worker
631*333d2b36SAndroid Build Coastguard Worker// DefinedInBpFile specifies that this rule applies to modules that are defined
632*333d2b36SAndroid Build Coastguard Worker// in bp files, and does not apply to modules that are auto generated by other modules.
633*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) DefinedInBpFile() Rule {
634*333d2b36SAndroid Build Coastguard Worker	r.definedInBp = true
635*333d2b36SAndroid Build Coastguard Worker	return r
636*333d2b36SAndroid Build Coastguard Worker}
637*333d2b36SAndroid Build Coastguard Worker
638*333d2b36SAndroid Build Coastguard Workerfunc selectMatcher(expected string) ValueMatcher {
639*333d2b36SAndroid Build Coastguard Worker	if expected == "*" {
640*333d2b36SAndroid Build Coastguard Worker		return anyMatcherInstance
641*333d2b36SAndroid Build Coastguard Worker	}
642*333d2b36SAndroid Build Coastguard Worker	return &equalMatcher{expected: expected}
643*333d2b36SAndroid Build Coastguard Worker}
644*333d2b36SAndroid Build Coastguard Worker
645*333d2b36SAndroid Build Coastguard Worker// Because specifies a reason for this rule.
646*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) Because(reason string) Rule {
647*333d2b36SAndroid Build Coastguard Worker	r.reason = reason
648*333d2b36SAndroid Build Coastguard Worker	return r
649*333d2b36SAndroid Build Coastguard Worker}
650*333d2b36SAndroid Build Coastguard Worker
651*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) String() string {
652*333d2b36SAndroid Build Coastguard Worker	s := []string{"neverallow requirements. Not allowed:"}
653*333d2b36SAndroid Build Coastguard Worker	if len(r.paths) > 0 {
654*333d2b36SAndroid Build Coastguard Worker		s = append(s, fmt.Sprintf("in dirs: %q", r.paths))
655*333d2b36SAndroid Build Coastguard Worker	}
656*333d2b36SAndroid Build Coastguard Worker	if len(r.moduleTypes) > 0 {
657*333d2b36SAndroid Build Coastguard Worker		s = append(s, fmt.Sprintf("module types: %q", r.moduleTypes))
658*333d2b36SAndroid Build Coastguard Worker	}
659*333d2b36SAndroid Build Coastguard Worker	if len(r.props) > 0 {
660*333d2b36SAndroid Build Coastguard Worker		s = append(s, fmt.Sprintf("properties matching: %s", r.props))
661*333d2b36SAndroid Build Coastguard Worker	}
662*333d2b36SAndroid Build Coastguard Worker	if len(r.directDeps) > 0 {
663*333d2b36SAndroid Build Coastguard Worker		s = append(s, fmt.Sprintf("dep(s): %q", SortedKeys(r.directDeps)))
664*333d2b36SAndroid Build Coastguard Worker	}
665*333d2b36SAndroid Build Coastguard Worker	if len(r.osClasses) > 0 {
666*333d2b36SAndroid Build Coastguard Worker		s = append(s, fmt.Sprintf("os class(es): %q", r.osClasses))
667*333d2b36SAndroid Build Coastguard Worker	}
668*333d2b36SAndroid Build Coastguard Worker	if len(r.unlessPaths) > 0 {
669*333d2b36SAndroid Build Coastguard Worker		s = append(s, fmt.Sprintf("EXCEPT in dirs: %q", r.unlessPaths))
670*333d2b36SAndroid Build Coastguard Worker	}
671*333d2b36SAndroid Build Coastguard Worker	if len(r.unlessModuleTypes) > 0 {
672*333d2b36SAndroid Build Coastguard Worker		s = append(s, fmt.Sprintf("EXCEPT module types: %q", r.unlessModuleTypes))
673*333d2b36SAndroid Build Coastguard Worker	}
674*333d2b36SAndroid Build Coastguard Worker	if len(r.unlessProps) > 0 {
675*333d2b36SAndroid Build Coastguard Worker		s = append(s, fmt.Sprintf("EXCEPT properties matching: %q", r.unlessProps))
676*333d2b36SAndroid Build Coastguard Worker	}
677*333d2b36SAndroid Build Coastguard Worker	if len(r.reason) != 0 {
678*333d2b36SAndroid Build Coastguard Worker		s = append(s, " which is restricted because "+r.reason)
679*333d2b36SAndroid Build Coastguard Worker	}
680*333d2b36SAndroid Build Coastguard Worker	if len(s) == 1 {
681*333d2b36SAndroid Build Coastguard Worker		s[0] = "neverallow requirements (empty)"
682*333d2b36SAndroid Build Coastguard Worker	}
683*333d2b36SAndroid Build Coastguard Worker	return strings.Join(s, "\n\t")
684*333d2b36SAndroid Build Coastguard Worker}
685*333d2b36SAndroid Build Coastguard Worker
686*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) appliesToPath(dir string) bool {
687*333d2b36SAndroid Build Coastguard Worker	includePath := len(r.paths) == 0 || HasAnyPrefix(dir, r.paths)
688*333d2b36SAndroid Build Coastguard Worker	excludePath := HasAnyPrefix(dir, r.unlessPaths)
689*333d2b36SAndroid Build Coastguard Worker	return includePath && !excludePath
690*333d2b36SAndroid Build Coastguard Worker}
691*333d2b36SAndroid Build Coastguard Worker
692*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) appliesToDirectDeps(ctx BottomUpMutatorContext) bool {
693*333d2b36SAndroid Build Coastguard Worker	if len(r.directDeps) == 0 {
694*333d2b36SAndroid Build Coastguard Worker		return true
695*333d2b36SAndroid Build Coastguard Worker	}
696*333d2b36SAndroid Build Coastguard Worker
697*333d2b36SAndroid Build Coastguard Worker	matches := false
698*333d2b36SAndroid Build Coastguard Worker	ctx.VisitDirectDeps(func(m Module) {
699*333d2b36SAndroid Build Coastguard Worker		if !matches {
700*333d2b36SAndroid Build Coastguard Worker			name := ctx.OtherModuleName(m)
701*333d2b36SAndroid Build Coastguard Worker			matches = r.directDeps[name]
702*333d2b36SAndroid Build Coastguard Worker		}
703*333d2b36SAndroid Build Coastguard Worker	})
704*333d2b36SAndroid Build Coastguard Worker
705*333d2b36SAndroid Build Coastguard Worker	return matches
706*333d2b36SAndroid Build Coastguard Worker}
707*333d2b36SAndroid Build Coastguard Worker
708*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) appliesToOsClass(osClass OsClass) bool {
709*333d2b36SAndroid Build Coastguard Worker	if len(r.osClasses) == 0 {
710*333d2b36SAndroid Build Coastguard Worker		return true
711*333d2b36SAndroid Build Coastguard Worker	}
712*333d2b36SAndroid Build Coastguard Worker
713*333d2b36SAndroid Build Coastguard Worker	for _, c := range r.osClasses {
714*333d2b36SAndroid Build Coastguard Worker		if c == osClass {
715*333d2b36SAndroid Build Coastguard Worker			return true
716*333d2b36SAndroid Build Coastguard Worker		}
717*333d2b36SAndroid Build Coastguard Worker	}
718*333d2b36SAndroid Build Coastguard Worker
719*333d2b36SAndroid Build Coastguard Worker	return false
720*333d2b36SAndroid Build Coastguard Worker}
721*333d2b36SAndroid Build Coastguard Worker
722*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) appliesToModuleType(moduleType string) bool {
723*333d2b36SAndroid Build Coastguard Worker	// Remove prefix for auto-generated modules
724*333d2b36SAndroid Build Coastguard Worker	moduleType = strings.TrimSuffix(moduleType, "__loadHookModule")
725*333d2b36SAndroid Build Coastguard Worker	moduleType = strings.TrimSuffix(moduleType, "__bottomUpMutatorModule")
726*333d2b36SAndroid Build Coastguard Worker	return (len(r.moduleTypes) == 0 || InList(moduleType, r.moduleTypes)) && !InList(moduleType, r.unlessModuleTypes)
727*333d2b36SAndroid Build Coastguard Worker}
728*333d2b36SAndroid Build Coastguard Worker
729*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) appliesToProperties(ctx BottomUpMutatorContext, properties []interface{}) bool {
730*333d2b36SAndroid Build Coastguard Worker	includeProps := hasAllProperties(ctx, properties, r.props)
731*333d2b36SAndroid Build Coastguard Worker	excludeProps := hasAnyProperty(ctx, properties, r.unlessProps)
732*333d2b36SAndroid Build Coastguard Worker	return includeProps && !excludeProps
733*333d2b36SAndroid Build Coastguard Worker}
734*333d2b36SAndroid Build Coastguard Worker
735*333d2b36SAndroid Build Coastguard Workerfunc (r *rule) appliesToBpDefinedModule(ctx BottomUpMutatorContext) bool {
736*333d2b36SAndroid Build Coastguard Worker	if !r.definedInBp {
737*333d2b36SAndroid Build Coastguard Worker		return true
738*333d2b36SAndroid Build Coastguard Worker	}
739*333d2b36SAndroid Build Coastguard Worker	return !ctx.OtherModuleIsAutoGenerated(ctx.Module()) == r.definedInBp
740*333d2b36SAndroid Build Coastguard Worker}
741*333d2b36SAndroid Build Coastguard Worker
742*333d2b36SAndroid Build Coastguard Workerfunc StartsWith(prefix string) ValueMatcher {
743*333d2b36SAndroid Build Coastguard Worker	return &startsWithMatcher{prefix}
744*333d2b36SAndroid Build Coastguard Worker}
745*333d2b36SAndroid Build Coastguard Worker
746*333d2b36SAndroid Build Coastguard Workerfunc Regexp(re string) ValueMatcher {
747*333d2b36SAndroid Build Coastguard Worker	r, err := regexp.Compile(re)
748*333d2b36SAndroid Build Coastguard Worker	if err != nil {
749*333d2b36SAndroid Build Coastguard Worker		panic(err)
750*333d2b36SAndroid Build Coastguard Worker	}
751*333d2b36SAndroid Build Coastguard Worker	return &regexMatcher{r}
752*333d2b36SAndroid Build Coastguard Worker}
753*333d2b36SAndroid Build Coastguard Worker
754*333d2b36SAndroid Build Coastguard Workerfunc NotInList(allowed []string) ValueMatcher {
755*333d2b36SAndroid Build Coastguard Worker	return &notInListMatcher{allowed}
756*333d2b36SAndroid Build Coastguard Worker}
757*333d2b36SAndroid Build Coastguard Worker
758*333d2b36SAndroid Build Coastguard Worker// assorted utils
759*333d2b36SAndroid Build Coastguard Worker
760*333d2b36SAndroid Build Coastguard Workerfunc cleanPaths(paths []string) []string {
761*333d2b36SAndroid Build Coastguard Worker	res := make([]string, len(paths))
762*333d2b36SAndroid Build Coastguard Worker	for i, v := range paths {
763*333d2b36SAndroid Build Coastguard Worker		res[i] = filepath.Clean(v) + "/"
764*333d2b36SAndroid Build Coastguard Worker	}
765*333d2b36SAndroid Build Coastguard Worker	return res
766*333d2b36SAndroid Build Coastguard Worker}
767*333d2b36SAndroid Build Coastguard Worker
768*333d2b36SAndroid Build Coastguard Workerfunc fieldNamesForProperties(propertyNames string) []string {
769*333d2b36SAndroid Build Coastguard Worker	names := strings.Split(propertyNames, ".")
770*333d2b36SAndroid Build Coastguard Worker	for i, v := range names {
771*333d2b36SAndroid Build Coastguard Worker		names[i] = proptools.FieldNameForProperty(v)
772*333d2b36SAndroid Build Coastguard Worker	}
773*333d2b36SAndroid Build Coastguard Worker	return names
774*333d2b36SAndroid Build Coastguard Worker}
775*333d2b36SAndroid Build Coastguard Worker
776*333d2b36SAndroid Build Coastguard Workerfunc hasAnyProperty(ctx BottomUpMutatorContext, properties []interface{}, props []ruleProperty) bool {
777*333d2b36SAndroid Build Coastguard Worker	for _, v := range props {
778*333d2b36SAndroid Build Coastguard Worker		if hasProperty(ctx, properties, v) {
779*333d2b36SAndroid Build Coastguard Worker			return true
780*333d2b36SAndroid Build Coastguard Worker		}
781*333d2b36SAndroid Build Coastguard Worker	}
782*333d2b36SAndroid Build Coastguard Worker	return false
783*333d2b36SAndroid Build Coastguard Worker}
784*333d2b36SAndroid Build Coastguard Worker
785*333d2b36SAndroid Build Coastguard Workerfunc hasAllProperties(ctx BottomUpMutatorContext, properties []interface{}, props []ruleProperty) bool {
786*333d2b36SAndroid Build Coastguard Worker	for _, v := range props {
787*333d2b36SAndroid Build Coastguard Worker		if !hasProperty(ctx, properties, v) {
788*333d2b36SAndroid Build Coastguard Worker			return false
789*333d2b36SAndroid Build Coastguard Worker		}
790*333d2b36SAndroid Build Coastguard Worker	}
791*333d2b36SAndroid Build Coastguard Worker	return true
792*333d2b36SAndroid Build Coastguard Worker}
793*333d2b36SAndroid Build Coastguard Worker
794*333d2b36SAndroid Build Coastguard Workerfunc hasProperty(ctx BottomUpMutatorContext, properties []interface{}, prop ruleProperty) bool {
795*333d2b36SAndroid Build Coastguard Worker	for _, propertyStruct := range properties {
796*333d2b36SAndroid Build Coastguard Worker		propertiesValue := reflect.ValueOf(propertyStruct).Elem()
797*333d2b36SAndroid Build Coastguard Worker		for _, v := range prop.fields {
798*333d2b36SAndroid Build Coastguard Worker			if !propertiesValue.IsValid() {
799*333d2b36SAndroid Build Coastguard Worker				break
800*333d2b36SAndroid Build Coastguard Worker			}
801*333d2b36SAndroid Build Coastguard Worker			propertiesValue = propertiesValue.FieldByName(v)
802*333d2b36SAndroid Build Coastguard Worker		}
803*333d2b36SAndroid Build Coastguard Worker		if !propertiesValue.IsValid() {
804*333d2b36SAndroid Build Coastguard Worker			continue
805*333d2b36SAndroid Build Coastguard Worker		}
806*333d2b36SAndroid Build Coastguard Worker
807*333d2b36SAndroid Build Coastguard Worker		check := func(value string) bool {
808*333d2b36SAndroid Build Coastguard Worker			return prop.matcher.Test(value)
809*333d2b36SAndroid Build Coastguard Worker		}
810*333d2b36SAndroid Build Coastguard Worker
811*333d2b36SAndroid Build Coastguard Worker		if matchValue(ctx, propertiesValue, check) {
812*333d2b36SAndroid Build Coastguard Worker			return true
813*333d2b36SAndroid Build Coastguard Worker		}
814*333d2b36SAndroid Build Coastguard Worker	}
815*333d2b36SAndroid Build Coastguard Worker	return false
816*333d2b36SAndroid Build Coastguard Worker}
817*333d2b36SAndroid Build Coastguard Worker
818*333d2b36SAndroid Build Coastguard Workerfunc matchValue(ctx BottomUpMutatorContext, value reflect.Value, check func(string) bool) bool {
819*333d2b36SAndroid Build Coastguard Worker	if !value.IsValid() {
820*333d2b36SAndroid Build Coastguard Worker		return false
821*333d2b36SAndroid Build Coastguard Worker	}
822*333d2b36SAndroid Build Coastguard Worker
823*333d2b36SAndroid Build Coastguard Worker	if value.Kind() == reflect.Ptr {
824*333d2b36SAndroid Build Coastguard Worker		if value.IsNil() {
825*333d2b36SAndroid Build Coastguard Worker			return check("")
826*333d2b36SAndroid Build Coastguard Worker		}
827*333d2b36SAndroid Build Coastguard Worker		value = value.Elem()
828*333d2b36SAndroid Build Coastguard Worker	}
829*333d2b36SAndroid Build Coastguard Worker
830*333d2b36SAndroid Build Coastguard Worker	switch v := value.Interface().(type) {
831*333d2b36SAndroid Build Coastguard Worker	case string:
832*333d2b36SAndroid Build Coastguard Worker		return check(v)
833*333d2b36SAndroid Build Coastguard Worker	case bool:
834*333d2b36SAndroid Build Coastguard Worker		return check(strconv.FormatBool(v))
835*333d2b36SAndroid Build Coastguard Worker	case int:
836*333d2b36SAndroid Build Coastguard Worker		return check(strconv.FormatInt((int64)(v), 10))
837*333d2b36SAndroid Build Coastguard Worker	case []string:
838*333d2b36SAndroid Build Coastguard Worker		for _, v := range v {
839*333d2b36SAndroid Build Coastguard Worker			if check(v) {
840*333d2b36SAndroid Build Coastguard Worker				return true
841*333d2b36SAndroid Build Coastguard Worker			}
842*333d2b36SAndroid Build Coastguard Worker		}
843*333d2b36SAndroid Build Coastguard Worker		return false
844*333d2b36SAndroid Build Coastguard Worker	case proptools.Configurable[string]:
845*333d2b36SAndroid Build Coastguard Worker		return check(v.GetOrDefault(ctx, ""))
846*333d2b36SAndroid Build Coastguard Worker	case proptools.Configurable[bool]:
847*333d2b36SAndroid Build Coastguard Worker		return check(strconv.FormatBool(v.GetOrDefault(ctx, false)))
848*333d2b36SAndroid Build Coastguard Worker	case proptools.Configurable[[]string]:
849*333d2b36SAndroid Build Coastguard Worker		for _, v := range v.GetOrDefault(ctx, nil) {
850*333d2b36SAndroid Build Coastguard Worker			if check(v) {
851*333d2b36SAndroid Build Coastguard Worker				return true
852*333d2b36SAndroid Build Coastguard Worker			}
853*333d2b36SAndroid Build Coastguard Worker		}
854*333d2b36SAndroid Build Coastguard Worker		return false
855*333d2b36SAndroid Build Coastguard Worker	}
856*333d2b36SAndroid Build Coastguard Worker
857*333d2b36SAndroid Build Coastguard Worker	panic("Can't handle type: " + value.Kind().String())
858*333d2b36SAndroid Build Coastguard Worker}
859*333d2b36SAndroid Build Coastguard Worker
860*333d2b36SAndroid Build Coastguard Workervar neverallowRulesKey = NewOnceKey("neverallowRules")
861*333d2b36SAndroid Build Coastguard Worker
862*333d2b36SAndroid Build Coastguard Workerfunc neverallowRules(config Config) []Rule {
863*333d2b36SAndroid Build Coastguard Worker	return config.Once(neverallowRulesKey, func() interface{} {
864*333d2b36SAndroid Build Coastguard Worker		// No test rules were set by setTestNeverallowRules, use the global rules
865*333d2b36SAndroid Build Coastguard Worker		return neverallows
866*333d2b36SAndroid Build Coastguard Worker	}).([]Rule)
867*333d2b36SAndroid Build Coastguard Worker}
868*333d2b36SAndroid Build Coastguard Worker
869*333d2b36SAndroid Build Coastguard Worker// Overrides the default neverallow rules for the supplied config.
870*333d2b36SAndroid Build Coastguard Worker//
871*333d2b36SAndroid Build Coastguard Worker// For testing only.
872*333d2b36SAndroid Build Coastguard Workerfunc setTestNeverallowRules(config Config, testRules []Rule) {
873*333d2b36SAndroid Build Coastguard Worker	config.Once(neverallowRulesKey, func() interface{} { return testRules })
874*333d2b36SAndroid Build Coastguard Worker}
875*333d2b36SAndroid Build Coastguard Worker
876*333d2b36SAndroid Build Coastguard Worker// Prepares for a test by setting neverallow rules and enabling the mutator.
877*333d2b36SAndroid Build Coastguard Worker//
878*333d2b36SAndroid Build Coastguard Worker// If the supplied rules are nil then the default rules are used.
879*333d2b36SAndroid Build Coastguard Workerfunc PrepareForTestWithNeverallowRules(testRules []Rule) FixturePreparer {
880*333d2b36SAndroid Build Coastguard Worker	return GroupFixturePreparers(
881*333d2b36SAndroid Build Coastguard Worker		FixtureModifyConfig(func(config Config) {
882*333d2b36SAndroid Build Coastguard Worker			if testRules != nil {
883*333d2b36SAndroid Build Coastguard Worker				setTestNeverallowRules(config, testRules)
884*333d2b36SAndroid Build Coastguard Worker			}
885*333d2b36SAndroid Build Coastguard Worker		}),
886*333d2b36SAndroid Build Coastguard Worker		FixtureRegisterWithContext(func(ctx RegistrationContext) {
887*333d2b36SAndroid Build Coastguard Worker			ctx.PostDepsMutators(registerNeverallowMutator)
888*333d2b36SAndroid Build Coastguard Worker		}),
889*333d2b36SAndroid Build Coastguard Worker	)
890*333d2b36SAndroid Build Coastguard Worker}
891