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  }