Method and device for preventing ROP (Return Oriented Programming) attack

By generating and adding PAC to the return address in pipeline-level mode, the PAC function implementation problem in the prior art is solved, software security is improved, and ROP attacks are prevented.

CN120509012AActive Publication Date: 2025-08-19上海芯联芯智能科技有限公司
View PDF 5 Cites 0 Cited by

Patent Information

Application Number
CN202511001138.8
Authority / Receiving Office
CN · China
Patent Type
Applications(China)
Current Assignee / Owner
Filing Date
2025-07-21
Publication Date
2025-08-19
Estimated Expiration
2045-07-21

AI Technical Summary

Technical Problem

When the existing technology introduced the pointer authentication code (PAC) function of ARMv8.3 version, there were problems such as high development costs, compatibility issues, difficult hardware updates, and difficult manufacturer coordination, which made it difficult to effectively prevent ROP attacks.

Method used

By identifying the target instructions and pipeline levels in function calls in pipeline-level mode, generating and adding PAC to the return address, using the instruction bypass unit to obtain the stack pointer and key, generating a return address carrying the PAC to prevent ROP attacks.

Benefits of technology

Without recompiling existing programs, the security of the software is improved, ROP attacks are curbed, and the protection capabilities of the system are enhanced.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN120509012A_ABST
    Figure CN120509012A_ABST
Patent Text Reader

Abstract

The invention discloses a method and device for preventing a return oriented programming ROP attack, and the method comprises the steps: pausing a target assembly line level if a first target instruction and the target assembly line level in function call are recognized when an assembly line level mode is adopted to process an instruction; the first target instruction is a first set instruction for executing a front and back stack pointer to point to a caller stack frame, or a second set instruction for executing the front and back stack pointer to point to a callee stack frame; obtaining a return address, a stack pointer and a key called by a function through an instruction bypass unit, and generating a PAC; adding the PAC to the reserved bit of the return address to obtain the return address carrying the PAC; after execution of the instruction bypass unit is completed, the first target instruction continues to be processed through the target assembly line level. By the adoption of the method, the PAC can be generated through the return address, the stack pointer and the secret key, the PAC is added into the return address, ROP attacks are prevented, and the safety of software is improved.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] The present application relates to the field of computer instruction processing technology, and in particular to a method and device for preventing return-oriented programming (ROP) attacks. Background Art

[0002] With the rapid development of computer technology, software security issues are becoming increasingly serious. In particular, malicious attacks against pointers, such as Return-Oriented Programming (ROP) attacks, pose a serious threat to system security.

[0003] Currently, ARM has introduced the Pointer Authentication Code (PAC) function in the ARMv8.3 version. This function takes advantage of the fact that the 64-bit architecture does not require the use of the full 64-bit address space. It embeds an authentication code in the unused bits to authenticate a pointer, and effectively prevents malicious attacks through the signature and verification mechanism.

[0004] However, the introduction of the PAC function faces many challenges. For example, existing software written in high-level programming languages needs to be recompiled to adapt to the new PAC instruction set, which not only increases development costs but also may cause compatibility issues. Secondly, for assembly language, developers need to manually add PAC-related instructions, a process that increases development difficulty and workload. Thirdly, only newer hardware implements the PAC function, and existing hardware that does not implement the PAC function cannot benefit from it. In addition, the full implementation of the PAC function requires close cooperation among many manufacturers. From hardware manufacturers to software developers, every link needs to be updated and adapted accordingly, which makes coordination difficult and limits the speed of advancement. Summary of the Invention

[0005] The present application provides a method and apparatus for preventing return-oriented programming (ROP) attacks, which are used to prevent ROP attacks by generating a PAC and adding the PAC to a return address.

[0006] In a first aspect, an embodiment of the present application provides a method for preventing ROP attacks, the method comprising: when processing instructions in a pipeline stage mode, if a first target instruction and a target pipeline stage in a function call are identified, pausing the target pipeline stage; the first target instruction is a first setting instruction that causes a stack pointer to point to a caller stack frame before and after execution, or the first target instruction is a second setting instruction that causes a stack pointer to point to a callee stack frame before and after execution; the before and after execution are before and / or after execution; the target pipeline stage is a specified pipeline stage in the pipeline; obtaining a return address, the stack pointer, and a key of the function call through an instruction bypass unit, and generating a PAC based on the return address, the stack pointer, and the key; adding the PAC to a reserved bit of the return address to obtain a return address carrying the PAC; the return address carrying the PAC is used to prevent ROP attacks against the return address; after the instruction bypass unit is executed, continuing to process the first target instruction through the target pipeline stage in the pipeline.

[0007] Using the above method, when the preset first target instruction and target pipeline stage are identified, the return address, stack pointer, and key are obtained, a PAC is generated, and the PAC is added to the reserved bits to obtain a return address carrying the PAC. Because this return address carries the PAC, it cannot be used normally. Therefore, only after the return address is stripped of the PAC and the signature is successfully verified can it be a valid address that can be used normally. In this way, through the pipeline stage bypass method of the instruction, existing programs can be protected by the PAC without recompiling, curbing ROP attacks and improving software security.

[0008] In one possible implementation, continuing to process the instruction through the target pipeline stage in the pipeline includes skipping instruction recognition and continuing to process the first target instruction directly from the target pipeline stage.

[0009] In a possible implementation, after obtaining the return address carrying the PAC, the method further includes: writing the return address carrying the PAC to the top of the stack or to a return address register.

[0010] In one possible implementation, the instruction is identified as the first target instruction in the following manner, including: (1) if a stack that grows from top to bottom is used, then an instruction that satisfies either of the following two conditions is determined to be the first target instruction: (a) the opcode in the instruction is an immediate addition opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is a negative value; (b) the opcode in the instruction is an immediate subtraction opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is a positive value; (2) if a stack that grows from bottom to top is used, then any of the following two conditions is determined to be satisfied. A conditional instruction is a first target instruction: (a) the opcode in the instruction is an immediate addition opcode, the source register is a stack pointer register, the destination register is a stack pointer register, and the immediate value is a positive value; (b) the opcode in the instruction is an immediate subtraction opcode, the source register is a stack pointer register, the destination register is a stack pointer register, and the immediate value is a negative value; the stack that grows from top to bottom is a stack with a bottom at a high address and a top at a low address; the stack that grows from bottom to top is a stack with a bottom at a low address and a top at a high address; the high address is a memory address with a larger address value; and the low address is a memory address with a smaller address value.

[0011] In one possible implementation, the first setting instruction is an instruction that sets the stack pointer to the caller stack frame before execution and to the callee stack frame after execution; the target pipeline stage is any pipeline stage in the pipeline that is not later than the write-back stage; the stage that is not later than the write-back stage includes the write-back stage; obtaining the return address of the function call and the stack pointer through the instruction bypass unit includes: reading the return address from the top of the stack or the return address register; and reading the stack pointer stored in the stack pointer register.

[0012] In one possible implementation, the second setting instruction is an instruction that causes the stack pointer to point to the caller stack frame before execution and to point to the callee stack frame after execution; the target pipeline stage is a write-back stage; and obtaining the return address of the function call and the stack pointer through an instruction bypass unit includes: reading the return address from the top of the stack or the return address register; and obtaining the stack pointer from the input of the target pipeline stage.

[0013] In a possible implementation, after obtaining the return address carrying the PAC, the method further includes: inputting the return address carrying the PAC as an instruction bypass result to the target pipeline stage.

[0014] In one possible implementation, the second setting instruction is an instruction for storing a return address on a stack; the target pipeline stage is any pipeline stage in the pipeline that is later than the decoding stage but not later than the memory access stage; the later than the decoding stage but not later than the memory access stage does not include the decoding stage and includes the memory access stage; Acquiring the return address of the function call and the stack pointer through the instruction bypass unit includes: acquiring the return address from the input of the target pipeline stage; and reading the stack pointer stored in the stack pointer register.

[0015] In one possible implementation, the first setting instruction is a jump instruction for a function call; the target pipeline is a memory access stage or a write-back stage; obtaining the return address of the function call and the stack pointer through an instruction bypass unit includes: obtaining the return address from the input of the target pipeline stage; and reading the stack pointer stored in the stack pointer register.

[0016] In one possible implementation, an instruction is identified as a first target instruction in the following manner, including: (1) if a stack that grows from top to bottom is used, determining an instruction that satisfies the following conditions as the first target instruction: the opcode in the instruction is a memory storage opcode, the source register is a return address register, the memory base register is a stack pointer register, and the offset is a positive value; (2) if a stack that grows from bottom to top is used, determining an instruction that satisfies the following conditions as the first target instruction: the opcode in the instruction is a memory storage opcode, the source register is a return address register, the memory base register is a stack pointer register, and the offset is a negative value; The stack that grows from top to bottom is a stack with the bottom at a high address and the top at a low address; the stack that grows from bottom to top is a stack with the bottom at a low address and the top at a high address; the high address is a memory address with a larger address value; the low address is a memory address with a smaller address value.

