From 2524111fc63343fd7372f5ea0266130adea778a5 Mon Sep 17 00:00:00 2001 From: Kevin Krakauer Date: Mon, 27 Aug 2018 10:48:02 -0700 Subject: [PATCH] runsc: Terminal resizing support. Implements the TIOCGWINSZ and TIOCSWINSZ ioctls, which allow processes to resize the terminal. This allows, for example, sshd to properly set the window size for ssh sessions. PiperOrigin-RevId: 210392504 Change-Id: I0d4789154d6d22f02509b31d71392e13ee4a50ba --- pkg/abi/linux/tty.go | 10 ++++++++++ pkg/sentry/fs/tty/line_discipline.go | 24 ++++++++++++++++++++++++ pkg/sentry/fs/tty/master.go | 4 ++++ pkg/sentry/fs/tty/slave.go | 4 ++++ 4 files changed, 42 insertions(+) diff --git a/pkg/abi/linux/tty.go b/pkg/abi/linux/tty.go index 81156867c..f63dc52aa 100644 --- a/pkg/abi/linux/tty.go +++ b/pkg/abi/linux/tty.go @@ -328,3 +328,13 @@ var DefaultSlaveTermios = KernelTermios{ InputSpeed: 38400, OutputSpeed: 38400, } + +// WindowSize corresponds to struct winsize defined in +// include/uapi/asm-generic/termios.h. +// +// +stateify savable +type WindowSize struct { + Rows uint16 + Cols uint16 + _ [4]byte // Padding for 2 unused shorts. +} diff --git a/pkg/sentry/fs/tty/line_discipline.go b/pkg/sentry/fs/tty/line_discipline.go index c7f6c5645..31804571e 100644 --- a/pkg/sentry/fs/tty/line_discipline.go +++ b/pkg/sentry/fs/tty/line_discipline.go @@ -76,6 +76,12 @@ const ( // // +stateify savable type lineDiscipline struct { + // sizeMu protects size. + sizeMu sync.Mutex `state:"nosave"` + + // size is the terminal size (width and height). + size linux.WindowSize + // inQueue is the input queue of the terminal. inQueue queue @@ -142,6 +148,24 @@ func (l *lineDiscipline) setTermios(ctx context.Context, io usermem.IO, args arc return 0, err } +func (l *lineDiscipline) windowSize(ctx context.Context, io usermem.IO, args arch.SyscallArguments) error { + l.sizeMu.Lock() + defer l.sizeMu.Unlock() + _, err := usermem.CopyObjectOut(ctx, io, args[2].Pointer(), l.size, usermem.IOOpts{ + AddressSpaceActive: true, + }) + return err +} + +func (l *lineDiscipline) setWindowSize(ctx context.Context, io usermem.IO, args arch.SyscallArguments) error { + l.sizeMu.Lock() + defer l.sizeMu.Unlock() + _, err := usermem.CopyObjectIn(ctx, io, args[2].Pointer(), &l.size, usermem.IOOpts{ + AddressSpaceActive: true, + }) + return err +} + func (l *lineDiscipline) masterReadiness() waiter.EventMask { // We don't have to lock a termios because the default master termios // is immutable. diff --git a/pkg/sentry/fs/tty/master.go b/pkg/sentry/fs/tty/master.go index c8dc08c1a..ae7540eff 100644 --- a/pkg/sentry/fs/tty/master.go +++ b/pkg/sentry/fs/tty/master.go @@ -172,6 +172,10 @@ func (mf *masterFileOperations) Ioctl(ctx context.Context, io usermem.IO, args a case linux.TIOCSPTLCK: // TODO: Implement pty locking. For now just pretend we do. return 0, nil + case linux.TIOCGWINSZ: + return 0, mf.t.ld.windowSize(ctx, io, args) + case linux.TIOCSWINSZ: + return 0, mf.t.ld.setWindowSize(ctx, io, args) default: return 0, syserror.ENOTTY } diff --git a/pkg/sentry/fs/tty/slave.go b/pkg/sentry/fs/tty/slave.go index ab92ced7e..963331b9b 100644 --- a/pkg/sentry/fs/tty/slave.go +++ b/pkg/sentry/fs/tty/slave.go @@ -150,6 +150,10 @@ func (sf *slaveFileOperations) Ioctl(ctx context.Context, io usermem.IO, args ar AddressSpaceActive: true, }) return 0, err + case linux.TIOCGWINSZ: + return 0, sf.si.t.ld.windowSize(ctx, io, args) + case linux.TIOCSWINSZ: + return 0, sf.si.t.ld.setWindowSize(ctx, io, args) default: return 0, syserror.ENOTTY }