summaryrefslogtreecommitdiffhomepage
path: root/pkg
diff options
context:
space:
mode:
authorNicolas Lacasse <nlacasse@google.com>2018-08-24 17:42:30 -0700
committerShentubot <shentubot@google.com>2018-08-24 17:43:21 -0700
commit106de2182d34197d76fb68863cd4a102ebac2dbb (patch)
tree9f3bce620feedb1c7f757c079157538c33b94a5a /pkg
parentc48708a041fcc9749e0162a7708f32e5a3d7e526 (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')
-rw-r--r--pkg/abi/linux/ioctl.go6
-rw-r--r--pkg/abi/linux/tty.go8
-rw-r--r--pkg/sentry/control/proc.go17
-rw-r--r--pkg/sentry/fs/host/BUILD1
-rw-r--r--pkg/sentry/fs/host/file.go19
-rw-r--r--pkg/sentry/fs/host/ioctl_unsafe.go19
6 files changed, 47 insertions, 23 deletions
diff --git a/pkg/abi/linux/ioctl.go b/pkg/abi/linux/ioctl.go
index 3ef046562..4d7a2dfd7 100644
--- a/pkg/abi/linux/ioctl.go
+++ b/pkg/abi/linux/ioctl.go
@@ -21,8 +21,12 @@ const (
TCGETS = 0x00005401
TCSETS = 0x00005402
TCSETSW = 0x00005403
- TIOCINQ = 0x0000541b
+ TIOCGPGRP = 0x0000540f
+ TIOCSPGRP = 0x00005410
TIOCOUTQ = 0x00005411
+ TIOCGWINSZ = 0x00005413
+ TIOCSWINSZ = 0x00005414
+ TIOCINQ = 0x0000541b
FIONREAD = TIOCINQ
FIONBIO = 0x00005421
TIOCGPTN = 0x80045430
diff --git a/pkg/abi/linux/tty.go b/pkg/abi/linux/tty.go
index 8c611d22a..81156867c 100644
--- a/pkg/abi/linux/tty.go
+++ b/pkg/abi/linux/tty.go
@@ -26,6 +26,14 @@ const (
disabledChar = 0
)
+// Winsize is struct winsize, defined in uapi/asm-generic/termios.h.
+type Winsize struct {
+ Row uint16
+ Col uint16
+ Xpixel uint16
+ Ypixel uint16
+}
+
// Termios is struct termios, defined in uapi/asm-generic/termbits.h.
type Termios struct {
InputFlags uint32
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
+}