[0017] In a second aspect, the present application provides a method for preventing return-oriented programming (ROP) attacks, the method comprising: when processing instructions in a pipeline stage mode, if a second target instruction and a target pipeline stage in a function call are identified, pausing the target pipeline stage; the second target instruction is a third setting instruction that causes a stack pointer to point to a caller's stack frame before and after execution, or the second target instruction is a fourth setting instruction that causes a stack pointer to point to a callee's stack frame before and after execution; the before and after execution are before and / or after execution; the target pipeline stage is a specified pipeline stage in the pipeline; obtaining a return address carrying a PAC, the stack pointer, and a key through an instruction bypass unit, and generating a PAC to be verified based on the return address, the stack pointer, and the key stripped of the PAC; if the PAC is the same as the PAC to be verified, continuing to process the second target instruction through the target pipeline stage in the pipeline; if the PAC is different from the PAC to be verified, triggering an exception, the exception indicating a ROP attack on the return address.

[0018] Using this method, when the preset second target instruction and target pipeline stage are identified, the return address, stack pointer, and key carrying the PAC are retrieved to generate a PAC to be verified. If the PAC to be verified matches the carried PAC, it can be determined that the return address carrying the PAC has not been attacked. In this way, by bypassing the pipeline stage of the instruction, existing programs can be protected by PAC without recompiling, curbing ROP attacks and improving software security.

[0019] In one possible implementation, continuing to process the second target instruction through the target pipeline stage in the pipeline includes skipping instruction recognition and continuing to process the second target instruction directly from the target pipeline stage.

[0020] In a possible implementation, the method further includes: if the PAC is identical to the PAC to be verified, writing a return address of the stripped PAC to a top of a stack or a return address register.

[0021] In one possible implementation, the instruction is identified as the second target instruction in the following manner, including: (1) if a stack that grows from top to bottom is used, then an instruction that satisfies either of the following two conditions is determined to be the second target instruction: (a) the opcode in the instruction is an immediate addition opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is a positive value; (b) the opcode in the instruction is an immediate subtraction opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is a negative value; (2) if a stack that grows from bottom to top is used, then an instruction that satisfies either of the following two conditions is determined to be the second target instruction. A conditional instruction is a second target instruction: (a) the opcode in the instruction is an immediate addition opcode, the source register is a stack pointer register, the destination register is a stack pointer register, and the immediate value is a negative value; (b) the opcode in the instruction is an immediate subtraction opcode, the source register is a stack pointer register, the destination register is a stack pointer register, and the immediate value is a positive value; the stack that grows from top to bottom is a stack with a bottom at a high address and a top at a low address; the stack that grows from bottom to top is a stack with a bottom at a low address and a top at a high address; the high address is a memory address with a larger address value; and the low address is a memory address with a smaller address value.

[0022] In one possible implementation, the third setting instruction is an instruction that sets the stack pointer to the callee stack frame before execution and to the caller stack frame after execution; the target pipeline stage is a write-back stage; obtaining a return address carrying a PAC through an instruction bypass unit, and the stack pointer includes: reading the return address carrying a PAC from the top of the stack or a return address register; and obtaining the stack pointer from the input of the target pipeline stage.

[0023] In one possible implementation, the fourth setting instruction is an instruction that sets the stack pointer to the callee stack frame before execution and to the caller stack frame after execution; the target pipeline stage is any pipeline stage in the pipeline that is not later than the write-back stage; the stage that is not later than the write-back stage includes the write-back stage; obtaining the return address carrying the PAC and the stack pointer through the instruction bypass unit includes: reading the return address carrying the PAC from the top of the stack or the return address register; and reading the stack pointer stored in the stack pointer register.

[0024] In a possible implementation, the method further includes: if the PAC is identical to the PAC to be verified, inputting the return address of the PAC stripped as an instruction bypass result to the target pipeline stage.

[0025] In one possible implementation, the fourth setting instruction is an instruction for loading a return address stored on a stack; the target pipeline stage is a write-back stage; obtaining the return address carrying the PAC and the stack pointer through an instruction bypass unit includes: obtaining the return address carrying the PAC from an input of the target pipeline stage; and reading the stack pointer stored in a stack pointer register.

[0026] In one possible implementation, the third setting instruction is a jump instruction for function return; the target pipeline stage is any pipeline stage in the pipeline that is later than the decoding stage but not later than the write-back stage; the later than the decoding stage but not later than the write-back stage does not include the decoding stage and includes the write-back stage; obtaining the return address carrying the PAC and the stack pointer through the instruction bypass unit includes: obtaining the return address carrying the PAC from the input of the target pipeline stage; and reading the stack pointer stored in the stack pointer register.

[0027] In one possible implementation, an instruction is identified as a second target instruction in the following manner, including: (1) if a stack that grows from top to bottom is used, an instruction that satisfies the following conditions is determined to be the second target instruction: the opcode in the instruction is a memory load opcode, the target register is a return address register, the memory base register is a stack pointer register, and the offset is a positive value; (2) if a stack that grows from bottom to top is used, an instruction that satisfies the following conditions is determined to be the second target instruction: the opcode in the instruction is a memory load opcode, the target register is a return address register, the memory base register is a stack pointer register, and the offset is a negative value; the stack that grows from top to bottom is a stack with a bottom at a high address and a top at a low address; the stack that grows from bottom to top is a stack with a bottom at a low address and a top at a high address; the high address is a memory address with a larger address value; and the low address is a memory address with a smaller address value.

[0028] In a third aspect, the present application provides a device for preventing return-oriented programming (ROP) attacks, the device comprising a memory for storing computer programs or instructions; and a processor for calling the computer programs or instructions stored in the memory to execute a method as in any possible implementation of the first and second aspects. BRIEF DESCRIPTION OF THE DRAWINGS

[0029] In order to more clearly illustrate the technical solutions in the embodiments of the present application, the following briefly introduces the drawings required for use in the description of the embodiments. Obviously, the drawings described below are only some embodiments of the present application. For ordinary technicians in this field, other drawings can be obtained based on these drawings without paying any creative labor.

[0030] Figure 1 A flowchart of a method for preventing ROP attacks provided in an embodiment of the present application; Figure 2 A flowchart of a method for preventing ROP attacks provided in an embodiment of the present application; Figure 3 A schematic diagram of a PAC signature and verification process provided in an embodiment of the present application; Figure 4 A schematic diagram of another PAC signing and verification process provided in an embodiment of the present application; Figure 5 A schematic diagram of another PAC signing and verification process provided in an embodiment of the present application; Figure 6 A schematic diagram of the structure of a device 6000 for preventing ROP attacks provided in an embodiment of the present application. DETAILED DESCRIPTION

[0031] To make the objectives, technical solutions, and advantages of this application more clear, this application will be further described in detail below with reference to the accompanying drawings. Obviously, the embodiments described are only some of the embodiments of this application, not all of them. Based on the embodiments in this application, all other embodiments obtained by ordinary technicians in this field without making any creative efforts are within the scope of protection of this application.

[0032] The present application provides a method for preventing ROP attacks, which is used to prevent ROP attacks by generating a PAC and adding the PAC to the return address, thereby improving the security of the software.

[0033] To facilitate understanding, some terms involved in this application are first explained.

[0034] The stack is an area in virtual memory used to store function states and local or temporary variables within a function during a function call. The stack is a last-in, first-out system, and the address at the top of the stack is called the stack pointer. Generally speaking, a stack grows from top to bottom. In other words, the address at the bottom of the stack is larger than the address at the top of the stack (i.e., the stack pointer). When the stack grows from top to bottom, the address at the bottom of the stack is the starting address of the stack, and the address at the top of the frame is the stack pointer. Whenever a new element needs to be pushed onto the stack, it is always pushed at the top of the stack, causing the stack pointer to point to a lower address. The stack in this application can also grow from bottom to top, and this application does not limit the stack growth method.

[0035] Stack frame: During a function call, a new stack frame is generated for each function call, and the current stack frame is released each time the function returns. Therefore, a stack frame is a stack area associated with a particular function call. For a given function, the stack frame size required is fixed. For the same function, when it is called multiple times, the stack frames occupied may not be located at the same address. If a function appears multiple times in a call chain at a given moment, it will occupy different stack frames each time it is called. For example, consider functions A, B, and C, and the following call chain: A -> B -> C -> B -> B -> C. Assuming the stack grows from top to bottom, the stack frames from top to bottom are: the stack frame for function A, the stack frame for the first call to function B, the stack frame for the first call to function C, the stack frame for the second call to function B, the stack frame for the third call to function B, and the stack frame for the second call to function C. Somewhere in the stack frame is stored the address to which the current function will return after execution completes.

