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
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 75dd86b..e453e62 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -383,32 +383,42 @@
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA") {
rule.Remoteable(android.RemoteRuleSupports{RBE: true})
- pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "metalava")
- 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"
+ if sandbox {
+ execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
+ 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(),
+ }
+ if v := ctx.Config().Getenv("RBE_METALAVA_INPUTS"); v != "" {
+ inputs = append(inputs, strings.Split(v, ",")...)
+ }
+ cmd.Text((&remoteexec.REParams{
+ Labels: labels,
+ ExecStrategy: execStrategy,
+ Inputs: inputs,
+ RSPFiles: []string{implicitsRsp.String()},
+ ToolchainInputs: []string{config.JavaCmd(ctx).String()},
+ Platform: map[string]string{remoteexec.PoolKey: pool},
+ EnvironmentVariables: []string{"ANDROID_PREFS_ROOT"},
+ }).NoVarTemplate(ctx.Config().RBEWrapper()))
}
- inputs := []string{
- ctx.Config().HostJavaToolPath(ctx, "metalava").String(),
- homeDir.String(),
- }
- if v := ctx.Config().Getenv("RBE_METALAVA_INPUTS"); v != "" {
- inputs = append(inputs, strings.Split(v, ",")...)
- }
- cmd.Text((&remoteexec.REParams{
- Labels: labels,
- ExecStrategy: execStrategy,
- Inputs: inputs,
- RSPFiles: []string{implicitsRsp.String()},
- ToolchainInputs: []string{config.JavaCmd(ctx).String()},
- Platform: map[string]string{remoteexec.PoolKey: pool},
- 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,18 +426,16 @@
FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
FlagWithInput("@", srcJarList)
- if javaHome := ctx.Config().Getenv("ANDROID_JAVA_HOME"); javaHome != "" {
- cmd.Implicit(android.PathForSource(ctx, javaHome))
- }
+ 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 implicitsRsp != nil {
+ cmd.FlagWithArg("--strict-input-files-exempt ", "@"+implicitsRsp.String())
+ }
}
if len(bootclasspath) > 0 {
@@ -465,6 +473,13 @@
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 @@
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,17 +625,21 @@
cmd.FlagWithArg("--error-message:compatibility:released ", msg)
}
- 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
- // add a large number of inputs to a file without exceeding bash command length limits (which
- // would happen if we use the WriteFile rule). The cp is needed because RuleBuilder sets the
- // rsp file to be ${output}.rsp.
- impCmd.Text("cp").
- FlagWithRspFileInputList("", android.PathForModuleOut(ctx, "metalava-implicits.rsp"), cmd.GetImplicits()).
- Output(implicitsRsp)
- impRule.Build("implicitsGen", "implicits generation")
- cmd.Implicit(implicitsRsp)
+ 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
+ // add a large number of inputs to a file without exceeding bash command length limits (which
+ // would happen if we use the WriteFile rule). The cp is needed because RuleBuilder sets the
+ // rsp file to be ${output}.rsp.
+ impCmd.Text("cp").
+ FlagWithRspFileInputList("", android.PathForModuleOut(ctx, "metalava-implicits.rsp"), cmd.GetImplicits()).
+ Output(implicitsRsp)
+ impRule.Build("implicitsGen", "implicits generation")
+ cmd.Implicit(implicitsRsp)
+ }
if generateStubs {
rule.Command().
@@ -652,7 +671,10 @@
rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
}
- rule.Restat()
+ // TODO(b/183630617): rewrapper doesn't support restat rules
+ if !sandbox {
+ rule.Restat()
+ }
zipSyncCleanupCmd(rule, srcJarDir)
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index d450c1a..c6db979 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -15,6 +15,7 @@
package java
import (
+ "reflect"
"strings"
"testing"
@@ -78,6 +79,25 @@
}
}
+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 {