github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/ring0/x86.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  //go:build 386 || amd64
    16  // +build 386 amd64
    17  
    18  package ring0
    19  
    20  // Useful bits.
    21  const (
    22  	_CR0_PE = 1 << 0
    23  	_CR0_ET = 1 << 4
    24  	_CR0_NE = 1 << 5
    25  	_CR0_AM = 1 << 18
    26  	_CR0_PG = 1 << 31
    27  
    28  	_CR4_PSE        = 1 << 4
    29  	_CR4_PAE        = 1 << 5
    30  	_CR4_PGE        = 1 << 7
    31  	_CR4_OSFXSR     = 1 << 9
    32  	_CR4_OSXMMEXCPT = 1 << 10
    33  	_CR4_FSGSBASE   = 1 << 16
    34  	_CR4_PCIDE      = 1 << 17
    35  	_CR4_OSXSAVE    = 1 << 18
    36  	_CR4_SMEP       = 1 << 20
    37  	_CR4_SMAP       = 1 << 21
    38  
    39  	_RFLAGS_AC       = 1 << 18
    40  	_RFLAGS_NT       = 1 << 14
    41  	_RFLAGS_IOPL0    = 1 << 12
    42  	_RFLAGS_IOPL1    = 1 << 13
    43  	_RFLAGS_IOPL     = _RFLAGS_IOPL0 | _RFLAGS_IOPL1
    44  	_RFLAGS_DF       = 1 << 10
    45  	_RFLAGS_IF       = 1 << 9
    46  	_RFLAGS_STEP     = 1 << 8
    47  	_RFLAGS_RESERVED = 1 << 1
    48  
    49  	_EFER_SCE = 0x001
    50  	_EFER_LME = 0x100
    51  	_EFER_LMA = 0x400
    52  	_EFER_NX  = 0x800
    53  
    54  	_MSR_STAR          = 0xc0000081
    55  	_MSR_LSTAR         = 0xc0000082
    56  	_MSR_CSTAR         = 0xc0000083
    57  	_MSR_SYSCALL_MASK  = 0xc0000084
    58  	_MSR_PLATFORM_INFO = 0xce
    59  	_MSR_MISC_FEATURES = 0x140
    60  
    61  	_PLATFORM_INFO_CPUID_FAULT = 1 << 31
    62  
    63  	_MISC_FEATURE_CPUID_TRAP = 0x1
    64  )
    65  
    66  const (
    67  	// KernelFlagsSet should always be set in the kernel.
    68  	KernelFlagsSet = _RFLAGS_RESERVED
    69  
    70  	// UserFlagsSet are always set in userspace.
    71  	//
    72  	// _RFLAGS_IOPL is a set of two bits and it shows the I/O privilege
    73  	// level. The Current Privilege Level (CPL) of the task must be less
    74  	// than or equal to the IOPL in order for the task or program to access
    75  	// I/O ports.
    76  	//
    77  	// Here, _RFLAGS_IOPL0 is used only to determine whether the task is
    78  	// running in the kernel or userspace mode. In the user mode, the CPL is
    79  	// always 3 and it doesn't matter what IOPL is set if it is bellow CPL.
    80  	//
    81  	// We need to have one bit which will be always different in user and
    82  	// kernel modes. And we have to remember that even though we have
    83  	// KernelFlagsClear, we still can see some of these flags in the kernel
    84  	// mode. This can happen when the goruntime switches on a goroutine
    85  	// which has been saved in the host mode. On restore, the popf
    86  	// instruction is used to restore flags and this means that all flags
    87  	// what the goroutine has in the host mode will be restored in the
    88  	// kernel mode.
    89  	//
    90  	// _RFLAGS_IOPL0 is never set in host and kernel modes and we always set
    91  	// it in the user mode. So if this flag is set, the task is running in
    92  	// the user mode and if it isn't set, the task is running in the kernel
    93  	// mode.
    94  	UserFlagsSet = _RFLAGS_RESERVED | _RFLAGS_IF | _RFLAGS_IOPL0
    95  
    96  	// KernelFlagsClear should always be clear in the kernel.
    97  	KernelFlagsClear = _RFLAGS_STEP | _RFLAGS_IF | _RFLAGS_IOPL | _RFLAGS_AC | _RFLAGS_NT
    98  
    99  	// UserFlagsClear are always cleared in userspace.
   100  	UserFlagsClear = _RFLAGS_NT | _RFLAGS_IOPL1
   101  )
   102  
   103  // IsKernelFlags returns true if rflags coresponds to the kernel mode.
   104  //
   105  //go:nosplit
   106  func IsKernelFlags(rflags uint64) bool {
   107  	return rflags&_RFLAGS_IOPL0 == 0
   108  }
   109  
   110  // Vector is an exception vector.
   111  type Vector uintptr
   112  
   113  // Exception vectors.
   114  const (
   115  	DivideByZero Vector = iota
   116  	Debug
   117  	NMI
   118  	Breakpoint
   119  	Overflow
   120  	BoundRangeExceeded
   121  	InvalidOpcode
   122  	DeviceNotAvailable
   123  	DoubleFault
   124  	CoprocessorSegmentOverrun
   125  	InvalidTSS
   126  	SegmentNotPresent
   127  	StackSegmentFault
   128  	GeneralProtectionFault
   129  	PageFault
   130  	_
   131  	X87FloatingPointException
   132  	AlignmentCheck
   133  	MachineCheck
   134  	SIMDFloatingPointException
   135  	VirtualizationException
   136  	SecurityException = 0x1e
   137  	SyscallInt80      = 0x80
   138  	_NR_INTERRUPTS    = 0x100
   139  )
   140  
   141  // System call vectors.
   142  const (
   143  	Syscall Vector = _NR_INTERRUPTS
   144  )
   145  
   146  // Selector is a segment Selector.
   147  type Selector uint16
   148  
   149  // SegmentDescriptor is a segment descriptor.
   150  type SegmentDescriptor struct {
   151  	bits [2]uint32
   152  }
   153  
   154  // descriptorTable is a collection of descriptors.
   155  type descriptorTable [32]SegmentDescriptor
   156  
   157  // SegmentDescriptorFlags are typed flags within a descriptor.
   158  type SegmentDescriptorFlags uint32
   159  
   160  // SegmentDescriptorFlag declarations.
   161  const (
   162  	SegmentDescriptorAccess     SegmentDescriptorFlags = 1 << 8  // Access bit (always set).
   163  	SegmentDescriptorWrite                             = 1 << 9  // Write permission.
   164  	SegmentDescriptorExpandDown                        = 1 << 10 // Grows down, not used.
   165  	SegmentDescriptorExecute                           = 1 << 11 // Execute permission.
   166  	SegmentDescriptorSystem                            = 1 << 12 // Zero => system, 1 => user code/data.
   167  	SegmentDescriptorPresent                           = 1 << 15 // Present.
   168  	SegmentDescriptorAVL                               = 1 << 20 // Available.
   169  	SegmentDescriptorLong                              = 1 << 21 // Long mode.
   170  	SegmentDescriptorDB                                = 1 << 22 // 16 or 32-bit.
   171  	SegmentDescriptorG                                 = 1 << 23 // Granularity: page or byte.
   172  )
   173  
   174  // Base returns the descriptor's base linear address.
   175  func (d *SegmentDescriptor) Base() uint32 {
   176  	return d.bits[1]&0xFF000000 | (d.bits[1]&0x000000FF)<<16 | d.bits[0]>>16
   177  }
   178  
   179  // Limit returns the descriptor size.
   180  func (d *SegmentDescriptor) Limit() uint32 {
   181  	l := d.bits[0]&0xFFFF | d.bits[1]&0xF0000
   182  	if d.bits[1]&uint32(SegmentDescriptorG) != 0 {
   183  		l <<= 12
   184  		l |= 0xFFF
   185  	}
   186  	return l
   187  }
   188  
   189  // Flags returns descriptor flags.
   190  func (d *SegmentDescriptor) Flags() SegmentDescriptorFlags {
   191  	return SegmentDescriptorFlags(d.bits[1] & 0x00F09F00)
   192  }
   193  
   194  // DPL returns the descriptor privilege level.
   195  func (d *SegmentDescriptor) DPL() int {
   196  	return int((d.bits[1] >> 13) & 3)
   197  }
   198  
   199  func (d *SegmentDescriptor) setNull() {
   200  	d.bits[0] = 0
   201  	d.bits[1] = 0
   202  }
   203  
   204  func (d *SegmentDescriptor) set(base, limit uint32, dpl int, flags SegmentDescriptorFlags) {
   205  	flags |= SegmentDescriptorPresent
   206  	if limit>>12 != 0 {
   207  		limit >>= 12
   208  		flags |= SegmentDescriptorG
   209  	}
   210  	d.bits[0] = base<<16 | limit&0xFFFF
   211  	d.bits[1] = base&0xFF000000 | (base>>16)&0xFF | limit&0x000F0000 | uint32(flags) | uint32(dpl)<<13
   212  }
   213  
   214  func (d *SegmentDescriptor) setCode32(base, limit uint32, dpl int) {
   215  	d.set(base, limit, dpl,
   216  		SegmentDescriptorDB|
   217  			SegmentDescriptorExecute|
   218  			SegmentDescriptorSystem)
   219  }
   220  
   221  func (d *SegmentDescriptor) setCode64(base, limit uint32, dpl int) {
   222  	d.set(base, limit, dpl,
   223  		SegmentDescriptorG|
   224  			SegmentDescriptorLong|
   225  			SegmentDescriptorExecute|
   226  			SegmentDescriptorSystem)
   227  }
   228  
   229  func (d *SegmentDescriptor) setData(base, limit uint32, dpl int) {
   230  	d.set(base, limit, dpl,
   231  		SegmentDescriptorWrite|
   232  			SegmentDescriptorSystem)
   233  }
   234  
   235  // setHi is only used for the TSS segment, which is magically 64-bits.
   236  func (d *SegmentDescriptor) setHi(base uint32) {
   237  	d.bits[0] = base
   238  	d.bits[1] = 0
   239  }
   240  
   241  // Gate64 is a 64-bit task, trap, or interrupt gate.
   242  type Gate64 struct {
   243  	bits [4]uint32
   244  }
   245  
   246  // idt64 is a 64-bit interrupt descriptor table.
   247  type idt64 [_NR_INTERRUPTS]Gate64
   248  
   249  func (g *Gate64) setInterrupt(cs Selector, rip uint64, dpl int, ist int) {
   250  	g.bits[0] = uint32(cs)<<16 | uint32(rip)&0xFFFF
   251  	g.bits[1] = uint32(rip)&0xFFFF0000 | SegmentDescriptorPresent | uint32(dpl)<<13 | 14<<8 | uint32(ist)&0x7
   252  	g.bits[2] = uint32(rip >> 32)
   253  }
   254  
   255  func (g *Gate64) setTrap(cs Selector, rip uint64, dpl int, ist int) {
   256  	g.setInterrupt(cs, rip, dpl, ist)
   257  	g.bits[1] |= 1 << 8
   258  }
   259  
   260  // TaskState64 is a 64-bit task state structure.
   261  type TaskState64 struct {
   262  	_              uint32
   263  	rsp0Lo, rsp0Hi uint32
   264  	rsp1Lo, rsp1Hi uint32
   265  	rsp2Lo, rsp2Hi uint32
   266  	_              [2]uint32
   267  	ist1Lo, ist1Hi uint32
   268  	ist2Lo, ist2Hi uint32
   269  	ist3Lo, ist3Hi uint32
   270  	ist4Lo, ist4Hi uint32
   271  	ist5Lo, ist5Hi uint32
   272  	ist6Lo, ist6Hi uint32
   273  	ist7Lo, ist7Hi uint32
   274  	_              [2]uint32
   275  	_              uint16
   276  	ioPerm         uint16
   277  }