From 3578188fac7199bb5df193d719ca26f95448077a Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Thu, 25 Jul 2019 15:41:09 +0100 Subject: [PATCH 1/2] Support restrictions based on a module's dependencies Adds a neverallow InDirectDeps(deps) verb that will allow a neverallow rule to restrict access to a specific dependency, irrespective of how it is specified. Bug: 137543088 Test: m nothing Change-Id: I0c6bb702d55175e9b78b79e86e96924c5dd83efa --- android/neverallow.go | 36 ++++++++++++++++++++++++++++++- android/neverallow_test.go | 44 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/android/neverallow.go b/android/neverallow.go index 23b645413..be396fc18 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -189,6 +189,10 @@ func neverallowMutator(ctx BottomUpMutatorContext) { continue } + if !n.appliesToDirectDeps(ctx) { + continue + } + ctx.ModuleErrorf("violates " + n.String()) } } @@ -246,6 +250,8 @@ type Rule interface { NotIn(path ...string) Rule + InDirectDeps(deps ...string) Rule + ModuleType(types ...string) Rule NotModuleType(types ...string) Rule @@ -268,6 +274,8 @@ type rule struct { paths []string unlessPaths []string + directDeps map[string]bool + moduleTypes []string unlessModuleTypes []string @@ -277,7 +285,7 @@ type rule struct { // Create a new NeverAllow rule. func NeverAllow() Rule { - return &rule{} + return &rule{directDeps: make(map[string]bool)} } func (r *rule) In(path ...string) Rule { @@ -290,6 +298,13 @@ func (r *rule) NotIn(path ...string) Rule { return r } +func (r *rule) InDirectDeps(deps ...string) Rule { + for _, d := range deps { + r.directDeps[d] = true + } + return r +} + func (r *rule) ModuleType(types ...string) Rule { r.moduleTypes = append(r.moduleTypes, types...) return r @@ -356,6 +371,9 @@ func (r *rule) String() string { for _, v := range r.unlessProps { s += " -" + strings.Join(v.fields, ".") + v.matcher.String() } + for k := range r.directDeps { + s += " deps:" + k + } if len(r.reason) != 0 { s += " which is restricted because " + r.reason } @@ -368,6 +386,22 @@ func (r *rule) appliesToPath(dir string) bool { return includePath && !excludePath } +func (r *rule) appliesToDirectDeps(ctx BottomUpMutatorContext) bool { + if len(r.directDeps) == 0 { + return true + } + + matches := false + ctx.VisitDirectDeps(func(m Module) { + if !matches { + name := ctx.OtherModuleName(m) + matches = r.directDeps[name] + } + }) + + return matches +} + func (r *rule) appliesToModuleType(moduleType string) bool { return (len(r.moduleTypes) == 0 || InList(moduleType, r.moduleTypes)) && !InList(moduleType, r.unlessModuleTypes) } diff --git a/android/neverallow_test.go b/android/neverallow_test.go index 02b436211..920b9a55c 100644 --- a/android/neverallow_test.go +++ b/android/neverallow_test.go @@ -16,13 +16,43 @@ package android import ( "testing" + + "github.com/google/blueprint" ) +func init() { + // Add extra rules needed for testing. + AddNeverAllowRules( + NeverAllow().InDirectDeps("not_allowed_in_direct_deps"), + ) +} + var neverallowTests = []struct { name string fs map[string][]byte expectedError string }{ + // Test General Functionality + + // in direct deps tests + { + name: "not_allowed_in_direct_deps", + fs: map[string][]byte{ + "top/Blueprints": []byte(` + cc_library { + name: "not_allowed_in_direct_deps", + }`), + "other/Blueprints": []byte(` + cc_library { + name: "libother", + static_libs: ["not_allowed_in_direct_deps"], + }`), + }, + expectedError: `module "libother": violates neverallow deps:not_allowed_in_direct_deps`, + }, + + // Test specific rules + // include_dir rule tests { name: "include_dir not allowed to reference art", @@ -242,6 +272,7 @@ func testNeverallow(t *testing.T, config Config, fs map[string][]byte) (*TestCon type mockCcLibraryProperties struct { Include_dirs []string Vendor_available *bool + Static_libs []string Vndk struct { Enabled *bool @@ -272,6 +303,19 @@ func newMockCcLibraryModule() Module { return m } +type neverallowTestDependencyTag struct { + blueprint.BaseDependencyTag + name string +} + +var staticDepTag = neverallowTestDependencyTag{name: "static"} + +func (c *mockCcLibraryModule) DepsMutator(ctx BottomUpMutatorContext) { + for _, lib := range c.properties.Static_libs { + ctx.AddDependency(ctx.Module(), staticDepTag, lib) + } +} + func (p *mockCcLibraryModule) GenerateAndroidBuildActions(ModuleContext) { } From f1c9bbee88e0691363edc29affe2f6ca16d6470f Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Fri, 26 Jul 2019 10:48:06 +0100 Subject: [PATCH 2/2] Support restrictions based on a module's OsClass Bug: 137543088 Test: m nothing Change-Id: Ibb05f222594d8180746b612c04ab1538a1cf3c0b --- android/neverallow.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/android/neverallow.go b/android/neverallow.go index be396fc18..8355bb3b8 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -175,6 +175,8 @@ func neverallowMutator(ctx BottomUpMutatorContext) { dir := ctx.ModuleDir() + "/" properties := m.GetProperties() + osClass := ctx.Module().Target().Os.Class + for _, r := range neverallows { n := r.(*rule) if !n.appliesToPath(dir) { @@ -189,6 +191,10 @@ func neverallowMutator(ctx BottomUpMutatorContext) { continue } + if !n.appliesToOsClass(osClass) { + continue + } + if !n.appliesToDirectDeps(ctx) { continue } @@ -252,6 +258,8 @@ type Rule interface { InDirectDeps(deps ...string) Rule + WithOsClass(osClasses ...OsClass) Rule + ModuleType(types ...string) Rule NotModuleType(types ...string) Rule @@ -276,6 +284,8 @@ type rule struct { directDeps map[string]bool + osClasses []OsClass + moduleTypes []string unlessModuleTypes []string @@ -305,6 +315,11 @@ func (r *rule) InDirectDeps(deps ...string) Rule { return r } +func (r *rule) WithOsClass(osClasses ...OsClass) Rule { + r.osClasses = append(r.osClasses, osClasses...) + return r +} + func (r *rule) ModuleType(types ...string) Rule { r.moduleTypes = append(r.moduleTypes, types...) return r @@ -374,6 +389,9 @@ func (r *rule) String() string { for k := range r.directDeps { s += " deps:" + k } + for _, v := range r.osClasses { + s += " os:" + v.String() + } if len(r.reason) != 0 { s += " which is restricted because " + r.reason } @@ -402,6 +420,20 @@ func (r *rule) appliesToDirectDeps(ctx BottomUpMutatorContext) bool { return matches } +func (r *rule) appliesToOsClass(osClass OsClass) bool { + if len(r.osClasses) == 0 { + return true + } + + for _, c := range r.osClasses { + if c == osClass { + return true + } + } + + return false +} + func (r *rule) appliesToModuleType(moduleType string) bool { return (len(r.moduleTypes) == 0 || InList(moduleType, r.moduleTypes)) && !InList(moduleType, r.unlessModuleTypes) }