[0036] Stack Pointer and Stack Pointer Register: The stack pointer indicates the address of the top of the stack, equivalent to the address of the top of the current stack frame. The stack pointer register is a register that stores the stack pointer. Reading the stack pointer register tells you the current address of the top of the stack; writing to the stack pointer register updates the address of the top of the stack after pushing or popping data from the stack. In particular, the stack pointer value changes with function calls, as stack frames are created and released during the call. Some instruction set architectures (ISAs), such as instruction set architectures (ISAs), automatically manage the stack pointer register. Specifically, dedicated instructions are provided to move the stack pointer with each push or pop of data. Other ISAs manage the stack pointer register manually, requiring additional instructions to update the stack pointer register before or after pushing or popping data. In these cases, the stack pointer register is typically updated after or before a batch of data is pushed or popped, rather than after each push or pop.

[0037] ROP: A crucial attack technique in computer security, it exploits existing code snippets within a program and cleverly combines them to achieve desired functionality. Attackers can construct ROP chains to execute arbitrary code, such as opening backdoors and stealing data. ROP can also bypass security mechanisms, such as writable XOR executables and stack non-executables.

[0038] PAC: Leveraging the fact that the 64-bit architecture doesn't require the full 64-bit address space, it embeds an authentication code in unused bits to authenticate a pointer and verify the validity of the authentication before using the pointer. This prevents certain malicious attacks and improves software security. PAC calculations use a specific algorithm that accepts three input parameters: a pointer (here, the original pointer before the PAC is embedded), a context, and a key. It produces a single output: the PAC, or Pointer Authentication Code.

[0039] The PAC is calculated using the algorithm described above and embedded into the corresponding pointer. A pointer containing a PAC cannot be used directly, so new instructions are provided to verify the PAC and recover the pointer. Since the algorithm is reproducible, one only needs to strip the PAC from the pointer containing the PAC, then use the algorithm again to calculate the PAC based on the PAC-stripped pointer, the context, and the key. The two PACs can then be compared for equality. If they are equal, the PAC verification passes, and the pointer is modified to the PAC-stripped form, making it valid for subsequent use. If they are not equal, the PAC verification fails, and the pointer remains invalid. Alternatively, if it was not already in an invalid form, such as a pointer without a PAC, this step will convert it to an invalid form, causing an exception when it is subsequently used.

[0040] Figure 1 The flowchart of a method for preventing ROP attacks provided in an embodiment of the present application can be executed by a CPU that processes instructions in pipeline mode. The method is used to add PAC to the reserved bit of the return address to obtain a return address carrying PAC, such as Figure 1 As shown, the process includes the following steps: Step 101 : When the CPU processes instructions in a pipeline stage mode, if it recognizes the first target instruction and the target pipeline stage in a function call, it pauses the target pipeline stage.

[0041] In step 102, the CPU obtains the return address, stack pointer, and key of the function call through the instruction bypass unit, generates a PAC based on the return address, stack pointer, and key, and adds the PAC to the reserved bits of the return address to obtain a return address carrying the PAC.

[0042] Step 103 : After the instruction bypass unit completes execution, the CPU continues to process the first target instruction through the target pipeline stage in the pipeline.

[0043] Specifically, the first target instruction is a first setting instruction that causes the stack pointer to point to the caller's stack frame before and after execution, or the first target instruction is a second setting instruction that causes the stack pointer to point to the callee's stack frame before and after execution, before and after execution is before and / or after execution, and the target pipeline stage is a specified pipeline stage in the pipeline. After identifying the first target instruction and the target pipeline stage, the instruction bypass unit obtains the return address, stack pointer, and key of the function call, generates a PAC based on the return address, stack pointer, and key, and adds the PAC to the reserved bit of the return address to obtain a return address carrying the PAC. The return address carrying the PAC is used to prevent ROP attacks on the return address. After the instruction bypass unit is executed, the first target instruction continues to be processed through the target pipeline stage in the pipeline.

[0044] In the embodiments of the present application, the return address of a function call is the pointer in the PAC algorithm. For the Class A instruction set architecture (ISA), which is generally a Complex Instruction Set Computer (CISC) architecture, the jump instruction used for function calls inserts the return address at the top of the stack. In this case, the data stored at the top of the stack is the return address. There are also jump instructions for function returns that directly read the return address from the top of the stack and jump to it, which is also known as a function return. In the Class A ISA, there is no return address register as described below. The jump instruction used for function calls also updates the stack pointer register (i.e., the stack pointer points to the caller's stack frame before execution and to the callee's stack frame after execution) and is also used to load the return address stored on the stack. The jump instruction used for function returns also updates the stack pointer register (i.e., the stack pointer points to the callee's stack frame before execution and to the caller's stack frame after execution) and is also used to load the return address stored on the stack. In the following text, these instructions are described separately, but in the Class A instruction set architecture, the instruction bypass behaviors of the jump instructions used for function calls, instructions for updating the stack pointer register (that is, instructions with the front stack pointer pointing to the caller's stack frame and the back stack pointer pointing to the callee's stack frame; or instructions with the front stack pointer pointing to the callee's stack frame and the back stack pointer pointing to the caller's stack frame), and instructions for loading the return address stored on the stack (or instructions for loading the return address stored on the stack) should be understood together. Similarly, the instruction bypass behaviors of the jump instructions used for function returns and instructions that also update the stack pointer register should be understood together.

[0045] In the B-class instruction set architecture (ISA), typically a reduced instruction set computer (RISC) architecture, function call instructions write the return address to a specific register, called the return address register. The data stored in this register is the return address. The prologue of a non-leaf function contains an instruction that copies the data in this register to the top of the stack. The data stored on the top of the stack is the return address. The epilogue of a non-leaf function contains an instruction that restores the return address from the top of the stack to a specific register. The data stored in this register is then used as the return address. Subsequently, an instruction uses this register to jump, representing the function return. While restoring the return address to another register is possible, the calling convention generally requires that the return address be restored to the return address register in the function epilogue. The jump instruction used for function calls in the B-class ISA does not update the stack pointer register; similarly, the jump instruction used for function returns in the B-class ISA does not update the stack pointer register.

[0046] In an embodiment of the present application, different types of pointers are allowed to use different keys to enhance security. For the same type of pointer, multiple different keys are available for selection. At the same time, user mode cannot access the value of the key to ensure security. Only kernel mode and higher privileged modes can access the currently effective key through special instructions. A control register can be defined to store the currently effective key, which allows the key to be accessed and modified by kernel space. Generally speaking, the kernel randomly generates a new key when starting a new program and backs up / restores it during context switching. Randomly generated keys can prevent replay attacks.

[0047] The instruction bypass unit generates different keys for different Address Space Identifiers (ASIDs). Generally, when the kernel switches processes, it simultaneously manipulates the CPU's control registers, thereby modifying the current ASID. Therefore, generating different keys for different ASIDs can achieve key isolation between processes. However, the range of ASID values is limited. In typical practice, the maximum is only 1024 or several thousand. In many use cases, the number of running processes does not exceed the ASID range, and key isolation between processes is sufficient. However, when the number of running processes exceeds the ASID range, some processes are forced to share ASIDs, resulting in insufficient key isolation between processes. Therefore, to enhance security in such situations and implement sufficient key isolation, the next implementation is provided.

[0048] A pair of instructions are designed and added to the matching list. These instructions were previously undefined or reserved. Because they were previously undefined or reserved, existing programs will not have these instructions. Executing these instructions causes a bypass. The instruction bypass unit first verifies the CPU's privileged state. If it is in user mode, an exception is raised and the program does not proceed. If it is in kernel mode or a higher privileged state, the program continues. The instructions are then parsed. One instruction reads the currently configured key and writes it to the register or memory address specified by the instruction. The other instruction reads the key from the register or memory address specified by the instruction and sets it as the current key. Thus, when switching processes, the kernel can use the first instruction to back up the previous process's key and then use the second instruction to configure the key for the next process to be executed. If a process is starting for the first time, the kernel generates a unique key using some method and configures it using the second instruction.

[0049] For PAC, the following restriction can optionally be implemented: all binary bits cannot be all 1s or all 0s. In other words, the PAC algorithm is restricted from outputting all 1s or all 0s. This ensures that a pointer with PAC, unless verified by the PAC, will always be considered an illegal address by the Memory Management Unit (MMU), making it impossible to use it directly or causing an exception if used.

[0050] It's also worth noting that many programming languages have the concept of function calls. Every function call involves a caller and a callee, and the passing of parameters and return values requires a common convention to specify how these parameters are passed. This is the calling convention. The calling convention creates function prologues and epilogues. The prologue is the sequence of instructions at the beginning of a function, while the epilogue is the sequence of instructions at the end. Based on the above explanations, the stack pointer value changes during a function call. However, as long as the program executes normally, the stack pointer value is guaranteed to be the same when entering a function (i.e., the prologue) and returning from the function (i.e., the epilogue) at the end of the function call.

[0051] Taking MIPS64 as an example, MIPS is a type of instruction set B. Taking MIPS64 and the stack growing from top to bottom as an example, a typical function prologue and function epilogue are described in assembly language as follows, where the lines starting with / / are explanations of the instructions: / / Register 31 contains the return address, which is written by the caller of the function when calling the function.

