Files

880 lines
31 KiB
Go
Raw Permalink Normal View History

// Copyright 2018 The gVisor Authors.
2018-04-27 10:37:02 -07:00
//
// 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 (
2019-12-06 16:58:28 -08:00
gocontext "context"
"runtime/trace"
2018-04-27 10:37:02 -07:00
"sync/atomic"
2019-06-13 16:49:09 -07:00
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/atomicbitops"
"gvisor.dev/gvisor/pkg/errors/linuxerr"
2021-03-29 13:28:32 -07:00
"gvisor.dev/gvisor/pkg/hostarch"
2022-05-06 12:18:45 -07:00
"gvisor.dev/gvisor/pkg/metric"
2019-06-13 16:49:09 -07:00
"gvisor.dev/gvisor/pkg/sentry/inet"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/kernel/futex"
"gvisor.dev/gvisor/pkg/sentry/kernel/sched"
"gvisor.dev/gvisor/pkg/sentry/ktime"
2019-06-13 16:49:09 -07:00
"gvisor.dev/gvisor/pkg/sentry/platform"
"gvisor.dev/gvisor/pkg/sentry/usage"
2020-01-28 15:13:46 -08:00
"gvisor.dev/gvisor/pkg/sentry/vfs"
2020-01-09 22:00:42 -08:00
"gvisor.dev/gvisor/pkg/sync"
2019-09-18 15:15:16 -07:00
"gvisor.dev/gvisor/pkg/waiter"
2018-04-27 10:37:02 -07:00
)
// TaskOrigin indicates how the task was initially created.
type TaskOrigin int
const (
// OriginUnknown indicates that task creation source is not known (or not important).
OriginUnknown TaskOrigin = iota
// OriginExec indicates that task was created due to an exec request inside a container.
OriginExec
)
2018-04-27 10:37:02 -07:00
// Task represents a thread of execution in the untrusted app. It
// includes registers and any thread-specific state that you would
// normally expect.
//
// Each task is associated with a goroutine, called the task goroutine, that
// executes code (application code, system calls, etc.) on behalf of that task.
// See Task.run (task_run.go).
//
// All fields that are "owned by the task goroutine" can only be mutated by the
// task goroutine while it is running. The task goroutine does not require
// synchronization to read these fields, although it still requires
// synchronization as described for those fields to mutate them.
//
// All fields that are "exclusive to the task goroutine" can only be accessed
// by the task goroutine while it is running. The task goroutine does not
// require synchronization to read or write these fields.
2018-08-02 10:41:44 -07:00
//
// +stateify savable
2018-04-27 10:37:02 -07:00
type Task struct {
taskNode
// goid is the task goroutine's ID. goid is owned by the task goroutine,
// but since it's used to detect cases where non-task goroutines
// incorrectly access state owned by, or exclusive to, the task goroutine,
// goid is always accessed using atomic memory operations.
goid atomicbitops.Int64 `state:"nosave"`
2018-04-27 10:37:02 -07:00
// runState is what the task goroutine is executing if it is not stopped.
// If runState is nil, the task goroutine should exit or has exited.
// runState is exclusive to the task goroutine.
runState taskRunState
2020-07-23 16:22:41 -07:00
// taskWorkCount represents the current size of the task work queue. It is
// used to avoid acquiring taskWorkMu when the queue is empty.
taskWorkCount atomicbitops.Int32
2020-07-23 16:22:41 -07:00
// taskWorkMu protects taskWork.
2023-05-18 09:56:24 -07:00
taskWorkMu taskWorkMutex `state:"nosave"`
2020-07-23 16:22:41 -07:00
// taskWork is a queue of work to be executed before resuming user execution.
// It is similar to the task_work mechanism in Linux.
//
// taskWork is exclusive to the task goroutine.
taskWork []TaskWorker
// haveSyscallReturn is true if image.Arch().Return() represents a value
2018-04-27 10:37:02 -07:00
// returned by a syscall (or set by ptrace after a syscall).
//
// haveSyscallReturn is exclusive to the task goroutine.
haveSyscallReturn bool
// interruptChan is notified whenever the task goroutine is interrupted
// (usually by a pending signal). interruptChan is effectively a condition
// variable that can be used in select statements.
//
// interruptChan is not saved; because saving interrupts all tasks,
// interruptChan is always notified after restore (see Task.run).
interruptChan chan struct{} `state:"nosave"`
// gostateSeq allows Task.TaskGoroutineStateTime() to read gostate and
// gostateTime atomically.
2018-04-27 10:37:02 -07:00
//
// gostateSeq is owned by the task goroutine.
gostateSeq sync.SeqCount `state:"nosave"`
// gostate is the current scheduling state of the task goroutine.
//
// gostate is owned by the task goroutine.
gostate atomicbitops.Uint32
// gostateTime was the value of Kernel.cpuClock when gostate was last
// updated or refreshed.
//
// gostateTime is owned by the task goroutine.
gostateTime atomicbitops.Int64
// appCPUClock approximates the amount of time the task goroutine has spent
// in TaskGoroutineRunningApp.
appCPUClock ktime.SyntheticClock
// appSysCPUClock approximates the amount of time the task goroutine has
// spent in TaskGoroutineRunningApp or TaskGoroutineRunningSys.
appSysCPUClock ktime.SyntheticClock
2018-04-27 10:37:02 -07:00
// yieldCount is the number of times the task goroutine has called
// Task.InterruptibleSleepStart, Task.UninterruptibleSleepStart, or
// Task.Yield(), voluntarily ceasing execution.
//
// yieldCount is accessed using atomic memory operations. yieldCount is
// owned by the task goroutine.
yieldCount atomicbitops.Uint64
2018-04-27 10:37:02 -07:00
// pendingSignals is the set of pending signals that may be handled only by
// this task.
//
// pendingSignals is protected by (taskNode.)tg.signalHandlers.mu
// (hereafter "the signal mutex"); see comment on
// ThreadGroup.signalHandlers.
pendingSignals pendingSignals
2018-08-31 13:57:02 -07:00
// signalMask is the set of signals whose delivery is currently blocked.
//
// signalMask is accessed using atomic memory operations, and is protected
// by the signal mutex (such that reading signalMask is safe if either the
// signal mutex is locked or if atomic memory operations are used, while
// writing signalMask requires both). signalMask is owned by the task
// goroutine.
signalMask atomicbitops.Uint64
2018-08-31 13:57:02 -07:00
// If the task goroutine is currently executing Task.sigtimedwait,
// realSignalMask is the previous value of signalMask, which has temporarily
// been replaced by Task.sigtimedwait. Otherwise, realSignalMask is 0.
//
// realSignalMask is exclusive to the task goroutine.
realSignalMask linux.SignalSet
2018-08-31 13:57:02 -07:00
2018-04-27 10:37:02 -07:00
// If haveSavedSignalMask is true, savedSignalMask is the signal mask that
// should be applied after the task has either delivered one signal to a
// user handler or is about to resume execution in the untrusted
// application.
//
// Both haveSavedSignalMask and savedSignalMask are exclusive to the task
// goroutine.
haveSavedSignalMask bool
savedSignalMask linux.SignalSet
// signalStack is the alternate signal stack used by signal handlers for
// which the SA_ONSTACK flag is set.
//
// signalStack is exclusive to the task goroutine.
2021-06-10 00:58:14 -07:00
signalStack linux.SignalStack
2018-04-27 10:37:02 -07:00
2019-09-18 15:15:16 -07:00
// signalQueue is a set of registered waiters for signal-related events.
//
// signalQueue is protected by the signalMutex. Note that the task does
// not implement all queue methods, specifically the readiness checks.
// The task only broadcast a notification on signal delivery.
signalQueue waiter.Queue
2019-09-18 15:15:16 -07:00
// If groupStopPending is true, the task should participate in a group
// stop in the interrupt path.
2018-04-27 10:37:02 -07:00
//
// groupStopPending is analogous to JOBCTL_STOP_PENDING in Linux.
2018-04-27 10:37:02 -07:00
//
// groupStopPending is protected by the signal mutex.
groupStopPending bool
2018-04-27 10:37:02 -07:00
// If groupStopAcknowledged is true, the task has already acknowledged that
// it is entering the most recent group stop that has been initiated on its
// thread group.
2018-04-27 10:37:02 -07:00
//
// groupStopAcknowledged is analogous to !JOBCTL_STOP_CONSUME in Linux.
//
// groupStopAcknowledged is protected by the signal mutex.
groupStopAcknowledged bool
// If trapStopPending is true, the task goroutine should enter a
// PTRACE_INTERRUPT-induced stop from the interrupt path.
//
// trapStopPending is analogous to JOBCTL_TRAP_STOP in Linux, except that
// Linux also sets JOBCTL_TRAP_STOP when a ptraced task detects
// JOBCTL_STOP_PENDING.
//
// trapStopPending is protected by the signal mutex.
trapStopPending bool
// If trapNotifyPending is true, this task is PTRACE_SEIZEd, and a group
// stop has begun or ended since the last time the task entered a
// ptrace-stop from the group-stop path.
//
// trapNotifyPending is analogous to JOBCTL_TRAP_NOTIFY in Linux.
//
// trapNotifyPending is protected by the signal mutex.
trapNotifyPending bool
2018-04-27 10:37:02 -07:00
// If stop is not nil, it is the internally-initiated condition that
// currently prevents the task goroutine from running.
//
// stop is protected by the signal mutex.
stop TaskStop
// stopCount is the number of active external stops (calls to
// Task.BeginExternalStop that have not been paired with a call to
// Task.EndExternalStop), plus 1 if stop is not nil. Hence stopCount is
// non-zero if the task goroutine should stop.
//
// Mutating stopCount requires both locking the signal mutex and using
// atomic memory operations. Reading stopCount requires either locking the
// signal mutex or using atomic memory operations. This allows Task.doStop
// to require only a single atomic read in the common case where stopCount
// is 0.
//
// stopCount is not saved, because external stops cannot be retained across
// a save/restore cycle. (Suppose a sentryctl command issues an external
// stop; after a save/restore cycle, the restored sentry has no knowledge
// of the pre-save sentryctl command, and the stopped task would remain
// stopped forever.)
stopCount atomicbitops.Int32 `state:"nosave"`
2018-04-27 10:37:02 -07:00
// endStopCond is signaled when stopCount transitions to 0. The combination
// of stopCount and endStopCond effectively form a sync.WaitGroup, but
// WaitGroup provides no way to read its counter value.
//
// Invariant: endStopCond.L is the signal mutex. (This is not racy because
// sync.Cond.Wait is the only user of sync.Cond.L; only the task goroutine
// calls sync.Cond.Wait; and only the task goroutine can change the
// identity of the signal mutex, in Task.finishExec.)
endStopCond sync.Cond `state:"nosave"`
// exitStatus is the task's exit status.
//
// exitStatus is protected by the signal mutex.
exitStatus linux.WaitStatus
2018-04-27 10:37:02 -07:00
// syscallRestartBlock represents a custom restart function to run in
// restart_syscall(2) to resume an interrupted syscall.
//
// syscallRestartBlock is exclusive to the task goroutine.
syscallRestartBlock SyscallRestartBlock
// p provides the mechanism by which the task runs code in userspace. The p
// interface object is immutable.
p platform.Context `state:"nosave"`
// k is the Kernel that this task belongs to. The k pointer is immutable.
k *Kernel
2018-09-27 15:00:03 -07:00
// containerID has no equivalent in Linux; it's used by runsc to track all
// tasks that belong to a given containers since cgroups aren't implemented.
// It's inherited by the children, is immutable, and may be empty.
//
// NOTE: cgroups can be used to track this when implemented.
containerID string
2018-08-31 13:57:02 -07:00
// mu protects some of the following fields.
2022-05-19 18:27:34 -07:00
mu taskMutex `state:"nosave"`
2018-08-31 13:57:02 -07:00
// image holds task data provided by the ELF loader.
2018-08-31 13:57:02 -07:00
//
// image is protected by mu, and is owned by the task goroutine.
image TaskImage
2018-08-31 13:57:02 -07:00
2019-07-02 19:27:51 -07:00
// fsContext is the task's filesystem context.
2018-08-31 13:57:02 -07:00
//
2019-07-02 19:27:51 -07:00
// fsContext is protected by mu, and is owned by the task goroutine.
fsContext *FSContext
2018-08-31 13:57:02 -07:00
2019-07-02 19:27:51 -07:00
// fdTable is the task's file descriptor table.
2018-08-31 13:57:02 -07:00
//
2019-07-02 19:27:51 -07:00
// fdTable is protected by mu, and is owned by the task goroutine.
fdTable *FDTable
2018-08-31 13:57:02 -07:00
2018-04-27 10:37:02 -07:00
// If vforkParent is not nil, it is the task that created this task with
// vfork() or clone(CLONE_VFORK), and should have its vforkStop ended when
// this TaskImage is released.
2018-04-27 10:37:02 -07:00
//
// vforkParent is protected by the TaskSet mutex.
vforkParent atomic.Pointer[Task] `state:".(*Task)"`
2018-04-27 10:37:02 -07:00
// exitState is the task's progress through the exit path.
//
// exitState is protected by the TaskSet mutex. exitState is owned by the
// task goroutine.
2024-10-01 12:44:40 -07:00
exitState atomicbitops.Uint32
2018-04-27 10:37:02 -07:00
// exitTracerNotified is true if the exit path has either signaled the
// task's tracer to indicate the exit, or determined that no such signal is
// needed. exitTracerNotified can only be true if exitState is
// TaskExitZombie or TaskExitDead.
//
// exitTracerNotified is protected by the TaskSet mutex.
exitTracerNotified bool
// exitTracerAcked is true if exitTracerNotified is true and either the
// task's tracer has acknowledged the exit notification, or the exit path
// has determined that no such notification is needed.
//
// exitTracerAcked is protected by the TaskSet mutex.
exitTracerAcked bool
// exitParentNotified is true if the exit path has either signaled the
// task's parent to indicate the exit, or determined that no such signal is
// needed. exitParentNotified can only be true if exitState is
// TaskExitZombie or TaskExitDead.
//
// exitParentNotified is protected by the TaskSet mutex.
exitParentNotified bool
// exitParentAcked is true if exitParentNotified is true and either the
// task's parent has acknowledged the exit notification, or the exit path
// has determined that no such acknowledgment is needed.
//
// exitParentAcked is protected by the TaskSet mutex.
exitParentAcked bool
// goroutineStopped is a WaitGroup whose counter value is 1 when the task
// goroutine is running and 0 when the task goroutine is stopped or has
// exited.
goroutineStopped sync.WaitGroup `state:"nosave"`
// ptraceTracer is the task that is ptrace-attached to this one. If
// ptraceTracer is nil, this task is not being traced.
2018-04-27 10:37:02 -07:00
//
// ptraceTracer is protected by the TaskSet mutex, and accessed with atomic
// operations. This allows paths that wouldn't otherwise lock the TaskSet
// mutex, notably the syscall path, to check if ptraceTracer is nil without
// additional synchronization.
ptraceTracer atomic.Pointer[Task] `state:".(*Task)"`
2018-04-27 10:37:02 -07:00
// ptraceTracees is the set of tasks that this task is ptrace-attached to.
//
// ptraceTracees is protected by the TaskSet mutex.
ptraceTracees map[*Task]struct{}
// ptraceSeized is true if ptraceTracer attached to this task with
// PTRACE_SEIZE.
//
// ptraceSeized is protected by the TaskSet mutex.
ptraceSeized bool
2018-04-27 10:37:02 -07:00
// ptraceOpts contains ptrace options explicitly set by the tracer. If
// ptraceTracer is nil, ptraceOpts is expected to be the zero value.
//
// ptraceOpts is protected by the TaskSet mutex.
ptraceOpts ptraceOptions
// ptraceSyscallMode controls ptrace behavior around syscall entry and
// exit.
//
// ptraceSyscallMode is protected by the TaskSet mutex.
ptraceSyscallMode ptraceSyscallMode
// If ptraceSinglestep is true, the next time the task executes application
// code, single-stepping should be enabled. ptraceSinglestep is stored
// independently of the architecture-specific trap flag because tracer
// detaching (which can happen concurrently with the tracee's execution if
// the tracer exits) must disable single-stepping, and the task's
// architectural state is implicitly exclusive to the task goroutine (no
// synchronization occurs before passing registers to SwitchToApp).
//
// ptraceSinglestep is analogous to Linux's TIF_SINGLESTEP.
//
// ptraceSinglestep is protected by the TaskSet mutex.
ptraceSinglestep bool
// If t is ptrace-stopped, ptraceCode is a ptrace-defined value set at the
// time that t entered the ptrace stop, reset to 0 when the tracer
// acknowledges the stop with a wait*() syscall. Otherwise, it is the
// signal number passed to the ptrace operation that ended the last ptrace
// stop on this task. In the latter case, the effect of ptraceCode depends
// on the nature of the ptrace stop; signal-delivery-stop uses it to
// conditionally override ptraceSiginfo, syscall-entry/exit-stops send the
// signal to the task after leaving the stop, and PTRACE_EVENT stops and
// traced group stops ignore it entirely.
//
// Linux contextually stores the equivalent of ptraceCode in
// task_struct::exit_code.
//
// ptraceCode is protected by the TaskSet mutex.
ptraceCode int32
// ptraceSiginfo is the value returned to the tracer by
// ptrace(PTRACE_GETSIGINFO) and modified by ptrace(PTRACE_SETSIGINFO).
// (Despite the name, PTRACE_PEEKSIGINFO is completely unrelated.)
// ptraceSiginfo is nil if the task is in a ptraced group-stop (this is
// required for PTRACE_GETSIGINFO to return EINVAL during such stops, which
// is in turn required to distinguish group stops from other ptrace stops,
// per subsection "Group-stop" in ptrace(2)).
//
// ptraceSiginfo is analogous to Linux's task_struct::last_siginfo.
//
// ptraceSiginfo is protected by the TaskSet mutex.
2021-06-10 10:23:53 -07:00
ptraceSiginfo *linux.SignalInfo
2018-04-27 10:37:02 -07:00
// ptraceEventMsg is the value set by PTRACE_EVENT stops and returned to
// the tracer by ptrace(PTRACE_GETEVENTMSG).
//
// ptraceEventMsg is protected by the TaskSet mutex.
ptraceEventMsg uint64
// ptraceYAMAExceptionAdded is true if a YAMA exception involving the task has
// been added before. This is used during task exit to decide whether we need
// to clean up YAMA exceptions.
//
// ptraceYAMAExceptionAdded is protected by the TaskSet mutex.
ptraceYAMAExceptionAdded bool
2018-04-27 10:37:02 -07:00
// The struct that holds the IO-related usage. The ioUsage pointer is
// immutable.
ioUsage *usage.IO
// logPrefix is a string containing the task's thread ID in the root PID
// namespace, and is prepended to log messages emitted by Task.Infof etc.
2024-03-04 12:49:13 +02:00
logPrefix atomic.Pointer[string] `state:"nosave"`
2019-12-06 16:58:28 -08:00
// traceContext and traceTask are both used for tracing, and are
// updated along with the logPrefix in updateInfoLocked.
//
// These are exclusive to the task goroutine.
traceContext gocontext.Context `state:"nosave"`
traceTask *trace.Task `state:"nosave"`
2018-04-27 10:37:02 -07:00
// creds is the task's credentials.
//
// creds.Load() may be called without synchronization. creds.Store() is
// serialized by mu. creds is owned by the task goroutine. All
// auth.Credentials objects that creds may point to, or have pointed to
// in the past, must be treated as immutable.
creds auth.AtomicPtrCredentials
2018-04-27 10:37:02 -07:00
// utsns is the task's UTS namespace.
//
// utsns is protected by mu. utsns is owned by the task goroutine.
2018-04-27 10:37:02 -07:00
utsns *UTSNamespace
// ipcns is the task's IPC namespace.
//
// ipcns is protected by mu. ipcns is owned by the task goroutine.
2018-04-27 10:37:02 -07:00
ipcns *IPCNamespace
2022-11-07 00:37:27 -08:00
// mountNamespace is the task's mount namespace.
2020-02-14 11:11:55 -08:00
//
// It is protected by mu. It is owned by the task goroutine.
2022-11-07 00:37:27 -08:00
mountNamespace *vfs.MountNamespace
2020-02-14 11:11:55 -08:00
2018-04-27 10:37:02 -07:00
// parentDeathSignal is sent to this task's thread group when its parent exits.
//
// parentDeathSignal is protected by mu.
parentDeathSignal linux.Signal
// seccomp contains all seccomp-bpf syscall filters applicable to the task.
// The type of the atomic is *taskSeccomp.
2024-03-04 12:49:13 +02:00
// Writing needs to be protected by the signal mutex.
2018-04-27 10:37:02 -07:00
//
// seccomp is owned by the task goroutine.
2024-03-04 12:49:13 +02:00
seccomp atomic.Pointer[taskSeccomp] `state:".(*taskSeccomp)"`
2018-04-27 10:37:02 -07:00
// If cleartid is non-zero, treat it as a pointer to a ThreadID in the
// task's virtual address space; when the task exits, set the pointed-to
// ThreadID to 0, and wake any futex waiters.
//
// cleartid is exclusive to the task goroutine.
2021-03-29 13:28:32 -07:00
cleartid hostarch.Addr
2018-04-27 10:37:02 -07:00
// This is mostly a fake cpumask just for sched_set/getaffinity as we
// don't really control the affinity.
//
// Invariant: allowedCPUMask.Size() ==
// sched.CPUMaskSize(Kernel.applicationCores).
//
// allowedCPUMask is protected by mu.
allowedCPUMask sched.CPUSet
// cpu is the fake cpu number returned by getcpu(2). cpu is ignored
// entirely if Kernel.useHostCores is true.
cpu atomicbitops.Int32
2018-04-27 10:37:02 -07:00
// This is used to keep track of changes made to a process' priority/niceness.
// It is mostly used to provide some reasonable return value from
// getpriority(2) after a call to setpriority(2) has been made.
// We currently do not actually modify a process' scheduling priority.
// NOTE: This represents the userspace view of priority (nice).
// This means that the value should be in the range [-20, 19].
//
// niceness is protected by mu.
niceness int
// This is used to track the numa policy for the current thread. This can be
// modified through a set_mempolicy(2) syscall. Since we always report a
// single numa node, all policies are no-ops. We only track this information
// so that we can return reasonable values if the application calls
// get_mempolicy(2) after setting a non-default policy. Note that in the
2019-06-06 16:27:09 -07:00
// real syscall, nodemask can be longer than a single unsigned long, but we
// always report a single node so never need to save more than a single
// bit.
2018-04-27 10:37:02 -07:00
//
// numaPolicy and numaNodeMask are protected by mu.
numaPolicy linux.NumaPolicy
2019-06-06 16:27:09 -07:00
numaNodeMask uint64
2018-04-27 10:37:02 -07:00
2023-07-24 15:42:22 -07:00
// netns is the task's network namespace. It has to be changed under mu
// so that GetNetworkNamespace can take a reference before it is
// released. It is changed only from the task goroutine.
netns *inet.Namespace
2018-04-27 10:37:02 -07:00
2020-01-06 11:41:13 -08:00
// If rseqPreempted is true, before the next call to p.Switch(),
// interrupt rseq critical regions as defined by rseqAddr and
// tg.oldRSeqCritical and write the task goroutine's CPU number to
// rseqAddr/oldRSeqCPUAddr.
2018-04-27 10:37:02 -07:00
//
2020-01-06 11:41:13 -08:00
// We support two ABIs for restartable sequences:
2018-04-27 10:37:02 -07:00
//
2020-01-06 11:41:13 -08:00
// 1. The upstream interface added in v4.18,
// 2. An "old" interface never merged upstream. In the implementation,
// this is referred to as "old rseq".
//
// rseqPreempted is exclusive to the task goroutine.
2018-04-27 10:37:02 -07:00
rseqPreempted bool `state:"nosave"`
2020-01-06 11:41:13 -08:00
// rseqCPU is the last CPU number written to rseqAddr/oldRSeqCPUAddr.
//
// If rseq is unused, rseqCPU is -1 for convenient use in
// platform.Context.Switch.
//
// rseqCPU is exclusive to the task goroutine.
rseqCPU int32
// oldRSeqCPUAddr is a pointer to the userspace old rseq CPU variable.
//
// oldRSeqCPUAddr is exclusive to the task goroutine.
2021-03-29 13:28:32 -07:00
oldRSeqCPUAddr hostarch.Addr
2020-01-06 11:41:13 -08:00
// rseqAddr is a pointer to the userspace linux.RSeq structure.
//
// rseqAddr is exclusive to the task goroutine.
2021-03-29 13:28:32 -07:00
rseqAddr hostarch.Addr
2020-01-06 11:41:13 -08:00
// rseqSignature is the signature that the rseq abort IP must be signed
// with.
//
// rseqSignature is exclusive to the task goroutine.
rseqSignature uint32
2018-04-27 10:37:02 -07:00
// copyScratchBuffer is a buffer available to CopyIn/CopyOut
// implementations that require an intermediate buffer to copy data
// into/out of. It prevents these buffers from being allocated/zeroed in
// each syscall and eventually garbage collected.
//
// copyScratchBuffer is exclusive to the task goroutine.
copyScratchBuffer [copyScratchBufferLen]byte `state:"nosave"`
// blockingTimer is used for blocking timeouts from ktime.SampledClocks.
// blockingTimerListener sends to blockingTimerChan when blockingTimer
// expires.
2018-04-27 10:37:02 -07:00
//
// blockingTimer is exclusive to the task goroutine.
blockingTimer *ktime.SampledTimer `state:"nosave"`
blockingTimerListener ktime.Listener `state:"nosave"`
blockingTimerChan <-chan struct{} `state:"nosave"`
2018-04-27 10:37:02 -07:00
// futexWaiter is used for futex(FUTEX_WAIT) syscalls.
//
// futexWaiter is exclusive to the task goroutine.
futexWaiter *futex.Waiter `state:"nosave"`
2020-07-23 17:40:46 -07:00
// robustList is a pointer to the head of the tasks's robust futex
// list.
2021-03-29 13:28:32 -07:00
robustList hostarch.Addr
2020-07-23 17:40:46 -07:00
2018-04-27 10:37:02 -07:00
// startTime is the real time at which the task started. It is set when
// a Task is created or invokes execve(2).
//
// startTime is protected by mu.
startTime ktime.Time
// kcov is the kcov instance providing code coverage owned by this task.
//
// kcov is exclusive to the task goroutine.
kcov *Kcov
2021-04-02 21:08:53 -07:00
// cgroups is the set of cgroups this task belongs to. This may be empty if
// no cgroup controllers are enabled. Protected by mu.
//
// +checklocks:mu
cgroups map[Cgroup]struct{}
2021-12-13 18:40:31 -08:00
2023-07-10 15:14:24 -07:00
// memCgID is the memory cgroup id.
memCgID atomicbitops.Uint32
2021-12-13 18:40:31 -08:00
// userCounters is a pointer to a set of user counters.
//
// The userCounters pointer is exclusive to the task goroutine, but the
// userCounters instance must be atomically accessed.
2023-11-08 12:17:31 -08:00
userCounters *UserCounters
// sessionKeyring is a pointer to the task's session keyring, if set.
// It is guaranteed to be of type "keyring".
//
// +checklocks:mu
sessionKeyring *auth.Key
// Origin is the origin of the task.
Origin TaskOrigin
// onDestroyAction is a set of callbacks that are executed when the
// task is destroyed.
onDestroyAction map[TaskDestroyAction]struct{}
2018-04-27 10:37:02 -07:00
}
2022-05-06 12:18:45 -07:00
// Task related metrics
var (
// syscallCounter is a metric that tracks how many syscalls the sentry has
// executed.
syscallCounter = metric.SentryProfiling.MustCreateNewUint64Metric(
"/task/syscalls", metric.Uint64Metadata{
Cumulative: true,
Description: "The number of syscalls the sentry has executed for the user.",
})
2022-05-06 12:18:45 -07:00
// faultCounter is a metric that tracks how many faults the sentry has had to
// handle.
faultCounter = metric.SentryProfiling.MustCreateNewUint64Metric(
"/task/faults", metric.Uint64Metadata{
Cumulative: true,
Description: "The number of faults the sentry has handled.",
})
2022-05-06 12:18:45 -07:00
)
2018-04-27 10:37:02 -07:00
// afterLoad is invoked by stateify.
2024-03-04 12:18:19 -08:00
func (t *Task) afterLoad(gocontext.Context) {
2019-12-06 16:58:28 -08:00
t.updateInfoLocked()
2024-03-04 12:49:13 +02:00
if ts := t.seccomp.Load(); ts != nil {
ts.populateCache(t)
}
2018-04-27 10:37:02 -07:00
t.interruptChan = make(chan struct{}, 1)
t.gostate.Store(uint32(TaskGoroutineNonexistent))
2018-04-27 10:37:02 -07:00
if t.stop != nil {
t.stopCount = atomicbitops.FromInt32(1)
2018-04-27 10:37:02 -07:00
}
t.endStopCond.L = &t.tg.signalHandlers.mu
t.rseqPreempted = true
t.futexWaiter = futex.NewWaiter()
t.p = t.k.Platform.NewContext(t.AsyncContext())
2018-04-27 10:37:02 -07:00
}
// copyScratchBufferLen is the length of Task.copyScratchBuffer.
const copyScratchBufferLen = 144 // sizeof(struct stat)
2018-04-27 10:37:02 -07:00
// CopyScratchBuffer returns a scratch buffer to be used in CopyIn/CopyOut
// functions. It must only be used within those functions and can only be used
// by the task goroutine; it exists to improve performance and thus
// intentionally lacks any synchronization.
//
// Callers should pass a constant value as an argument if possible, which will
// allow the compiler to inline and optimize out the if statement below.
2018-04-27 10:37:02 -07:00
func (t *Task) CopyScratchBuffer(size int) []byte {
if size > copyScratchBufferLen {
return make([]byte, size)
}
return t.copyScratchBuffer[:size]
}
// FutexWaiter returns the Task's futex.Waiter.
func (t *Task) FutexWaiter() *futex.Waiter {
return t.futexWaiter
}
// Kernel returns the Kernel containing t.
func (t *Task) Kernel() *Kernel {
return t.k
}
// SetClearTID sets t's cleartid.
//
// Preconditions: The caller must be running on the task goroutine.
2021-03-29 13:28:32 -07:00
func (t *Task) SetClearTID(addr hostarch.Addr) {
2018-04-27 10:37:02 -07:00
t.cleartid = addr
}
// SetSyscallRestartBlock sets the restart block for use in
// restart_syscall(2). After registering a restart block, a syscall should
// return ERESTART_RESTARTBLOCK to request a restart using the block.
//
// Precondition: The caller must be running on the task goroutine.
func (t *Task) SetSyscallRestartBlock(r SyscallRestartBlock) {
t.syscallRestartBlock = r
}
// SyscallRestartBlock returns the currently registered restart block for use in
// restart_syscall(2). This function is *not* idempotent and may be called once
// per syscall. This function must not be called if a restart block has not been
// registered for the current syscall.
//
// Precondition: The caller must be running on the task goroutine.
func (t *Task) SyscallRestartBlock() SyscallRestartBlock {
r := t.syscallRestartBlock
// Explicitly set the restart block to nil so that a future syscall can't
// accidentally reuse it.
t.syscallRestartBlock = nil
return r
}
2018-08-31 13:57:02 -07:00
// IsChrooted returns true if the root directory of t's FSContext is not the
// root directory of t's MountNamespace.
//
// Preconditions: The caller must be running on the task goroutine, or t.mu
// must be locked.
func (t *Task) IsChrooted() bool {
realRoot := t.mountNamespace.Root(t)
defer realRoot.DecRef(t)
2022-11-21 13:54:38 -08:00
root := t.fsContext.RootDirectory()
2022-11-07 00:37:27 -08:00
defer root.DecRef(t)
2018-08-31 13:57:02 -07:00
return root != realRoot
}
// TaskImage returns t's TaskImage.
2018-08-31 13:57:02 -07:00
//
// Precondition: The caller must be running on the task goroutine, or t.mu must
// be locked.
func (t *Task) TaskImage() *TaskImage {
return &t.image
2018-08-31 13:57:02 -07:00
}
// FSContext returns t's FSContext. FSContext does not take an additional
// reference on the returned FSContext.
//
// Precondition: The caller must be running on the task goroutine, or t.mu must
// be locked.
func (t *Task) FSContext() *FSContext {
2019-07-02 19:27:51 -07:00
return t.fsContext
2018-08-31 13:57:02 -07:00
}
2019-07-02 19:27:51 -07:00
// FDTable returns t's FDTable. FDMTable does not take an additional reference
// on the returned FDMap.
2018-08-31 13:57:02 -07:00
//
// Precondition: The caller must be running on the task goroutine, or t.mu must
// be locked.
2019-07-02 19:27:51 -07:00
func (t *Task) FDTable() *FDTable {
return t.fdTable
}
2019-10-29 13:58:20 -07:00
// GetFile is a convenience wrapper for t.FDTable().Get.
2019-07-02 19:27:51 -07:00
//
2019-10-28 10:18:55 -07:00
// Precondition: same as FDTable.Get.
2022-11-21 13:54:38 -08:00
func (t *Task) GetFile(fd int32) *vfs.FileDescription {
2019-07-02 19:27:51 -07:00
f, _ := t.fdTable.Get(fd)
return f
}
// NewFDs is a convenience wrapper for t.FDTable().NewFDs.
//
// This automatically passes the task as the context.
//
// Precondition: same as FDTable.
2022-11-21 13:54:38 -08:00
func (t *Task) NewFDs(fd int32, files []*vfs.FileDescription, flags FDFlags) ([]int32, error) {
2019-07-02 19:27:51 -07:00
return t.fdTable.NewFDs(t, fd, files, flags)
}
2022-11-21 13:54:38 -08:00
// NewFDFrom is a convenience wrapper for t.FDTable().NewFD.
2020-02-25 13:25:36 -08:00
//
// This automatically passes the task as the context.
//
// Precondition: same as FDTable.Get.
2023-03-21 13:18:19 -07:00
func (t *Task) NewFDFrom(minFD int32, file *vfs.FileDescription, flags FDFlags) (int32, error) {
return t.fdTable.NewFD(t, minFD, file, flags)
2020-02-25 13:25:36 -08:00
}
2019-07-02 19:27:51 -07:00
// NewFDAt is a convenience wrapper for t.FDTable().NewFDAt.
//
// This automatically passes the task as the context.
//
// Precondition: same as FDTable.
func (t *Task) NewFDAt(fd int32, file *vfs.FileDescription, flags FDFlags) (*vfs.FileDescription, error) {
2019-07-02 19:27:51 -07:00
return t.fdTable.NewFDAt(t, fd, file, flags)
2018-08-31 13:57:02 -07:00
}
// WithMuLocked executes f with t.mu locked.
func (t *Task) WithMuLocked(f func(*Task)) {
t.mu.Lock()
f(t)
t.mu.Unlock()
2018-08-31 13:57:02 -07:00
}
2023-08-01 11:10:08 -07:00
// MountNamespace returns t's MountNamespace.
2022-11-21 13:54:38 -08:00
func (t *Task) MountNamespace() *vfs.MountNamespace {
2020-02-14 11:11:55 -08:00
t.mu.Lock()
defer t.mu.Unlock()
2022-11-07 00:37:27 -08:00
return t.mountNamespace
2020-02-14 11:11:55 -08:00
}
2023-08-01 11:10:08 -07:00
// GetMountNamespace returns t's MountNamespace. A reference is taken on the
// returned mount namespace.
func (t *Task) GetMountNamespace() *vfs.MountNamespace {
t.mu.Lock()
defer t.mu.Unlock()
mntns := t.mountNamespace
if mntns != nil {
mntns.IncRef()
}
return mntns
2023-08-01 11:10:08 -07:00
}
2018-09-27 15:00:03 -07:00
// ContainerID returns t's container ID.
func (t *Task) ContainerID() string {
return t.containerID
}
2020-03-05 18:21:39 -08:00
2023-11-15 15:41:30 -08:00
// RestoreContainerID sets t's container ID in case the restored container ID
// is different from when it was saved.
func (t *Task) RestoreContainerID(cid string) {
t.containerID = cid
}
2020-03-13 13:17:59 -07:00
// OOMScoreAdj gets the task's thread group's OOM score adjustment.
func (t *Task) OOMScoreAdj() int32 {
return t.tg.oomScoreAdj.Load()
2020-03-05 18:21:39 -08:00
}
2020-03-13 13:17:59 -07:00
// SetOOMScoreAdj sets the task's thread group's OOM score adjustment. The
// value should be between -1000 and 1000 inclusive.
2020-03-05 18:21:39 -08:00
func (t *Task) SetOOMScoreAdj(adj int32) error {
if adj > 1000 || adj < -1000 {
return linuxerr.EINVAL
2020-03-05 18:21:39 -08:00
}
t.tg.oomScoreAdj.Store(adj)
2020-03-05 18:21:39 -08:00
return nil
}
2020-03-20 12:00:21 -07:00
2021-06-14 12:24:04 -07:00
// KUID returns t's kuid.
func (t *Task) KUID() uint32 {
2020-03-20 12:00:21 -07:00
return uint32(t.Credentials().EffectiveKUID)
}
2021-06-14 12:24:04 -07:00
// KGID returns t's kgid.
func (t *Task) KGID() uint32 {
2020-03-20 12:00:21 -07:00
return uint32(t.Credentials().EffectiveKGID)
}
// SetKcov sets the kcov instance associated with t.
func (t *Task) SetKcov(k *Kcov) {
t.kcov = k
}
// ResetKcov clears the kcov instance associated with t.
func (t *Task) ResetKcov() {
if t.kcov != nil {
2020-10-03 09:24:34 -07:00
t.kcov.OnTaskExit()
t.kcov = nil
}
}