# H-KPP: Hypervisor-Assisted Kernel Patch Protection
## 4 Kernel Objects Protection  
H-KPP detects the modification of three types of kernel object fields. The first type includes static objects, like the interrupt vector and the system-call table. Because the content of these static objects does not change during the execution of the operating system, H-KPP computes the hash of these objects after their initialization and then verifies their integrity by periodically comparing their hash results with the precomputed value. H-KPP uses SHA-1 as its hashing algorithm.  
The second type includes function pointers of various objects, like the i_fop field of the inode object (see Figure 3). These pointers may be assigned different values depending on the loaded modules. For example, each file system can define a new set of functions pointed by the i_fop field. Therefore, H-KPP limits its verification procedure to checking that the i_fop field points to a module's variable and that each field of this variable points to the beginning of some function. The verification itself is performed periodically by traversing the object graph as depicted in Figure 3. More precisely, H-KPP traverses the inodes and constructs a set of all the objects pointed by the i_fop field. Then, H-KPP verifies that the fields of these objects point to functions. If so, H-KPP stores a pair consisting of an object address and its hash in H-KPP's internal data structure. In the future, instead of verifying each field of an object separately, H-KPP hashes it and compares its hash to the previously stored value.  
The third type includes fields whose values are subject to certain invariants. For example, no two task_struct objects should reference the same credentials object via their cred fields. H-KPP performs this verification by traversing the list of processes and storing the addresses stored in the cred fields in an array. Then, H-KPP sorts the array and verifies that consecutive items are different.  
Another example is the equality invariant over the sets of task_struct objects. As depicted in Figure 4, the set of active processes can be constructed using information from two sources: (1) the linked list formed by the tasks field of the task_struct, (2) the tree formed by the children and the sibling fields of the task_struct. H-KPP periodically tests the sets of task_struct objects obtained from these sources. For each source, H-KPP stores the addresses of the structures in an array. Then, the arrays are sorted and compared.  
Figure 2: Layout of the kernel’s load_info structure.  
The verification procedure relies on the kernel symbols and the register values for locating and traversing the object graph. H-KPP intercepts the assignment to the LSTAR register, which signifies the completion of the kernel's initialization. At this point, H-KPP configures the VMX_PREEMPTION_TIMER, which induces periodic transitions to the hypervisor, thus allowing H-KPP to perform the periodic verification of the kernel objects. Table 4 summarizes the performed verifications.  
Figure 4: A graph of the task_struct obejts. The gs register points to a structure, whose current_task field (black arrow) references the currently running task_struct object. From this object we can climb up the process tree using the parent field (red arrows). After reaching the root, we can descend using the children (brown arrows) and sibling fields (blue arrows). In addition, all the processes can be traversed using the tasks field (green arrows).  
Figure 3: A graph of the inode objects. The super_blocks variable points to a linked list of all the super_block objects. Each super_block object contains a linked list of inode objects defined by the s_inodes and the i_sb_list fields of the super_block and the inode objects. Each inode object points via its i_top field to the file_operations object which contains pointers to various functions, like read, write, iterate, etc.