[0052] / / Prolog

[0053] / / Update the stack pointer register ( sp), subtract the stack frame size (FRAME_SIZE) from its value, that is, push the top of the stack down.

[0054] / / Among them, the stack frame size must be large enough to accommodate the registers to be backed up, and also large enough to accommodate the local variables used by the function, which will not be repeated here.

[0055] daddiu sp, sp,-FRAME_SIZE

[0056] / / Will 31 The return address stored in the register is pushed to the bottom of the current stack frame

[0057] sd 31,FRAME_SIZE-8( sp)

[0058] / / There may be other instructions for backing up other registers, which are omitted here.

[0059] <...Function body...>

[0060] / / Epilogue epilog

[0061] / / Pop the return address from the bottom of the current stack frame to 31 registers.

[0062] / / ld rt,offset( base) will be added from offset( base) (inclusive) until offset+8( base) (excluding) is stored in the register rt in.

[0063] ld 31,FRAME_SIZE-8( sp)

[0064] / / Update the stack pointer register ( sp), add its value to the stack frame size (FRAME_SIZE), that is, push the top of the stack back to its original position, / / In fact, it restores the value of the stack pointer register.

[0065] daddiu sp, sp,FRAME_SIZE

[0066] / / Jump to 31 Execution continues at the address stored in the register.

[0067] jr 31

[0068] nop

[0069] The above code shows that the stack pointer register has the same value at the following times: before the first daddiu instruction (i.e., before the function prologue) and after the second daddiu instruction. At this time, the stack pointer register has the old value, pointing to the top of the caller's stack frame. Between the first daddiu instruction and the second daddiu instruction (i.e., between these two instructions), the stack pointer register has the new value, pointing to the top of the stack frame of the current function (i.e., the callee).

[0070] Therefore, when signing the PAC, there are two situations: determining the context corresponding to the stack pointer according to the old value of the stack pointer register and determining the context corresponding to the stack pointer according to the new value of the stack pointer register.

[0071] (1) Determine the context corresponding to the stack pointer based on the old value of the stack pointer register

[0072] There are two appropriate times to use the old value of the stack pointer register to determine the context corresponding to the stack pointer. The first appropriate time is the first daddiu instruction in the above code. This daddiu instruction is used to update the stack pointer register by subtracting the callee's stack frame size from its value. Before the execution of this instruction, the stack pointer points to the top of the caller's stack frame (equivalent to the old value in the stack pointer register). After the execution of this instruction, the stack pointer points to the top of the callee's stack frame (equivalent to the new value in the stack pointer register). The second appropriate time is not reflected in the above assembly code, because MIPS has a series of instructions such as jal / jalr / bal specifically for function calls. These instructions write the return address to the function at the same time as the jump. 31 register (i.e. the return address register of the MIPS architecture), so instructions such as jal / jalr / bal are the second appropriate opportunity. Both instructions are first-target instructions.

[0073] For the first appropriate opportunity, the first setting instruction is an instruction that sets the stack pointer to the caller stack frame before execution (equivalent to the value in the stack pointer register being the old value) and the stack pointer to the callee stack frame after execution (equivalent to the value in the stack pointer register being the new value). The target pipeline stage is any pipeline stage in the pipeline that is not later than the write-back stage. Not later than the write-back stage means that the write-back stage may be included. The return address and stack pointer of the function call are obtained through the instruction bypass unit, including reading the return address from the top of the stack or the return address register, and reading the stack pointer stored in the stack pointer register.

[0074] Specifically, the first setting instruction is the first daddiu instruction in the above code. When the first setting instruction is recognized, the instruction bypass unit has the following pipeline stage bypass mode.

[0075] (1) The first pipeline stage bypass method at the right time

[0076] For pipeline stage bypass, the bypassed pipeline stage must be any pipeline stage no later than the write-back stage, which is the stage that writes to the register. Otherwise, only the The new value of the sp register is obtained. It is also possible to bypass the write-back stage because before the write-back stage is completed, The sp register still has the old value, and the instruction bypass unit only completes the The PAC signature of the return address on register 31 is obtained at this time The value of the sp register is still the old value, use it and rewrite 31 register, set the bypassed pipeline stage as the current pipeline stage, set the instruction bypass result as the input of the current pipeline stage, that is, keep the input of the current pipeline stage unchanged, so that this daddiu instruction skips an instruction match, so that the instruction is executed normally, and finally completes the normal execution. Rewriting of sp register.

[0077] Specifically, one or more pipeline stages are matched, no later than the write-back stage, as the pipeline stages that need to be bypassed in the matching entries. This ensures that the stack pointer register value has not been updated and can still retrieve the old value. The stack pointer register value is read as context. For class A instruction set architectures, the return address is read from the top of the stack; for class B instruction set architectures, the return address is read from the return address register. Combined with the current key, the PAC signature is completed to generate the PAC. The PAC is embedded in the reserved bits of the return address. Then, for class A instruction set architectures, the return address with the PAC is written to the top of the stack; for class B instruction set architectures, the return address with the PAC is written to the return address register.

[0078] In one possible implementation, if a stack that grows from top to bottom is used, the instruction is identified as the first target instruction in the following manner, including: if the opcode in the instruction is an immediate addition opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is a negative value, then the instruction is the first target instruction; or if the opcode in the instruction is an immediate subtraction opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is a positive value, then the instruction is the first target instruction.

[0079] Because instructions with the same purpose have different names in different instruction set architectures, this application does not limit the specific names of opcodes. This application embodiment uses the MIPS64 instruction set architecture, and takes the stack growing from top to bottom and the opcode being an immediate addition opcode as an example. Therefore, in the MIPS64 instruction set architecture, the opcode in the instruction is DADDIU (an immediate addition opcode), and the immediate value is a negative value.

[0080] Specifically, since the daddiu instruction itself can also be used for ordinary calculation purposes, this use is not what we want to match. We only want to match its The sp register (stack pointer register) is decremented. Therefore, when using mask matching, the matching opcode is DADDIU and the matching source register domain is sp, matching destination register domain is However, the immediate value cannot be matched because the value filled there is the stack frame size, which is different for different functions. The matching items are shown in Table 1: Table 1

[0081] Here, 1 indicates that the bit is 1, 0 indicates that the bit is 0, and x indicates that the bit can have any value. As can be seen from Table 1, bits masked as 1 participate in the match, while bits masked as 0 do not. This also applies to the subsequent tables and will not be repeated here.

[0082] Since in the function's prologue, either no stack frame is allocated, or once a stack frame is allocated, the top of the stack must be pushed down (since this example uses a top-down growing stack), when we need to further subdivide the match, we hope to only match the case where the top of the stack is pushed down, that is, When sp is decremented, the immediate value must be filled with a negative number. Note that according to the instruction definition of daddiu, the immediate value filled in is actually a signed number. That is, its highest bit can be used to determine the sign of the immediate value. When it is 1, the immediate value must be negative, otherwise it must be non-negative. Examples of matching items are shown in Table 2:

[0083] Table 2

[0084] In one possible implementation, if the AArch64 (also called ARM64 or Arm A64) instruction set architecture is used, and the stack grows from top to bottom, and the opcode is an immediate subtraction opcode, then the opcode in the instruction is SUB (and it is an immediate subtraction opcode), and the immediate value is a positive value. For example, if the matching item in this example is described in AArch64 assembly language, it is SUB SP, SP, # ; Among them, SUB indicates that the matching opcode is an immediate subtraction opcode, SP is the stack pointer register of AArch64, the first SP indicates that the matching destination register is the stack pointer register, and the second SP indicates that the matching source register is the stack pointer register, # Indicates matching of positive immediate values.

[0085] In one possible implementation, if a stack that grows from bottom to top is used, an instruction that satisfies either of the following two conditions is determined to be the first target instruction: (a) The instruction's opcode is an immediate addition opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is positive; (b) The instruction's opcode is an immediate subtraction opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is negative. A stack that grows from bottom to top is one with the bottom at a lower address and the top at a higher address. The higher address is the memory address with the larger address value, while the lower address is the memory address with the smaller address value. The specific matching method is not detailed here.

[0086] For the second appropriate opportunity, the first setting instruction is a jump instruction for a function call, the target pipeline is a memory access level or a write-back level, and the return address and stack pointer of the function call are obtained through the instruction bypass unit, including obtaining the return address from the input of the target pipeline level and reading the stack pointer stored in the stack pointer register.

[0087] The jump instruction used for function call, the behavior of the instruction itself can be described as: writing the return address to the top of the stack (for class A instruction set architecture) or writing it to the return address register (for class B instruction set architecture), and then jumping to the target address.

[0088] Specifically, the first setting instruction may be an instruction such as jal / jalr / bal. When the first setting instruction is recognized, the instruction bypass unit has the following pipeline stage bypass mode.

[0089] (2) The second pipeline stage bypass method at the right time

