A method for protecting general memory integrity based on the Intel CET mechanism
By setting up a dedicated shadow stack page in the program and using the WRSS instruction of the Intel CET mechanism for overhead reduction, the problem of high performance overhead in existing memory isolation methods is solved, achieving efficient protection of sensitive memory and improving processor processing efficiency.
Patent Information
- Application Number
- CN202111430587.6
- Authority / Receiving Office
- CN · China
- Patent Type
- Patents(China)
- Current Assignee / Owner
- Filing Date
- 2021-11-29
- Publication Date
- 2026-01-23
- Estimated Expiration
- 2041-11-29
AI Technical Summary
Existing memory isolation methods suffer from high performance overhead and are difficult to effectively protect the integrity of sensitive memory. In particular, the Intel CET mechanism involves significant write overhead, resulting in low efficiency of the processor in protecting the integrity of general memory.
During program execution, the page containing sensitive data and/or sensitive code is set as a dedicated shadow stack page, and overhead reduction processing is performed through the WRSS instruction of the Intel CET mechanism, including lossless compression and adaptive write operations. This reduces write overhead by being independent of the shadow stack page maintained by the Intel CET mechanism.
It effectively protects the integrity of sensitive data and sensitive code, while reducing the processor's performance overhead in protecting general memory integrity and improving the processor's processing efficiency.
Smart Images

Figure CN114266036B_ABST
Abstract
Description
Technical Field
[0001] This invention relates to the field of computer information security, specifically to the field of software security, and more specifically, to a method for protecting general memory integrity based on the Intel CET mechanism. Background Technology
[0002] With the rapid development of information technology and the widespread adoption of computers, computers are widely used in all aspects of society, including military, education, finance, and scientific research. At the same time, computer security problems are emerging one after another, seriously impacting national security and the economy. For example, the Code Red virus, which broke out in July 2001, launched a massive attack on many servers. The attacked servers, following the virus's instructions, sent large amounts of data to government websites, ultimately causing website paralysis and resulting in $2.6 billion in losses globally. From January 1, 2020 to the present, the Microsoft Security Response Center (MSRC) has reported 37,964 vulnerabilities (bugs), of which 5,264 are classified as high-severity. Another MSRC report indicates that 70% of the vulnerabilities added annually to the Common Vulnerabilities & Exposures (CVE) dictionary are related to memory safety issues.
[0003] In memory security issues, compromising the integrity of sensitive memory (including sensitive data and sensitive code) poses a significant threat to system security.
[0004] Many defense mechanisms against memory corruption attacks rely on ensuring the integrity of sensitive data to function properly. Examples include the secure regions and secure stacks of Code Pointer Integrity (CPI) mechanisms, the shadow stack in shadow stack defense mechanisms, and the metadata of CFIXX mechanisms, which guarantee the integrity of object types in C++. The Write XOR Execute (W^X) mechanism, used to defend against code injection attacks, prevents memory pages from having both write and execute permissions simultaneously. However, dynamic code generation techniques widely used in Just-In-Time (JIT) compilers and dynamic binary translation dynamically generate and modify code, storing it in a code cache. Since sensitive code resides in the code cache, its integrity must be protected.
[0005] In-process isolation is a crucial means of ensuring system security. It guarantees that even if an attacker compromises a user process, they cannot execute sensitive code or access sensitive data. In-process isolation is currently the mainstream research direction in academia. In-process isolation methods can be divided into three types: address-based isolation methods, domain-based isolation methods, and privileged access-based isolation methods, which are described below:
[0006] 1. Address-based isolation methods. Address-based isolation methods require instrumenting each memory access instruction to constrain the address range that these instructions can access, ensuring that access to safe regions is impossible. Pure software address isolation methods, such as Software Fault Isolation (SFI), divide code and data into different regions, with code in each region only able to access the corresponding data. Since SFI is implemented purely in software, it incurs a significant performance overhead for memory-intensive programs. To accelerate address isolation methods, Intel introduced Memory Protection Extensions (MPX) to speed up boundary checks. MPX allows programmers to create a set of boundaries to identify the upper and lower bounds of address ranges. By instrumenting all memory access instructions and using MPX hardware to check whether the accessed memory address falls within a safe region, address-based isolation methods introduce a significant performance overhead for protecting memory-intensive programs, and this is where its performance bottleneck lies.
[0007] 2. Domain-Based Isolation Methods. The basic idea of domain-based isolation methods is to grant access permissions to a secure region before accessing it, and to immediately close the access permissions after access is complete. This way, even if an attacker knows the location of the secure region, they cannot access critical data. However, critical data protected by information hiding techniques is frequently accessed by defense mechanisms, such as code pointer integrity, control flow integrity, and shadow stack techniques. These defense mechanisms access the secure region during function returns, function calls, and indirect control flow jumps. For example, in the SPEC CPU2006 benchmark suite, the average execution frequency of function calls and function returns is approximately 58 million times per second, and the average execution frequency of indirect jump instructions is approximately 43 million times per second. Therefore, the performance bottleneck of domain isolation methods is the need for frequent access permission switching. Pure software-based domain isolation methods, such as using the Mprotect system call to modify access permissions before and after accessing the secure region, incur significant performance overhead due to the approximately 20,000 clock cycles required for a single system call to switch between user mode and kernel mode.
[0008] To accelerate domain-based isolation methods and improve the speed of switching access permissions, some researchers have proposed using Extended Page Table (EPT) technology in hardware-assisted memory virtualization to isolate secure regions. This method sets up two EPTs: one records the address mappings of secure regions (called the secure EPT), and the other records the address mappings of non-secure regions (called the non-secure EPT). Then, the `vmfunc` instruction provided by Intel (approximately 140 clock cycles) is used to quickly switch between these two EPTs to achieve isolation. Alternatively, Intel Memory Protection Keys (MPK) hardware can be used to isolate secure regions. MPK can divide the user memory space into 16 regions, using 4 bits in the page table entry to identify the region to which the page belongs, and adding a PKRU register to control the read and write permissions of each region, achieving isolation.
[0009] 3. Privileged Access-Based Isolation Methods. Some research also protects secure regions by adding new hardware to the processor. For example, some researchers have added a bit to page table entries to identify whether a page is a sensitive data page and extended the x86 instruction set to provide a dedicated memory access instruction, `smov`, for accessing sensitive data pages (referred to as the IMIX mechanism). Similarly, the MicroStache mechanism adopts a similar design approach to the IMIX mechanism, but with further isolation at the cache level to block potential cache-based side-channel attacks. Both the IMIX and MicroStache mechanisms only require setting the page containing the secure region as a protected page and then accessing that region through a dedicated memory access instruction to achieve protection of the secure region.
[0010] In summary, existing memory isolation methods still suffer from significant performance overhead, hindering their large-scale deployment. The main problem with methods that rely on additional hardware is the lack of actual hardware support, preventing immediate deployment to protect the integrity and confidentiality of secure areas within a system.
[0011] Due to the high performance overhead of existing software implementations, Intel introduced Control-flow Enforcement Technology (CET) to protect sensitive memory. This includes the newly added hardware shadow stack mechanism CET.SHSTK (SHSTK mechanism) in the latest processors and a new hardware-implemented coarse-grained control flow integrity (IBT) defense mechanism for forward edges. The SSTK mechanism is a crucial and effective defense against ROP attacks, ensuring that the return address on the stack is not tampered with by attackers. When the program executes a Call instruction and pushes the return address onto the main stack, the SSTK mechanism simultaneously pushes the return address onto the hardware shadow stack pointed to by the SSP register (the page containing the return address is the shadow stack page). When the program executes a Ret instruction, the SSTK mechanism compares the return addresses on the main stack and the hardware shadow stack; if they do not match, a #GP exception is thrown. Normal read instructions can read the shadow stack page, but normal write instructions cannot write to the shadow stack page; otherwise, an exception will be triggered. Only the WRSS instruction can write to the shadow stack page.
[0012] However, the write overhead of the WRSS instruction is large, making the isolation overhead of the existing technology too large. Moreover, since the CET mechanism involves multiple tasks, it is difficult to directly adjust the CET mechanism. Summary of the Invention
[0013] Therefore, the purpose of this invention is to overcome the shortcomings of the prior art and provide a method for protecting general memory integrity based on the Intel CET mechanism.
[0014] The objective of this invention is achieved through the following technical solution:
[0015] According to a first aspect of the present invention, a method for protecting general memory integrity based on the Intel CET mechanism is provided, comprising: during program execution, setting the page containing sensitive data and / or sensitive code to be protected as a dedicated shadow stack page, wherein the dedicated shadow stack page is independent of the shadow stack page maintained by the CET mechanism itself; before performing a write operation on the dedicated shadow stack page, performing overhead reduction processing on the content to be written that needs to have its write overhead reduced; writing the overhead-reduced content to be written to the dedicated shadow stack page using the WRSS instruction of the CET mechanism; and using the dedicated shadow stack page to protect the integrity of sensitive data and / or sensitive code.
[0016] In some embodiments of the present invention, the step of performing overhead reduction processing on the content to be written that needs to have reduced write overhead includes: when the amount of data of the content to be written exceeds a predetermined threshold, performing lossless compression processing on the content to be written, wherein multiple bits in the address space that are not used by the addressing process are used to reduce the actual memory size occupied by the content to be written.
[0017] In some embodiments of the present invention, the content to be written that requires reduced write overhead includes metadata of a sensitive pointer, the metadata of which includes the value of the sensitive pointer, the upper bound of the object it points to, and the lower bound of the object it points to; the step of performing lossless compression on the content to be written includes: calculating a first difference and a second difference based on the metadata of the sensitive pointer, wherein the first difference is the difference obtained by subtracting the lower bound of the object it points to from the value of the sensitive pointer, and the second difference is the difference obtained by subtracting the value of the sensitive pointer from the upper bound of the object it points to; and storing the value of the sensitive pointer, the first difference, and the second difference using multiple bits in the address space that are not used by the addressing process and multiple bits used by the addressing process.
[0018] In some embodiments of the present invention, the step of writing the overhead-reduced content to be written to a dedicated shadow stack page via the WRSS instruction of the CET mechanism includes: writing the value of the sensitive pointer, the first difference, and the second difference to a specified bit in the dedicated shadow stack page according to the data writing rule corresponding to the category of the sensitive pointer, and using the corresponding bit in the address space that is not used by the addressing process as an extended category indicator bit to record the category of the sensitive pointer.
[0019] In some embodiments of the present invention, the step of protecting the integrity of sensitive data and / or sensitive code using the dedicated shadow stack page further includes: before dereferencing the corresponding pointer stored in ordinary memory, determining whether the dereferencing is safe based on the metadata of the sensitive pointer whose backup is stored in the dedicated shadow stack page.
[0020] In some embodiments of the present invention, the method further includes: writing the content to be written, which does not require reducing write overhead, directly to a dedicated shadow stack page using the WRSS instruction of the CET mechanism.
[0021] In some embodiments of the present invention, the content to be written that does not require reducing write overhead includes a metadata table for recording virtual table pointers; the step of using the dedicated shadow stack page to protect the integrity of sensitive data and / or sensitive code further includes: before performing an indirect call on the target function based on the corresponding virtual table pointer stored in ordinary memory, comparing the virtual table pointer with the virtual table pointer recorded in the metadata table in the dedicated shadow stack page to determine whether the indirect call is safe.
[0022] In some embodiments of the present invention, the step of performing overhead reduction processing on the content to be written that needs to reduce write overhead before performing a write operation on the dedicated shadow stack page includes: when the amount of data of the content to be written is less than a predetermined threshold, occupying a reserved register to temporarily store the content to be written and waiting for other content to be written with a data amount less than the predetermined threshold to be stored, until the total amount of data of the content to be written in the reserved register is greater than or equal to the predetermined threshold before performing the write through the WRSS instruction.
[0023] In some embodiments of the present invention, the content to be written includes machine code generated by the JIT compiler, and the machine code is sensitive code; wherein, the step of performing overhead reduction processing on the content to be written that needs to reduce write overhead before performing write operation on the dedicated shadow stack page includes: storing the corresponding machine code in a reserved register in the order of generation, and performing write operation by means of the WRSS instruction until the total amount of data to be written reaches a predetermined threshold.
[0024] According to a second aspect of the present invention, a method for protecting program security based on the Intel CET mechanism is provided, the method comprising: obtaining program source code; compiling the program source code using a compiler to protect the integrity of sensitive data and / or sensitive code in accordance with the method described in the first aspect when the program is executed.
[0025] In some embodiments of the present invention, the step of compiling the program source code using a compiler includes: inserting corresponding protection logic code according to the information of sensitive data and / or sensitive code that need to be protected in the program source code, so that when the compiled program is executed, the integrity of the sensitive data and / or sensitive code is protected by the corresponding protection logic code in accordance with the method described in the first aspect.
[0026] According to a third aspect of the invention, an electronic device is provided, comprising: one or more processors; and a memory for storing executable instructions; wherein the one or more processors are configured to implement the methods of the first aspect and / or the second aspect via executing the executable instructions. Attached Figure Description
[0027] The embodiments of the present invention will be further described below with reference to the accompanying drawings, wherein:
[0028] Figure 1 This is a schematic diagram illustrating how a shadow stack page / dedicated shadow stack page can perform a write operation via the WRSS instruction, but cannot be written by a normal write instruction, according to an embodiment of the present invention.
[0029] Figure 2 The original data structure of the metadata of sensitive pointers according to embodiments of the present invention is processed by overhead reduction / lossless compression.
[0030] Figure 3 The data structure of the metadata of four different types of sensitive pointers according to embodiments of the present invention after overhead reduction processing / lossless compression processing;
[0031] Figure 4 This describes the process by which the JIT compiler interprets and executes JavaScript files and converts them into machine code in existing technologies.
[0032] Figure 5 This is a schematic diagram illustrating the setting of NX to 0 in the code cache containing sensitive code, based on an embodiment of the present invention using Intel CET technology.
[0033] Figure 6 To modify the Chakra engine's JIT compiler according to embodiments of the present invention so as to utilize the protection mechanism of the present invention to perform a process of protecting sensitive code;
[0034] Figure 7 This is a schematic diagram illustrating how, according to an embodiment of the present invention, a reserved register is temporarily used to store the content to be written while waiting for other content to be written, whose data volume is less than a predetermined threshold, to be stored. Detailed Implementation
[0035] To make the objectives, technical solutions, and advantages of this invention clearer, the invention will be further described in detail below with reference to the accompanying drawings and specific embodiments. It should be understood that the specific embodiments described herein are merely illustrative and are not intended to limit the invention.
[0036] As mentioned in the background section, the WRSS instruction incurs significant write overhead, resulting in excessive isolation overhead in existing technologies. Furthermore, due to the multifaceted nature of the Intel CET mechanism, direct adjustments to the Intel CET mechanism are difficult to implement. Therefore, this invention utilizes the Intel CET mechanism to achieve general memory integrity protection. To ensure compatibility with the Intel CET mechanism and avoid conflicts with its own maintained shadow stack pages, this invention establishes a dedicated shadow stack page, independent of the Intel CET mechanism's own shadow stack pages. When writing content to this dedicated shadow stack page that requires reduced write overhead, it performs corresponding overhead reduction processing, thereby reducing the number of WRSS instruction calls. This allows for the protection of sensitive data and / or sensitive code with lower overhead, reducing the processor's performance overhead in protecting general memory integrity and ultimately improving the processor's efficiency for other tasks.
[0037] Before describing the embodiments of the present invention in detail, some of the terms used therein are explained as follows:
[0038] The WRSS instruction is an instruction in Intel CET technology that can modify the contents of a shadow stack page. Intel CET technology can maintain a shadow stack in memory for the corresponding thread (the thread that needs to be protected). See [link to documentation]. Figure 1 The memory space shown has its shadow stack's base address stored in the SSP (Shadow Stack Pointer) register. The shadow stack is composed of shadow stack pages. Ordinary write instructions do not have write permissions to shadow stack pages, but the WRSS instruction does. Compared to ordinary memory access instructions, the WRSS instruction has a significantly higher time overhead for a single memory write. Specifically, a single mov instruction takes less than one clock cycle, while a single WRSS instruction takes approximately 12 clock cycles. The WRSS instructions include the WRSSQ instruction (writes 8 bytes at a time) and the WRSSD instruction (writes 4 bytes at a time). The WRSSQ instruction writes 8 bytes from the source register to the destination shadow stack page, and the destination address must be 8-byte aligned. The WRSSD instruction writes 4 bytes from the source register to the destination shadow stack page, and the destination address must be 4-byte aligned. The overhead of writing 4 bytes with the WRSSD instruction is comparable to that of writing 8 bytes with the WRSSQ instruction. Therefore, the WRSSQ instruction is more efficient. Thus, the following specific embodiments use the WRSSQ instruction as an example. However, it should be understood that in some cases, those skilled in the art may also use the WRSSD instructions to make corresponding adjustments to achieve the present invention.
[0039] Dereferencing a pointer means referencing the value of the object that the pointer points to. For example, referencing the value of a variable stored at a certain address.
[0040] According to one embodiment of the present invention, for compatibility and conflict avoidance, the present invention sets up a dedicated shadow stack page to protect sensitive data and / or sensitive code outside the shadow stack page maintained by the Intel CET mechanism (sometimes referred to as the CET mechanism). (The term "dedicated" is used to distinguish it from the shadow stack page maintained by the Intel CET mechanism itself; the dedicated shadow stack page is also a type of shadow stack page.) The WRSS instruction can operate on both the shadow stack page maintained by the Intel CET mechanism and the dedicated shadow stack page. To reduce write overhead, different content to be written is distinguished and corresponding write processing is performed.
[0041] If the content to be written does not require reducing write overhead, then the content to be written is directly written to a dedicated shadow stack page using the WRSS instruction;
[0042] If the content to be written needs to reduce write overhead, and the amount of data to be written exceeds a predetermined threshold, then the content to be written is losslessly compressed and written to a dedicated shadow stack page using the WRSS instruction.
[0043] If the content to be written needs to reduce write overhead, and the amount of data to be written is less than a predetermined threshold, then when the amount of data to be written reaches the predetermined threshold, it is written to a dedicated shadow stack page using the WRSS instruction.
[0044] According to one embodiment of the present invention, if the implementer writes a new program, the implementer can write protection logic for specific sensitive data and / or sensitive code in the program according to the scheme of the present invention during programming, so as to achieve a low-overhead protection mechanism through a dedicated shadow stack page.
[0045] According to one embodiment of the present invention, if the implementer has already written a program, but the program does not protect sensitive data and / or sensitive code through shadow stack pages, the programmer can use the compiler to modify the protection logic of the original protection mechanism in the program according to the preset adjustment logic during program optimization, thereby saving time and effort. For clarity, the following embodiments are mainly described from the perspective of adjusting the protection logic of the original protection mechanism in the program through the compiler. However, it should be understood that the following embodiments are only illustrative, and there are many other implementation methods in the art, which will not be listed one by one.
[0046] Protecting general memory integrity mainly involves two aspects: protecting sensitive data and protecting sensitive code. The technical solution of this invention will be described from these two aspects respectively:
[0047] I. Protecting Sensitive Data
[0048] In the embodiment for protecting sensitive data, the LLVM compiler is used as an example to illustrate the process of adjusting the original protection mechanism in the program to transform it into the protection mechanism of this invention. The LLVM (Low Level Virtual Machine) compiler (framework) is a modular, reusable collection of compiler and toolchain technologies. Most of the logic of the LLVM compiler handles compilation optimization and code generation, which consists of one or more intermediate optimization processes (i.e., Passes; some literature refers to "one Pass" as "one run"). To adjust the original protection mechanism, the LLVM compiler can be used as the underlying framework. By adding a CETIS (CET-based memory Isolation Technology, abbreviation for the protection mechanism of this invention) Pass in the middle of the LLVM compiler, the protection of sensitive data can be achieved, preventing attackers from compromising the integrity of sensitive data. The following examples, using the CFIXX defense mechanism and the CPI mechanism, demonstrate how the CETIS mechanism of this invention can be combined with these defense mechanisms to achieve memory integrity protection with low overhead.
[0049] (1) Taking the protection of sensitive data in the CFIXX defense mechanism as an example, the following explanation is given for the case where the content to be written does not need to reduce write overhead.
[0050] C++ is a programming language evolved from C. C++ supports procedural programming like C, object-based programming with abstract data types, and object-oriented programming with inheritance and polymorphism. Dynamic allocation via virtual tables is the core of polymorphism in C++, allowing subclasses to override virtual functions inherited from their parent classes. In C++, each polymorphic class has one or more virtual tables containing function pointers to all virtual functions of that class. The virtual table is indexed by the first field of the class object, the virtual table pointer, which is initialized in the class object's constructor. Dynamic allocation uses the virtual table pointer to identify the object's underlying type. At each virtual function call point, the program first finds the target virtual function pointer in the virtual table using the virtual table pointer of the object's class, and then executes the target function through indirect call. The virtual table is located in a read-only memory area (Rodata segment), while the virtual table pointer is stored in a read-write memory area. Therefore, if an attacker exploits a program vulnerability to tamper with the virtual table pointer, they can launch a control flow hijacking attack, such as a counterfeit object-oriented programming (COOP) attack.
[0051] To defend against the aforementioned attacks, it is necessary to ensure the object type integrity (OTI) of C++ programs, in other words, to ensure the integrity of the virtual table pointers. The CFIXX defense mechanism ensures that the virtual table pointers of objects are not tampered with by attackers at runtime. Specifically, it modifies the LLVM compiler so that the program stores a backup of the virtual table pointers in a metadata table at runtime, and ensures the integrity of the metadata table through address isolation.
[0052] According to one embodiment of the present invention, based on the CFIXX defense mechanism, an intermediate optimization process (Pass, also referred to as "one pass" in some literature) is added to the LLVM compiler. This intermediate optimization process generates protection logic using a dedicated shadow stack page based on the protection logic in the original CFIXX defense mechanism. Specifically, by modifying the allocation and storage of the metadata table used to back up the virtual table pointer in the C++ program, the storage location of the metadata table is set to a dedicated shadow stack page, and the WRSSQ instruction is used to write the virtual table pointer to the metadata table at the dedicated shadow stack page. The protection logic in the original CFIXX defense mechanism is discarded (for example, by deleting the implementation code of the original CFIXX defense mechanism). Since the original CFIXX defense mechanism writes an 8-byte virtual table pointer to the metadata table each time, the content to be written here (virtual table pointer) can be directly set to content that does not require reducing write overhead, and directly written to the dedicated shadow stack page using the WRSSQ instruction of the CET mechanism. During program execution, before making an indirect call to the target function based on the corresponding virtual table pointer stored in ordinary memory, the consistency between the virtual table pointer in ordinary memory and the virtual table pointer recorded in the metadata table of the dedicated shadow stack page is compared. If they match, the indirect call is safe, and execution continues. If they do not match, the indirect call is unsafe, an exception is thrown, and execution stops. After adjustment, the protection function of the original CFIXX defense mechanism can be achieved using the defense mechanism of this invention, but the overhead of implementing the defense mechanism of this invention during program execution is smaller.
[0053] (2) The Code Pointer Integrity Mechanism (CPI mechanism) is also a mechanism to ensure the integrity of sensitive data. The following explains how the present invention protects the Code Pointer Integrity Mechanism (CPI). It also explains the situation where the write overhead needs to be reduced and the amount of data to be written exceeds a predetermined threshold.
[0054] The CPI mechanism aims to protect the integrity of sensitive pointers, preventing attackers from tampering with them and thus preventing control flow hijacking attacks. In CPI, the definition of a sensitive pointer is recursive, including all code pointers (such as function pointers, return addresses, etc.) and pointers that can be used to access sensitive pointers. Sensitive data in CPI is divided into two parts: a safe stack, which stores return address values and objects that can be proven safe through static analysis; insecure objects are stored in an unsafe stack. In CPI implementations, the main program stack is set as a safe stack. The other part is the safe pointer store, which stores metadata for sensitive pointers other than return addresses. See [link to relevant documentation]. Figure 2 'a' includes the value of the sensitive pointer, as well as the upper bound and lower bound of the object it points to. Before dereferencing the pointer, the metadata of the sensitive pointer in the safe pointer storage area is used to determine whether the dereferencing is safe (i.e., for code pointers, it is determined whether they have been tampered with, and for data pointers, it is determined whether the target accessed is out of bounds).
[0055] According to one embodiment of the present invention, the present invention modifies the LLVM compiler to use the CET mechanism to replace the security stack and protect the return address in the program from tampering; simultaneously, the page containing the secure pointer storage area is set as a dedicated shadow stack page, that is, the metadata of the sensitive pointer is stored in the dedicated shadow stack page. Taking the x86_64 processor as an example, the metadata (value, upper, lower) of each sensitive pointer is 24 bytes. Directly using the WRSSQ instruction requires writing to the dedicated shadow stack page three times, which increases the performance overhead of isolation. In the prior art, bits 48-63 of the 8-byte address space are not used by the addressing process. Therefore, the present invention utilizes these unused bits to employ a lossless compression method for metadata, minimizing the amount of data written to sensitive memory each time. According to one embodiment of the present invention, see... Figure 2 b. Compress the 24 bytes to 16 bytes. The compressed data structure (or Compress_val structure) is shown below. Figure 2 c. Among them, since the current x86_64 processor can index 2 48In the byte address space, the lower 48 bits of the user-space pointer are valid, while the higher 16 bits are all 0. Therefore, the lower 48 bits (bits 0-47) of the `Compress_val` structure are used to store the value of the sensitive pointer (`Value`), and the remaining bits are mainly used to store the first difference `Offset1` (bits 48-54) and the second difference `Offset2` (bits 55-61). The value of the first difference `Offset1` is equal to the value of the sensitive pointer `Value` minus the lower bound of the object pointed to by the sensitive pointer `Lower`, and the value of the second difference `Offset2` is equal to the upper bound of the object pointed to by the sensitive pointer `upper` minus the value of the sensitive pointer `Value`. In this invention, objects greater than or equal to 128 bytes are called "large objects," and objects less than 128 bytes are called "small objects." The 62nd and 63rd bits of the Compress_val structure are the Extend bits (i.e., extended category indicator bits), used to identify the category of the sensitive pointer corresponding to this metadata: when Extend = 1, it indicates that the sensitive pointer is a code pointer; when Extend = 2, it indicates that the sensitive pointer is a data pointer to a small object (Offset1 and Offset2 can both be encoded with 7 bits); when Extend = 3, it indicates that the sensitive pointer is a data pointer to a large object; when Extend = 0, it indicates that the sensitive pointer has been released.
[0056] According to one embodiment of the present invention, different types of pointers can have different metadata compression strategies, see [link to relevant documentation]. Figure 3 a- Figure 3 d. This section provides an illustrative approach to address space utilization under metadata compression strategies for four different types of pointers. The gray area represents the actual usage area. Specifically, from... Figure 3 As shown in 'a', the code pointer only needs to store the pointer value (only 8 bytes), and only a portion of the bits in the lower 8 bytes of the address are needed. After compression, only one write operation is required using the WRSSQ instruction. Figure 3 In instruction b, the data pointer to the small object stores the pointer's value (Value) and two offsets. Since it's a data pointer to a small object, the maximum value of either the first difference (Offset1) or the second difference (Offset2) only occupies 7 bits. Because the Extend bit only occupies 2 bits, bits 48-61 of the lower 8 bytes are just enough to store the two offsets. Therefore, the data pointer to the small object only needs 8 bytes, and after compression, only one write operation is required using the WRSSQ instruction. Figure 3In C++, data pointers to large objects cannot store two offsets in bits 48 to 61, so an additional 8 bytes are needed to write the offsets. Therefore, the high 8 bytes of the 16-byte instruction are used to store the two offsets (e.g., bits 64-95 store Offset1, bits 96-127 store Offset2). The original 24 bytes can be compressed to 16 bytes. After compression, the WRSSQ instruction is used to perform two write operations. When the pointer is released, only the Extend bit in the low 8 bytes needs to be set to 0. It can be seen that under the above metadata compression strategy, only data pointers to large objects need to be written to 16 bytes; in other cases, only 8 bytes need to be written, minimizing the performance overhead of updating the safe region. When dereferencing a pointer, this invention decompresses the pointer's metadata according to the corresponding compression strategy based on the Extend value, and then uses the original CPI checking logic to check whether the pointer is valid. Before dereferencing the corresponding pointer stored in ordinary memory, the system determines whether the dereferencing is safe based on the metadata of the sensitive pointer whose backup is stored in a dedicated shadow stack page. If not, an exception is thrown and execution stops; if so, the pointer is dereferencing.
[0057] II. Protecting Sensitive Code
[0058] In addition to protecting sensitive data, this invention can also protect the integrity of sensitive code. The following description uses an example of protecting the integrity of sensitive code to illustrate a scenario where write overhead needs to be reduced, and the amount of data to be written is less than a predetermined threshold.
[0059] The performance of the JavaScript engine has a crucial impact on the entire browser, and JIT (Just-In-Time) compilation optimization is designed to improve the performance of the JavaScript engine. For example... Figure 4 As shown, the parser in a JavaScript engine first parses the input JavaScript file into bytecode, which is then interpreted and executed by the interpreter. When the same piece of script code is repeatedly executed within a loop, the efficiency is very low if the interpreter repeatedly executes the related bytecode. The JIT compiler can directly generate machine instructions from the source code, which are then executed directly on the next execution. JIT compilation is only enabled when the target function or loop statement is frequently called. After JIT compilation, the corresponding machine instructions are generated and stored in memory as native code. This memory space storing native code is called the code cache. The next time this statement or function is called, the machine code (machine instructions) will be executed directly. Once JIT generation is complete, the program can directly call the JIT-generated machine code.
[0060] Bytecode is interpreted and executed in a restricted virtual machine environment, while machine code in the code buffer is executed directly by the native processor. Therefore, the JIT compiler limits the ability to issue code buffers; for example, it will not issue potentially dangerous instructions such as system call instructions. Since the JIT compiler needs to write the generated machine code into memory, the most direct method is to set the page containing the machine code as a readable, writable, and executable page, as seen in the JavaScriptCore engine implementation on Intel processors. However, this breaks the W^X strategy, making the code buffer an easy target for attackers. Therefore, some engines use a domain isolation method based on the mprotect() system call to protect the code buffer from being tampered with by attackers. This involves setting the code buffer to readable and writable during issuance, and then setting it to readable and executable after issuance, as seen in the JavaScriptCore engine implementation on ARM processors and Chakra. To reduce the performance overhead of frequent mprotect() system calls, JavaScript engines first store the machine code generated by the JIT compiler in a buffer, and then use the memcpy() memory copy function to copy the machine code from the buffer to the code buffer in one go after generation.
[0061] For sensitive code, this invention can protect it by setting up a dedicated shadow stack page. Instead of storing the sensitive code in ordinary memory, the page storing the sensitive code is simply set as an executable dedicated shadow stack page, thus achieving the protection purpose. According to one embodiment of this invention, the invention utilizes Intel CET technology to protect the code cache area where the sensitive code resides. The NX bit in the page table entry corresponding to the dedicated shadow stack page storing the sensitive code is set to 0, making the page containing the sensitive code a shadow stack page with executable permissions. In Intel CET technology, the shadow stack page is a read-only dirty page, and its page table entry attributes are as follows... Figure 5 As shown: the dirty bit D is set to 1, and the read / write bit R / W is set to 0. Since the NX bit (used to indicate whether the page is non-executable, 0 for executable and 1 for non-executable) and the read / write bit and dirty bit are separate in the page table entry, the NX bit in the page table entry corresponding to the page where the code cache is located can be set to 0, so that the page where the code cache is located is a shadow stack page with executable permissions.
[0062] According to one embodiment of the present invention, taking the Chakra engine as an example, the present invention can be deployed on the Chakra engine. The Chakra engine is a JavaScript engine developed by Microsoft for the Microsoft Edge browser. The Chakra engine compiles scripts on a separate CPU core in just-in-time, running in parallel with the browser. Before and after generating the code buffer, the Chakra engine uses the mprotect() system call to switch the write permissions of the code buffer, preventing it from having both write and execute permissions simultaneously. Since the buffer caches the machine code generated by the JIT compiler, and the page containing it is readable and writable, attackers can indirectly tamper with the code buffer by modifying the buffer in the Chakra engine. To defend against attacks targeting the buffer, the Chakra engine strengthens the protection of the buffer, such as... Figure 4 As shown, when the Chakra engine's JIT compiler compiles each IR into machine code and stores it in the buffer, it calculates the checksum byte by byte for the machine code. After executing the memcpy() operation, it recalculates the checksum byte by byte for the machine code in the code buffer and compares the calculated checksum with the previous checksum. Only if the comparison is successful will the machine code in the code buffer be used; otherwise, an error will be reported.
[0063] According to one embodiment of the present invention, see Figure 6 This invention modifies the Chakra engine's JIT compiler, setting the page containing the code cache (which stores sensitive code) as a dedicated shadow stack page for executable code. It also abandons the Chakra engine's original buffer and verification processes, using the WRSSQ instruction to directly write the compiled machine code into the code cache. However, the code segments generated by the JIT compiler vary in length and are typically short. Since the WRSSQ instruction must write 8 bytes to an 8-byte aligned destination address each time, writing consecutively generated small bytes of data into the code cache requires executing multiple WRSSQ instructions. For example, if the JIT compiler consecutively generates 4 bytes / 2 bytes / 2 bytes of code, sequentially writing it into the code cache requires the following operation (assuming the destination address of the 4-byte code is 0x1000, which is 8-byte aligned):
[0064] ① Read 4 bytes from memory at address 0x1004, concatenate them with the 4 bytes of code to be written, and then use the WRSSQ instruction to write these 8 bytes of content into the code buffer at address 0x1000;
[0065] ② Read 4 bytes and 2 bytes from 0x1000 and 0x1006 respectively, concatenate them with the 2 bytes to be written, and then use the WRSSQ instruction to write these 8 bytes of content into the code buffer at address 0x1000;
[0066] ③ Read 6 bytes from 0x1000 and concatenate them with the 2 bytes to be written. Then use the WRSSQ instruction to write these 8 bytes into the code buffer at address 0x1000.
[0067] The above write operation requires executing 3 WRSSQ instructions. To further improve performance, this invention proposes a register-as-buffer technique. According to an example of this invention, such as... Figure 7 As shown, this invention utilizes a register as a buffer to temporarily store short code snippets in the XMM register (this register can be reserved by CETIS for storing only code snippets). The WRSSQ instruction is used to write the code snippet into the code buffer only when the register content reaches 8 bytes. The first index (index1) points to code not yet committed to the code buffer, and the second index (index2) marks the current writable position, thus achieving ordered commit of code snippets. In this example, using this register-as-buffer technique reduces the number of WRSSQ instruction executions from 3 to 1, significantly decreasing the number of WRSSQ instruction executions and improving CETIS performance. To ensure consistency between the XMM register and memory, a flush operation is performed before reading the code buffer content to synchronize the contents of the XMM register to memory. In addition to using the XMM register as a buffer register, other general-purpose registers, such as %R14 and %R15, can also be used as buffer registers. The technical solution of this embodiment can achieve at least the following beneficial technical effects: Since the present invention does not require calculating the check code, verifying the check code, or performing memcpy operations, it improves the efficiency of protecting the integrity of the code cache area.
[0068] According to an embodiment of the present invention, a method for protecting program security based on the Intel CET mechanism is provided, comprising: obtaining program source code; and compiling the program source code using a compiler to protect the integrity of sensitive data and / or sensitive code according to the method for protecting general memory integrity based on the Intel CET mechanism when the program is executed. Preferably, the step of compiling the program source code using a compiler includes: inserting corresponding protection logic code according to the information of sensitive data and / or sensitive code that need to be protected in the program source code, so that the compiled program, when executed, protects the integrity of sensitive data and / or sensitive code according to the method for protecting general memory integrity based on the Intel CET mechanism through the corresponding protection logic code. Preferably, the information of sensitive data and / or sensitive code that need to be protected can be a pointer or pointer range of specified sensitive data and / or sensitive code, and the compiler inserts corresponding protection logic code into the program according to the pointer or pointer range of sensitive data and / or sensitive code. Alternatively, the program source code may contain protection logic code corresponding to the original protection mechanism, in which case the logic code corresponding to the original protection mechanism records the information of the sensitive data and / or sensitive code that need to be protected. Preferably, the method for protecting program security based on the Intel CET mechanism includes: inserting corresponding protection logic code and deleting the logic code corresponding to the original protection mechanism (such as CPI, CFIXX, etc.) in the program source code to protect sensitive data and / or sensitive code, so that when the compiled program is executed, the integrity of sensitive data and / or sensitive code is protected by the corresponding protection logic code in accordance with the method of protecting general memory integrity based on the Intel CET mechanism.
[0069] It should be noted that although the steps are described in a specific order above, it does not mean that the steps must be executed in the above specific order. In fact, some of these steps can be executed concurrently, or even in a different order, as long as the required function can be achieved.
[0070] This invention can be a system, method, and / or computer program product. A computer program product may include a computer-readable storage medium having computer-readable program instructions loaded thereon for causing a processor to implement various aspects of the invention.
[0071] Computer-readable storage media can be tangible devices that hold and store instructions for use by an instruction execution device. Computer-readable storage media can include, for example, but not limited to, electrical storage devices, magnetic storage devices, optical storage devices, electromagnetic storage devices, semiconductor storage devices, or any suitable combination thereof. More specific examples (a non-exhaustive list) of computer-readable storage media include: portable computer disks, hard disks, random access memory (RAM), read-only memory (ROM), erasable programmable read-only memory (EPROM or flash memory), static random access memory (SRAM), portable compact disc read-only memory (CD-ROM), digital multifunction disc (DVD), memory sticks, floppy disks, mechanical encoding devices, such as punch cards or recessed protrusions storing instructions thereon, and any suitable combination thereof.
[0072] The various embodiments of the present invention have been described above. These descriptions are exemplary and not exhaustive, nor are they limited to the disclosed embodiments. Many modifications and variations will be apparent to those skilled in the art without departing from the scope and spirit of the described embodiments. The terminology used herein is chosen to best explain the principles, practical application, or technical improvements to the embodiments in the market, or to enable others skilled in the art to understand the embodiments disclosed herein.
Claims
1. A method for protecting general memory integrity based on the Intel CET mechanism, characterized in that, include: During program execution, the page containing sensitive data and / or sensitive code that needs protection is set as a dedicated shadow stack page. The dedicated shadow stack page is independent of the shadow stack page maintained by the CET mechanism itself. Before performing write operations on the dedicated shadow stack page, the content to be written that needs to have its write overhead reduced is processed accordingly. The overhead-reduced content to be written is written to a dedicated shadow stack page using the WRSS instruction of the CET mechanism; The integrity of sensitive data and / or sensitive code is protected using the dedicated shadow stack page.
2. The method according to claim 1, characterized in that, The steps for performing overhead reduction processing on the content to be written that requires reduced write overhead include: When the amount of data to be written exceeds a predetermined threshold, lossless compression is performed on the data to be written, which reduces the actual memory size occupied by the data to be written by utilizing multiple bits in the address space that are not used by the addressing process.
3. The method according to claim 2, characterized in that, The content to be written that requires reduced write overhead includes the metadata of sensitive pointers, which includes the value of the sensitive pointer, the upper bound and the lower bound of the object it points to; The steps for lossless compression of the content to be written include: The first difference and the second difference are calculated based on the metadata of the sensitive pointer. The first difference is the value of the sensitive pointer minus the lower bound of the object it points to. The second difference is the upper bound of the object pointed to by the sensitive pointer minus the value of the sensitive pointer. The value of the sensitive pointer, the first difference, and the second difference are stored using multiple bits in the address space that are not used by the addressing process and multiple bits that are used by the addressing process.
4. The method according to claim 3, characterized in that, The step of writing the overhead-reduced content to a dedicated shadow stack page using the WRSS instruction of the CET mechanism includes: Based on the different categories of sensitive pointers, the values of the sensitive pointers, the first difference, and the second difference are written to the specified bits in the dedicated shadow stack page according to the data writing rules corresponding to the category. The corresponding bits in the address space that are not used by the addressing process are used as extended category indicator bits to record the category of the sensitive pointer.
5. The method according to claim 4, characterized in that, The step of protecting the integrity of sensitive data and / or sensitive code using the dedicated shadow stack page further includes: Before dereferencing the corresponding pointer stored in ordinary memory, the safety of the dereferencing is determined based on the metadata of the sensitive pointer whose backup is stored in a dedicated shadow stack page.
6. The method according to any one of claims 1-5, characterized in that, The method further includes: Content that does not require reduced write overhead is directly written to a dedicated shadow stack page using the WRSS instruction of the CET mechanism.
7. The method according to claim 6, characterized in that, The content to be written that does not require reducing write overhead includes a metadata table used to record virtual table pointers; The step of protecting the integrity of sensitive data and / or sensitive code using the dedicated shadow stack page further includes: Before making an indirect call to the target function based on the corresponding virtual table pointer stored in ordinary memory, the virtual table pointer is compared with the virtual table pointer recorded in the metadata table in the dedicated shadow stack page to determine whether the indirect call is safe.
8. The method according to claim 1, characterized in that, The step of performing overhead reduction processing on the content to be written, which requires reduced write overhead, before performing a write operation on the dedicated shadow stack page includes: When the amount of data to be written is less than a predetermined threshold, a reserved register is used to temporarily store the data to be written and wait for other data to be written that is less than the predetermined threshold to be stored. Only when the total amount of data to be written in the reserved register is greater than or equal to the predetermined threshold will the WRSS instruction be used to execute the write operation.
9. The method according to claim 8, characterized in that, The content to be written includes machine code generated by the JIT compiler, and the machine code is sensitive code. The step of performing overhead reduction processing on the content to be written, which requires reduced write overhead, before performing a write operation on the dedicated shadow stack page includes: The corresponding machine code is stored in the reserved registers in the order it is generated, and the WRSS instruction is used to write the data until the total amount of data to be written reaches a predetermined threshold.
10. A method for protecting program security based on the Intel CET mechanism, characterized in that, The method includes: Obtain the program source code; The program source code is compiled using a compiler to protect the integrity of sensitive data and / or sensitive code during program execution in accordance with the method described in any one of claims 1-9.
11. The method for protecting program security based on the Intel CET mechanism according to claim 10, characterized in that, The steps of compiling the program source code using a compiler include: Based on the information of sensitive data and / or sensitive code that needs to be protected in the program source code, corresponding protection logic code is inserted so that when the compiled program is executed, the integrity of the sensitive data and / or sensitive code is protected by the corresponding protection logic code in accordance with the method described in any one of claims 1-9.
12. An electronic device, characterized in that, include: One or more processors; as well as Memory, wherein the memory is used to store executable instructions; The one or more processors are configured to implement the method of any one of claims 1 to 11 by executing the executable instructions.