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  }