[0090] For pipeline stage bypass, the instruction bypass unit obtains the input of the target pipeline stage and completes the PAC signature. The value of the sp register is still the old value, so it is used, and the signed return address is used as the bypass result, setting the bypassed pipeline stage to the current pipeline stage. This causes the jump instruction used for the function call to temporarily skip an instruction match, allowing the instruction to enter the current pipeline stage. However, at this time, the input of the current pipeline stage has been rewritten with the return address with the PAC signature. This causes the return address with the PAC to be written to the top of the stack for the A-type instruction set architecture, or to the return address register for the B-type instruction set architecture.

[0091] Specifically, for class A instruction set architectures, the memory access stage (the stage that performs memory access) is matched. For class B instruction set architectures, the writeback stage (the stage that writes to registers) is matched as the pipeline stage to be bypassed. This allows the return address to be directly obtained from the pipeline stage input. The value of the stack pointer register is read as context, and the return address is obtained from the input of the current pipeline stage. This is combined with the current key to complete the PAC signature and generate the PAC. The PAC is embedded in the return address, and the return address with the PAC is used as the instruction bypass result.

[0092] When using a mask to match such instructions, you only need to match the opcode, because such instructions will always write the return address to 31, regardless of the values in the other fields. The opcodes for these instructions vary; some use a single opcode, while others use multiple. You should match enough opcode levels until you can determine the instruction type. Details are not provided here.

[0093] (2) Determine the context corresponding to the stack pointer based on the new value of the stack pointer register

[0094] There are two appropriate times to use the new value of the stack pointer register to determine the context corresponding to the stack pointer. The first appropriate time is the first daddiu instruction in the above code. The daddiu instruction is used to update the stack pointer register and subtract the callee's stack frame size from its value. Before the instruction is executed, the stack pointer points to the top of the caller's stack frame (equivalent to the value in the stack pointer register being the old value). After the instruction is executed, the stack pointer points to the top of the callee's stack frame (equivalent to the value in the stack pointer register being the new value). The second appropriate time is the sd instruction in the above assembly code, which is used to The value of register 31 is backed up to the stack. These two instructions are the first target instructions.

[0095] For the first appropriate timing, the second setting instruction is an instruction that sets the stack pointer to the caller's stack frame before execution (equivalent to the value in the stack pointer register being the old value) and the stack pointer to the callee's stack frame after execution (equivalent to the value in the stack pointer register being the new value). The target pipeline stage is the write-back stage, and the return address and stack pointer of the function call are obtained through the instruction bypass unit, including reading the return address from the top of the stack or the return address register, and obtaining the stack pointer from the input of the target pipeline stage.

[0096] Specifically, the second setting instruction is the first daddiu instruction in the above code. When the second setting instruction is recognized, the instruction bypass unit has the following pipeline stage bypass mode.

[0097] (1) The first pipeline stage bypass method at the right time

[0098] For pipeline stage bypass, you can choose to bypass the write-back stage, which is the stage that writes to the register. The instruction bypass unit only completes the The PAC signature of the return address on register 31, the input of the write-back stage is The new value of the sp register is used and overwritten Register 31 sets the bypassed pipeline stage as the current pipeline stage. This allows this instruction to temporarily skip an instruction match, allowing the instruction to be executed normally, and finally completes the normal execution. Rewriting of sp register.

[0099] Specifically, for the A-class instruction set architecture, the return address is read from the top of the stack; for the B-class instruction set architecture, the return address is read from the return address register. Combined with the current key, the PAC signature is completed to generate the PAC. The PAC is embedded in the reserved bits of the return address. Then, for the A-class instruction set architecture, the return address with the PAC is written to the top of the stack; for the B-class instruction set architecture, the return address with the PAC is written to the return address register.

[0100] How to match the first daddiu instruction has been described above and will not be repeated here.

[0101] For the second suitable opportunity, the second setting instruction is an instruction for storing a return address on a stack, specifically an instruction for backing up a return address stored in a return address register on the stack. The target pipeline stage is any pipeline stage in the pipeline that is later than the decode stage but not later than the memory access stage, excluding the decode stage but including the memory access stage. Obtaining the return address and stack pointer of the function call through the instruction bypass unit includes: obtaining the return address from an input of the target pipeline stage and reading the stack pointer stored in the stack pointer register.

[0102] Specifically, the second setting instruction may be the sd instruction in the above assembly code. When the second setting instruction is identified, the instruction bypass unit has the following pipeline stage bypass mode.

[0103] (2) The second pipeline stage bypass method at the right time

[0104] For pipeline stage bypass, the next stage of the bypass decoding stage, to be precise, is the next stage of the pipeline stage that takes out the register value. After the instruction bypass unit obtains the input of the pipeline stage, that is, The value in register 31, that is, the return address, reads the value of the stack pointer register as the context, combines it with the current key, completes the PAC signature to generate the PAC, and embeds the PAC into the return address. The value of the sp register is already the new value, which is used, and the signed return address is used as the bypass result. The pipeline stage after bypass is set as the current pipeline stage, so that this instruction temporarily skips an instruction match, so that the instruction can enter the current pipeline stage. However, at this time, the input of the current pipeline stage has been rewritten as the return address with PAC after the PAC signature. In this way, the return address with PAC can be written to the specified location on the stack by the current pipeline stage or the subsequent pipeline stage.

[0105] It is also possible to bypass the memory access level, that is, the level for memory access. After the instruction bypass unit obtains the input of the pipeline level, that is, the return address to be written to the memory, it reads the value of the stack pointer register as the context, combines it with the current key, completes the PAC signature to generate the PAC, and embeds the PAC into the return address. The value of the sp register is already the new value, which is used, and the signed return address is used as the bypass result. The pipeline stage after bypass is set as the current pipeline stage, so that this instruction temporarily skips an instruction match, so that the instruction can enter the current pipeline stage. However, at this time, the input of the current pipeline stage has been rewritten as the return address with PAC after the PAC signature. In this way, the return address with PAC can be written to the specified location on the stack by the current pipeline stage, that is, the memory access stage.

[0106] If a top-down stack is used, an instruction is identified as the first target instruction by the following method: the instruction's opcode is a memory store opcode, the source register is the return address register, the memory base register is the stack pointer register, and the offset is a positive value. A top-down stack is one in which the bottom of the stack is at a high address and the top of the stack is at a low address, where the high address is the memory address with the larger address value, and the low address is the memory address with the smaller address value.

[0107] Specifically, since instructions with the same purpose may have different names in different instruction set architectures, this application does not limit the specific names of opcodes. This application embodiment uses the MIPS64 instruction set architecture, and takes the stack as an example, where it grows from top to bottom. Therefore, in the MIPS64 instruction set architecture, the opcode in the instruction is SD (a memory storage opcode), and the offset is a positive value.

[0108] Specifically, when using mask matching for this type of instruction, the sd instruction is a memory access instruction that uses a base register plus an immediate offset for addressing. It reads the data stored in the source register and writes it to the memory address determined by the addressing mode. If data is to be written to the stack, the base register should be sp. In this case, the matching item must match both the instruction as sd and the source register used by the instruction as 31, and also match the base register used by the instruction sp. Examples of matching items are shown in Table 3: Table 3

[0109] Furthermore, considering that when accessing data in the stack, the data should be located in the stack rather than outside the stack, and the memory address range occupied by the stack can be expressed from the bottom of the stack to the top of the stack, and considering The address stored in the sp register points to the top of the stack. Since this example uses a top-down stack, the target address of a legal memory access to the stack must be higher than the top of the stack. When sp is used as the base register, the offset must be a positive integer to place the target memory address on the stack rather than outside it. Since the offset in the above instruction is a signed integer, to make this offset a positive integer, its highest bit must be 0. Therefore, a preferred match is shown in Table 4: Table 4

[0110] In one possible implementation, if a bottom-up stack is used, the instruction is identified as the first target instruction in the following manner: the opcode in the instruction is a memory store opcode, the source register is the return address register, the memory base register is the stack pointer register, and the offset is a negative value. A bottom-up stack is one where the bottom is at a low address and the top is at a high address; the high address is the memory address with the larger address value, and the low address is the memory address with the smaller address value. Specifically, taking the MIPS64 instruction set architecture and the bottom-up stack as an example, the opcode in the instruction is SD (a memory store opcode) and the offset is a negative value. The matching example is similar to Table 4, except that the binary number in bit 15, which represents the sign of the immediate value, is 0.

[0111] Figure 2 This is a flowchart of a method for preventing ROP attacks provided by an embodiment of the present application. This flowchart can be executed by a CPU that processes instructions in pipeline mode. The method is used to determine whether the PAC to be verified is the same as the PAC carried by the return address. Figure 2 As shown, the process includes the following steps: Step 201 : When the CPU processes instructions in a pipeline stage mode, if it recognizes a second target instruction and a target pipeline stage in a function call, it pauses the target pipeline stage.

[0112] In step 202, the CPU obtains the return address, stack pointer, and key carrying the PAC through the instruction bypass unit, and generates a PAC to be verified based on the return address, stack pointer, and key stripped from the PAC.

