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 }