Intel® Kernel Guard Technology (Intel® KGT) is a policy specification and enforcement framework for ensuring runtime integrity of kernel and platform assets. The iKGT framework is currently based on a thin VMX-root layer software component called xmon. Xmon de-privileges the operating system, traps accesses to specified assets using VTx controls (VMCS/EPT), and performs actions specified by the policy. Xmon executes below the kernel (ring 0), and the policy enforcement is therefore rooted outside the kernel. Access to critical kernel and platform assets such as kernel code pages, kernel page-table mappings, kernel interrupt descriptor table (IDT), Control Registers (CRs), MSRs can be monitored and their integrity can be protected by specifying appropriate policy actions.
Figure 1.0 shows the high-level architecture of an iKGT-enabled system.
Figure 1.0 iKGT Architecture
The following sections cover the details of iKGT framework components.
1.1 Policy File
The policy file lists the assets to be monitored and the actions to be taken when monitoring events occur. The example policy file below shows how CR4:SMEP can be monitored and hardened by installing this policy.
{
"cr4": {
"SMEP": {
"enable": 1,
"write_access": LOG_SKIP
}
},
"log": {
"log.txt": "/config/xmon/log/log.txt"
}
}
1.2 Python Script
The python script takes policy.json (file) as input and issues the necessary commands to set up directories and files in configfs to enable monitoring of the assets specified in the policy. Driver callbacks are triggered when file and directories are created/updated in configfs.
1.3 IKGT Agent Driver
iKGT agent driver is an example driver. This is a ring-0 policy component responsible for configuring protections using configfs entries.
- Hooks configfs callbacks and handles configfs interface
- Validates configfs policy data
- Calls xmon hypercall API to set up protections
- Sets up shared memory channels for log and message and communicates with xmon policy plugin
- The IKGT agent driver itself is not trusted automatically; the xmon policy plugin will perform the required checks to ensure that the policies communicated meet the policy constraints.
1.4 Xmon
xmon is a thin software component that uses VT-x to de-privilege the operating system.
- Executes in vmx-root ring 0 (ring -1) below the kernel
- De-privileges the operating system
- Does not virtualize devices. All devices are passthrough to the guest OS
- Allows addition (build time) of policy-specific plugin modules
- Uses VTx controls/EPT to generate hardware-assisted transitions from guest OS to itself
- Delivers access events to the policy plugin and takes action specified by the policy module
- Supports a hypercall API that can be called from the guest OS for setting up protections
- Supports VMX-root API that can be called from plugin module (handler)
- xmon is agnostic with respect to OS, use-case, and policy
1.5 Policy Plugin (Handler)
The use-case or policy-specific code that can be linked with xmon includes a sample policy module that implements the kernel code and platform integrity policy. Actions include:
- Executes in vmx-root ring 0
- Fields the access-events
- Can call xmon handler API
- Can maintain policy state and make decisions based on that state
- Communicates responses to xmon based on the policy state
Note: The policy plugin can be implemented to run in vmx-root ring 3, which incurs additional performance costs if increased privilege separation is mandated.
1.6 Xmon Loader
This Multi-boot compliant (MB2) loader is responsible for bootstrapping xmon.
- The xmon-loader in embedded in xmon package boot image
- The xmon boot image is a grub module and is specified in grub.cfg as first kernel
- The linux kernel and ramdisk are specified as additional grub modules
- Optionally, a policy file can be specified as an additional grub module
- Grub loads the xmon image and starts executing xmon loader at the offset specified in MB2 header
- xmon loader, after completing its own initialization, in turn launches Linux
- Based on MB1/2 protocol, gets Linux kernel vmlinuz (bzImage) and Initrd module location and size from Multiboot Information (MBI) structure
- Based on Linux Boot Protocol, prepares boot_params structure, and then jumps to the 32-bit entry of Linux kernel
- xmon loader itself is a transient component and is required only for bootup. It is scrubbed from memory (and hence the TCB) once the xmon assumes control of the platform
- The xmon loader can be replaced with any alternative loader or can be replaced with an alternative boot scheme that implements the xmon launch requirements
1.7 Configfs
Configfs allows policy setup from user space.
- Allows file-system based management of kernel objects from user space
- Assets are represented by config-items (directories)
- Config-items can be created/destroyed by user space (mkdir/rmdir)
- Attributes of objects are represented by files
- Contents of files represent value of the attribute
- Lifecycle management of config-items is owned by user space
- Kernel module backing this responds to these configfs actions
- Creation/deletion of directory
- Reads and writes from the files
- Configuration/policy is captured and stored in config file system
- Can be queried
- Permission model based on Unix file permissions uid/gid based discretionary access control (DAC)
1.8 Configfs Namespace
- The configfs is mounted as /config. The IKGT agent driver creates ikgt directory under /config and registers its callbacks.
- When a subdirectory is created under /ikgt, the agent receives a callback.
- Each directory under /config/ikgt represents a unique platform or kernel asset.
- Depending on the name of the directory, the agent registers additional callbacks to handle creation of sub-directories in that newly created directory.
Example: The following table shows how the configfs directories can be set up to monitor and log all write accesses to CR0 write-protect (WP) bit.
Command | Action |
---|---|
mkdir /config/ikgt/cr0/WP | Identify CR0:WP as an asset to be monitored by creating the directories. This will automatically create files write_access and enable under /config/ikgt/cr0/WP |
echo LOG_ALLOW > /config/ikgt/cr0/WP/write_access | Specify the action to be taken when a write operation an attempt to perform write access is detected |
echo 1 > /config/ikgt/cr0/WP/enable | Turn the protection on |
Table 1.0 below lists the assets that can be monitored using IKGT in the current sample policy implementation.
Asset | Comments | Example commands |
---|---|---|
CR0 | Monitor write access to individual bits of CR0 | mkdir /config/ikgt/cr0/WP; echo LOG_SKIP > /config/ikgt/cr0/WP/write_access; echo 1 > /config/ikgt/cr0/WP/enable |
CR4 | Monitor write access to individual bits of CR4 | mkdir /config/cr4/SMEP; echo LOG_SKIP > /config/ikgt/cr4/SMEP/write_access; echo 1 > /config/ikgt/cr4/SMEP/enable |
IDTR * | Monitor loads and stores of Interrupt Descriptor Table Register | |
GDTR * | Monitor loads and stores of Global Descriptor Table Register | mkdir /config/cr0/SMEP; echo LOG_ALLOW > /config/cr0/WP/write_access; echo 1 > /config/cr0/WP/enable |
MSR | Monitor write access to given MSR | mkdir /config/ikgt/msr/EFER; echo LOG_ALLOW > /config/ikgt/msr/EFER/write_access; echo 1 > /config/ikgt/msr/EFER/enable |
Memory * | Monitor specific type of access to pages in given memory range. | |
kernel-code | Make kernel code pages and page-table mapping of kernel code non-modifiable | mkdir /config/ikgt/memory/kernel-code; echo 1 > /config/ikgt/memory/kernel-code/enable; |
IDT | Make the Interrupt Descriptor table non-modifiable | |
syscall-table | Make the syscall table non-modifiable | |
custom | Monitor specific type of access to pages in given memory range | mkdir /config/ikgt/memory/custom/my-range; echo 0xABCDEF > /config/ikgt/memory/custom/my-range/start-address; echo 4096 > /config/ikgt/memory/custom/my-range/size; echo 1 > /config/ikgt/memory/custom/my-range/enable; |
IO * | Monitor reads/writes to specified IO ports | |
Report * | Query policy state and status of specified asset. Response can be signed/encrypted by xmon | cat query.txt > /config/ikgt/report/query.txt; cat /config/ikgt/report/response.txt |
* These features are not released yet.
1.9 Configfs Attributes
The attributes of a monitored asset are represented by files in the directory that represent the assets. The iKGT driver automatically creates the attribute files when a directory for that asset is created using mkdir. The attribute files contain a value that specify actions to be taken when that asset is accessed. The following table explains different attributes and the meanings of those attributes.
Attribute | Meaning | Comments |
---|---|---|
Enable | Turns Asset Monitoring on or off | When value is 0, monitoring is OFF When value is 1, monitoring is ON |
Sticky Value | Once the resource is set to a given value, modifications are disallowed until the next platform reboot. | This attribute can also be used to support one-time transitions |
write_access, read_access, execute_access | The value in these files specifies the action(s) to take when that type of access is detected | ALLOW, SKIP, LOG_ALLOW and LOG_SKIP, write_access can have additional STICKY bit |
start-address | Used for custom memory range asset and specifies the page address of the memory to be monitored | |
size | Used for custom memory range asset and specifies the size of memory range to be monitored |