diff options
author | Nicolas Lacasse <nlacasse@google.com> | 2018-08-24 17:42:30 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-08-24 17:43:21 -0700 |
commit | 106de2182d34197d76fb68863cd4a102ebac2dbb (patch) | |
tree | 9f3bce620feedb1c7f757c079157538c33b94a5a /pkg/sentry | |
parent | c48708a041fcc9749e0162a7708f32e5a3d7e526 (diff) |
runsc: Terminal support for "docker exec -ti".
This CL adds terminal support for "docker exec". We previously only supported
consoles for the container process, but not exec processes.
The SYS_IOCTL syscall was added to the default seccomp filter list, but only
for ioctls that get/set winsize and termios structs. We need to allow these
ioctl for all containers because it's possible to run "exec -ti" on a
container that was started without an attached console, after the filters
have been installed.
Note that control-character signals are still not properly supported.
Tested with:
$ docker run --runtime=runsc -it alpine
In another terminial:
$ docker exec -it <containerid> /bin/sh
PiperOrigin-RevId: 210185456
Change-Id: I6d2401e53a7697bb988c120a8961505c335f96d9
Diffstat (limited to 'pkg/sentry')
-rw-r--r-- | pkg/sentry/control/proc.go | 17 | ||||
-rw-r--r-- | pkg/sentry/fs/host/BUILD | 1 | ||||
-rw-r--r-- | pkg/sentry/fs/host/file.go | 19 | ||||
-rw-r--r-- | pkg/sentry/fs/host/ioctl_unsafe.go | 19 |
4 files changed, 34 insertions, 22 deletions
diff --git a/pkg/sentry/control/proc.go b/pkg/sentry/control/proc.go index d94ae560f..2493c5175 100644 --- a/pkg/sentry/control/proc.go +++ b/pkg/sentry/control/proc.go @@ -19,7 +19,6 @@ import ( "encoding/json" "fmt" "sort" - "syscall" "text/tabwriter" "time" @@ -73,6 +72,10 @@ type ExecArgs struct { // Capabilities is the list of capabilities to give to the process. Capabilities *auth.TaskCapabilities + // StdioIsPty indicates that FDs 0, 1, and 2 are connected to a host + // pty fd. + StdioIsPty bool + // FilePayload determines the files to give to the new process. urpc.FilePayload } @@ -108,17 +111,11 @@ func (proc *Proc) Exec(args *ExecArgs, waitStatus *uint32) error { mounter := fs.FileOwnerFromContext(ctx) for appFD, f := range args.FilePayload.Files { - // Copy the underlying FD. - newFD, err := syscall.Dup(int(f.Fd())) - if err != nil { - return err - } - f.Close() + enableIoctl := args.StdioIsPty && appFD <= 2 - // Install the given file as an FD. - file, err := host.NewFile(ctx, newFD, mounter) + // Import the given file FD. This dups the FD as well. + file, err := host.ImportFile(ctx, int(f.Fd()), mounter, enableIoctl) if err != nil { - syscall.Close(newFD) return err } defer file.DecRef() diff --git a/pkg/sentry/fs/host/BUILD b/pkg/sentry/fs/host/BUILD index 29c79284a..f1252b0f2 100644 --- a/pkg/sentry/fs/host/BUILD +++ b/pkg/sentry/fs/host/BUILD @@ -48,7 +48,6 @@ go_library( "//pkg/unet", "//pkg/waiter", "//pkg/waiter/fdnotifier", - "@org_golang_x_sys//unix:go_default_library", ], ) diff --git a/pkg/sentry/fs/host/file.go b/pkg/sentry/fs/host/file.go index f9bef6d93..8d2463c78 100644 --- a/pkg/sentry/fs/host/file.go +++ b/pkg/sentry/fs/host/file.go @@ -18,7 +18,6 @@ import ( "fmt" "syscall" - "golang.org/x/sys/unix" "gvisor.googlesource.com/gvisor/pkg/abi/linux" "gvisor.googlesource.com/gvisor/pkg/fd" "gvisor.googlesource.com/gvisor/pkg/log" @@ -296,7 +295,7 @@ func (f *fileOperations) Ioctl(ctx context.Context, io usermem.IO, args arch.Sys fd := f.iops.fileState.FD() ioctl := args[1].Uint64() switch ioctl { - case unix.TCGETS: + case linux.TCGETS: termios, err := ioctlGetTermios(fd) if err != nil { return 0, err @@ -306,7 +305,7 @@ func (f *fileOperations) Ioctl(ctx context.Context, io usermem.IO, args arch.Sys }) return 0, err - case unix.TCSETS, unix.TCSETSW: + case linux.TCSETS, linux.TCSETSW: var termios linux.Termios if _, err := usermem.CopyObjectIn(ctx, io, args[2].Pointer(), &termios, usermem.IOOpts{ AddressSpaceActive: true, @@ -316,7 +315,7 @@ func (f *fileOperations) Ioctl(ctx context.Context, io usermem.IO, args arch.Sys err := ioctlSetTermios(fd, ioctl, &termios) return 0, err - case unix.TIOCGPGRP: + case linux.TIOCGPGRP: // Args: pid_t *argp // When successful, equivalent to *argp = tcgetpgrp(fd). // Get the process group ID of the foreground process group on @@ -332,7 +331,7 @@ func (f *fileOperations) Ioctl(ctx context.Context, io usermem.IO, args arch.Sys }) return 0, err - case unix.TIOCSPGRP: + case linux.TIOCSPGRP: // Args: const pid_t *argp // Equivalent to tcsetpgrp(fd, *argp). // Set the foreground process group ID of this terminal. @@ -343,10 +342,10 @@ func (f *fileOperations) Ioctl(ctx context.Context, io usermem.IO, args arch.Sys log.Warningf("Ignoring application ioctl(TIOCSPGRP) call") return 0, nil - case unix.TIOCGWINSZ: + case linux.TIOCGWINSZ: // Args: struct winsize *argp // Get window size. - winsize, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ) + winsize, err := ioctlGetWinsize(fd) if err != nil { return 0, err } @@ -355,16 +354,16 @@ func (f *fileOperations) Ioctl(ctx context.Context, io usermem.IO, args arch.Sys }) return 0, err - case unix.TIOCSWINSZ: + case linux.TIOCSWINSZ: // Args: const struct winsize *argp // Set window size. - var winsize unix.Winsize + var winsize linux.Winsize if _, err := usermem.CopyObjectIn(ctx, io, args[2].Pointer(), &winsize, usermem.IOOpts{ AddressSpaceActive: true, }); err != nil { return 0, err } - err := unix.IoctlSetWinsize(fd, unix.TIOCSWINSZ, &winsize) + err := ioctlSetWinsize(fd, &winsize) return 0, err default: diff --git a/pkg/sentry/fs/host/ioctl_unsafe.go b/pkg/sentry/fs/host/ioctl_unsafe.go index 3c07c3850..bc965a1c2 100644 --- a/pkg/sentry/fs/host/ioctl_unsafe.go +++ b/pkg/sentry/fs/host/ioctl_unsafe.go @@ -23,7 +23,7 @@ import ( func ioctlGetTermios(fd int) (*linux.Termios, error) { var t linux.Termios - _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.TCGETS, uintptr(unsafe.Pointer(&t))) + _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), linux.TCGETS, uintptr(unsafe.Pointer(&t))) if errno != 0 { return nil, errno } @@ -37,3 +37,20 @@ func ioctlSetTermios(fd int, req uint64, t *linux.Termios) error { } return nil } + +func ioctlGetWinsize(fd int) (*linux.Winsize, error) { + var w linux.Winsize + _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), linux.TIOCGWINSZ, uintptr(unsafe.Pointer(&w))) + if errno != 0 { + return nil, errno + } + return &w, nil +} + +func ioctlSetWinsize(fd int, w *linux.Winsize) error { + _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), linux.TIOCSWINSZ, uintptr(unsafe.Pointer(w))) + if errno != 0 { + return errno + } + return nil +} |