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