Merge "soong_ui path.go: improve comments." am: 55e0022fc0
Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1502731 Change-Id: Id91fb286b18739f485b8b021c91bd548701c8694
This commit is contained in:
commit
e6f2194126
1 changed files with 46 additions and 5 deletions
|
@ -29,6 +29,9 @@ import (
|
||||||
"android/soong/ui/metrics"
|
"android/soong/ui/metrics"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// parsePathDir returns the list of filenames of readable files in a directory.
|
||||||
|
// This does not recurse into subdirectories, and does not contain subdirectory
|
||||||
|
// names in the list.
|
||||||
func parsePathDir(dir string) []string {
|
func parsePathDir(dir string) []string {
|
||||||
f, err := os.Open(dir)
|
f, err := os.Open(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -54,10 +57,12 @@ func parsePathDir(dir string) []string {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// A "lite" version of SetupPath used for dumpvars, or other places that need
|
// SetupLitePath is the "lite" version of SetupPath used for dumpvars, or other
|
||||||
// minimal overhead (but at the expense of logging). If tmpDir is empty, the
|
// places that does not need the full logging capabilities of path_interposer,
|
||||||
// default TMPDIR is used from config.
|
// wants the minimal performance overhead, and still get the benefits of $PATH
|
||||||
|
// hermeticity.
|
||||||
func SetupLitePath(ctx Context, config Config, tmpDir string) {
|
func SetupLitePath(ctx Context, config Config, tmpDir string) {
|
||||||
|
// Don't replace the path twice.
|
||||||
if config.pathReplaced {
|
if config.pathReplaced {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -67,6 +72,7 @@ func SetupLitePath(ctx Context, config Config, tmpDir string) {
|
||||||
|
|
||||||
origPath, _ := config.Environment().Get("PATH")
|
origPath, _ := config.Environment().Get("PATH")
|
||||||
|
|
||||||
|
// If tmpDir is empty, the default TMPDIR is used from config.
|
||||||
if tmpDir == "" {
|
if tmpDir == "" {
|
||||||
tmpDir, _ = config.Environment().Get("TMPDIR")
|
tmpDir, _ = config.Environment().Get("TMPDIR")
|
||||||
}
|
}
|
||||||
|
@ -74,8 +80,10 @@ func SetupLitePath(ctx Context, config Config, tmpDir string) {
|
||||||
ensureEmptyDirectoriesExist(ctx, myPath)
|
ensureEmptyDirectoriesExist(ctx, myPath)
|
||||||
|
|
||||||
os.Setenv("PATH", origPath)
|
os.Setenv("PATH", origPath)
|
||||||
|
// Iterate over the ACL configuration of host tools for this build.
|
||||||
for name, pathConfig := range paths.Configuration {
|
for name, pathConfig := range paths.Configuration {
|
||||||
if !pathConfig.Symlink {
|
if !pathConfig.Symlink {
|
||||||
|
// Excludes 'Forbidden' and 'LinuxOnlyPrebuilt' PathConfigs.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +96,7 @@ func SetupLitePath(ctx Context, config Config, tmpDir string) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Symlink allowed host tools into a directory for hermeticity.
|
||||||
err = os.Symlink(origExec, filepath.Join(myPath, name))
|
err = os.Symlink(origExec, filepath.Join(myPath, name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Fatalln("Failed to create symlink:", err)
|
ctx.Fatalln("Failed to create symlink:", err)
|
||||||
|
@ -96,14 +105,26 @@ func SetupLitePath(ctx Context, config Config, tmpDir string) {
|
||||||
|
|
||||||
myPath, _ = filepath.Abs(myPath)
|
myPath, _ = filepath.Abs(myPath)
|
||||||
|
|
||||||
|
// Set up the checked-in prebuilts path directory for the current host OS.
|
||||||
prebuiltsPath, _ := filepath.Abs("prebuilts/build-tools/path/" + runtime.GOOS + "-x86")
|
prebuiltsPath, _ := filepath.Abs("prebuilts/build-tools/path/" + runtime.GOOS + "-x86")
|
||||||
myPath = prebuiltsPath + string(os.PathListSeparator) + myPath
|
myPath = prebuiltsPath + string(os.PathListSeparator) + myPath
|
||||||
|
|
||||||
|
// Set $PATH to be the directories containing the host tool symlinks, and
|
||||||
|
// the prebuilts directory for the current host OS.
|
||||||
config.Environment().Set("PATH", myPath)
|
config.Environment().Set("PATH", myPath)
|
||||||
config.pathReplaced = true
|
config.pathReplaced = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetupPath uses the path_interposer to intercept calls to $PATH binaries, and
|
||||||
|
// communicates with the interposer to validate allowed $PATH binaries at
|
||||||
|
// runtime, using logs as a medium.
|
||||||
|
//
|
||||||
|
// This results in hermetic directories in $PATH containing only allowed host
|
||||||
|
// tools for the build, and replaces $PATH to contain *only* these directories,
|
||||||
|
// and enables an incremental restriction of tools allowed in the $PATH without
|
||||||
|
// breaking existing use cases.
|
||||||
func SetupPath(ctx Context, config Config) {
|
func SetupPath(ctx Context, config Config) {
|
||||||
|
// Don't replace $PATH twice.
|
||||||
if config.pathReplaced {
|
if config.pathReplaced {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -112,9 +133,11 @@ func SetupPath(ctx Context, config Config) {
|
||||||
defer ctx.EndTrace()
|
defer ctx.EndTrace()
|
||||||
|
|
||||||
origPath, _ := config.Environment().Get("PATH")
|
origPath, _ := config.Environment().Get("PATH")
|
||||||
|
// The directory containing symlinks from binaries in $PATH to the interposer.
|
||||||
myPath := filepath.Join(config.OutDir(), ".path")
|
myPath := filepath.Join(config.OutDir(), ".path")
|
||||||
interposer := myPath + "_interposer"
|
interposer := myPath + "_interposer"
|
||||||
|
|
||||||
|
// Bootstrap the path_interposer Go binary with microfactory.
|
||||||
var cfg microfactory.Config
|
var cfg microfactory.Config
|
||||||
cfg.Map("android/soong", "build/soong")
|
cfg.Map("android/soong", "build/soong")
|
||||||
cfg.TrimPath, _ = filepath.Abs(".")
|
cfg.TrimPath, _ = filepath.Abs(".")
|
||||||
|
@ -122,15 +145,20 @@ func SetupPath(ctx Context, config Config) {
|
||||||
ctx.Fatalln("Failed to build path interposer:", err)
|
ctx.Fatalln("Failed to build path interposer:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save the original $PATH in a file.
|
||||||
if err := ioutil.WriteFile(interposer+"_origpath", []byte(origPath), 0777); err != nil {
|
if err := ioutil.WriteFile(interposer+"_origpath", []byte(origPath), 0777); err != nil {
|
||||||
ctx.Fatalln("Failed to write original path:", err)
|
ctx.Fatalln("Failed to write original path:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Communication with the path interposer works over log entries. Set up the
|
||||||
|
// listener channel for the log entries here.
|
||||||
entries, err := paths.LogListener(ctx.Context, interposer+"_log")
|
entries, err := paths.LogListener(ctx.Context, interposer+"_log")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Fatalln("Failed to listen for path logs:", err)
|
ctx.Fatalln("Failed to listen for path logs:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Loop over all log entry listener channels to validate usage of only
|
||||||
|
// allowed PATH tools at runtime.
|
||||||
go func() {
|
go func() {
|
||||||
for log := range entries {
|
for log := range entries {
|
||||||
curPid := os.Getpid()
|
curPid := os.Getpid()
|
||||||
|
@ -140,6 +168,8 @@ func SetupPath(ctx Context, config Config) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Compute the error message along with the process tree, including
|
||||||
|
// parents, for this log line.
|
||||||
procPrints := []string{
|
procPrints := []string{
|
||||||
"See https://android.googlesource.com/platform/build/+/master/Changes.md#PATH_Tools for more information.",
|
"See https://android.googlesource.com/platform/build/+/master/Changes.md#PATH_Tools for more information.",
|
||||||
}
|
}
|
||||||
|
@ -150,6 +180,7 @@ func SetupPath(ctx Context, config Config) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate usage against disallowed or missing PATH tools.
|
||||||
config := paths.GetConfig(log.Basename)
|
config := paths.GetConfig(log.Basename)
|
||||||
if config.Error {
|
if config.Error {
|
||||||
ctx.Printf("Disallowed PATH tool %q used: %#v", log.Basename, log.Args)
|
ctx.Printf("Disallowed PATH tool %q used: %#v", log.Basename, log.Args)
|
||||||
|
@ -165,8 +196,10 @@ func SetupPath(ctx Context, config Config) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// Create the .path directory.
|
||||||
ensureEmptyDirectoriesExist(ctx, myPath)
|
ensureEmptyDirectoriesExist(ctx, myPath)
|
||||||
|
|
||||||
|
// Compute the full list of binaries available in the original $PATH.
|
||||||
var execs []string
|
var execs []string
|
||||||
for _, pathEntry := range filepath.SplitList(origPath) {
|
for _, pathEntry := range filepath.SplitList(origPath) {
|
||||||
if pathEntry == "" {
|
if pathEntry == "" {
|
||||||
|
@ -185,8 +218,14 @@ func SetupPath(ctx Context, config Config) {
|
||||||
ctx.Fatalln("TEMPORARY_DISABLE_PATH_RESTRICTIONS was a temporary migration method, and is now obsolete.")
|
ctx.Fatalln("TEMPORARY_DISABLE_PATH_RESTRICTIONS was a temporary migration method, and is now obsolete.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create symlinks from the path_interposer binary to all binaries for each
|
||||||
|
// directory in the original $PATH. This ensures that during the build,
|
||||||
|
// every call to a binary that's expected to be in the $PATH will be
|
||||||
|
// intercepted by the path_interposer binary, and validated with the
|
||||||
|
// LogEntry listener above at build time.
|
||||||
for _, name := range execs {
|
for _, name := range execs {
|
||||||
if !paths.GetConfig(name).Symlink {
|
if !paths.GetConfig(name).Symlink {
|
||||||
|
// Ignore host tools that shouldn't be symlinked.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,11 +239,13 @@ func SetupPath(ctx Context, config Config) {
|
||||||
|
|
||||||
myPath, _ = filepath.Abs(myPath)
|
myPath, _ = filepath.Abs(myPath)
|
||||||
|
|
||||||
// We put some prebuilts in $PATH, since it's infeasible to add dependencies for all of
|
// We put some prebuilts in $PATH, since it's infeasible to add dependencies
|
||||||
// them.
|
// for all of them.
|
||||||
prebuiltsPath, _ := filepath.Abs("prebuilts/build-tools/path/" + runtime.GOOS + "-x86")
|
prebuiltsPath, _ := filepath.Abs("prebuilts/build-tools/path/" + runtime.GOOS + "-x86")
|
||||||
myPath = prebuiltsPath + string(os.PathListSeparator) + myPath
|
myPath = prebuiltsPath + string(os.PathListSeparator) + myPath
|
||||||
|
|
||||||
|
// Replace the $PATH variable with the path_interposer symlinks, and
|
||||||
|
// checked-in prebuilts.
|
||||||
config.Environment().Set("PATH", myPath)
|
config.Environment().Set("PATH", myPath)
|
||||||
config.pathReplaced = true
|
config.pathReplaced = true
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue