# JITScanner: Just-in-Time Executable Page Check in the Linux Operating System +
## 3 The JITScanner System
### Executable-Page Access Interception
The shadow state machine within our system implements a time-separated alternating mechanism between write and execute permissions for pages. When a page is in \"write mode\" in the shadow state machine, it allows page-update operations without triggering user execution-mode interruptions such as page faults or interception via our kernel-level support. However, any attempt to execute instructions from that page will result in a fault, redirecting control to our kernel-level hook for interception and handling. Conversely, when a page is in \"exec mode\" within the shadow state machine, it permits instruction-fetch operations. In this mode, attempts to update the page will trigger a fault, intercepted by our kernel-level support for handling. This alternating logic between write and execute permissions ensures a controlled and secure mechanism for managing page access and operations within the application's address space. A representation of this logic is shown in Figure 3.  
With our facility that manages page permissions dynamically, we have the capability to trigger the page-verification process whenever the access mode transitions between write and execute permissions. However, based on the goals of our solution, we believe that conducting a signature check on the executable page is essential only during instruction fetches. This is the critical moment where potential exploitation of malicious code could occur, making it the prime instance for initiating the signature check. Figure 3: Shadow state machine for WX permissions. By specifically targeting the instruction-fetch operations for page verification, we can efficiently focus our security measures on the most vulnerable points in time, ensuring that checks for malicious signatures are conducted precisely when the executable page is being accessed for instruction execution. This targeted approach enhances the effectiveness of our security measures while optimizing performance by avoiding unnecessary checks during other access modes. To support shadowing, we set the XD bit on the lowest level of the page table (the PTE), disabling instruction fetches from the page as soon as the WX page is materialized. By doing this, when the user program tries to execute the instructions on the page, a page fault occurs due to the lack of required permissions. We intercept this page fault and do the following:  
* Clear the XD bit, to allow the user to execute the page from now on;
* Clear the W bit, to disable writes on the page;
* Suppress the SIGSEGV signal generated by the invalid access to prevent the kernel from terminating the user program or making it run an SIGSEGV handler. To handle the interception of kernel-level functions responsible for delivering the SIGSEGV signal during CPU fetches, our approach involves suppressing this signal, since the page fault is generated by our shadowing mechanism. In Linux, faults occurring during instruction fetches are managed within the architecture-specific code of the kernel before calling the handle_mm_fault() function. However, these functions cannot be directly hooked using the kprobe mechanism. As an alternative, we have chosen to place a kernel probe on the force_sig_fault() function, which is triggered whenever an invalid memory access occurs. By hooking into this function, we can effectively suppress the delivery of the signal. Moreover, the synchronous checking of page content and the passage of page snapshots to the asynchronous checker are handled through the hook installed on the return of the handle_mm_fault() function. This comprehensive approach enables us to intercept and manage the necessary signals and functions, ensuring the seamless operation of our shadowing mechanism and the subsequent verification processes. To effectively handle the hook for the force_sig_fault() kernel function, it is crucial to differentiate between standard invalid-access faults and those triggered by our shadow state machine. For this purpose, we utilize two unused bits within the lowest level page table entry (PTE) of the x86 processor.