diff --git a/mount/init.go b/mount/init.go index daec6ac86..f8bd8b30c 100644 --- a/mount/init.go +++ b/mount/init.go @@ -52,9 +52,17 @@ func InitializeMountNamespace(rootfs, console string, mountConfig *MountConfig) if err := SetupPtmx(rootfs, console, mountConfig.MountLabel); err != nil { return err } + + // stdin, stdout and stderr could be pointing to /dev/null from parent namespace. + // Re-open them inside this namespace. + if err := reOpenDevNull(rootfs); err != nil { + return fmt.Errorf("Failed to reopen /dev/null %s", err) + } + if err := setupDevSymlinks(rootfs); err != nil { return fmt.Errorf("dev symlinks %s", err) } + if err := syscall.Chdir(rootfs); err != nil { return fmt.Errorf("chdir into %s %s", rootfs, err) } @@ -203,3 +211,29 @@ func newSystemMounts(rootfs, mountLabel string, mounts Mounts) []mount { return systemMounts } + +// Is stdin, stdout or stderr were to be pointing to '/dev/null', +// this method will make them point to '/dev/null' from within this namespace. +func reOpenDevNull(rootfs string) error { + var stat, devNullStat syscall.Stat_t + file, err := os.Open(filepath.Join(rootfs, "/dev/null")) + if err != nil { + return fmt.Errorf("Failed to open /dev/null - %s", err) + } + defer file.Close() + if err = syscall.Fstat(int(file.Fd()), &devNullStat); err != nil { + return fmt.Errorf("Failed to stat /dev/null - %s", err) + } + for fd := 0; fd < 3; fd++ { + if err = syscall.Fstat(fd, &stat); err != nil { + return fmt.Errorf("Failed to stat fd %d - %s", fd, err) + } + if stat.Rdev == devNullStat.Rdev { + // Close and re-open the fd. + if err = syscall.Dup2(int(file.Fd()), fd); err != nil { + return fmt.Errorf("Failed to dup fd %d to fd %d - %s", file.Fd(), fd) + } + } + } + return nil +}