Allow neverallow rules to be defined by custom bootstrap_go_packages

* Adds a Rule interface to hide the rule struct and expose the mutator
functions.
* Makes the neverallow() function public as NeverAllow().
* Adds AddNeverAllowRules func to add more rules.
* Moves the population of the builtin rules to init() function.

Bug: 136159343
Test: m droid
      - changed a built in rule to cause build failure to ensure the
	    rules were still being applied, then reverted the change and
		ran 'm droid' again.

Change-Id: Ie3a4456d1f6bc12c5b4931bf698333275347fdf0
This commit is contained in:
Paul Duffin
2019-06-27 14:08:51 +01:00
parent 32147a984d
commit 18af090842

View File

@@ -31,62 +31,65 @@ import (
// work regardless of these restrictions. // work regardless of these restrictions.
// //
// A module is disallowed if all of the following are true: // A module is disallowed if all of the following are true:
// - it is in one of the "in" paths // - it is in one of the "In" paths
// - it is not in one of the "notIn" paths // - it is not in one of the "NotIn" paths
// - it has all "with" properties matched // - it has all "With" properties matched
// - - values are matched in their entirety // - - values are matched in their entirety
// - - nil is interpreted as an empty string // - - nil is interpreted as an empty string
// - - nested properties are separated with a '.' // - - nested properties are separated with a '.'
// - - if the property is a list, any of the values in the list being matches // - - if the property is a list, any of the values in the list being matches
// counts as a match // counts as a match
// - it has none of the "without" properties matched (same rules as above) // - it has none of the "Without" properties matched (same rules as above)
func registerNeverallowMutator(ctx RegisterMutatorsContext) { func registerNeverallowMutator(ctx RegisterMutatorsContext) {
ctx.BottomUp("neverallow", neverallowMutator).Parallel() ctx.BottomUp("neverallow", neverallowMutator).Parallel()
} }
var neverallows = createNeverAllows() var neverallows = []Rule{}
func createNeverAllows() []*rule { func init() {
rules := []*rule{} AddNeverAllowRules(createTrebleRules()...)
rules = append(rules, createTrebleRules()...) AddNeverAllowRules(createLibcoreRules()...)
rules = append(rules, createLibcoreRules()...) AddNeverAllowRules(createMediaRules()...)
rules = append(rules, createMediaRules()...) AddNeverAllowRules(createJavaDeviceForHostRules()...)
rules = append(rules, createJavaDeviceForHostRules()...)
return rules
} }
func createTrebleRules() []*rule { // Add a NeverAllow rule to the set of rules to apply.
return []*rule{ func AddNeverAllowRules(rules ...Rule) {
neverallow(). neverallows = append(neverallows, rules...)
in("vendor", "device"). }
with("vndk.enabled", "true").
without("vendor", "true"). func createTrebleRules() []Rule {
because("the VNDK can never contain a library that is device dependent."), return []Rule{
neverallow(). NeverAllow().
with("vndk.enabled", "true"). In("vendor", "device").
without("vendor", "true"). With("vndk.enabled", "true").
without("owner", ""). Without("vendor", "true").
because("a VNDK module can never have an owner."), Because("the VNDK can never contain a library that is device dependent."),
NeverAllow().
With("vndk.enabled", "true").
Without("vendor", "true").
Without("owner", "").
Because("a VNDK module can never have an owner."),
// TODO(b/67974785): always enforce the manifest // TODO(b/67974785): always enforce the manifest
neverallow(). NeverAllow().
without("name", "libhidltransport-impl-internal"). Without("name", "libhidltransport-impl-internal").
with("product_variables.enforce_vintf_manifest.cflags", "*"). With("product_variables.enforce_vintf_manifest.cflags", "*").
because("manifest enforcement should be independent of ."), Because("manifest enforcement should be independent of ."),
// TODO(b/67975799): vendor code should always use /vendor/bin/sh // TODO(b/67975799): vendor code should always use /vendor/bin/sh
neverallow(). NeverAllow().
without("name", "libc_bionic_ndk"). Without("name", "libc_bionic_ndk").
with("product_variables.treble_linker_namespaces.cflags", "*"). With("product_variables.treble_linker_namespaces.cflags", "*").
because("nothing should care if linker namespaces are enabled or not"), Because("nothing should care if linker namespaces are enabled or not"),
// Example: // Example:
// *neverallow().with("Srcs", "main.cpp")) // *NeverAllow().with("Srcs", "main.cpp"))
} }
} }
func createLibcoreRules() []*rule { func createLibcoreRules() []Rule {
var coreLibraryProjects = []string{ var coreLibraryProjects = []string{
"libcore", "libcore",
"external/apache-harmony", "external/apache-harmony",
@@ -103,35 +106,35 @@ func createLibcoreRules() []*rule {
// Core library constraints. The sdk_version: "none" can only be used in core library projects. // Core library constraints. The sdk_version: "none" can only be used in core library projects.
// Access to core library targets is restricted using visibility rules. // Access to core library targets is restricted using visibility rules.
rules := []*rule{ rules := []Rule{
neverallow(). NeverAllow().
notIn(coreLibraryProjects...). NotIn(coreLibraryProjects...).
with("sdk_version", "none"), With("sdk_version", "none"),
} }
return rules return rules
} }
func createMediaRules() []*rule { func createMediaRules() []Rule {
return []*rule{ return []Rule{
neverallow(). NeverAllow().
with("libs", "updatable-media"). With("libs", "updatable-media").
because("updatable-media includes private APIs. Use updatable_media_stubs instead."), Because("updatable-media includes private APIs. Use updatable_media_stubs instead."),
} }
} }
func createJavaDeviceForHostRules() []*rule { func createJavaDeviceForHostRules() []Rule {
javaDeviceForHostProjectsWhitelist := []string{ javaDeviceForHostProjectsWhitelist := []string{
"external/guava", "external/guava",
"external/robolectric-shadows", "external/robolectric-shadows",
"framework/layoutlib", "framework/layoutlib",
} }
return []*rule{ return []Rule{
neverallow(). NeverAllow().
notIn(javaDeviceForHostProjectsWhitelist...). NotIn(javaDeviceForHostProjectsWhitelist...).
moduleType("java_device_for_host", "java_host_for_device"). ModuleType("java_device_for_host", "java_host_for_device").
because("java_device_for_host can only be used in whitelisted projects"), Because("java_device_for_host can only be used in whitelisted projects"),
} }
} }
@@ -144,7 +147,8 @@ func neverallowMutator(ctx BottomUpMutatorContext) {
dir := ctx.ModuleDir() + "/" dir := ctx.ModuleDir() + "/"
properties := m.GetProperties() properties := m.GetProperties()
for _, n := range neverallows { for _, r := range neverallows {
n := r.(*rule)
if !n.appliesToPath(dir) { if !n.appliesToPath(dir) {
continue continue
} }
@@ -166,6 +170,23 @@ type ruleProperty struct {
value string // e.x.: true value string // e.x.: true
} }
// A NeverAllow rule.
type Rule interface {
In(path ...string) Rule
NotIn(path ...string) Rule
ModuleType(types ...string) Rule
NotModuleType(types ...string) Rule
With(properties, value string) Rule
Without(properties, value string) Rule
Because(reason string) Rule
}
type rule struct { type rule struct {
// User string for why this is a thing. // User string for why this is a thing.
reason string reason string
@@ -180,31 +201,32 @@ type rule struct {
unlessProps []ruleProperty unlessProps []ruleProperty
} }
func neverallow() *rule { // Create a new NeverAllow rule.
func NeverAllow() Rule {
return &rule{} return &rule{}
} }
func (r *rule) in(path ...string) *rule { func (r *rule) In(path ...string) Rule {
r.paths = append(r.paths, cleanPaths(path)...) r.paths = append(r.paths, cleanPaths(path)...)
return r return r
} }
func (r *rule) notIn(path ...string) *rule { func (r *rule) NotIn(path ...string) Rule {
r.unlessPaths = append(r.unlessPaths, cleanPaths(path)...) r.unlessPaths = append(r.unlessPaths, cleanPaths(path)...)
return r return r
} }
func (r *rule) moduleType(types ...string) *rule { func (r *rule) ModuleType(types ...string) Rule {
r.moduleTypes = append(r.moduleTypes, types...) r.moduleTypes = append(r.moduleTypes, types...)
return r return r
} }
func (r *rule) notModuleType(types ...string) *rule { func (r *rule) NotModuleType(types ...string) Rule {
r.unlessModuleTypes = append(r.unlessModuleTypes, types...) r.unlessModuleTypes = append(r.unlessModuleTypes, types...)
return r return r
} }
func (r *rule) with(properties, value string) *rule { func (r *rule) With(properties, value string) Rule {
r.props = append(r.props, ruleProperty{ r.props = append(r.props, ruleProperty{
fields: fieldNamesForProperties(properties), fields: fieldNamesForProperties(properties),
value: value, value: value,
@@ -212,7 +234,7 @@ func (r *rule) with(properties, value string) *rule {
return r return r
} }
func (r *rule) without(properties, value string) *rule { func (r *rule) Without(properties, value string) Rule {
r.unlessProps = append(r.unlessProps, ruleProperty{ r.unlessProps = append(r.unlessProps, ruleProperty{
fields: fieldNamesForProperties(properties), fields: fieldNamesForProperties(properties),
value: value, value: value,
@@ -220,7 +242,7 @@ func (r *rule) without(properties, value string) *rule {
return r return r
} }
func (r *rule) because(reason string) *rule { func (r *rule) Because(reason string) Rule {
r.reason = reason r.reason = reason
return r return r
} }