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  }