diff options
Diffstat (limited to 'pkg/sentry/kernel')
-rw-r--r-- | pkg/sentry/kernel/BUILD | 1 | ||||
-rw-r--r-- | pkg/sentry/kernel/sessions.go | 12 | ||||
-rw-r--r-- | pkg/sentry/kernel/task_start.go | 3 | ||||
-rw-r--r-- | pkg/sentry/kernel/thread_group.go | 179 | ||||
-rw-r--r-- | pkg/sentry/kernel/tty.go | 28 |
5 files changed, 2 insertions, 221 deletions
diff --git a/pkg/sentry/kernel/BUILD b/pkg/sentry/kernel/BUILD index 41bee9a22..e61d39c82 100644 --- a/pkg/sentry/kernel/BUILD +++ b/pkg/sentry/kernel/BUILD @@ -144,7 +144,6 @@ go_library( "threads.go", "timekeeper.go", "timekeeper_state.go", - "tty.go", "uts_namespace.go", "vdso.go", "version.go", diff --git a/pkg/sentry/kernel/sessions.go b/pkg/sentry/kernel/sessions.go index e5f297478..81fcd8258 100644 --- a/pkg/sentry/kernel/sessions.go +++ b/pkg/sentry/kernel/sessions.go @@ -47,11 +47,6 @@ type Session struct { // The id is immutable. id SessionID - // foreground is the foreground process group. - // - // This is protected by TaskSet.mu. - foreground *ProcessGroup - // ProcessGroups is a list of process groups in this Session. This is // protected by TaskSet.mu. processGroups processGroupList @@ -265,14 +260,12 @@ func (pg *ProcessGroup) SendSignal(info *arch.SignalInfo) error { func (tg *ThreadGroup) CreateSession() error { tg.pidns.owner.mu.Lock() defer tg.pidns.owner.mu.Unlock() - tg.signalHandlers.mu.Lock() - defer tg.signalHandlers.mu.Unlock() return tg.createSession() } // createSession creates a new session for a threadgroup. // -// Precondition: callers must hold TaskSet.mu and the signal mutex for writing. +// Precondition: callers must hold TaskSet.mu for writing. func (tg *ThreadGroup) createSession() error { // Get the ID for this thread in the current namespace. id := tg.pidns.tgids[tg] @@ -353,9 +346,6 @@ func (tg *ThreadGroup) createSession() error { ns.processGroups[ProcessGroupID(local)] = pg } - // Disconnect from the controlling terminal. - tg.tty = nil - return nil } diff --git a/pkg/sentry/kernel/task_start.go b/pkg/sentry/kernel/task_start.go index ae6fc4025..d60cd62c7 100644 --- a/pkg/sentry/kernel/task_start.go +++ b/pkg/sentry/kernel/task_start.go @@ -172,10 +172,9 @@ func (ts *TaskSet) newTask(cfg *TaskConfig) (*Task, error) { if parentPG := tg.parentPG(); parentPG == nil { tg.createSession() } else { - // Inherit the process group and terminal. + // Inherit the process group. parentPG.incRefWithParent(parentPG) tg.processGroup = parentPG - tg.tty = t.parent.tg.tty } } tg.tasks.PushBack(t) 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 diff --git a/pkg/sentry/kernel/tty.go b/pkg/sentry/kernel/tty.go deleted file mode 100644 index 34f84487a..000000000 --- a/pkg/sentry/kernel/tty.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2018 The gVisor Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package kernel - -import "sync" - -// TTY defines the relationship between a thread group and its controlling -// terminal. -// -// +stateify savable -type TTY struct { - mu sync.Mutex `state:"nosave"` - - // tg is protected by mu. - tg *ThreadGroup -} |