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