github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/sentry/platform/systrap/usertrap/usertrap.go (about) 1 // Copyright 2021 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 usertrap implements the library to replace syscall instructions with 16 // function calls. 17 // 18 // The most often used pattern of performing a system call is a sequence of two 19 // instruction: mov sysno, %eax; syscall. The size of the mov instruction is 5 20 // bytes and the size of the syscall instruction is 2 bytes. These two 21 // instruction can be replaced with a single jmp instruction with an absolute 22 // address below 2 gigabytes. 23 // 24 // Here is a few tricks: 25 // - The GS register is used to access a per-thread memory. 26 // - The syscall instruction is replaced with the "jmp *%ds:offset" instruction. 27 // On x86_64, ds is always zero. offset is a 32-bit signed integer. This 28 // means that a service mapping for a table with syscall trampolines has to 29 // be mapped below 2GB. 30 // - We can't touch a process stack, so we have to use the jmp instruction 31 // instead of callq and generate a new function call for each replaced 32 // instruction. Each trampoline contains a syscall number and an return 33 // address. 34 // - The address for the syscall table is set so that the syscall instruction 35 // is replaced on an invalid instruction. This allows us to handle races 36 // when two threads are executing the same syscall concurrently. And this 37 // allows us to restart a syscall if it has been interrupted by a signal. 38 // 39 // +checkalignedignore 40 package usertrap 41 42 import "fmt" 43 44 var ( 45 // ErrFaultRestart indicates that the current stub thread has to be restarted. 46 ErrFaultRestart = fmt.Errorf("need to restart stub thread") 47 // ErrFaultSyscall indicates that the current fault has to be handled as a system call. 48 ErrFaultSyscall = fmt.Errorf("need to handle as syscall") 49 )