github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/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/nicocha30/gvisor-ligolo/pkg/abi/linux" 21 "github.com/nicocha30/gvisor-ligolo/pkg/context" 22 "github.com/nicocha30/gvisor-ligolo/pkg/cpuid" 23 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/inet" 24 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel/auth" 25 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel/ipc" 26 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel/shm" 27 ktime "github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel/time" 28 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/limits" 29 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/pgalloc" 30 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/platform" 31 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/unimpl" 32 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/uniqueid" 33 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/vfs" 34 "github.com/nicocha30/gvisor-ligolo/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 return t.utsns 77 case ipc.CtxIPCNamespace: 78 if !isTaskGoroutine { 79 t.mu.Lock() 80 defer t.mu.Unlock() 81 } 82 ipcns := t.ipcns 83 ipcns.IncRef() 84 return ipcns 85 case CtxTask: 86 return t 87 case auth.CtxCredentials: 88 return t.creds.Load() 89 case auth.CtxThreadGroupID: 90 return int32(t.tg.ID()) 91 case vfs.CtxRoot: 92 if !isTaskGoroutine { 93 t.mu.Lock() 94 defer t.mu.Unlock() 95 } 96 return t.fsContext.RootDirectory() 97 case vfs.CtxMountNamespace: 98 if !isTaskGoroutine { 99 t.mu.Lock() 100 defer t.mu.Unlock() 101 } 102 t.mountNamespace.IncRef() 103 return t.mountNamespace 104 case inet.CtxStack: 105 return t.NetworkContext() 106 case ktime.CtxRealtimeClock: 107 return t.k.RealtimeClock() 108 case limits.CtxLimits: 109 return t.tg.limits 110 case linux.CtxSignalNoInfoFunc: 111 return func(sig linux.Signal) error { 112 return t.SendSignal(SignalInfoNoInfo(sig, t, t)) 113 } 114 case pgalloc.CtxMemoryCgroupID: 115 return t.memCgID.Load() 116 case pgalloc.CtxMemoryFile: 117 return t.k.mf 118 case pgalloc.CtxMemoryFileProvider: 119 return t.k 120 case platform.CtxPlatform: 121 return t.k 122 case shm.CtxDeviceID: 123 return t.k.sysVShmDevID 124 case uniqueid.CtxGlobalUniqueID: 125 return t.k.UniqueID() 126 case uniqueid.CtxGlobalUniqueIDProvider: 127 return t.k 128 case uniqueid.CtxInotifyCookie: 129 return t.k.GenerateInotifyCookie() 130 case unimpl.CtxEvents: 131 return t.k 132 case cpuid.CtxFeatureSet: 133 return t.k.featureSet 134 default: 135 return nil 136 } 137 } 138 139 // fallbackContext adds a level of indirection for embedding to resolve 140 // ambiguity for method resolution. We favor context.NoTask. 141 type fallbackTask struct { 142 *Task 143 } 144 145 // taskAsyncContext implements context.Context for a goroutine that performs 146 // work on behalf of a Task, but is not the task goroutine. 147 type taskAsyncContext struct { 148 context.NoTask 149 fallbackTask 150 } 151 152 // Value implements context.Context.Value. 153 func (t *taskAsyncContext) Value(key any) any { 154 return t.fallbackTask.contextValue(key, false /* isTaskGoroutine */) 155 } 156 157 // AsyncContext returns a context.Context representing t. The returned 158 // context.Context is intended for use by goroutines other than t's task 159 // goroutine; for example, signal delivery to t will not interrupt goroutines 160 // that are blocking using the returned context.Context. 161 func (t *Task) AsyncContext() context.Context { 162 return &taskAsyncContext{ 163 fallbackTask: fallbackTask{t}, 164 } 165 }