github.com/ttpreport/gvisor-ligolo@v0.0.0-20240123134145-a858404967ba/pkg/sentry/kernel/task_image.go (about) 1 // Copyright 2018 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 "fmt" 19 20 "github.com/ttpreport/gvisor-ligolo/pkg/abi/linux/errno" 21 "github.com/ttpreport/gvisor-ligolo/pkg/context" 22 "github.com/ttpreport/gvisor-ligolo/pkg/hostarch" 23 "github.com/ttpreport/gvisor-ligolo/pkg/sentry/arch" 24 "github.com/ttpreport/gvisor-ligolo/pkg/sentry/kernel/futex" 25 "github.com/ttpreport/gvisor-ligolo/pkg/sentry/loader" 26 "github.com/ttpreport/gvisor-ligolo/pkg/sentry/mm" 27 "github.com/ttpreport/gvisor-ligolo/pkg/syserr" 28 ) 29 30 var errNoSyscalls = syserr.New("no syscall table found", errno.ENOEXEC) 31 32 // Auxmap contains miscellaneous data for the task. 33 type Auxmap map[string]any 34 35 // TaskImage is the subset of a task's data that is provided by the loader. 36 // 37 // +stateify savable 38 type TaskImage struct { 39 // Name is the thread name set by the prctl(PR_SET_NAME) system call. 40 Name string 41 42 // Arch is the architecture-specific context (registers, etc.) 43 Arch *arch.Context64 44 45 // MemoryManager is the task's address space. 46 MemoryManager *mm.MemoryManager 47 48 // fu implements futexes in the address space. 49 fu *futex.Manager 50 51 // st is the task's syscall table. 52 st *SyscallTable `state:".(syscallTableInfo)"` 53 } 54 55 // release releases all resources held by the TaskImage. release is called by 56 // the task when it execs into a new TaskImage. 57 func (image *TaskImage) release(ctx context.Context) { 58 // Nil out pointers so that if the task is saved after release, it doesn't 59 // follow the pointers to possibly now-invalid objects. 60 if image.MemoryManager != nil { 61 image.MemoryManager.DecUsers(ctx) 62 image.MemoryManager = nil 63 } 64 image.fu = nil 65 } 66 67 // Fork returns a duplicate of image. The copied TaskImage always has an 68 // independent arch.Context64. If shareAddressSpace is true, the copied 69 // TaskImage shares an address space with the original; otherwise, the copied 70 // TaskImage has an independent address space that is initially a duplicate 71 // of the original's. 72 func (image *TaskImage) Fork(ctx context.Context, k *Kernel, shareAddressSpace bool) (*TaskImage, error) { 73 newImage := &TaskImage{ 74 Name: image.Name, 75 Arch: image.Arch.Fork(), 76 st: image.st, 77 } 78 if shareAddressSpace { 79 newImage.MemoryManager = image.MemoryManager 80 if newImage.MemoryManager != nil { 81 if !newImage.MemoryManager.IncUsers() { 82 // Shouldn't be possible since image.MemoryManager should be a 83 // counted user. 84 panic(fmt.Sprintf("TaskImage.Fork called with userless TaskImage.MemoryManager")) 85 } 86 } 87 newImage.fu = image.fu 88 } else { 89 newMM, err := image.MemoryManager.Fork(ctx) 90 if err != nil { 91 return nil, err 92 } 93 newImage.MemoryManager = newMM 94 newImage.fu = k.futexes.Fork() 95 } 96 return newImage, nil 97 } 98 99 // Arch returns t's arch.Context64. 100 // 101 // Preconditions: The caller must be running on the task goroutine, or t.mu 102 // must be locked. 103 func (t *Task) Arch() *arch.Context64 { 104 return t.image.Arch 105 } 106 107 // MemoryManager returns t's MemoryManager. MemoryManager does not take an 108 // additional reference on the returned MM. 109 // 110 // Preconditions: The caller must be running on the task goroutine, or t.mu 111 // must be locked. 112 func (t *Task) MemoryManager() *mm.MemoryManager { 113 return t.image.MemoryManager 114 } 115 116 // SyscallTable returns t's syscall table. 117 // 118 // Preconditions: The caller must be running on the task goroutine, or t.mu 119 // must be locked. 120 func (t *Task) SyscallTable() *SyscallTable { 121 return t.image.st 122 } 123 124 // Stack returns the userspace stack. 125 // 126 // Preconditions: The caller must be running on the task goroutine, or t.mu 127 // must be locked. 128 func (t *Task) Stack() *arch.Stack { 129 return &arch.Stack{ 130 Arch: t.Arch(), 131 IO: t.MemoryManager(), 132 Bottom: hostarch.Addr(t.Arch().Stack()), 133 } 134 } 135 136 // LoadTaskImage loads a specified file into a new TaskImage. 137 // 138 // args.MemoryManager does not need to be set by the caller. 139 func (k *Kernel) LoadTaskImage(ctx context.Context, args loader.LoadArgs) (*TaskImage, *syserr.Error) { 140 // Prepare a new user address space to load into. 141 m := mm.NewMemoryManager(k, k, k.SleepForAddressSpaceActivation) 142 defer m.DecUsers(ctx) 143 args.MemoryManager = m 144 145 os, ac, name, err := loader.Load(ctx, args, k.extraAuxv, k.vdso) 146 if err != nil { 147 return nil, err 148 } 149 150 // Lookup our new syscall table. 151 st, ok := LookupSyscallTable(os, ac.Arch()) 152 if !ok { 153 // No syscall table found. This means that the ELF binary does not match 154 // the architecture. 155 return nil, errNoSyscalls 156 } 157 158 if !m.IncUsers() { 159 panic("Failed to increment users count on new MM") 160 } 161 return &TaskImage{ 162 Name: name, 163 Arch: ac, 164 MemoryManager: m, 165 fu: k.futexes.Fork(), 166 st: st, 167 }, nil 168 }