diff options
Diffstat (limited to 'pkg/sentry/kernel/thread_group.go')
-rw-r--r-- | pkg/sentry/kernel/thread_group.go | 179 |
1 files changed, 0 insertions, 179 deletions
diff --git a/pkg/sentry/kernel/thread_group.go b/pkg/sentry/kernel/thread_group.go index 0eef24bfb..2a97e3e8e 100644 --- a/pkg/sentry/kernel/thread_group.go +++ b/pkg/sentry/kernel/thread_group.go @@ -19,13 +19,10 @@ import ( "sync/atomic" "gvisor.dev/gvisor/pkg/abi/linux" - "gvisor.dev/gvisor/pkg/sentry/arch" "gvisor.dev/gvisor/pkg/sentry/fs" - "gvisor.dev/gvisor/pkg/sentry/kernel/auth" ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time" "gvisor.dev/gvisor/pkg/sentry/limits" "gvisor.dev/gvisor/pkg/sentry/usage" - "gvisor.dev/gvisor/pkg/syserror" ) // A ThreadGroup is a logical grouping of tasks that has widespread @@ -248,12 +245,6 @@ type ThreadGroup struct { // // mounts is immutable. mounts *fs.MountNamespace - - // tty is the thread group's controlling terminal. If nil, there is no - // controlling terminal. - // - // tty is protected by the signal mutex. - tty *TTY } // newThreadGroup returns a new, empty thread group in PID namespace ns. The @@ -333,176 +324,6 @@ func (tg *ThreadGroup) forEachChildThreadGroupLocked(fn func(*ThreadGroup)) { } } -// SetControllingTTY sets tty as the controlling terminal of tg. -func (tg *ThreadGroup) SetControllingTTY(tty *TTY, arg int32) error { - tty.mu.Lock() - defer tty.mu.Unlock() - - // We might be asked to set the controlling terminal of multiple - // processes, so we lock both the TaskSet and SignalHandlers. - tg.pidns.owner.mu.Lock() - defer tg.pidns.owner.mu.Unlock() - tg.signalHandlers.mu.Lock() - defer tg.signalHandlers.mu.Unlock() - - // "The calling process must be a session leader and not have a - // controlling terminal already." - tty_ioctl(4) - if tg.processGroup.session.leader != tg || tg.tty != nil { - return syserror.EINVAL - } - - // "If this terminal is already the controlling terminal of a different - // session group, then the ioctl fails with EPERM, unless the caller - // has the CAP_SYS_ADMIN capability and arg equals 1, in which case the - // terminal is stolen, and all processes that had it as controlling - // terminal lose it." - tty_ioctl(4) - if tty.tg != nil && tg.processGroup.session != tty.tg.processGroup.session { - if !auth.CredentialsFromContext(tg.leader).HasCapability(linux.CAP_SYS_ADMIN) || arg != 1 { - return syserror.EPERM - } - // Steal the TTY away. Unlike TIOCNOTTY, don't send signals. - for othertg := range tg.pidns.owner.Root.tgids { - // This won't deadlock by locking tg.signalHandlers - // because at this point: - // - We only lock signalHandlers if it's in the same - // session as the tty's controlling thread group. - // - We know that the calling thread group is not in - // the same session as the tty's controlling thread - // group. - if othertg.processGroup.session == tty.tg.processGroup.session { - othertg.signalHandlers.mu.Lock() - othertg.tty = nil - othertg.signalHandlers.mu.Unlock() - } - } - } - - // Set the controlling terminal and foreground process group. - tg.tty = tty - tg.processGroup.session.foreground = tg.processGroup - // Set this as the controlling process of the terminal. - tty.tg = tg - - return nil -} - -// ReleaseControllingTTY gives up tty as the controlling tty of tg. -func (tg *ThreadGroup) ReleaseControllingTTY(tty *TTY) error { - tty.mu.Lock() - defer tty.mu.Unlock() - - // We might be asked to set the controlling terminal of multiple - // processes, so we lock both the TaskSet and SignalHandlers. - tg.pidns.owner.mu.RLock() - defer tg.pidns.owner.mu.RUnlock() - - // Just below, we may re-lock signalHandlers in order to send signals. - // Thus we can't defer Unlock here. - tg.signalHandlers.mu.Lock() - - if tg.tty == nil || tg.tty != tty { - tg.signalHandlers.mu.Unlock() - return syserror.ENOTTY - } - - // "If the process was session leader, then send SIGHUP and SIGCONT to - // the foreground process group and all processes in the current - // session lose their controlling terminal." - tty_ioctl(4) - // Remove tty as the controlling tty for each process in the session, - // then send them SIGHUP and SIGCONT. - - // If we're not the session leader, we don't have to do much. - if tty.tg != tg { - tg.tty = nil - tg.signalHandlers.mu.Unlock() - return nil - } - - tg.signalHandlers.mu.Unlock() - - // We're the session leader. SIGHUP and SIGCONT the foreground process - // group and remove all controlling terminals in the session. - var lastErr error - for othertg := range tg.pidns.owner.Root.tgids { - if othertg.processGroup.session == tg.processGroup.session { - othertg.signalHandlers.mu.Lock() - othertg.tty = nil - if othertg.processGroup == tg.processGroup.session.foreground { - if err := othertg.leader.sendSignalLocked(&arch.SignalInfo{Signo: int32(linux.SIGHUP)}, true /* group */); err != nil { - lastErr = err - } - if err := othertg.leader.sendSignalLocked(&arch.SignalInfo{Signo: int32(linux.SIGCONT)}, true /* group */); err != nil { - lastErr = err - } - } - othertg.signalHandlers.mu.Unlock() - } - } - - return lastErr -} - -// ForegroundProcessGroup returns the process group ID of the foreground -// process group. -func (tg *ThreadGroup) ForegroundProcessGroup(tty *TTY) (int32, error) { - tty.mu.Lock() - defer tty.mu.Unlock() - - tg.pidns.owner.mu.Lock() - defer tg.pidns.owner.mu.Unlock() - tg.signalHandlers.mu.Lock() - defer tg.signalHandlers.mu.Unlock() - - // "When fd does not refer to the controlling terminal of the calling - // process, -1 is returned" - tcgetpgrp(3) - if tg.tty != tty { - return -1, syserror.ENOTTY - } - - return int32(tg.processGroup.session.foreground.id), nil -} - -// SetForegroundProcessGroup sets the foreground process group of tty to pgid. -func (tg *ThreadGroup) SetForegroundProcessGroup(tty *TTY, pgid ProcessGroupID) (int32, error) { - tty.mu.Lock() - defer tty.mu.Unlock() - - tg.pidns.owner.mu.Lock() - defer tg.pidns.owner.mu.Unlock() - tg.signalHandlers.mu.Lock() - defer tg.signalHandlers.mu.Unlock() - - // TODO(b/129283598): "If tcsetpgrp() is called by a member of a - // background process group in its session, and the calling process is - // not blocking or ignoring SIGTTOU, a SIGTTOU signal is sent to all - // members of this background process group." - - // tty must be the controlling terminal. - if tg.tty != tty { - return -1, syserror.ENOTTY - } - - // pgid must be positive. - if pgid < 0 { - return -1, syserror.EINVAL - } - - // pg must not be empty. Empty process groups are removed from their - // pid namespaces. - pg, ok := tg.pidns.processGroups[pgid] - if !ok { - return -1, syserror.ESRCH - } - - // pg must be part of this process's session. - if tg.processGroup.session != pg.session { - return -1, syserror.EPERM - } - - tg.processGroup.session.foreground.id = pgid - return 0, nil -} - // itimerRealListener implements ktime.Listener for ITIMER_REAL expirations. // // +stateify savable |