github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/pkg/sentry/kernel/thread_group.go (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package kernel
    16  
    17  import (
    18  	"sync/atomic"
    19  
    20  	"github.com/MerlinKodo/gvisor/pkg/abi/linux"
    21  	"github.com/MerlinKodo/gvisor/pkg/atomicbitops"
    22  	"github.com/MerlinKodo/gvisor/pkg/context"
    23  	"github.com/MerlinKodo/gvisor/pkg/errors/linuxerr"
    24  	"github.com/MerlinKodo/gvisor/pkg/sentry/kernel/auth"
    25  	ktime "github.com/MerlinKodo/gvisor/pkg/sentry/kernel/time"
    26  	"github.com/MerlinKodo/gvisor/pkg/sentry/limits"
    27  	"github.com/MerlinKodo/gvisor/pkg/sentry/usage"
    28  	"github.com/MerlinKodo/gvisor/pkg/sync"
    29  )
    30  
    31  // A ThreadGroup is a logical grouping of tasks that has widespread
    32  // significance to other kernel features (e.g. signal handling). ("Thread
    33  // groups" are usually called "processes" in userspace documentation.)
    34  //
    35  // ThreadGroup is a superset of Linux's struct signal_struct.
    36  //
    37  // +stateify savable
    38  type ThreadGroup struct {
    39  	threadGroupNode
    40  
    41  	// signalHandlers is the set of signal handlers used by every task in this
    42  	// thread group. (signalHandlers may also be shared with other thread
    43  	// groups.)
    44  	//
    45  	// signalHandlers.mu (hereafter "the signal mutex") protects state related
    46  	// to signal handling, as well as state that usually needs to be atomic
    47  	// with signal handling, for all ThreadGroups and Tasks using
    48  	// signalHandlers. (This is analogous to Linux's use of struct
    49  	// sighand_struct::siglock.)
    50  	//
    51  	// The signalHandlers pointer can only be mutated during an execve
    52  	// (Task.finishExec). Consequently, when it's possible for a task in the
    53  	// thread group to be completing an execve, signalHandlers is protected by
    54  	// the owning TaskSet.mu. Otherwise, it is possible to read the
    55  	// signalHandlers pointer without synchronization. In particular,
    56  	// completing an execve requires that all other tasks in the thread group
    57  	// have exited, so task goroutines do not need the owning TaskSet.mu to
    58  	// read the signalHandlers pointer of their thread groups.
    59  	signalHandlers *SignalHandlers
    60  
    61  	// pendingSignals is the set of pending signals that may be handled by any
    62  	// task in this thread group.
    63  	//
    64  	// pendingSignals is protected by the signal mutex.
    65  	pendingSignals pendingSignals
    66  
    67  	// If groupStopDequeued is true, a task in the thread group has dequeued a
    68  	// stop signal, but has not yet initiated the group stop.
    69  	//
    70  	// groupStopDequeued is analogous to Linux's JOBCTL_STOP_DEQUEUED.
    71  	//
    72  	// groupStopDequeued is protected by the signal mutex.
    73  	groupStopDequeued bool
    74  
    75  	// groupStopSignal is the signal that caused a group stop to be initiated.
    76  	//
    77  	// groupStopSignal is protected by the signal mutex.
    78  	groupStopSignal linux.Signal
    79  
    80  	// groupStopPendingCount is the number of active tasks in the thread group
    81  	// for which Task.groupStopPending is set.
    82  	//
    83  	// groupStopPendingCount is analogous to Linux's
    84  	// signal_struct::group_stop_count.
    85  	//
    86  	// groupStopPendingCount is protected by the signal mutex.
    87  	groupStopPendingCount int
    88  
    89  	// If groupStopComplete is true, groupStopPendingCount transitioned from
    90  	// non-zero to zero without an intervening SIGCONT.
    91  	//
    92  	// groupStopComplete is analogous to Linux's SIGNAL_STOP_STOPPED.
    93  	//
    94  	// groupStopComplete is protected by the signal mutex.
    95  	groupStopComplete bool
    96  
    97  	// If groupStopWaitable is true, the thread group is indicating a waitable
    98  	// group stop event (as defined by EventChildGroupStop).
    99  	//
   100  	// Linux represents the analogous state as SIGNAL_STOP_STOPPED being set
   101  	// and group_exit_code being non-zero.
   102  	//
   103  	// groupStopWaitable is protected by the signal mutex.
   104  	groupStopWaitable bool
   105  
   106  	// If groupContNotify is true, then a SIGCONT has recently ended a group
   107  	// stop on this thread group, and the first task to observe it should
   108  	// notify its parent. groupContInterrupted is true iff SIGCONT ended an
   109  	// incomplete group stop. If groupContNotify is false, groupContInterrupted is
   110  	// meaningless.
   111  	//
   112  	// Analogues in Linux:
   113  	//
   114  	//	- groupContNotify && groupContInterrupted is represented by
   115  	//		SIGNAL_CLD_STOPPED.
   116  	//
   117  	//	- groupContNotify && !groupContInterrupted is represented by
   118  	//		SIGNAL_CLD_CONTINUED.
   119  	//
   120  	//	- !groupContNotify is represented by neither flag being set.
   121  	//
   122  	// groupContNotify and groupContInterrupted are protected by the signal
   123  	// mutex.
   124  	groupContNotify      bool
   125  	groupContInterrupted bool
   126  
   127  	// If groupContWaitable is true, the thread group is indicating a waitable
   128  	// continue event (as defined by EventGroupContinue).
   129  	//
   130  	// groupContWaitable is analogous to Linux's SIGNAL_STOP_CONTINUED.
   131  	//
   132  	// groupContWaitable is protected by the signal mutex.
   133  	groupContWaitable bool
   134  
   135  	// exiting is true if all tasks in the ThreadGroup should exit. exiting is
   136  	// analogous to Linux's SIGNAL_GROUP_EXIT.
   137  	//
   138  	// exiting is protected by the signal mutex. exiting can only transition
   139  	// from false to true.
   140  	exiting bool
   141  
   142  	// exitStatus is the thread group's exit status.
   143  	//
   144  	// While exiting is false, exitStatus is protected by the signal mutex.
   145  	// When exiting becomes true, exitStatus becomes immutable.
   146  	exitStatus linux.WaitStatus
   147  
   148  	// terminationSignal is the signal that this thread group's leader will
   149  	// send to its parent when it exits.
   150  	//
   151  	// terminationSignal is protected by the TaskSet mutex.
   152  	terminationSignal linux.Signal
   153  
   154  	// liveGoroutines is the number of non-exited task goroutines in the thread
   155  	// group.
   156  	//
   157  	// liveGoroutines is not saved; it is reset as task goroutines are
   158  	// restarted by Task.Start.
   159  	liveGoroutines sync.WaitGroup `state:"nosave"`
   160  
   161  	timerMu threadGroupTimerMutex `state:"nosave"`
   162  
   163  	// itimerRealTimer implements ITIMER_REAL for the thread group.
   164  	itimerRealTimer *ktime.Timer
   165  
   166  	// itimerVirtSetting is the ITIMER_VIRTUAL setting for the thread group.
   167  	//
   168  	// itimerVirtSetting is protected by the signal mutex.
   169  	itimerVirtSetting ktime.Setting
   170  
   171  	// itimerProfSetting is the ITIMER_PROF setting for the thread group.
   172  	//
   173  	// itimerProfSetting is protected by the signal mutex.
   174  	itimerProfSetting ktime.Setting
   175  
   176  	// rlimitCPUSoftSetting is the setting for RLIMIT_CPU soft limit
   177  	// notifications for the thread group.
   178  	//
   179  	// rlimitCPUSoftSetting is protected by the signal mutex.
   180  	rlimitCPUSoftSetting ktime.Setting
   181  
   182  	// cpuTimersEnabled is non-zero if itimerVirtSetting.Enabled is true,
   183  	// itimerProfSetting.Enabled is true, rlimitCPUSoftSetting.Enabled is true,
   184  	// or limits.Get(CPU) is finite.
   185  	//
   186  	// cpuTimersEnabled is protected by the signal mutex.
   187  	cpuTimersEnabled atomicbitops.Uint32
   188  
   189  	// timers is the thread group's POSIX interval timers. nextTimerID is the
   190  	// TimerID at which allocation should begin searching for an unused ID.
   191  	//
   192  	// timers and nextTimerID are protected by timerMu.
   193  	timers      map[linux.TimerID]*IntervalTimer
   194  	nextTimerID linux.TimerID
   195  
   196  	// exitedCPUStats is the CPU usage for all exited tasks in the thread
   197  	// group. exitedCPUStats is protected by the TaskSet mutex.
   198  	exitedCPUStats usage.CPUStats
   199  
   200  	// childCPUStats is the CPU usage of all joined descendants of this thread
   201  	// group. childCPUStats is protected by the TaskSet mutex.
   202  	childCPUStats usage.CPUStats
   203  
   204  	// ioUsage is the I/O usage for all exited tasks in the thread group.
   205  	// The ioUsage pointer is immutable.
   206  	ioUsage *usage.IO
   207  
   208  	// maxRSS is the historical maximum resident set size of the thread group, updated when:
   209  	//
   210  	//	- A task in the thread group exits, since after all tasks have
   211  	//		exited the MemoryManager is no longer reachable.
   212  	//
   213  	//	- The thread group completes an execve, since this changes
   214  	//		MemoryManagers.
   215  	//
   216  	// maxRSS is protected by the TaskSet mutex.
   217  	maxRSS uint64
   218  
   219  	// childMaxRSS is the maximum resident set size in bytes of all joined
   220  	// descendants of this thread group.
   221  	//
   222  	// childMaxRSS is protected by the TaskSet mutex.
   223  	childMaxRSS uint64
   224  
   225  	// Resource limits for this ThreadGroup. The limits pointer is immutable.
   226  	limits *limits.LimitSet
   227  
   228  	// processGroup is the processGroup for this thread group.
   229  	//
   230  	// processGroup is protected by the TaskSet mutex.
   231  	processGroup *ProcessGroup
   232  
   233  	// execed indicates an exec has occurred since creation. This will be
   234  	// set by finishExec, and new TheadGroups will have this field cleared.
   235  	// When execed is set, the processGroup may no longer be changed.
   236  	//
   237  	// execed is protected by the TaskSet mutex.
   238  	execed bool
   239  
   240  	// oldRSeqCritical is the thread group's old rseq critical region.
   241  	oldRSeqCritical atomic.Value `state:".(*OldRSeqCriticalRegion)"`
   242  
   243  	// tty is the thread group's controlling terminal. If nil, there is no
   244  	// controlling terminal.
   245  	//
   246  	// tty is protected by the signal mutex.
   247  	tty *TTY
   248  
   249  	// oomScoreAdj is the thread group's OOM score adjustment. This is
   250  	// currently not used but is maintained for consistency.
   251  	// TODO(gvisor.dev/issue/1967)
   252  	oomScoreAdj atomicbitops.Int32
   253  
   254  	// isChildSubreaper and hasChildSubreaper correspond to Linux's
   255  	// signal_struct::is_child_subreaper and has_child_subreaper.
   256  	//
   257  	// Both fields are protected by the TaskSet mutex.
   258  	//
   259  	// Quoting from signal.h:
   260  	// "PR_SET_CHILD_SUBREAPER marks a process, like a service manager, to
   261  	// re-parent orphan (double-forking) child processes to this process
   262  	// instead of 'init'. The service manager is able to receive SIGCHLD
   263  	// signals and is able to investigate the process until it calls
   264  	// wait(). All children of this process will inherit a flag if they
   265  	// should look for a child_subreaper process at exit"
   266  	isChildSubreaper  bool
   267  	hasChildSubreaper bool
   268  }
   269  
   270  // NewThreadGroup returns a new, empty thread group in PID namespace pidns. The
   271  // thread group leader will send its parent terminationSignal when it exits.
   272  // The new thread group isn't visible to the system until a task has been
   273  // created inside of it by a successful call to TaskSet.NewTask.
   274  func (k *Kernel) NewThreadGroup(pidns *PIDNamespace, sh *SignalHandlers, terminationSignal linux.Signal, limits *limits.LimitSet) *ThreadGroup {
   275  	tg := &ThreadGroup{
   276  		threadGroupNode: threadGroupNode{
   277  			pidns: pidns,
   278  		},
   279  		signalHandlers:    sh,
   280  		terminationSignal: terminationSignal,
   281  		ioUsage:           &usage.IO{},
   282  		limits:            limits,
   283  	}
   284  	tg.itimerRealTimer = ktime.NewTimer(k.timekeeper.monotonicClock, &itimerRealListener{tg: tg})
   285  	tg.timers = make(map[linux.TimerID]*IntervalTimer)
   286  	tg.oldRSeqCritical.Store(&OldRSeqCriticalRegion{})
   287  	return tg
   288  }
   289  
   290  // saveOldRSeqCritical is invoked by stateify.
   291  func (tg *ThreadGroup) saveOldRSeqCritical() *OldRSeqCriticalRegion {
   292  	return tg.oldRSeqCritical.Load().(*OldRSeqCriticalRegion)
   293  }
   294  
   295  // loadOldRSeqCritical is invoked by stateify.
   296  func (tg *ThreadGroup) loadOldRSeqCritical(r *OldRSeqCriticalRegion) {
   297  	tg.oldRSeqCritical.Store(r)
   298  }
   299  
   300  // SignalHandlers returns the signal handlers used by tg.
   301  //
   302  // Preconditions: The caller must provide the synchronization required to read
   303  // tg.signalHandlers, as described in the field's comment.
   304  func (tg *ThreadGroup) SignalHandlers() *SignalHandlers {
   305  	return tg.signalHandlers
   306  }
   307  
   308  // Limits returns tg's limits.
   309  func (tg *ThreadGroup) Limits() *limits.LimitSet {
   310  	return tg.limits
   311  }
   312  
   313  // Release releases the thread group's resources.
   314  func (tg *ThreadGroup) Release(ctx context.Context) {
   315  	// Timers must be destroyed without holding the TaskSet or signal mutexes
   316  	// since timers send signals with Timer.mu locked.
   317  	tg.itimerRealTimer.Destroy()
   318  	var its []*IntervalTimer
   319  	tg.pidns.owner.mu.Lock()
   320  	tg.signalHandlers.mu.Lock()
   321  	for _, it := range tg.timers {
   322  		its = append(its, it)
   323  	}
   324  	tg.timers = make(map[linux.TimerID]*IntervalTimer) // nil maps can't be saved
   325  	tg.signalHandlers.mu.Unlock()
   326  	tg.pidns.owner.mu.Unlock()
   327  	for _, it := range its {
   328  		it.DestroyTimer()
   329  	}
   330  }
   331  
   332  // forEachChildThreadGroupLocked indicates over all child ThreadGroups.
   333  //
   334  // Precondition: TaskSet.mu must be held.
   335  func (tg *ThreadGroup) forEachChildThreadGroupLocked(fn func(*ThreadGroup)) {
   336  	tg.walkDescendantThreadGroupsLocked(func(child *ThreadGroup) bool {
   337  		fn(child)
   338  		// Don't recurse below the immediate children.
   339  		return false
   340  	})
   341  }
   342  
   343  // walkDescendantThreadGroupsLocked recursively walks all descendent
   344  // ThreadGroups and executes the visitor function. If visitor returns false for
   345  // a given ThreadGroup, then that ThreadGroups descendants are excluded from
   346  // further iteration.
   347  //
   348  // This corresponds to Linux's walk_process_tree.
   349  //
   350  // Precondition: TaskSet.mu must be held.
   351  func (tg *ThreadGroup) walkDescendantThreadGroupsLocked(visitor func(*ThreadGroup) bool) {
   352  	for t := tg.tasks.Front(); t != nil; t = t.Next() {
   353  		for child := range t.children {
   354  			if child == child.tg.leader {
   355  				if !visitor(child.tg) {
   356  					// Don't recurse below child.
   357  					continue
   358  				}
   359  				child.tg.walkDescendantThreadGroupsLocked(visitor)
   360  			}
   361  		}
   362  	}
   363  }
   364  
   365  // SetControllingTTY sets tty as the controlling terminal of tg.
   366  func (tg *ThreadGroup) SetControllingTTY(tty *TTY, steal bool, isReadable bool) error {
   367  	tty.mu.Lock()
   368  	defer tty.mu.Unlock()
   369  
   370  	// We might be asked to set the controlling terminal of multiple
   371  	// processes, so we lock both the TaskSet and SignalHandlers.
   372  	tg.pidns.owner.mu.Lock()
   373  	defer tg.pidns.owner.mu.Unlock()
   374  	tg.signalHandlers.mu.Lock()
   375  	defer tg.signalHandlers.mu.Unlock()
   376  
   377  	// "The calling process must be a session leader and not have a
   378  	// controlling terminal already." - tty_ioctl(4)
   379  	if tg.processGroup.session.leader != tg || tg.tty != nil {
   380  		return linuxerr.EINVAL
   381  	}
   382  
   383  	creds := auth.CredentialsFromContext(tg.leader)
   384  	hasAdmin := creds.HasCapabilityIn(linux.CAP_SYS_ADMIN, creds.UserNamespace.Root())
   385  
   386  	// "If this terminal is already the controlling terminal of a different
   387  	// session group, then the ioctl fails with EPERM, unless the caller
   388  	// has the CAP_SYS_ADMIN capability and arg equals 1, in which case the
   389  	// terminal is stolen, and all processes that had it as controlling
   390  	// terminal lose it." - tty_ioctl(4)
   391  	if tty.tg != nil && tg.processGroup.session != tty.tg.processGroup.session {
   392  		// Stealing requires CAP_SYS_ADMIN in the root user namespace.
   393  		if !hasAdmin || !steal {
   394  			return linuxerr.EPERM
   395  		}
   396  		// Steal the TTY away. Unlike TIOCNOTTY, don't send signals.
   397  		for othertg := range tg.pidns.owner.Root.tgids {
   398  			// This won't deadlock by locking tg.signalHandlers
   399  			// because at this point:
   400  			//	- We only lock signalHandlers if it's in the same
   401  			//		session as the tty's controlling thread group.
   402  			//	- We know that the calling thread group is not in
   403  			//		the same session as the tty's controlling thread
   404  			//		group.
   405  			if othertg.processGroup.session == tty.tg.processGroup.session {
   406  				othertg.signalHandlers.mu.NestedLock(signalHandlersLockTg)
   407  				othertg.tty = nil
   408  				othertg.signalHandlers.mu.NestedUnlock(signalHandlersLockTg)
   409  			}
   410  		}
   411  	}
   412  
   413  	if !isReadable && !hasAdmin {
   414  		return linuxerr.EPERM
   415  	}
   416  
   417  	// Set the controlling terminal and foreground process group.
   418  	tg.tty = tty
   419  	tg.processGroup.session.foreground = tg.processGroup
   420  	// Set this as the controlling process of the terminal.
   421  	tty.tg = tg
   422  
   423  	return nil
   424  }
   425  
   426  // ReleaseControllingTTY gives up tty as the controlling tty of tg.
   427  func (tg *ThreadGroup) ReleaseControllingTTY(tty *TTY) error {
   428  	tty.mu.Lock()
   429  	defer tty.mu.Unlock()
   430  
   431  	// We might be asked to set the controlling terminal of multiple
   432  	// processes, so we lock both the TaskSet and SignalHandlers.
   433  	tg.pidns.owner.mu.RLock()
   434  	defer tg.pidns.owner.mu.RUnlock()
   435  
   436  	// Just below, we may re-lock signalHandlers in order to send signals.
   437  	// Thus we can't defer Unlock here.
   438  	tg.signalHandlers.mu.Lock()
   439  
   440  	if tg.tty == nil || tg.tty != tty {
   441  		tg.signalHandlers.mu.Unlock()
   442  		return linuxerr.ENOTTY
   443  	}
   444  
   445  	// "If the process was session leader, then send SIGHUP and SIGCONT to
   446  	// the foreground process group and all processes in the current
   447  	// session lose their controlling terminal." - tty_ioctl(4)
   448  	// Remove tty as the controlling tty for each process in the session,
   449  	// then send them SIGHUP and SIGCONT.
   450  
   451  	// If we're not the session leader, we don't have to do much.
   452  	if tty.tg != tg {
   453  		tg.tty = nil
   454  		tg.signalHandlers.mu.Unlock()
   455  		return nil
   456  	}
   457  
   458  	tg.signalHandlers.mu.Unlock()
   459  
   460  	// We're the session leader. SIGHUP and SIGCONT the foreground process
   461  	// group and remove all controlling terminals in the session.
   462  	var lastErr error
   463  	for othertg := range tg.pidns.owner.Root.tgids {
   464  		if othertg.processGroup.session == tg.processGroup.session {
   465  			othertg.signalHandlers.mu.Lock()
   466  			othertg.tty = nil
   467  			if othertg.processGroup == tg.processGroup.session.foreground {
   468  				if err := othertg.leader.sendSignalLocked(&linux.SignalInfo{Signo: int32(linux.SIGHUP)}, true /* group */); err != nil {
   469  					lastErr = err
   470  				}
   471  				if err := othertg.leader.sendSignalLocked(&linux.SignalInfo{Signo: int32(linux.SIGCONT)}, true /* group */); err != nil {
   472  					lastErr = err
   473  				}
   474  			}
   475  			othertg.signalHandlers.mu.Unlock()
   476  		}
   477  	}
   478  
   479  	return lastErr
   480  }
   481  
   482  // ForegroundProcessGroupID returns the foreground process group ID of the
   483  // thread group.
   484  func (tg *ThreadGroup) ForegroundProcessGroupID(tty *TTY) (ProcessGroupID, error) {
   485  	tty.mu.Lock()
   486  	defer tty.mu.Unlock()
   487  
   488  	tg.pidns.owner.mu.Lock()
   489  	defer tg.pidns.owner.mu.Unlock()
   490  	tg.signalHandlers.mu.Lock()
   491  	defer tg.signalHandlers.mu.Unlock()
   492  
   493  	// fd must refer to the controlling terminal of the calling process.
   494  	// See tcgetpgrp(3)
   495  	if tg.tty != tty {
   496  		return 0, linuxerr.ENOTTY
   497  	}
   498  
   499  	return tg.processGroup.session.foreground.id, nil
   500  }
   501  
   502  // SetForegroundProcessGroupID sets the foreground process group of tty to
   503  // pgid.
   504  func (tg *ThreadGroup) SetForegroundProcessGroupID(tty *TTY, pgid ProcessGroupID) error {
   505  	tty.mu.Lock()
   506  	defer tty.mu.Unlock()
   507  
   508  	tg.pidns.owner.mu.Lock()
   509  	defer tg.pidns.owner.mu.Unlock()
   510  	tg.signalHandlers.mu.Lock()
   511  	defer tg.signalHandlers.mu.Unlock()
   512  
   513  	// tty must be the controlling terminal.
   514  	if tg.tty != tty {
   515  		return linuxerr.ENOTTY
   516  	}
   517  
   518  	// pgid must be positive.
   519  	if pgid < 0 {
   520  		return linuxerr.EINVAL
   521  	}
   522  
   523  	// pg must not be empty. Empty process groups are removed from their
   524  	// pid namespaces.
   525  	pg, ok := tg.pidns.processGroups[pgid]
   526  	if !ok {
   527  		return linuxerr.ESRCH
   528  	}
   529  
   530  	// pg must be part of this process's session.
   531  	if tg.processGroup.session != pg.session {
   532  		return linuxerr.EPERM
   533  	}
   534  
   535  	signalAction := tg.signalHandlers.actions[linux.SIGTTOU]
   536  	// If the calling process is a member of a background group, a SIGTTOU
   537  	// signal is sent to all members of this background process group.
   538  	// We need also need to check whether it is ignoring or blocking SIGTTOU.
   539  	ignored := signalAction.Handler == linux.SIG_IGN
   540  	blocked := (linux.SignalSet(tg.leader.signalMask.RacyLoad()) & linux.SignalSetOf(linux.SIGTTOU)) != 0
   541  	if tg.processGroup.id != tg.processGroup.session.foreground.id && !ignored && !blocked {
   542  		tg.leader.sendSignalLocked(SignalInfoPriv(linux.SIGTTOU), true)
   543  		return linuxerr.ERESTARTSYS
   544  	}
   545  
   546  	tg.processGroup.session.foreground = pg
   547  	return nil
   548  }
   549  
   550  // SetChildSubreaper marks this ThreadGroup sets the isChildSubreaper field on
   551  // this ThreadGroup, and marks all child ThreadGroups as having a subreaper.
   552  // Recursion stops if we find another subreaper process, which is either a
   553  // ThreadGroup with isChildSubreaper bit set, or a ThreadGroup with PID=1
   554  // inside a PID namespace.
   555  func (tg *ThreadGroup) SetChildSubreaper(isSubreaper bool) {
   556  	ts := tg.TaskSet()
   557  	ts.mu.Lock()
   558  	defer ts.mu.Unlock()
   559  	tg.isChildSubreaper = isSubreaper
   560  	tg.walkDescendantThreadGroupsLocked(func(child *ThreadGroup) bool {
   561  		// Is this child PID 1 in its PID namespace, or already a
   562  		// subreaper?
   563  		if child.isInitInLocked(child.PIDNamespace()) || child.isChildSubreaper {
   564  			// Don't set hasChildSubreaper, and don't recurse.
   565  			return false
   566  		}
   567  		child.hasChildSubreaper = isSubreaper
   568  		return true // Recurse.
   569  	})
   570  }
   571  
   572  // IsChildSubreaper returns whether this ThreadGroup is a child subreaper.
   573  func (tg *ThreadGroup) IsChildSubreaper() bool {
   574  	ts := tg.TaskSet()
   575  	ts.mu.RLock()
   576  	defer ts.mu.RUnlock()
   577  	return tg.isChildSubreaper
   578  }
   579  
   580  // IsInitIn returns whether this ThreadGroup has TID 1 int the given
   581  // PIDNamespace.
   582  func (tg *ThreadGroup) IsInitIn(pidns *PIDNamespace) bool {
   583  	ts := tg.TaskSet()
   584  	ts.mu.RLock()
   585  	defer ts.mu.RUnlock()
   586  	return tg.isInitInLocked(pidns)
   587  }
   588  
   589  // isInitInLocked returns whether this ThreadGroup has TID 1 in the given
   590  // PIDNamespace.
   591  //
   592  // Preconditions: TaskSet.mu must be locked.
   593  func (tg *ThreadGroup) isInitInLocked(pidns *PIDNamespace) bool {
   594  	return pidns.tgids[tg] == initTID
   595  }
   596  
   597  // itimerRealListener implements ktime.Listener for ITIMER_REAL expirations.
   598  //
   599  // +stateify savable
   600  type itimerRealListener struct {
   601  	tg *ThreadGroup
   602  }
   603  
   604  // NotifyTimer implements ktime.TimerListener.NotifyTimer.
   605  func (l *itimerRealListener) NotifyTimer(exp uint64, setting ktime.Setting) (ktime.Setting, bool) {
   606  	l.tg.SendSignal(SignalInfoPriv(linux.SIGALRM))
   607  	return ktime.Setting{}, false
   608  }