Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6aa5c403 authored by Colin Cross's avatar Colin Cross
Browse files

Strengthen metalava sandbox support using sbox

Run sandbox metalava rules inside sbox, which copies only the expected
inputs into a separate directory tree.  This ensures it can't read any
extra inputs.

Test: m hwbinder.stubs
Test: TestDroidstubs
Test: TestDroidstubsSandboxed
Change-Id: I71a83e3af6a385cc23f895397c2c883a2ac5fa22
parent cb77f75a
Loading
Loading
Loading
Loading
+69 −47
Original line number Diff line number Diff line
@@ -383,13 +383,22 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi

	if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA") {
		rule.Remoteable(android.RemoteRuleSupports{RBE: true})
		pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "metalava")
		if sandbox {
			execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
		labels := map[string]string{"type": "compile", "lang": "java", "compiler": "metalava"}
		if !sandbox {
			execStrategy = remoteexec.LocalExecStrategy
			labels["shallow"] = "true"
		}
			labels := map[string]string{"type": "tool", "name": "metalava"}
			// TODO: metalava pool rejects these jobs
			pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
			rule.Rewrapper(&remoteexec.REParams{
				Labels:          labels,
				ExecStrategy:    execStrategy,
				ToolchainInputs: []string{config.JavaCmd(ctx).String()},
				Platform:        map[string]string{remoteexec.PoolKey: pool},
			})
		} else {
			execStrategy := remoteexec.LocalExecStrategy
			labels := map[string]string{"type": "compile", "lang": "java", "compiler": "metalava", "shallow": "true"}
			pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "metalava")

			inputs := []string{
				ctx.Config().HostJavaToolPath(ctx, "metalava").String(),
				homeDir.String(),
@@ -407,8 +416,9 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi
				EnvironmentVariables: []string{"ANDROID_PREFS_ROOT"},
			}).NoVarTemplate(ctx.Config().RBEWrapper()))
		}
	}

	cmd.BuiltTool("metalava").
	cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
		Flag(config.JavacVmFlags).
		Flag("-J--add-opens=java.base/java.util=ALL-UNNAMED").
		FlagWithArg("-encoding ", "UTF-8").
@@ -416,19 +426,17 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi
		FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
		FlagWithInput("@", srcJarList)

	if !sandbox {
		if javaHome := ctx.Config().Getenv("ANDROID_JAVA_HOME"); javaHome != "" {
			cmd.Implicit(android.PathForSource(ctx, javaHome))
		}

	if sandbox {
		cmd.FlagWithOutput("--strict-input-files ", android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"violations.txt"))
	} else {
		cmd.FlagWithOutput("--strict-input-files:warn ", android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"violations.txt"))
	}

		if implicitsRsp != nil {
			cmd.FlagWithArg("--strict-input-files-exempt ", "@"+implicitsRsp.String())
		}
	}

	if len(bootclasspath) > 0 {
		cmd.FlagWithInputList("-bootclasspath ", bootclasspath.Paths(), ":")
@@ -465,6 +473,13 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {

	rule := android.NewRuleBuilder(pctx, ctx)

	sandbox := proptools.Bool(d.Javadoc.properties.Sandbox)
	if sandbox {
		rule.Sbox(android.PathForModuleOut(ctx, "metalava"),
			android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
			SandboxInputs()
	}

	if BoolDefault(d.properties.High_mem, false) {
		// This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
		rule.HighMem()
@@ -485,7 +500,7 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	homeDir := android.PathForModuleOut(ctx, "metalava", "home")
	cmd := metalavaCmd(ctx, rule, javaVersion, d.Javadoc.srcFiles, srcJarList,
		deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths, implicitsRsp, homeDir,
		Bool(d.Javadoc.properties.Sandbox))
		sandbox)
	cmd.Implicits(d.Javadoc.implicits)

	d.stubsFlags(ctx, cmd, stubsDir)
@@ -610,6 +625,9 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
		cmd.FlagWithArg("--error-message:compatibility:released ", msg)
	}

	if !sandbox {
		// When sandboxing is enabled RuleBuilder tracks all the inputs needed for remote execution.
		// Without it we have to do it manually.
		impRule := android.NewRuleBuilder(pctx, ctx)
		impCmd := impRule.Command()
		// An action that copies the ninja generated rsp file to a new location. This allows us to
@@ -621,6 +639,7 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
			Output(implicitsRsp)
		impRule.Build("implicitsGen", "implicits generation")
		cmd.Implicit(implicitsRsp)
	}

	if generateStubs {
		rule.Command().
@@ -652,7 +671,10 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
		rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
	}

	// TODO(b/183630617): rewrapper doesn't support restat rules
	if !sandbox {
		rule.Restat()
	}

	zipSyncCleanupCmd(rule, srcJarDir)

+20 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
package java

import (
	"reflect"
	"strings"
	"testing"

@@ -78,6 +79,25 @@ func TestDroidstubs(t *testing.T) {
	}
}

func TestDroidstubsSandbox(t *testing.T) {
	ctx, _ := testJavaWithFS(t, `
		droidstubs {
			name: "bar-stubs",
			srcs: ["bar-doc/a.java"],
			sandbox: true,
		}
		`,
		map[string][]byte{
			"bar-doc/a.java": nil,
		})

	m := ctx.ModuleForTests("bar-stubs", "android_common")
	metalava := m.Rule("metalava")
	if g, w := metalava.Inputs.Strings(), []string{"bar-doc/a.java"}; !reflect.DeepEqual(w, g) {
		t.Errorf("Expected inputs %q, got %q", w, g)
	}
}

func TestDroidstubsWithSystemModules(t *testing.T) {
	ctx, _ := testJava(t, `
		droidstubs {