Sandbox the OUT_DIR environment variable

Currently, OUT_DIR is inherited from the parent process, leading to
scripts being able to find the output directory when the enviornment
variable is set to an absolute path. When sandboxing a command,
also rewrite the OUT_DIR environment variable to the sandboxed one,
so that scripts can't find the real out dir.

Bug: 307824623
Test: Presubmits
Change-Id: I325071121a60bddc4105df680fbdfe3d11dc94e2
This commit is contained in:
Cole Faust
2024-08-23 14:41:51 -07:00
parent 079871cd55
commit 1ead86c1a5
4 changed files with 295 additions and 47 deletions

View File

@@ -27,6 +27,7 @@ import (
"os"
"os/exec"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
@@ -51,6 +52,8 @@ const (
sandboxDirPlaceholder = "__SBOX_SANDBOX_DIR__"
)
var envVarNameRegex = regexp.MustCompile("^[a-zA-Z0-9_-]+$")
func init() {
flag.StringVar(&sandboxesRoot, "sandbox-path", "",
"root of temp directory to put the sandbox into")
@@ -238,6 +241,48 @@ func readManifest(file string) (*sbox_proto.Manifest, error) {
return &manifest, nil
}
func createEnv(command *sbox_proto.Command) ([]string, error) {
env := []string{}
if command.DontInheritEnv == nil || !*command.DontInheritEnv {
env = os.Environ()
}
for _, envVar := range command.Env {
if envVar.Name == nil || !envVarNameRegex.MatchString(*envVar.Name) {
name := "nil"
if envVar.Name != nil {
name = *envVar.Name
}
return nil, fmt.Errorf("Invalid environment variable name: %q", name)
}
if envVar.State == nil {
return nil, fmt.Errorf("Must set state")
}
switch state := envVar.State.(type) {
case *sbox_proto.EnvironmentVariable_Value:
env = append(env, *envVar.Name+"="+state.Value)
case *sbox_proto.EnvironmentVariable_Unset:
if !state.Unset {
return nil, fmt.Errorf("Can't have unset set to false")
}
prefix := *envVar.Name + "="
for i := 0; i < len(env); i++ {
if strings.HasPrefix(env[i], prefix) {
env = append(env[:i], env[i+1:]...)
i--
}
}
case *sbox_proto.EnvironmentVariable_Inherit:
if !state.Inherit {
return nil, fmt.Errorf("Can't have inherit set to false")
}
env = append(env, *envVar.Name+"="+os.Getenv(*envVar.Name))
default:
return nil, fmt.Errorf("Unhandled state type")
}
}
return env, nil
}
// runCommand runs a single command from a manifest. If the command references the
// __SBOX_DEPFILE__ placeholder it returns the name of the depfile that was used.
func runCommand(command *sbox_proto.Command, tempDir string, commandIndex int) (depFile string, err error) {
@@ -313,6 +358,12 @@ func runCommand(command *sbox_proto.Command, tempDir string, commandIndex int) (
return "", fmt.Errorf("Failed to update PATH: %w", err)
}
}
cmd.Env, err = createEnv(command)
if err != nil {
return "", err
}
err = cmd.Run()
if err != nil {