[0113] Step 203: If the PAC is the same as the PAC to be verified, continue processing the second target instruction through the target pipeline stage in the pipeline; if the PAC is different from the PAC to be verified, trigger an exception.

[0114] Specifically, the second target instruction is a third setting instruction that causes the stack pointer to point to the caller's stack frame before and after execution, or the second target instruction is a fourth setting instruction that causes the stack pointer to point to the callee's stack frame before and after execution. Before and after execution refers to before and / or after execution, and the target pipeline stage is a specified pipeline stage in the pipeline. After identifying the second target instruction and the target pipeline stage, the instruction bypass unit obtains the return address, stack pointer, and key carrying the PAC, and generates a PAC to be verified based on the return address, stack pointer, and key stripped of the PAC. If the PAC is the same as the PAC to be verified, the second target instruction continues to be processed through the target pipeline stage in the pipeline; if the PAC is different from the PAC to be verified, an exception is triggered, and the exception indicates a ROP attack on the return address.

[0115] When verifying the PAC signature, there are two situations: determining the context corresponding to the stack pointer according to the old value of the stack pointer register and determining the context corresponding to the stack pointer according to the new value of the stack pointer register.

[0116] (1) Determine the context corresponding to the stack pointer based on the old value of the stack pointer register

[0117] There are two suitable occasions to use the old value of the stack pointer register to determine the context corresponding to the stack pointer. The first suitable occasion is the second daddiu instruction in the above code, which is the instruction used to restore the stack pointer register. Simply use the restored stack pointer register value as the context to perform signature verification in the bypass and modify it accordingly. The second suitable time is the jr instruction mentioned above, which is the actual use of 31 register, at this time, it is only necessary to use the restored stack pointer register value as the context in the bypass to perform signature verification and modify the jump target address accordingly.

[0118] For the first appropriate timing, the third setting instruction is an instruction that sets the stack pointer to the callee stack frame before execution (equivalent to the value in the stack pointer register being the new value) and points to the caller stack frame after execution (equivalent to the value in the stack pointer register being the old value), the target pipeline stage is the write-back stage, and obtaining the return address and stack pointer carrying the PAC through the instruction bypass unit includes: reading the return address carrying the PAC from the top of the stack or the return address register; and obtaining the stack pointer from the input of the target pipeline stage.

[0119] Specifically, the third setting instruction is the second daddiu instruction in the above code. When the third setting instruction is recognized, the instruction bypass unit has the following pipeline stage bypass mode.

[0120] (1) The first pipeline stage bypass method at the right time

[0121] For pipeline stage bypass, you can choose to bypass the write-back stage, that is, the stage that writes to the register. The instruction bypass unit only completes the 31 The PAC signature of the return address on the register, at this time the input of the write-back stage is The old value of the sp register after restoration is used and overwritten Register 31, set the bypassed pipeline stage as the current pipeline stage, that is, the write-back stage, set the instruction bypass result as the input of the current pipeline stage, that is, keep the input of the current pipeline stage unchanged, so that this instruction temporarily skips an instruction match, so that the instruction is completed through normal execution. Rewriting of sp register.

[0122] Specifically, for class A instruction set architectures, the return address with the PAC is read from the top of the stack; for class B instruction set architectures, the return address with the PAC is read from the return address register. The PAC is stripped from the return address to obtain the original return address. The updated stack pointer register value from the current pipeline stage input is used as context, and the original return address is regenerated using the current key. This PAC is compared with the previously stripped PAC. If the comparison is consistent, the original return address is written to the top of the stack for class A instruction set architectures and to the return address register for class B instruction set architectures. Otherwise, the return address with the PAC is maintained as is or an invalid address is written. Optionally, if the comparison is inconsistent, an exception can be directly raised without proceeding to the next step.

[0123] In one possible implementation, if a stack that grows from top to bottom is used, the instruction is identified as the second target instruction in the following manner: if the opcode in the instruction is an immediate addition opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is positive, then the instruction is the second target instruction; or if the opcode in the instruction is an immediate subtraction opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is negative, then the instruction is the second target instruction. A stack that grows from top to bottom is a stack with a high address at the bottom and a low address at the top, where the high address is the memory address with the larger address value; the low address is the memory address with the smaller address value.

[0124] The embodiment of the present application takes the MIPS64 instruction set architecture, and takes the stack growing from top to bottom and the opcode being an immediate addition opcode as an example. Therefore, in the MIPS64 instruction set architecture, the opcode in the instruction is DADDIU (an immediate addition opcode), and the immediate value is a positive value.

[0125] Specifically, since at the end of the function, either the stack frame is not released or the top of the stack is pushed up once the stack frame is released (since this example uses a top-down growing stack), here, we hope to only match the case where the top of the stack is pushed up, that is, When sp is incremented, the immediate value must be filled with a positive number. According to the instruction definition of daddiu, its highest bit can be used to determine the sign of the immediate value. The highest bit of the immediate value must be 0. The matching items are shown in Table 5: Table 5

[0126] In one possible implementation, if a stack that grows from the bottom up is used, an instruction that satisfies either of the following two conditions is determined to be the second target instruction: (a) the opcode in the instruction is an immediate addition opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is negative; (b) the opcode in the instruction is an immediate subtraction opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is positive. A stack that grows from the bottom up is a stack with a low address at the bottom and a high address at the top; a high address is a memory address with a larger address value, and a low address is a memory address with a smaller address value. The specific matching method will not be described in detail here.

[0127] For the second appropriate opportunity, the third setting instruction is a jump instruction for function return, the target pipeline stage is a memory access stage or a write-back stage, and the return address carrying the PAC and the stack pointer are obtained through the instruction bypass unit, including: obtaining the return address carrying the PAC from the input of the target pipeline stage, and reading the stack pointer stored in the stack pointer register.

[0128] Specifically, the third setting instruction may be a jr instruction. When the third setting instruction is recognized, the instruction bypass unit has the following pipeline stage bypass mode.

[0129] (2) The second pipeline stage bypass method at the right time

[0130] For pipeline stage bypassing, for the B-class instruction set architecture, the pipeline stage to be bypassed is any stage between the decode stage (excluding) and the write-back stage (inclusive). This allows the return address with the PAC to be directly obtained from the pipeline stage input. The PAC is stripped from the return address to obtain the original return address. The stack pointer register value is read as context, combined with the current key, and the original return address is used to generate a new PAC to complete the PAC signature verification. This is compared with the previously stripped PAC. If the comparison is consistent, the signature verification passes. After the signature verification passes, the return address without the PAC is used as the bypass result. If the signature verification fails, an exception can be raised. Optionally, the return address can be maintained as is or invalidated. The pipeline stage after bypassing is set to the current pipeline stage, i.e., the target pipeline stage in the match. This causes the bypass result to be used for the jump, thus executing the jump using the address after the PAC signature verification.

[0131] For Class A ISAs, since the jump instructions used for function returns directly retrieve the return address from the stack, the return address with the PAC can be directly retrieved from the pipeline input by bypassing the next stage of the memory access stage. The remaining process remains the same. It is worth noting that, generally speaking, the next stage of the memory access stage is any pipeline stage between the decode stage (excluding) and the write-back stage (inclusive).

[0132] The jr instruction is an instruction that reads the address stored in the source register and jumps to the address. In this case, the match must match both the instruction as jr and the source register used by the instruction as 31. Also note that the jr instruction uses a secondary opcode, so two levels of opcodes must be matched to determine that the instruction is jr. Examples of matching items are shown in Table 6: Table 6

[0133] (2) Determine the context corresponding to the stack pointer based on the new value of the stack pointer register

[0134] There are two suitable times to use the new value of the stack pointer register to determine the context corresponding to the stack pointer. The first suitable time is the second daddiu instruction mentioned above, which is the instruction used to restore the stack pointer register. Simply use the current value of the stack pointer register (the value before the instruction is executed) in the bypass, rather than the value after the restoration, as the context to perform signature verification and modify accordingly. The second suitable time is the ld instruction in the above code, which is used to pop the return address from the bottom of the current stack frame to 31 register, in this case, we only need to use the current value of the stack pointer register as the context to perform the signature verification in the bypass and write the return address after the signature verification to 31 hits.

[0135] For the first appropriate timing, the fourth setting instruction is an instruction that sets the stack pointer to the callee stack frame before execution (equivalent to the value in the stack pointer register being the new value) and to the caller stack frame after execution (equivalent to the value in the stack pointer register being the old value), the target pipeline stage is no later than the write-back stage, and obtaining the return address carrying the PAC and the stack pointer through the instruction bypass unit includes: reading the return address carrying the PAC from the top of the stack or the return address register, and obtaining the stack pointer from the input of the target pipeline stage.

[0136] Specifically, the fourth setting instruction is the second daddiu instruction in the above code. When the second setting instruction is recognized, the instruction bypass unit has the following pipeline stage bypass mode.

