diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go index 12ee6a3ef95..2584f9dac4f 100644 --- a/libcontainer/container_linux.go +++ b/libcontainer/container_linux.go @@ -346,6 +346,15 @@ func (c *Container) start(process *Process) (retErr error) { if err := utils.CloseExecFrom(3); err != nil { return fmt.Errorf("unable to mark non-stdio fds as cloexec: %w", err) } + + // We should let stdio could be accessed in userns container. + // Please see https://github.com/opencontainers/runc/issues/4475 + // Because the default permission of stdio is 0o700, other user can't access + // them. If we don't change the permission to 0o666, We'll get an error msg if + // we access stdio in a userns container: ***: /dev/std***: Permission denied. + if err := c.fixStdioPermission(); err != nil { + return fmt.Errorf("unable to change permission of stdio: %w", err) + } if err := parent.start(); err != nil { return fmt.Errorf("unable to start container process: %w", err) } @@ -506,6 +515,32 @@ func isDmzBinarySafe(c *configs.Config) bool { return false } +func (c *Container) fixStdioPermission() error { + rootuid, err := c.Config().HostRootUID() + if err != nil { + return err + } + rootgid, err := c.Config().HostRootGID() + if err != nil { + return err + } + uid := os.Getuid() + gid := os.Getgid() + + if uid != rootuid && gid != rootgid { + if err := os.Stdin.Chmod(0o666); err != nil { + return err + } + if err := os.Stdout.Chmod(0o666); err != nil { + return err + } + if err := os.Stderr.Chmod(0o666); err != nil { + return err + } + } + return nil +} + func (c *Container) newParentProcess(p *Process) (parentProcess, error) { comm, err := newProcessComm() if err != nil {