github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/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/SagerNet/gvisor/pkg/abi/linux" 21 "github.com/SagerNet/gvisor/pkg/context" 22 "github.com/SagerNet/gvisor/pkg/log" 23 "github.com/SagerNet/gvisor/pkg/sentry/fs" 24 "github.com/SagerNet/gvisor/pkg/sentry/inet" 25 "github.com/SagerNet/gvisor/pkg/sentry/kernel/auth" 26 ktime "github.com/SagerNet/gvisor/pkg/sentry/kernel/time" 27 "github.com/SagerNet/gvisor/pkg/sentry/limits" 28 "github.com/SagerNet/gvisor/pkg/sentry/pgalloc" 29 "github.com/SagerNet/gvisor/pkg/sentry/platform" 30 "github.com/SagerNet/gvisor/pkg/sentry/unimpl" 31 "github.com/SagerNet/gvisor/pkg/sentry/uniqueid" 32 "github.com/SagerNet/gvisor/pkg/sentry/vfs" 33 "github.com/SagerNet/gvisor/pkg/sync" 34 ) 35 36 // Deadline implements context.Context.Deadline. 37 func (t *Task) Deadline() (time.Time, bool) { 38 return time.Time{}, false 39 } 40 41 // Done implements context.Context.Done. 42 func (t *Task) Done() <-chan struct{} { 43 return nil 44 } 45 46 // Err implements context.Context.Err. 47 func (t *Task) Err() error { 48 return nil 49 } 50 51 // Value implements context.Context.Value. 52 // 53 // Preconditions: The caller must be running on the task goroutine. 54 func (t *Task) Value(key interface{}) interface{} { 55 // This function is very hot; skip this check outside of +race builds. 56 if sync.RaceEnabled { 57 t.assertTaskGoroutine() 58 } 59 return t.contextValue(key, true /* isTaskGoroutine */) 60 } 61 62 func (t *Task) contextValue(key interface{}, isTaskGoroutine bool) interface{} { 63 switch key { 64 case CtxCanTrace: 65 return t.CanTrace 66 case CtxKernel: 67 return t.k 68 case CtxPIDNamespace: 69 return t.tg.pidns 70 case CtxUTSNamespace: 71 if !isTaskGoroutine { 72 t.mu.Lock() 73 defer t.mu.Unlock() 74 } 75 return t.utsns 76 case CtxIPCNamespace: 77 if !isTaskGoroutine { 78 t.mu.Lock() 79 defer t.mu.Unlock() 80 } 81 ipcns := t.ipcns 82 ipcns.IncRef() 83 return ipcns 84 case CtxTask: 85 return t 86 case auth.CtxCredentials: 87 return t.creds.Load() 88 case context.CtxThreadGroupID: 89 return int32(t.tg.ID()) 90 case fs.CtxRoot: 91 if !isTaskGoroutine { 92 t.mu.Lock() 93 defer t.mu.Unlock() 94 } 95 return t.fsContext.RootDirectory() 96 case vfs.CtxRoot: 97 if !isTaskGoroutine { 98 t.mu.Lock() 99 defer t.mu.Unlock() 100 } 101 return t.fsContext.RootDirectoryVFS2() 102 case vfs.CtxMountNamespace: 103 if !isTaskGoroutine { 104 t.mu.Lock() 105 defer t.mu.Unlock() 106 } 107 t.mountNamespaceVFS2.IncRef() 108 return t.mountNamespaceVFS2 109 case fs.CtxDirentCacheLimiter: 110 return t.k.DirentCacheLimiter 111 case inet.CtxStack: 112 return t.NetworkContext() 113 case ktime.CtxRealtimeClock: 114 return t.k.RealtimeClock() 115 case limits.CtxLimits: 116 return t.tg.limits 117 case linux.CtxSignalNoInfoFunc: 118 return func(sig linux.Signal) error { 119 return t.SendSignal(SignalInfoNoInfo(sig, t, t)) 120 } 121 case pgalloc.CtxMemoryFile: 122 return t.k.mf 123 case pgalloc.CtxMemoryFileProvider: 124 return t.k 125 case platform.CtxPlatform: 126 return t.k 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 default: 136 return nil 137 } 138 } 139 140 // taskAsyncContext implements context.Context for a goroutine that performs 141 // work on behalf of a Task, but is not the task goroutine. 142 type taskAsyncContext struct { 143 context.NoopSleeper 144 145 t *Task 146 } 147 148 // AsyncContext returns a context.Context representing t. The returned 149 // context.Context is intended for use by goroutines other than t's task 150 // goroutine; for example, signal delivery to t will not interrupt goroutines 151 // that are blocking using the returned context.Context. 152 func (t *Task) AsyncContext() context.Context { 153 return taskAsyncContext{t: t} 154 } 155 156 // Debugf implements log.Logger.Debugf. 157 func (ctx taskAsyncContext) Debugf(format string, v ...interface{}) { 158 ctx.t.Debugf(format, v...) 159 } 160 161 // Infof implements log.Logger.Infof. 162 func (ctx taskAsyncContext) Infof(format string, v ...interface{}) { 163 ctx.t.Infof(format, v...) 164 } 165 166 // Warningf implements log.Logger.Warningf. 167 func (ctx taskAsyncContext) Warningf(format string, v ...interface{}) { 168 ctx.t.Warningf(format, v...) 169 } 170 171 // IsLogging implements log.Logger.IsLogging. 172 func (ctx taskAsyncContext) IsLogging(level log.Level) bool { 173 return ctx.t.IsLogging(level) 174 } 175 176 // Deadline implements context.Context.Deadline. 177 func (ctx taskAsyncContext) Deadline() (time.Time, bool) { 178 return time.Time{}, false 179 } 180 181 // Done implements context.Context.Done. 182 func (ctx taskAsyncContext) Done() <-chan struct{} { 183 return nil 184 } 185 186 // Err implements context.Context.Err. 187 func (ctx taskAsyncContext) Err() error { 188 return nil 189 } 190 191 // Value implements context.Context.Value. 192 func (ctx taskAsyncContext) Value(key interface{}) interface{} { 193 return ctx.t.contextValue(key, false /* isTaskGoroutine */) 194 }