STM/Readme.STMPE

200 lines
8.9 KiB
Plaintext

STMPE Addtions to the STM API
AddPEVMtempVMCALL:
AddPEVMpermVMCALL:
Create a protected execution (PE) virtual machine (VM) and load a
module to be executed in that VM.
AddPEVMtempVMCALL:
The module is temporarily loaded in a VM,
executed, and the VM torn down afterwards. i.e. protected execution.
Input and Return register values: same as AddPEVMpermVMCALL.
AddPEVMpermVMCALL:
The module is permanently loaded in a VM and
persists. It is expected that this will be allowed only when the MLE
is initially brought up to allow for a measurement engine to be
loaded. This module is executed by the RunPeVmVMCALL.
Input registers:
EAX = STM_API_ADD_TEMP_PE or STM_API_ADD_PERM_PE_VM
EBX = low 32 bits of physical address of a caller created structure
containing module load information (struct module_info)
ECX = high 32 bits of physical address of a caller created structure
containing module load information (struct module_info)
Return register values:
CF = 0: No error, EAX set to STM_SUCCESS (0)
CF = 1: An error occurred, EAX holds relevant error value
EAX: Error/success return
RunPeVmVMCALL
This call runs the VM that was created via the AddSTMVmVMCALL vmcall.
Entrypoint into the module will be that defined during the
AddSTMVmVMCALL.
Input registers:
EAX = RunPeVmVMCALL
Output registers:
CF = 0: No error, EAX set to STM_SUCCESS (0)
CF = 1: An error occurred, EAX holds relevant error value EAX = -1 (actual
error values TBD)
EndAddPeVmVMCALL
Turns off the ability to add a permanent PE VM. This function is normally
ran at the end of the MLE's processing to ensure that no permanent
untrusted entity resides in the STM.
Bit definitions for the additions to the STM API
STM_API_ADD_TEMP_PE_VM 0x00010009
STM_API_ADD_PERM_PE_VM 0x0001000a
STM_API_END_PERM_PE_VM 0x0001000c
STM_API_RUN_PERM_PE_VM 0x0001000b
STM_API_ADD_PERM_PE_VM_NORUN 0x0001000d
Information block used to pass information about the PE module to the STM:
struct module_info {
u64 module_address; - physical address of VM/PE (SMM) module to load
u64 module_load_address; - guest-physical load address of module (must be
- within the range of address_space_start and
- address_space_start+addresss_space_size)
u32 module_size; - size of module in bytes
u32 module_entry_point; - relative offset from start of module
u64 address_space_start; - guest-physical address space start of module
u32 address_space_size; - module size in bytes
u32 vmconfig; - flags specifying how VM supporting module should
- be configured (see below for definitions)
u64 cr3_load; - guest-physical address to initialize cr3 to if
- paging enabled
u64 shared_page; - guest-physical address of a shared page (must not
- be in SMRAM space). segment will have R/W
- permission. value placed in RBX register of STM
- module.
struct region *segment; - guest-physical address of an array of R/O
- segments terminated with a null element.
- value placed in RCX register of STM module.
u32 shared_page_size; - size of shared page
u32 DoNotClearSize; - block at beginning of data not to be cleared
u64 ModuleDataSection; - start address of the module data section
} __attribute__((__packed__));
vmconfig settings:
SET_CS_L (1<<13) - cs.l set 64bit mode for cs (req. SET_IA32E is set)
SET_CS_D (1<<14) - cs.d default mode (0: 16bit seg, 1: 32-bit)
must be set if SET_CS_L is set
SET_IA32E (1<<15) - sets IA32e mode; when set, cr0.pg, cr0.pe, and
cr0.pae will be set as well
SET_CR0_PG (1<<31) - set cr0.pg
SET_CR0_PE (1<<0) - set cr0.pe
SET_CR4_PAE (1<<3) - set cr4.pae
SET_PERM_VM (1<<2) - VM can be re-executed using
STM_API_RUN_VM(RunPeVmVMCALL)
SET_PERM_VM_RUN_ONCE (1<<20) - run perm VM only once, then breakdown
SET_PERM_VM_CRASH_BREAKDOWN (1<<21) - if Perm VM crashes, then breakdown
SET_PERM_VM_RUN_SMI (1<<22) - Run VM/PE via SMI timer
SET_VM_CLEAR_MEMORY (1<<23) - Clear heap before each run
SET_VM_TEXT_RW (1<<24) - set VM/PE text space as RW
SET_VM_EXEC_HEAP (1<<25) - allow execution in Heap Space
SET_PERM_VM_HANDLE_INT (1<<26) - allow perm VM/PE to handle internal interrupts
error returns - placed in eax upon return to caller:
PE_SUCCESS 0 - PE setup/ran sucessfully
PE_FAIL -1 - catchall PE ERROR
PE_SPACE_TOO_LARGE 0x80040001 - requested memory space too large
PE_MODULE_ADDRESS_TOO_LOW 0x80040002 - PE module start below address space start
PE_MODULE_TOO_LARGE 0x80040003 - PE module too large for address space
(or located such that it overflows
the end of the address space
PE_NO_PT_SPACE 0x80040004 - not enough space left for PE VM
page tables
PE_NO_RL_SPACE 0x80040005 - not enough space left for resource
list
PE_MEMORY_AC_SETUP_FAILURE 0x80040006 - could not setup accesses to PE space
(internal error)
PE_SHARED_MEMORY_SETUP_ERROR 0x80040007 - could not setup shared memory
PE_MODULE_MAP_FAILURE 0x80040008 - could not map in the address space
PE_SHARED_MAP_FAILURE 0x80040009 - could not map in the shared page
PE_VMCS_ALLOC_FAIL 0x8004000A - could not allocate VMCS memory
PE_VMLAUNCH_ERROR 0x8004000B - attempted to launch PE VM with bad
- guest VM state
PE_VM_BAD_ACCESS 0x8004000C - PE VM attempted to access protected
memory out of bounds)
PE_VM_SETUP_ERROR_D_L 0x8004000D - CS_D and CS_L cannot be set to one at
the same time
PE_VM_SETUP_ERROR_IA32E_D 0x8004000E - SET_IA32E must be set when CS_L is
set
PE_VM_TRIPLE_FAULT 0x8004000F - PE VM crashed with a triple fault
PE_VM_PAGE_FAULT 0x80040010 - PE VM crashed with a page fault
Region list structure
struct region {
u64 address; - page aligned physical address
u32 size; - size of segment
u32 padding; - align structure to 64-bits
} __attribute__((__packed__));
Notes:
Interrupts and faults:
If the PE module encounters a fault, the VM/PE will be terminated. A future
STM/PE version will allow for faults to be handled by the PE module. In this
instance, the PE module will need to properly setup an IDT along with the
necessary handlers.
The VM/PE will not receive external interrupts.
Memory allocation errors:
Allocation errors for the PE module most likely mean that there is not enough
contiguous memory to fit the PE module in. The memory allocation could be
modified to allocate memory in smaller blocks from the STM heap, but as more
pages are allocated, the higher the overhead necessary for page tables.
Memory allocation errors for the overhead really mean that you should consider
reducing the size of the PE module. As at this point heap memory may
be getting so limited as the affect the operation of the STM itself.
To prevent this, the size of the PE module should be limited to
ensure that there is enough heap space for the STM to function.
MSR and I/O access:
Read and write access to the IA32_EFER_MSR is allowed, write access
to other MSRs are ignored and read attempts to other MSRs will return 0.
IO ports:
Access attempts to I/O ports are generally ignored except for 0x3D8 and 0x3F8.
0x3D8 and 0x3F8 (aka COM2 and COM1 respectively) can be used to send character strings through the STM console port.
No formatting, etc is done (any byte combinations that can pose a security issue will be delt with a necessary).
for debugging a VM/PE debugging output can be sent through:
RDX: port - 0x3F8 or 0x3D8
RCX: number of bytes (maximun length is 200. Stings longer than that will be truncated)
DS:ESI location in PE/VM where output is located
Use either instruction OUTSB/OUTSW/OUTSD (0x6E or Ox6F)
Note: do not use a loop with a rep statement (which is what is normally done)