github.com/ttpreport/gvisor-ligolo@v0.0.0-20240123134145-a858404967ba/pkg/sentry/arch/arch.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 arch provides abstractions around architecture-dependent details, 16 // such as syscall calling conventions, native types, etc. 17 package arch 18 19 import ( 20 "fmt" 21 "io" 22 23 "github.com/ttpreport/gvisor-ligolo/pkg/abi/linux" 24 "github.com/ttpreport/gvisor-ligolo/pkg/cpuid" 25 "github.com/ttpreport/gvisor-ligolo/pkg/hostarch" 26 "github.com/ttpreport/gvisor-ligolo/pkg/marshal" 27 "github.com/ttpreport/gvisor-ligolo/pkg/sentry/arch/fpu" 28 "github.com/ttpreport/gvisor-ligolo/pkg/sentry/limits" 29 ) 30 31 // Arch describes an architecture. 32 type Arch int 33 34 const ( 35 // AMD64 is the x86-64 architecture. 36 AMD64 Arch = iota 37 // ARM64 is the aarch64 architecture. 38 ARM64 39 ) 40 41 // String implements fmt.Stringer. 42 func (a Arch) String() string { 43 switch a { 44 case AMD64: 45 return "amd64" 46 case ARM64: 47 return "arm64" 48 default: 49 return fmt.Sprintf("Arch(%d)", a) 50 } 51 } 52 53 // contextInterface provides architecture-dependent information for a thread. 54 // This is currently not referenced, because there exists only one concrete 55 // implementation of this interface (*Context64), which we reference directly 56 // wherever this interface could otherwise be used in order to avoid the 57 // overhead involved in calling functions on interfaces in Go. 58 // This interface is still useful in order to see the entire 59 // architecture-dependent call surface it must support, as this is difficult 60 // to follow across the rest of this module due to the conditional compilation 61 // of the files that make it up. 62 // 63 // NOTE(b/34169503): Currently we use uintptr here to refer to a generic native 64 // register value. While this will work for the foreseeable future, it isn't 65 // strictly correct. We may want to create some abstraction that makes this 66 // more clear or enables us to store values of arbitrary widths. This is 67 // particularly true for RegisterMap(). 68 type contextInterface interface { 69 // Arch returns the architecture for this Context. 70 Arch() Arch 71 72 // Native converts a generic type to a native value. 73 // 74 // Because the architecture is not specified here, we may be dealing 75 // with return values of varying sizes (for example ARCH_GETFS). This 76 // is a simple utility function to convert to the native size in these 77 // cases, and then we can CopyOut. 78 Native(val uintptr) marshal.Marshallable 79 80 // Value converts a native type back to a generic value. 81 // Once a value has been converted to native via the above call -- it 82 // can be converted back here. 83 Value(val marshal.Marshallable) uintptr 84 85 // Width returns the number of bytes for a native value. 86 Width() uint 87 88 // Fork creates a clone of the context. 89 Fork() *Context64 90 91 // SyscallNo returns the syscall number. 92 SyscallNo() uintptr 93 94 // SyscallSaveOrig save orignal register value. 95 SyscallSaveOrig() 96 97 // SyscallArgs returns the syscall arguments in an array. 98 SyscallArgs() SyscallArguments 99 100 // Return returns the return value for a system call. 101 Return() uintptr 102 103 // SetReturn sets the return value for a system call. 104 SetReturn(value uintptr) 105 106 // RestartSyscall reverses over the current syscall instruction, such that 107 // when the application resumes execution the syscall will be re-attempted. 108 RestartSyscall() 109 110 // RestartSyscallWithRestartBlock reverses over the current syscall 111 // instraction and overwrites the current syscall number with that of 112 // restart_syscall(2). This causes the application to restart the current 113 // syscall with a custom function when execution resumes. 114 RestartSyscallWithRestartBlock() 115 116 // IP returns the current instruction pointer. 117 IP() uintptr 118 119 // SetIP sets the current instruction pointer. 120 SetIP(value uintptr) 121 122 // Stack returns the current stack pointer. 123 Stack() uintptr 124 125 // SetStack sets the current stack pointer. 126 SetStack(value uintptr) 127 128 // TLS returns the current TLS pointer. 129 TLS() uintptr 130 131 // SetTLS sets the current TLS pointer. Returns false if value is invalid. 132 SetTLS(value uintptr) bool 133 134 // SetOldRSeqInterruptedIP sets the register that contains the old IP 135 // when an "old rseq" restartable sequence is interrupted. 136 SetOldRSeqInterruptedIP(value uintptr) 137 138 // StateData returns a pointer to underlying architecture state. 139 StateData() *State 140 141 // RegisterMap returns a map of all registers. 142 RegisterMap() (map[string]uintptr, error) 143 144 // SignalSetup modifies the context in preparation for handling the 145 // given signal. 146 // 147 // st is the stack where the signal handler frame should be 148 // constructed. 149 // 150 // act is the SigAction that specifies how this signal is being 151 // handled. 152 // 153 // info is the SignalInfo of the signal being delivered. 154 // 155 // alt is the alternate signal stack (even if the alternate signal 156 // stack is not going to be used). 157 // 158 // sigset is the signal mask before entering the signal handler. 159 // 160 // featureSet is the application CPU feature set. 161 SignalSetup(st *Stack, act *linux.SigAction, info *linux.SignalInfo, alt *linux.SignalStack, sigset linux.SignalSet, featureSet cpuid.FeatureSet) error 162 163 // SignalRestore restores context after returning from a signal 164 // handler. 165 // 166 // st is the current thread stack. 167 // 168 // rt is true if SignalRestore is being entered from rt_sigreturn and 169 // false if SignalRestore is being entered from sigreturn. 170 // 171 // featureSet is the application CPU feature set. 172 // 173 // SignalRestore returns the thread's new signal mask. 174 SignalRestore(st *Stack, rt bool, featureSet cpuid.FeatureSet) (linux.SignalSet, linux.SignalStack, error) 175 176 // SingleStep returns true if single stepping is enabled. 177 SingleStep() bool 178 179 // SetSingleStep enables single stepping. 180 SetSingleStep() 181 182 // ClearSingleStep disables single stepping. 183 ClearSingleStep() 184 185 // FloatingPointData will be passed to underlying save routines. 186 FloatingPointData() *fpu.State 187 188 // NewMmapLayout returns a layout for a new MM, where MinAddr for the 189 // returned layout must be no lower than min, and MaxAddr for the returned 190 // layout must be no higher than max. Repeated calls to NewMmapLayout may 191 // return different layouts. 192 NewMmapLayout(min, max hostarch.Addr, limits *limits.LimitSet) (MmapLayout, error) 193 194 // PIELoadAddress returns a preferred load address for a 195 // position-independent executable within l. 196 PIELoadAddress(l MmapLayout) hostarch.Addr 197 198 // Hack around our package dependences being too broken to support the 199 // equivalent of arch_ptrace(): 200 201 // PtracePeekUser implements ptrace(PTRACE_PEEKUSR). 202 PtracePeekUser(addr uintptr) (marshal.Marshallable, error) 203 204 // PtracePokeUser implements ptrace(PTRACE_POKEUSR). 205 PtracePokeUser(addr, data uintptr) error 206 207 // PtraceGetRegs implements ptrace(PTRACE_GETREGS) by writing the 208 // general-purpose registers represented by this Context to dst and 209 // returning the number of bytes written. 210 PtraceGetRegs(dst io.Writer) (int, error) 211 212 // PtraceSetRegs implements ptrace(PTRACE_SETREGS) by reading 213 // general-purpose registers from src into this Context and returning the 214 // number of bytes read. 215 PtraceSetRegs(src io.Reader) (int, error) 216 217 // PtraceGetRegSet implements ptrace(PTRACE_GETREGSET) by writing the 218 // register set given by architecture-defined value regset from this 219 // Context to dst and returning the number of bytes written, which must be 220 // less than or equal to maxlen. 221 PtraceGetRegSet(regset uintptr, dst io.Writer, maxlen int, fs cpuid.FeatureSet) (int, error) 222 223 // PtraceSetRegSet implements ptrace(PTRACE_SETREGSET) by reading the 224 // register set given by architecture-defined value regset from src and 225 // returning the number of bytes read, which must be less than or equal to 226 // maxlen. 227 PtraceSetRegSet(regset uintptr, src io.Reader, maxlen int, fs cpuid.FeatureSet) (int, error) 228 229 // FullRestore returns 'true' if all CPU registers must be restored 230 // when switching to the untrusted application. Typically a task enters 231 // and leaves the kernel via a system call. Platform.Switch() may 232 // optimize for this by not saving/restoring all registers if allowed 233 // by the ABI. For e.g. the amd64 ABI specifies that syscall clobbers 234 // %rcx and %r11. If FullRestore returns true then these optimizations 235 // must be disabled and all registers restored. 236 FullRestore() bool 237 } 238 239 // Compile-time assertion that Context64 implements contextInterface. 240 var _ = (contextInterface)((*Context64)(nil)) 241 242 // MmapDirection is a search direction for mmaps. 243 type MmapDirection int 244 245 const ( 246 // MmapBottomUp instructs mmap to prefer lower addresses. 247 MmapBottomUp MmapDirection = iota 248 249 // MmapTopDown instructs mmap to prefer higher addresses. 250 MmapTopDown 251 ) 252 253 // MmapLayout defines the layout of the user address space for a particular 254 // MemoryManager. 255 // 256 // Note that "highest address" below is always exclusive. 257 // 258 // +stateify savable 259 type MmapLayout struct { 260 // MinAddr is the lowest mappable address. 261 MinAddr hostarch.Addr 262 263 // MaxAddr is the highest mappable address. 264 MaxAddr hostarch.Addr 265 266 // BottomUpBase is the lowest address that may be returned for a 267 // MmapBottomUp mmap. 268 BottomUpBase hostarch.Addr 269 270 // TopDownBase is the highest address that may be returned for a 271 // MmapTopDown mmap. 272 TopDownBase hostarch.Addr 273 274 // DefaultDirection is the direction for most non-fixed mmaps in this 275 // layout. 276 DefaultDirection MmapDirection 277 278 // MaxStackRand is the maximum randomization to apply to stack 279 // allocations to maintain a proper gap between the stack and 280 // TopDownBase. 281 MaxStackRand uint64 282 } 283 284 // Valid returns true if this layout is valid. 285 func (m *MmapLayout) Valid() bool { 286 if m.MinAddr > m.MaxAddr { 287 return false 288 } 289 if m.BottomUpBase < m.MinAddr { 290 return false 291 } 292 if m.BottomUpBase > m.MaxAddr { 293 return false 294 } 295 if m.TopDownBase < m.MinAddr { 296 return false 297 } 298 if m.TopDownBase > m.MaxAddr { 299 return false 300 } 301 return true 302 } 303 304 // SyscallArgument is an argument supplied to a syscall implementation. The 305 // methods used to access the arguments are named after the ***C type name*** and 306 // they convert to the closest Go type available. For example, Int() refers to a 307 // 32-bit signed integer argument represented in Go as an int32. 308 // 309 // Using the accessor methods guarantees that the conversion between types is 310 // correct, taking into account size and signedness (i.e., zero-extension vs 311 // signed-extension). 312 type SyscallArgument struct { 313 // Prefer to use accessor methods instead of 'Value' directly. 314 Value uintptr 315 } 316 317 // SyscallArguments represents the set of arguments passed to a syscall. 318 type SyscallArguments [6]SyscallArgument 319 320 // Pointer returns the hostarch.Addr representation of a pointer argument. 321 func (a SyscallArgument) Pointer() hostarch.Addr { 322 return hostarch.Addr(a.Value) 323 } 324 325 // Int returns the int32 representation of a 32-bit signed integer argument. 326 func (a SyscallArgument) Int() int32 { 327 return int32(a.Value) 328 } 329 330 // Uint returns the uint32 representation of a 32-bit unsigned integer argument. 331 func (a SyscallArgument) Uint() uint32 { 332 return uint32(a.Value) 333 } 334 335 // Int64 returns the int64 representation of a 64-bit signed integer argument. 336 func (a SyscallArgument) Int64() int64 { 337 return int64(a.Value) 338 } 339 340 // Uint64 returns the uint64 representation of a 64-bit unsigned integer argument. 341 func (a SyscallArgument) Uint64() uint64 { 342 return uint64(a.Value) 343 } 344 345 // SizeT returns the uint representation of a size_t argument. 346 func (a SyscallArgument) SizeT() uint { 347 return uint(a.Value) 348 } 349 350 // ModeT returns the int representation of a mode_t argument. 351 func (a SyscallArgument) ModeT() uint { 352 return uint(uint16(a.Value)) 353 }