[0137] (1) The first pipeline stage bypass method at the right time

[0138] For pipeline stage bypass, the bypassed pipeline stage must be no later than the write-back stage, that is, the stage that writes to the register, otherwise only the The old value of the sp register is lost. It is also possible to bypass the write-back stage because before the write-back stage is completed, The sp register still has the new value. The instruction bypass unit only completes the 31 The PAC signature of the return address on the register is obtained at this time The value of the sp register is still the new value, use it and rewrite Register 31 sets the bypassed pipeline stage as the current pipeline stage, so that this instruction temporarily skips an instruction match, so that the instruction is executed normally and finally completes the Rewriting of sp register.

[0139] Specifically, for the A-class instruction set architecture, the return address with the PAC is read from the top of the stack; for the B-class instruction set architecture, the return address with the PAC is read from the return address register. The PAC is stripped from the return address to obtain the original return address. The stack pointer register value at the input of the current pipeline stage is used as context. Here, the stack pointer register value has not yet been updated and is therefore still a fresh value. Using the current key, a new PAC is generated using the PAC-stripped return address. This is then compared with the previously stripped PAC. If the two match, the original return address is written to the top of the stack for the A-class instruction set architecture and to the return address register for the B-class instruction set architecture. Otherwise, the return address with the PAC is maintained as is or an invalid address is written. Optionally, an exception can be raised if the comparison is inconsistent, without proceeding to the next step.

[0140] How to match the second daddiu instruction has been described above and will not be repeated here.

[0141] For the second appropriate opportunity, the fourth setting instruction is an instruction for restoring the return address stored on the stack to the return address register, the target pipeline stage is the write-back stage, and the return address and stack pointer carrying the PAC are obtained through the instruction bypass unit, including obtaining the return address carrying the PAC from the input of the target pipeline stage and reading the stack pointer stored in the stack pointer register.

[0142] Specifically, the fourth setting instruction may be the ld instruction in the above assembly code. When the fourth setting instruction is identified, the instruction bypass unit has the following pipeline stage bypass mode.

[0143] (2) The second pipeline stage bypass method at the right time

[0144] For pipeline level bypass, you can choose to bypass the write-back level, that is, the level that writes to the register. The instruction bypass unit completes the PAC signature of the return address. The value of the sp register is still the new value, so it is used. The input of the write-back stage is the data at the target memory address, that is, the return address with the PAC signature. After setting the bypass, the pipeline stage is the current pipeline stage, that is, the write-back stage. This makes this instruction temporarily skip an instruction match, so that the instruction can enter the write-back stage. However, at this time, the input of the write-back stage has been rewritten to the return address after the PAC signature is verified, so that the return address after the PAC signature is written into the write-back stage. 31 registers.

[0145] Specifically, a return address with a PAC is obtained from the input of the write-back pipeline stage, and the PAC in the return address is stripped to obtain the original return address. The value of the stack pointer register is read as context, and the PAC is regenerated using the original return address in combination with the current key. This is compared with the previously stripped PAC. If the comparison is consistent, the original return address is used as the instruction bypass result; otherwise, the original input of the current pipeline stage is maintained as the instruction bypass result, or an illegal address is used as the instruction bypass result. Optionally, if the comparison is inconsistent, an exception can be directly raised without proceeding to the next step.

[0146] If a top-down growing stack is used, an instruction is identified as a second target instruction in the following manner: if the opcode in the instruction is a memory load opcode, the target register is the return address register, the memory base register is the stack pointer register, and the offset is a positive value, then the instruction is a second target instruction.

[0147] The embodiment of the present application uses the MIPS64 instruction set architecture, and takes the stack growing from top to bottom as an example. Therefore, in the MIPS64 instruction set architecture, the opcode in the instruction is LD (belonging to the memory load opcode), and the offset is a positive value.

[0148] Specifically, when using mask matching for this type of instruction, the ld instruction is a memory access instruction that uses a base register plus an immediate offset to access data. It reads data from a specific memory address and writes it to the target register. If data is to be read from the stack, the base register should be sp. In this case, the matching item must match both the instruction ld and the target register used by the instruction. 31, and also match the base register used by the instruction sp. Examples of matching items are shown in Table 7: Table 7

[0149] Furthermore, considering that when accessing data in the stack, the data should be located in the stack rather than outside the stack, and the memory address range occupied by the stack can be expressed from the bottom of the stack to the top of the stack, and considering The address stored in the sp register points to the top of the stack. Since this example uses a top-down stack, the target address of a legal memory access to the stack must be higher than the top of the stack. When sp is used as the base register, the offset must be a positive integer to place the target memory address on the stack rather than outside it. Since the offset in the above instruction is a signed integer, to make this offset a positive integer, its highest bit must be 0. Therefore, a preferred match is shown in Table 8: Table 8

[0150] In one possible implementation, if a bottom-up stack is used, an instruction that satisfies the following conditions is determined to be the second target instruction: the opcode in the instruction is a memory load opcode, the target register is the return address register, the memory base register is the stack pointer register, and the offset is a negative value. A bottom-up stack is a stack with a low address at the bottom and a high address at the top; the high address is the memory address with the larger address value; the low address is the memory address with the smaller address value. Specifically, taking the MIPS64 instruction set architecture and the stack growing from the bottom up as an example, in the MIPS64 instruction set architecture, the opcode in the instruction is LD (a memory load opcode) and the offset is a negative value. The matching example is similar to Table 8, except that the binary number representing the positive or negative sign of the immediate value in bit 15 is 1.

[0151] Therefore, as mentioned above, the PAC signature can be placed in the reserved bits of the pointer. Figure 3 A schematic diagram of a PAC signing and verification process provided in an embodiment of the present application. To implement PAC, we must define which bit fields of the pointer are used to embed the PAC, and we must ensure that no additional information is lost during this process. Specifically, the valid bits of the pointer cannot be used, and the identification of the high / low address cannot be lost, or at least the lost information can be recovered.

[0152] The reserved bits and high / low address identifiers of existing pointers are actually two sides of the same coin. This is due to the following two rules that generally apply simultaneously: when the highest bit is 1, it indicates a high address (kernel space address), and when the lowest bit is 0, it indicates a low address (user space address). Every bit from the highest bit to the most significant bit is a reserved bit. All reserved bits must be synchronized with the highest bit to the same binary value; otherwise, the pointer is invalid, meaning it is an illegal memory address or a non-canonical memory address. In other words, the highest bit and the reserved bits must be all 1s or all 0s to prevent it from being a valid address.

[0153] Therefore, as long as a pointer is legal, not only its highest bit but also any reserved bits are related to the high / low address. Therefore, the highest bit and the reserved bits can be collectively referred to as the reserved bit and the high / low address identifier.

[0154] Based on this, the present invention provides a method for redefining the pointer bit field, which can embed the PAC without losing any existing valid information. That is, the original use of the valid bits is not changed, and the reserved bits and high / low address identifiers are reallocated.

[0155] In a possible implementation, at least one bit is used as a high / low address identifier, and the position and length may not be limited. The remaining bits are used to embed the PAC. Figure 4 Another PAC signature and verification process diagram provided in this application embodiment, from Figure 4 As can be seen from the figure, the highest bit can be used as a high / low address identifier, and the remaining reserved bits are all used to embed PAC.

[0156] Figure 5 This is a schematic diagram of another PAC signing and verification process provided by an embodiment of the present application. In one possible implementation, all bits of the pointer are used to embed the PAC. During PAC verification, since the original pointer must be restored first, the possible values of the reserved bits and the high / low address identifiers can be exhaustively enumerated when restoring the original pointer. There are actually only two possible values: either all 1s or all 0s. If either value results in a successful PAC verification, the original high / low address identifier values are restored, thus confirming the correct value of the original pointer.

[0157] Figure 6 Schematic diagram of a device 6000 for preventing ROP attacks provided in an embodiment of the present application. Figure 6 As shown, it includes at least one processor 601 and a memory 602 connected to the at least one processor 601. The specific connection medium between the processor 601 and the memory 602 is not limited in the embodiment of the present application. Figure 6For example, the processor 601 and the memory 602 are connected via a bus. The bus can be divided into an address bus, a data bus, a control bus, and the like.

[0158] In an embodiment of the present application, the memory 602 stores instructions that can be executed by at least one processor 601. The at least one processor 601 can implement the steps of the above-mentioned method for preventing ROP attacks by executing the instructions stored in the memory 602.

[0159] The processor 601 is the control center of the computer device. It can connect the various parts of the computer device using various interfaces and lines, and perform resource settings by running or executing instructions stored in the memory 602 and calling data stored in the memory 602. Optionally, the processor 601 may include one or more processing units. The processor 601 may integrate an application processor and a modem processor. The application processor mainly processes the operating system, user interface, and application programs, while the modem processor mainly processes wireless communications. It is understood that the modem processor may not be integrated into the processor 601. In some embodiments, the processor 601 and the memory 602 may be implemented on the same chip. In some embodiments, they may also be implemented on separate chips.

