gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/sentry/kernel/task_context.go (about)

     1  // Copyright 2020 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  	"time"
    19  
    20  	"gvisor.dev/gvisor/pkg/abi/linux"
    21  	"gvisor.dev/gvisor/pkg/context"
    22  	"gvisor.dev/gvisor/pkg/cpuid"
    23  	"gvisor.dev/gvisor/pkg/devutil"
    24  	"gvisor.dev/gvisor/pkg/sentry/inet"
    25  	"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
    26  	"gvisor.dev/gvisor/pkg/sentry/kernel/ipc"
    27  	"gvisor.dev/gvisor/pkg/sentry/kernel/shm"
    28  	ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
    29  	"gvisor.dev/gvisor/pkg/sentry/limits"
    30  	"gvisor.dev/gvisor/pkg/sentry/pgalloc"
    31  	"gvisor.dev/gvisor/pkg/sentry/platform"
    32  	"gvisor.dev/gvisor/pkg/sentry/unimpl"
    33  	"gvisor.dev/gvisor/pkg/sentry/uniqueid"
    34  	"gvisor.dev/gvisor/pkg/sentry/vfs"
    35  	"gvisor.dev/gvisor/pkg/sync"
    36  )
    37  
    38  // Deadline implements context.Context.Deadline.
    39  func (*Task) Deadline() (time.Time, bool) {
    40  	return time.Time{}, false
    41  }
    42  
    43  // Done implements context.Context.Done.
    44  func (*Task) Done() <-chan struct{} {
    45  	return nil
    46  }
    47  
    48  // Err implements context.Context.Err.
    49  func (*Task) Err() error {
    50  	return nil
    51  }
    52  
    53  // Value implements context.Context.Value.
    54  //
    55  // Preconditions: The caller must be running on the task goroutine.
    56  func (t *Task) Value(key any) any {
    57  	// This function is very hot; skip this check outside of +race builds.
    58  	if sync.RaceEnabled {
    59  		t.assertTaskGoroutine()
    60  	}
    61  	return t.contextValue(key, true /* isTaskGoroutine */)
    62  }
    63  
    64  func (t *Task) contextValue(key any, isTaskGoroutine bool) any {
    65  	switch key {
    66  	case CtxCanTrace:
    67  		return t.CanTrace
    68  	case CtxKernel:
    69  		return t.k
    70  	case CtxPIDNamespace:
    71  		return t.tg.pidns
    72  	case CtxUTSNamespace:
    73  		if !isTaskGoroutine {
    74  			t.mu.Lock()
    75  			defer t.mu.Unlock()
    76  		}
    77  		utsns := t.utsns
    78  		utsns.IncRef()
    79  		return utsns
    80  	case ipc.CtxIPCNamespace:
    81  		if !isTaskGoroutine {
    82  			t.mu.Lock()
    83  			defer t.mu.Unlock()
    84  		}
    85  		ipcns := t.ipcns
    86  		ipcns.IncRef()
    87  		return ipcns
    88  	case CtxTask:
    89  		return t
    90  	case auth.CtxCredentials:
    91  		return t.creds.Load()
    92  	case auth.CtxThreadGroupID:
    93  		return int32(t.tg.ID())
    94  	case vfs.CtxRoot:
    95  		if !isTaskGoroutine {
    96  			t.mu.Lock()
    97  			defer t.mu.Unlock()
    98  		}
    99  		return t.fsContext.RootDirectory()
   100  	case vfs.CtxMountNamespace:
   101  		if !isTaskGoroutine {
   102  			t.mu.Lock()
   103  			defer t.mu.Unlock()
   104  		}
   105  		t.mountNamespace.IncRef()
   106  		return t.mountNamespace
   107  	case devutil.CtxDevGoferClient:
   108  		return t.k.GetDevGoferClient(t.k.ContainerName(t.containerID))
   109  	case inet.CtxStack:
   110  		return t.NetworkContext()
   111  	case ktime.CtxRealtimeClock:
   112  		return t.k.RealtimeClock()
   113  	case limits.CtxLimits:
   114  		return t.tg.limits
   115  	case linux.CtxSignalNoInfoFunc:
   116  		return func(sig linux.Signal) error {
   117  			return t.SendSignal(SignalInfoNoInfo(sig, t, t))
   118  		}
   119  	case pgalloc.CtxMemoryCgroupID:
   120  		return t.memCgID.Load()
   121  	case pgalloc.CtxMemoryFile:
   122  		return t.k.mf
   123  	case platform.CtxPlatform:
   124  		return t.k
   125  	case shm.CtxDeviceID:
   126  		return t.k.sysVShmDevID
   127  	case uniqueid.CtxGlobalUniqueID:
   128  		return t.k.UniqueID()
   129  	case uniqueid.CtxGlobalUniqueIDProvider:
   130  		return t.k
   131  	case uniqueid.CtxInotifyCookie:
   132  		return t.k.GenerateInotifyCookie()
   133  	case unimpl.CtxEvents:
   134  		return t.k
   135  	case cpuid.CtxFeatureSet:
   136  		return t.k.featureSet
   137  	default:
   138  		return nil
   139  	}
   140  }
   141  
   142  // fallbackContext adds a level of indirection for embedding to resolve
   143  // ambiguity for method resolution. We favor context.NoTask.
   144  type fallbackTask struct {
   145  	*Task
   146  }
   147  
   148  // taskAsyncContext implements context.Context for a goroutine that performs
   149  // work on behalf of a Task, but is not the task goroutine.
   150  type taskAsyncContext struct {
   151  	context.NoTask
   152  	fallbackTask
   153  }
   154  
   155  // Value implements context.Context.Value.
   156  func (t *taskAsyncContext) Value(key any) any {
   157  	return t.fallbackTask.contextValue(key, false /* isTaskGoroutine */)
   158  }
   159  
   160  // AsyncContext returns a context.Context representing t. The returned
   161  // context.Context is intended for use by goroutines other than t's task
   162  // goroutine; for example, signal delivery to t will not interrupt goroutines
   163  // that are blocking using the returned context.Context.
   164  func (t *Task) AsyncContext() context.Context {
   165  	return &taskAsyncContext{
   166  		fallbackTask: fallbackTask{t},
   167  	}
   168  }