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  )