summaryrefslogtreecommitdiff
path: root/vendor/github.com/projectatomic/buildah/chroot/run.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/projectatomic/buildah/chroot/run.go')
-rw-r--r--vendor/github.com/projectatomic/buildah/chroot/run.go70
1 files changed, 60 insertions, 10 deletions
diff --git a/vendor/github.com/projectatomic/buildah/chroot/run.go b/vendor/github.com/projectatomic/buildah/chroot/run.go
index 2cae5b9da..9a70e0f51 100644
--- a/vendor/github.com/projectatomic/buildah/chroot/run.go
+++ b/vendor/github.com/projectatomic/buildah/chroot/run.go
@@ -98,6 +98,7 @@ func RunUsingChroot(spec *specs.Spec, bundlePath string, stdin io.Reader, stdout
if err = ioutils.AtomicWriteFile(filepath.Join(bundlePath, "config.json"), specbytes, 0600); err != nil {
return errors.Wrapf(err, "error storing runtime configuration")
}
+ logrus.Debugf("config = %v", string(specbytes))
// Run the grandparent subprocess in a user namespace that reuses the mappings that we have.
uidmap, gidmap, err := util.GetHostIDMappings("")
@@ -381,11 +382,15 @@ func runUsingChrootMain() {
logrus.Error(what)
return false
}
- for readFd := range relays {
+ for readFd, writeFd := range relays {
if err := unix.SetNonblock(readFd, true); err != nil {
logrus.Errorf("error setting descriptor %d (%s) non-blocking: %v", readFd, fdDesc[readFd], err)
return
}
+ if err := unix.SetNonblock(writeFd, false); err != nil {
+ logrus.Errorf("error setting descriptor %d (%s) blocking: %v", relays[writeFd], fdDesc[writeFd], err)
+ return
+ }
}
go func() {
buffers := make(map[int]*bytes.Buffer)
@@ -429,6 +434,26 @@ func runUsingChrootMain() {
continue
}
}
+ // If this is the last of the data we'll be able to read
+ // from this descriptor, read as much as there is to read.
+ for rfd.Revents&unix.POLLHUP == unix.POLLHUP {
+ nr, err := unix.Read(int(rfd.Fd), b)
+ logIfNotRetryable(err, fmt.Sprintf("read %s: %v", fdDesc[int(rfd.Fd)], err))
+ if nr <= 0 {
+ break
+ }
+ if wfd, ok := relays[int(rfd.Fd)]; ok {
+ nwritten, err := buffers[wfd].Write(b[:nr])
+ if err != nil {
+ logrus.Debugf("buffer: %v", err)
+ break
+ }
+ if nwritten != nr {
+ logrus.Debugf("buffer: expected to buffer %d bytes, wrote %d", nr, nwritten)
+ break
+ }
+ }
+ }
}
if nread == 0 {
removeFds[int(rfd.Fd)] = struct{}{}
@@ -592,8 +617,7 @@ func runUsingChroot(spec *specs.Spec, bundlePath string, ctty *os.File, stdin io
// main() for parent subprocess. Its main job is to try to make our
// environment look like the one described by the runtime configuration blob,
-// and then launch the intended command as a child, since we can't exec()
-// directly.
+// and then launch the intended command as a child.
func runUsingChrootExecMain() {
args := os.Args[1:]
var options runUsingChrootExecSubprocOptions
@@ -630,6 +654,31 @@ func runUsingChrootExecMain() {
}
}
+ // Try to chroot into the root. Do this before we potentially block the syscall via the
+ // seccomp profile.
+ var oldst, newst unix.Stat_t
+ if err := unix.Stat(options.Spec.Root.Path, &oldst); err != nil {
+ fmt.Fprintf(os.Stderr, "error stat()ing intended root directory %q: %v\n", options.Spec.Root.Path, err)
+ os.Exit(1)
+ }
+ if err := unix.Chdir(options.Spec.Root.Path); err != nil {
+ fmt.Fprintf(os.Stderr, "error chdir()ing to intended root directory %q: %v\n", options.Spec.Root.Path, err)
+ os.Exit(1)
+ }
+ if err := unix.Chroot(options.Spec.Root.Path); err != nil {
+ fmt.Fprintf(os.Stderr, "error chroot()ing into directory %q: %v\n", options.Spec.Root.Path, err)
+ os.Exit(1)
+ }
+ if err := unix.Stat("/", &newst); err != nil {
+ fmt.Fprintf(os.Stderr, "error stat()ing current root directory: %v\n", err)
+ os.Exit(1)
+ }
+ if oldst.Dev != newst.Dev || oldst.Ino != newst.Ino {
+ fmt.Fprintf(os.Stderr, "unknown error chroot()ing into directory %q: %v\n", options.Spec.Root.Path, err)
+ os.Exit(1)
+ }
+ logrus.Debugf("chrooted into %q", options.Spec.Root.Path)
+
// not doing because it's still shared: creating devices
// not doing because it's not applicable: setting annotations
// not doing because it's still shared: setting sysctl settings
@@ -663,20 +712,21 @@ func runUsingChrootExecMain() {
os.Exit(1)
}
- // Try to chroot into the root.
- if err := unix.Chroot(options.Spec.Root.Path); err != nil {
- fmt.Fprintf(os.Stderr, "error chroot()ing into directory %q: %v\n", options.Spec.Root.Path, err)
- os.Exit(1)
- }
+ // Try to change to the directory.
cwd := options.Spec.Process.Cwd
if !filepath.IsAbs(cwd) {
cwd = "/" + cwd
}
+ cwd = filepath.Clean(cwd)
+ if err := unix.Chdir("/"); err != nil {
+ fmt.Fprintf(os.Stderr, "error chdir()ing into new root directory %q: %v\n", options.Spec.Root.Path, err)
+ os.Exit(1)
+ }
if err := unix.Chdir(cwd); err != nil {
- fmt.Fprintf(os.Stderr, "error chdir()ing into directory %q: %v\n", cwd, err)
+ fmt.Fprintf(os.Stderr, "error chdir()ing into directory %q under root %q: %v\n", cwd, options.Spec.Root.Path, err)
os.Exit(1)
}
- logrus.Debugf("chrooted into %q, changed working directory to %q", options.Spec.Root.Path, cwd)
+ logrus.Debugf("changed working directory to %q", cwd)
// Drop privileges.
user := options.Spec.Process.User