[0160] The processor 601 can be a general-purpose processor, such as a central processing unit (CPU), a digital signal processor, an application-specific integrated circuit (ASIC), a field-programmable gate array or other programmable logic device, a discrete gate or transistor logic device, or a discrete hardware component, and can implement or execute the various methods, steps, and logic block diagrams disclosed in the embodiments of this application. A general-purpose processor can be a microprocessor or any conventional processor. The steps of the methods disclosed in the embodiments of this application can be directly implemented as being executed by a hardware processor, or can be executed by a combination of hardware and software modules in the processor.

[0161] Memory 602, as a non-volatile computer-readable storage medium, can be used to store non-volatile software programs, non-volatile computer executable programs, and modules. Memory 602 may include at least one type of storage medium, such as flash memory, a hard disk, a multimedia card, a card-type memory, random access memory (RAM), static random access memory (SRAM), programmable read-only memory (PROM), read-only memory (ROM), electrically erasable programmable read-only memory (EEPROM), magnetic storage, a magnetic disk, an optical disk, and the like. Memory 602 is any other medium that can be used to carry or store desired program code in the form of instructions or data structures and can be accessed by a computer, but is not limited thereto. Memory 602 in the embodiments of the present application may also be a circuit or any other device capable of performing a storage function, used to store program instructions and / or data.

[0162] Those skilled in the art will appreciate that the embodiments of the present application may be provided as methods, systems, or computer program products. Therefore, the present application may take the form of an entirely hardware embodiment, an entirely software embodiment, or an embodiment combining software and hardware. Furthermore, the present application may take the form of a computer program product implemented on one or more computer-usable storage media (including but not limited to magnetic disk storage, CD-ROM, optical storage, etc.) containing computer-usable program code.

[0163] The present application is described with reference to the flowcharts and / or block diagrams of the methods, devices (systems), and computer program products according to the present application. It should be understood that each process and / or block in the flowchart and / or block diagram, as well as the combination of processes and / or blocks in the flowchart and / or block diagram, can be implemented by computer program instructions. These computer program instructions can be provided to a processor of a general-purpose computer, a special-purpose computer, an embedded processor, or other programmable data processing device to produce a machine, so that the instructions executed by the processor of the computer or other programmable data processing device generate instructions for implementing the processes in the flowchart and / or block diagram. Figure 1 a process or multiple processes and / or boxes Figure 1 A device that provides the functions specified in a block or multiple blocks.

[0164] These computer program instructions may also be stored in a computer readable memory that can direct a computer or other programmable data processing device to work in a specific manner, so that the instructions stored in the computer readable memory produce an article of manufacture comprising an instruction device, which implements the process Figure 1 a process or multiple processes and / or boxes Figure 1 The function specified in one or more boxes.

[0165] These computer program instructions can also be loaded onto a computer or other programmable data processing device so that a series of operational steps are executed on the computer or other programmable device to produce a computer-implemented process, thereby providing the instructions executed on the computer or other programmable device for implementing the process. Figure 1 a process or multiple processes and / or boxes Figure 1 A step that specifies a function in one or more boxes.

[0166] Obviously, those skilled in the art may make various changes and modifications to this application without departing from the spirit and scope of this application. Thus, if these modifications and variations of this application fall within the scope of the claims of this application and their equivalents, this application is intended to include these modifications and variations.

Claims

1. A method for preventing return-oriented programming (ROP) attacks, characterized in that: The method comprises: When processing instructions in a pipeline stage mode, if a first target instruction and a target pipeline stage in a function call are identified, the target pipeline stage is paused; the first target instruction is a first setting instruction that causes a stack pointer to point to a caller stack frame before and after execution, or the first target instruction is a second setting instruction that causes a stack pointer to point to a callee stack frame before and after execution; the before and after execution are before execution and / or after execution; and the target pipeline stage is a specified pipeline stage in the pipeline; Obtaining the return address of the function call, the stack pointer, and the key through the instruction bypass unit, and generating a pointer authentication code (PAC) based on the return address, the stack pointer, and the key; adding the PAC to a reserved bit of the return address to obtain a return address carrying the PAC; the return address carrying the PAC is used to prevent ROP attacks targeting the return address; After the instruction bypass unit completes execution, the first target instruction continues to be processed through the target pipeline stage in the pipeline.

2. The method according to claim 1, characterized in that The first setting instruction is an instruction that sets the stack pointer to point to the caller's stack frame before execution and to point to the callee's stack frame after execution; The target pipeline stage is any pipeline stage in the pipeline that is not later than the write-back stage; The no later than the write-back stage includes the write-back stage; Obtaining the return address of the function call and the stack pointer through the instruction bypass unit includes: Read the return address from the top of the stack or the return address register; Read the stack pointer stored in the stack pointer register.

3. The method according to claim 1, characterized in that The second setting instruction is an instruction that sets the stack pointer to point to the caller's stack frame before execution and to point to the callee's stack frame after execution; The target pipeline stage is a write-back stage; Obtaining the return address of the function call and the stack pointer through the instruction bypass unit includes: Read the return address from the top of the stack or the return address register; A stack pointer is obtained from an input of the target pipeline stage.

4. The method according to claim 1, wherein The second setting instruction is an instruction for storing a return address on a stack; The target pipeline stage is any pipeline stage in the pipeline that is later than the decoding stage but not later than the memory access stage; the stage later than the decoding stage but not later than the memory access stage does not include the decoding stage and includes the memory access stage; Obtaining the return address of the function call and the stack pointer through the instruction bypass unit includes: obtaining a return address from an input of the target pipeline stage; Read the stack pointer stored in the stack pointer register.

5. The method according to claim 1, wherein The first setting instruction is a jump instruction for function call; The target pipeline is a memory access stage or a write-back stage; Obtaining the return address of the function call and the stack pointer through the instruction bypass unit includes: obtaining a return address from an input of the target pipeline stage; Read the stack pointer stored in the stack pointer register.

6. A method for preventing return-oriented programming (ROP) attacks, characterized in that: The method comprises: When processing instructions in a pipeline stage mode, if a second target instruction and a target pipeline stage in a function call are identified, the target pipeline stage is paused; the second target instruction is a third setting instruction that causes a stack pointer to point to a caller's stack frame before and after execution, or the second target instruction is a fourth setting instruction that causes a stack pointer to point to a callee's stack frame before and after execution; the before and after execution are before execution and / or after execution; and the target pipeline stage is a specified pipeline stage in the pipeline; Obtaining, through an instruction bypass unit, a return address carrying a pointer authentication code (PAC), the stack pointer, and a key, and generating a PAC to be verified based on the return address, the stack pointer, and the key stripped of the PAC; If the PAC is the same as the PAC to be verified, continuing processing the second target instruction through the target pipeline stage in the pipeline; If the PAC is different from the PAC to be verified, an exception is raised, which indicates a ROP attack on the return address.

7. The method according to claim 6, characterized in that The third setting instruction is an instruction that sets the stack pointer to the callee stack frame before execution and the stack pointer to the caller stack frame after execution; The target pipeline stage is a write-back stage; The return address carrying the PAC is obtained through the instruction bypass unit, and the stack pointer includes: Read the return address with PAC from the top of the stack or the return address register; A stack pointer is obtained from an input of the target pipeline stage.

8. The method according to claim 6, characterized in that The fourth setting instruction is an instruction that sets the stack pointer to the callee stack frame before execution and the stack pointer to the caller stack frame after execution; The target pipeline stage is any pipeline stage in the pipeline that is not later than the write-back stage; The no later than the write-back stage includes the write-back stage; Obtaining the return address carrying the PAC and the stack pointer through the instruction bypass unit includes: Read the return address with PAC from the top of the stack or the return address register; The stack pointer stored in the stack pointer register is read.

9. The method according to claim 6, characterized in that The fourth setting instruction is an instruction for loading the return address stored on the stack; The target pipeline stage is a write-back stage; Obtaining the return address carrying the PAC and the stack pointer through the instruction bypass unit includes: Obtaining a return address carrying a PAC from an input of the target pipeline stage; Read the stack pointer stored in the stack pointer register.

10. The method according to claim 6, characterized in that The third setting instruction is a jump instruction for function return; The target pipeline stage is any pipeline stage in the pipeline that is later than the decoding stage but not later than the write-back stage; the stage later than the decoding stage but not later than the write-back stage does not include the decoding stage and includes the write-back stage; Obtaining the return address carrying the PAC and the stack pointer through the instruction bypass unit includes: Obtaining a return address carrying a PAC from an input of the target pipeline stage; Read the stack pointer stored in the stack pointer register.

Citation Information

Patent Citations

  • Stack buffer overflow attack defense method based on LBR

    CN109858253A

  • Return Oriented Programming (ROP) Attack Protection

    US20160171211A1

  • Control flow protection based on phantom addressing

    US20220019657A1

  • Consistent Speculation of Pointer Authentication

    US20250094567A1

  • Control flow integrity

    WO2023169654A1