Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

os/exec: LookPath() doesn't consider chroot #39341

Open
sdclarke opened this issue Jun 1, 2020 · 5 comments
Open

os/exec: LookPath() doesn't consider chroot #39341

sdclarke opened this issue Jun 1, 2020 · 5 comments

Comments

@sdclarke
Copy link

@sdclarke sdclarke commented Jun 1, 2020

What version of Go are you using (go version)?

$ go version
go version go1.14.3 linux/amd64

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/scottclarke/.cache/go-build"
GOENV="/home/scottclarke/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/scottclarke/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build189733440=/tmp/go-build -gno-record-gcc-switches"

What did you do?

package main

import (
	"log"
	"os"
	"os/exec"
	"syscall"
)

func main() {
	cmd := exec.Command("hello")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Dir = "/"
	cmd.Env = []string{"PATH=/bin"}
	cmd.SysProcAttr = &syscall.SysProcAttr{Chroot: "/home/scottclarke/chroot"}
	if err := cmd.Start(); err != nil {
		log.Fatalf("%#v", err.Error())
	}
	cmd.Wait()
}

Where /home/scottclarke/chroot contains a chroot which has an executable file /bin/hello, and there is no executable hello in the PATH of the system prior to the chroot.

What did you expect to see?

The hello executable being run, producing the output hello world.

What did you see instead?

The following error:
2020/06/01 11:36:32 "exec: \"hello\": executable file not found in $PATH"

This happens because the exec.Command() function calls LookPath() and sets the lookPathErr if it fails, which is checked in Start() and causes a failure. However this doesn't take into account the fact that the command will be run in a chroot.

@Sunnycheey
Copy link

@Sunnycheey Sunnycheey commented Jun 4, 2020

Hello, I want to help to solve the problem. Is it suitable to check whether file path exists in the cmd.Start function?

Loading

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Jun 4, 2020

Perhaps cmd.Start should ignore an earlier lookPathErr if Chroot is set. I don't think we can simply move the LookPath call, as that would change code that calls exec.Command and then looks at Path.

Loading

@Sunnycheey
Copy link

@Sunnycheey Sunnycheey commented Jun 6, 2020

I have found some bug in my code, so I close the original PR. The problem is more complex than I thought, because I also need to deal with Dir and Env variable, and the most difficult thing is I cannot figure out how to debug, since I must use the compiled Go binary to compile the new source. But I have tried to make some changes in this repo .

Loading

@gopherbot
Copy link

@gopherbot gopherbot commented Jun 6, 2020

Change https://golang.org/cl/236780 mentions this issue: os/exec: deal with chroot invalid in start a cmd fix #39341

Loading

Sunnycheey added a commit to Sunnycheey/go that referenced this issue Jun 6, 2020
@EdSchouten
Copy link

@EdSchouten EdSchouten commented Jun 15, 2020

One thing to be careful for when fixing this is that chrooting will also affect the targets of symlinks. For example, a root directory containing a symlink pointing to /bin/foo may eventually expand to a different location depending on whether symlink expansion happens inside or outside the chroot.

One workaround we're using in bb-remote-execution is that we prepend /usr/bin/env -- to the command, so that it's not Go, but /usr/bin/env that does the $PATH lookup. This is of course suboptimal.

Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants