Call-flow security with an authenticated shadow stack
By assigning shadow stack target IDs to indirectly called functions and comparing them at execution, the method ensures secure and efficient forward CFI, addressing inefficiencies and vulnerabilities in existing hardware solutions, particularly on ARM and Intel processors.
Patent Information
- Application Number
- PCT/EP2024/068201
- Authority / Receiving Office
- WO · WO
- Patent Type
- Applications
- Current Assignee / Owner
- Filing Date
- 2024-06-27
- Publication Date
- 2026-01-02
AI Technical Summary
Implementing fine-grained forward control flow integrity (CFI) for indirectly called functions is computationally challenging and inefficient, especially with existing hardware solutions, leading to high overhead and vulnerability in current software protection mechanisms.
A method utilizing a shadow stack, such as ARM Guarded Control Stack (GCS) or Intel Control-flow Enforcement Technology (CET), assigns a shadow stack target ID to each indirectly called function at compile time, placing it on a shadow stack and comparing it with an own target ID at execution, aborting the program if there's a mismatch, ensuring secure and efficient forward CFI.
This approach provides a lightweight, secure, and efficient solution for fine-grained forward CFI, enhancing security by ensuring only legitimate functions are executed, compatible with standard ARM and Intel architectures, and reducing vulnerabilities from type-based solutions.
Smart Images

Figure EP2024068201_02012026_PF_FP_ABST
Abstract
Description
[0001] CALL-FLOW SECURITY WITH AN AUTHENTICATED SHADOW STACK
[0002] TECHNICAL FIELD
[0003] The present disclosure relates to methods and devices using shadow stack hardware implementations to provide secure forward call flow integrity, CFI, regimes.
[0004] BACKGROUND
[0005] Call Flow Integrity, CFI, is a security mechanism designed to protect software against control flow attacks such as Return- Oriented Programming, ROP, and Jump-Oriented Programming, JOP. These attacks exploit vulnerabilities to alter the intended execution flow of a program, leading to unauthorized actions.
[0006] CFI ensures that the control flow of a program follows a legitimate and predefined path. It does this by verifying the validity of control flow transfers, such as function calls and returns, against a control flow graph constructed during the program's compilation. Any deviation from the expected flow raises an alert or terminates the execution, thereby preventing exploits.
[0007] Forward or forward-edge CFI protects indirect calls and jumps by ensuring they target valid locations.
[0008] Backward or backward-edge CFI protects return addresses by verifying them against expected values, often using shadow stacks.
[0009] Forward, especially fine-grained forward CFI is computationally challenging to implement. Due to Fan-out / Fan-in, if the outgoing edges of a function call is thoroughly checked against the call flow graph, CFG - representation of all possible execution paths in the program, constructed at compile time, to protect forward CFI, the complexity of the check causes immense overhead if instrumented / inserted by the compiler. To alleviate this problem, most forward CFI solutions applied in practice are type-based, i.e. functions are grouped based on type, e.g. by their parameter count and type, which can be done by the compiler and make comparison overhead significantly less. While specialized hardware architecture to follow / enforce the known call flow graph of the program can be designed, these specialized designs are not commercially viable at present.
[0010] The present disclosure allows implementing high performance forward CFI re-using a hardware feature implementing a shadow stack, for example ARM Guarded Control Stack, GCS, or Intel Control-flow Enforcement Technology, CET, which are already standard features at present.
[0011] SUMMARY
[0012] The present disclosure attempts to solve these problems.
[0013] The present disclosure relates to implementing forward control flow integrity for indirectly called functions.
[0014] The present disclosure is defined by the scope of the independent claims. The dependent claims provide advantageous embodiments of the present disclosure.
[0015] The present disclosure provides in a first aspect of a computer-implemented method of implementing forward control flow integrity for indirectly called functions, comprising: assigning, at a compile time, a shadow stack target identification, shadow stack target ID, to each of indirectly called functions; placing, at a call site, each shadow stack target ID of the indirectly called functions on a shadow stack; and adding instructions to each of the indirectly called functions at the compile time, wherein the instructions comprise: loading the shadow stack target ID of a respective indirectly called function from the shadow stack; setting an own target identification, target ID, of the respective indirectly called function; comparing the shadow stack target ID and the own target ID and aborting program execution in case of a mismatch.
[0016] In the method above, a shadow stack target identification, shadow stack target ID, is assigned to each indirectly called function, the number of which is not specifically limited herein, at compile time. Each shadow stack target ID is, at a call site, placed on a shadow stack. Further, instructions are added to each of the indirectly called functions at compile time, namely instructions to load the shadow stack target ID of a respective indirectly called function from the shadow stack and to set an own target identification, target ID, of the respective indirectly called function. Once the shadow stack target ID is loaded and the own target ID is set, the shadow stack target ID and the own target ID are compared and if there is a mismatch between the two, program execution is aborted.
[0017] This offers a lightweight solution for fine-grained forward CFI, utilizing hardware features that are already available.
[0018] According to an implementation of the method of the first aspect, the method may further comprise: each of the shadow stack target ID and the own target ID comprises a group ID and an individual ID, wherein the group ID refers to a set of indirectly called functions and the individual ID refers to one specific indirectly called function, and wherein indirectly called function are called either via their group ID or individual ID or via both their group ID and individual ID, and wherein at least one of the group ID or the individual ID are compared, wherein if both group ID and individual ID are compared, the program is aborted in case there is a mismatch for each of the two comparisons.
[0019] Thus, a lightweight solution for accessing a function individually or as one of an assigned group is provided. Indirect function calls accessing a selection of multiple functions are common in current programming environments and specifically addressed by this implementation. The mismatch criteria when addressing a function may be either / or match criteria if group and individual IDs are used.
[0020] According to an implementation of the method of the first aspect, the method may further comprise: the shadow stack target ID and the own target ID are assigned as ordinal values or as hashes of a code of the function.
[0021] There are several methods to assign the shadow stack target ID and the own target ID. Specifically, ordinal numbers or hashes of the function code may be used, for example using SHA1.
[0022] According to an implementation of the method of the first aspect, the method may further comprise: each of the indirectly called functions is executed from the start of the respective indirectly called function.
[0023] If protections are included in the program code, it is important that this code is indeed executed. This implementation specifically provides that technical means ensure that the code of each indirectly called function is carried out from the start.
[0024] According to an implementation of the method of the first aspect, the method may further comprise: adding the instructions to each of the indirectly called functions comprises adding the instructions to a function preamble of each of the indirectly called functions.
[0025] In this implementation, the instructions are specifically added to a function preamble, putting them at the start of the function code.
[0026] According to an implementation of the method of the first aspect, the method may further comprise: the method is carried out on an ARM processor.
[0027] ARM processors offer several hardware features providing synergetic effects if the method of the first aspect is carried out on them. According to an implementation of the method of the first aspect, the method may further comprise: each of the indirectly called functions is executed from the start of the respective indirectly called function via ARM Branch Target Identification, BIT
[0028] ARM Branch Target Identification BTI is a security mechanism that marks valid branch targets in the code.
[0029] According to an implementation of the method of the first aspect, the method may further comprise: the shadow stack is an ARM Guarded Control Stack, GCS.
[0030] ARM GCS is a security feature that protects return addresses from tampering by maintaining a separate, protected stack for these addresses. ARM GCS is a hardware implementation of the shadow stack.
[0031] According to an implementation of the method of the first aspect, the method may further comprise: loading from the shadow stack comprises using Guarded Control Stack Push, GCSPUSH and / or Guarded Control Stack Pop, GCSPOP.
[0032] PUSH / POP commands are commonly used to load values from the stack, for a Guarded Control Stack, GCS, specific PUSH / POP commands are used.
[0033] According to an implementation of the method of the first aspect, the method may further comprise: loading from the shadow stack comprises using direct memory read.
[0034] Direct memory read essentially allows direct reading from RAM.
[0035] The present disclosure provides a second aspect of a data processing device. The data processing device comprises means for carrying out the method according to the first aspect.
[0036] The data processing device may include any kind of stationary or mobile computer or any device containing a computer, processor etc., for example desktop computers, cellphones, laptops.
[0037] According to an implementation of the data processing device of the second aspect, the data processing device comprises a Reduced Instruction Set Computer, RISC, processor, wherein the RISC processor is an ARM processor.
[0038] RISC processors are designed according to a philosophy that uses a small, highly optimized set of instructions, each designed to execute very quickly. ARM processors are RISC processors. As mentioned, ARM processors may offer several hardware features providing synergetic effects if the method of the first aspect is carried out on them.
[0039] According to an implementation of the data processing device of the second aspect, the data processing device is a Complex Instruction Set Computer, CISC, processor.
[0040] Complex Instruction Set Computer, CISC, processors are designed to execute a broad range of complex instructions, each capable of performing multiple low-level operations, like memory access, arithmetic, and control tasks, within a single instruction. As with ARM processors, they offer several hardware features providing synergetic effects if the method of the first aspect is carried out on them.
[0041] According to an implementation of the data processing device of the second aspect, the data processing device is an Intel x86- 64 instruction set processor, wherein the Intel x86-64 processor supports Indirect Branch Tracking, IBT, and Control-flow Enforcement Technology, CET.
[0042] Intel x86-64 instruction set processor are CISC processors. Intel's Control-flow Enforcement Technology, CET, is designed to protect against control flow attacks. It includes features like shadow stacks for return address protection and Indirect Branch Tracking, IBT, to ensure indirect branches only target valid destinations. The present disclosure provides a third aspect of a computer program comprising instructions, which, when the program is executed by a computer, cause the computer to carry out the steps of the method of the first aspect.
[0043] Summarizing, the present disclosure has several advantages over the prior art. It offers improved efficiency for hardware- assisted CFI with legacy / standard CPU cores, especially with ARM architectures. Further, it provides a significantly improved security level, over Pointer Authentication Code, PAC-based default forward CFI solutions. A shadow-stack and fine-grained forward CFI scheme eliminates the PAC risk of replaying integrity MACs and moves forward CFI from a type-based solution to an exact solution. It can also be implemented on standard ARM hardware as a compiler extension.
[0044] BRIEF DESCRIPTION OF DRAWINGS
[0045] In the following embodiments of the present disclosure are described in more detail with reference to the attached figures and drawings, in which:
[0046] Fig. 1 shows a flow diagram of an exemplary method disclosed herein.
[0047] Fig. 2 shows an exemplary embodiment, wherein one function indirectly calls another function, wherein the function identification set in the program code, own id, is compared to the function identification stored in the shadow stack, Target id.
[0048] Fig. 3 shows a further exemplary embodiment. In Fig. 3, the function identification is split into two parts, of which one is a group identification, shared part, and one is an individual identification, Function ID. The callee function may be called either by the individual identification, Fund, or by the group identification, Funcx, via multiple-choice.
[0049] DETAILED DESCRIPTION
[0050] In the description of embodiments of this application, "and / or" describes an association relationship between associated objects and indicates that three relationships may exist. For example, A and / or B may indicate the following three cases: Only A exists, both A and B exist, and only B exists. In this application, "at least one" means one or more, and "a plurality of' means two or more. In addition, it should be understood that in description of this application, terms such as "first", "second", and "third" are merely used for distinguishing and description, but should not be understood as indicating or implying relative importance, or should not be understood as indicating or implying a sequence.
[0051] The following description mentions examples pertaining to ARM or Intel instruction set processors. None of this is intended to limit the scope of this disclosure to any of these variants, any processor with the functionality mentioned may be used for carrying out the disclosed methods. Whenever any kind of shadow stack technology is mentioned, said shadow stack technology refers to the general concept of shadow stacks, not any particular implementation. Some definitions are given in order to facilitate the understanding of the disclosure.
[0052] Instructions: Assembly / machine code instructions are low-level commands executed directly by a computer's CPU. Each instruction performs a specific operation, such as arithmetic calculations, data movement, or control flow changes. These instructions form the fundamental building blocks of software, enabling the execution of complex tasks by specifying precise operations for the hardware.
[0053] Call site: In programming, a call site refers to the specific location in the code where a function is invoked. It is the point at which control is transferred to the function, and it often includes the passing of arguments to the function being called.
[0054] Forward CFI: Forward Control Flow Integrity, CFI, ensures that indirect control flow transfers, such as function calls and jumps, only go to valid, pre-determined targets. Fine-grained forward CFI enforces this policy at a very detailed level, ensuring that even specific calls only go to specific allowed targets, enhancing security. Shadow Stack: A shadow stack is a security feature that maintains a separate, protected copy of the call stack, storing return addresses. This helps prevent return address tampering by ensuring that the return address on the regular stack matches the one on the shadow stack during function returns.
[0055] Compile time: Compile time refers to the period during which source code is translated into executable code by a compiler. It is distinct from runtime, which is when the program is executed. Compile time involves syntax checking, optimization, and code generation. The phrase “at compile time” herein especially refers to a point or period in time during any time in the course of compilation.
[0056] Indirect function call: An indirect function call is a call to a function through a pointer or reference, rather than by a direct call to a specific function name. This allows for dynamic decision-making at runtime about which function to execute.
[0057] Function identifier / ID: In the context of indirect function calls, a function ID is a unique identifier assigned to a function. It is used to ensure that indirect calls go to legitimate targets by verifying the function's identity before execution.
[0058] POP: The POP instruction removes the top value from the stack and loads it into a specified register. This operation decreases the stack pointer, effectively moving it up the stack, making the previously stored value available for use.
[0059] PUSH: The PUSH instruction saves a value from a specified register onto the stack. This operation increases the stack pointer, effectively moving it down the stack, and stores the register's value at the new top of the stack.
[0060] Stack: In computing, a stack is a data structure that operates on a Last In, First Out, LIFO, principle. It is used for managing function calls, local variables, and control flow. Elements are added to the stack using the PUSH operation and removed using the POP operation. The stack pointer keeps track of the top of the stack.
[0061] Register: A register is a small, fast storage location within a CPU used to hold temporary data and instructions. Registers are used for arithmetic operations, data manipulation, and addressing during program execution, providing quick access to frequently used values.
[0062] Direct memory read: Direct memory read refers to accessing and reading data directly from a specific memory address in the system's main memory, RAM. This operation bypasses the CPU cache and involves retrieving the exact value stored at the given memory address, often used in low-level programming and hardware interfacing.
[0063] Reduced Instruction Set Computer, RISC: RISC is a CPU design philosophy that uses a small, highly optimized set of instructions, each designed to execute very quickly. The simplicity of RISC instructions allows for faster execution and more efficient pipelining compared to Complex Instruction Set Computing, CISC, architectures.
[0064] ARM processor: An ARM processor is a type of CPU based on the RISC architecture developed by ARM Holdings. ARM processors are known for their power efficiency and are widely used in mobile devices, embedded systems, and increasingly in servers and personal computers.
[0065] Complex Instruction Set Computer, CISC Processors: Complex Instruction Set Computer, CISC, processors are designed to execute a broad range of complex instructions, each capable of performing multiple low-level operations, like memory access, arithmetic, and control tasks, within a single instruction. This architecture allows for more functionality per instruction, reducing the number of instructions per program. However, it typically results in more complex hardware and longer instruction execution times compared to Reduced Instruction Set Computer, RISC, processors. CISC architectures are exemplified by Intel's x86 processors, which emphasize rich instruction sets to optimize code density and ease programming.
[0066] Intel x86-64 instruction set processor: The Intel x86-64 instruction set processor is a CPU that supports the 64-bit extension of the x86 architecture. It includes a wide range of instructions and is known for its backward compatibility with 32-bit and 16- bit software, making it a versatile and widely used architecture in desktops, laptops, and servers. ARM Guarded Control Stack, GCS: ARM Guarded Control Stack, GCS, is a security feature that protects return addresses from tampering by maintaining a separate, protected stack for these addresses. It ensures the integrity of control flow by verifying return addresses during function returns. At least in the context of this specification, it is an implementation of the shadow stack.
[0067] GCSPUSH, GCSPUSHM / GCSPUSHX: GCSPUSH is an ARM instruction used to push values onto the Guarded Control Stack, GCS. GCSPUSHM and GCSPUSHX are variants that handle multiple registers and extended functionality, respectively. This operation helps protect return addresses by storing them in a secured stack.
[0068] GCSPOP, GCSPOPM / GCSPOPX: GCSPOP is an ARM instruction used to pop values from the Guarded Control Stack, GCS. GCSPOPM and GCSPOPX are variants that handle multiple registers and extended functionality, respectively. This operation helps ensure the integrity of return addresses by retrieving them from a secured stack.
[0069] ARM Branch Target Identification, BTI: ARM Branch Target Identification, BTI, is a security mechanism that marks valid branch targets in the code. It helps prevent control flow hijacking by ensuring that indirect branches and jumps only go to legitimate, marked locations.
[0070] Control-flow Enforcement Technology, CET: Intel's Control-flow Enforcement Technology, CET, is designed to protect against control flow attacks. It includes features like shadow stacks for return address protection and Indirect Branch Tracking, IBT, to ensure indirect branches only target valid destinations.
[0071] Intel Indirect Branch Tracking, IBT: Intel Indirect Branch Tracking, IBT, is a feature of CET that ensures indirect branches, meaning calls and jumps, can only go to designated, valid targets. This prevents attackers from redirecting the control flow to malicious code through indirect branch manipulation.
[0072] XOM / XAM protection: Execute-Only Memory, XOM, or Execute-Exclusive Memory, XAM, is a security feature that prevents code stored in specific memory regions from being read or written, only allowing it to be executed. This protection enhances security by preventing attackers from inspecting, modifying, or copying executable code, thereby mitigating certain types of attacks such as reverse engineering and code injection.
[0073] .text memory: The .text segment, or text segment, in computing refers to a section of a program's memory that contains executable instructions. It is a read-only segment, meaning the instructions stored within it cannot be modified during runtime, which helps protect the integrity of the code and prevents certain types of attacks. The .text segment typically includes the compiled code of a program and is distinct from other segments like .data, for initialized data, and .bss, for uninitialized data.
[0074] The present disclosure provides Fine-grained forward CFI, for indirect branches, via shadow stack technology in an efficient and secure manner, and makes it compatible with XOM protection, which is typically not possible with fine-grained CFI, if branch target information needs to be retrieved, read, from the code segment.
[0075] The present disclosure provides a computer-implemented method of implementing forward control flow integrity for indirectly called functions according to a process schematically illustrated by Fig. 1. Therein, a shadow stack target identification, shadow stack target ID, is assigned to each indirectly called function (SI), the number of which is not specifically limited herein, at compile time. Each shadow stack target ID is, at a call site, placed on a shadow stack (S2). Further, instructions are added to each of the indirectly called functions at compile time (S3), wherein the instructions comprise: loading the shadow stack target ID of a respective indirectly called function from the shadow stack (S31 ); setting an own target identification, target ID, of the respective indirectly called function (S32); comparing the shadow stack target ID and the own target ID and aborting program execution in case of a mismatch (S33). Said instructions may optionally be included in a function prologue or preamble. The function prologue, also known as the function preamble, is a sequence of instructions at the beginning of a function that sets up the stack frame for the function's execution. It typically involves saving the return address, saving the current base pointer, and allocating space on the stack for local variables. This setup ensures that the function has the necessary context and resources to execute correctly, and it allows the function to return control to the correct location in the calling code.
[0076] The function ID, namely the shadow target ID and the own target ID, may be set in an arbitrary manner, namely it may optionally be assigned as ordinal values or as hash of a code of the function, for example using SHA1.
[0077] Optionally, each of the indirectly called functions is executed from the start of the respective indirectly called function, meaning it is technologically ensured that each such function is executed from the start, for example, but not limited to ARM BTI and Intel IBT, and the instructions added to each of the indirectly called functions are added specifically to a function preamble of each of the indirectly called functions.
[0078] The method may optionally be carried out on an ARM processor. Further optionally, as mentioned above, each of the indirectly called functions may be executed from the start of the respective indirectly called function via ARM BTI. The shadow stack 105 may optionally be implemented via ARM GCS or Intel CET. Further optionally, reading from the shadow stack 105 may using Guarded Control Stack Push, GCSPUSH and / or Guarded Control Stack Pop, GCSPOP and / or using direct memory read.
[0079] Fig. 2 shows an example embodiment of this method. Therein, one function, caller function 101, indirectly calls another function, callee function 102, wherein the function identification set in the program code, own id, is compared to the function identification stored in the shadow stack 105, Target id, and wherein the memory permissions for the shadow stack 105 are “read” and “controlled write”, e. g. via GCSPUSH / GCSPOP commands.
[0080] Therein, the compiler optionally instruments the code with ARM BTI or similar technology, Intel IBT etc. This can guarantee that any function is always executed from the start, thus jumping to the middle of the function is not possible. Consequently, it can be guaranteed that checks in the beginning of the called function, e.g. in the function preamble of the callee function 102, are in fact unconditionally executed.
[0081] The compiler maintains a unique identifier for every function it compiles. This compiler-internal enumeration may be used in the setup of forward CFI. Optionally, specific setups are used for functions called from many places / caller functions 101 that may need to call one of several functions at a specific call site, cf. the example of Fig. 3.
[0082] When the compiler writes out the indirect call in the resulting binary, it additionally adds, in the case of an ARM processor, a GCSPUSH instruction to add the identifier of the function to be called to the top of the shadow stack 105.
[0083] When the compiler writes out a function to binary code, for all indirectly called functions or all functions, including the target function discussed above, it will add to the function preamble a setting of its own target ID, programmatically, to a register, a load from the shadow stack 105, either double pop, if PUSH and POP commands are used, or a straight-forward read from one location below the top of the stack, if the return address lies on top. This value is compared to the target Id, and if there is not a match, execution is aborted.
[0084] This example provides forward CFI, wherein it does not matter if the target function address comes from a safe place or not, the right function is anyway unconditionally called.
[0085] Stack reading can optionally be optimized, using direct memory read, or managed with GCSPUSH / GCSPOP which will be slightly slower, since the top of the stack in this case needs to be “reorganized”. If GCSPUSH / GCSPOP is used, exemplary assembler code at a call site and at the called functions is:
[0086] Call Site:
[0087] Idr xl, [x2] movz x3, #0xlDd0 movk x3, #0x48f4, Isl #16 gcspushm x3 blr xl
[0088] Called function: gcspopm xl6 gcspopm xl7 gcspushm xl7 gcspushx xl6 movz x9, #0xlDd0 movk x9, #0x48f4, Isl #16 cmp x9, xl6
[0089] Further, no .text memory, meaning memory that contains executable instructions, see above; beyond the protected shadow stack 105, is addressed, which achieves the ability to operate with XOM, and makes the method insensitive to all memory attacks, i.e., for the fixed, single target call site, the fact that the target address is read from memory is not an attack vector anymore.
[0090] In a specific embodiment, the computer-implemented method of implementing forward control flow integrity for indirectly called functions may optionally further provide one or more shadow stack target IDs and own target IDs, wherein each of the shadow stack target ID and the own target ID comprises a group ID and an individual ID, wherein the group ID refers to a set of indirectly called functions and the individual ID refers to one specific indirectly called function, and wherein indirectly called function are called either via their group ID or individual ID or via both their group ID and individual ID, and wherein at least one of the group ID or the individual ID are compared. Optionally, the program may be aborted if there is a mismatch in both comparisons, namely the comparison of shadow stack group target ID and own target group ID and shadow stack individual target ID and own individual target ID. In this aspect, the compiler, possibly with programmer assistance, may label the target group functions with a common group Id.
[0091] A specific example for the embodiment above is provided in Fig. 3. The callee function 202 may be called either by the individual identification, Fund, by a first caller function 201 or by the group identification, Funcx, via multiple-choice by a second caller function 203. In this specific example, considering a 64-bit architecture, with 64-bit registers, two 32-bit IDs can share a single 64-bit memory word. Considering for example an ARM processor, the GCS-stack also holds a 64-bit word. Thus, in one option, the callee function 202 may consider upper and lower bits separately. A call can occur with the group Id or the function-specific, individual ID, depending on the call site, and the target function can resolve this based on the location of the digits in the value recovered from GCS, and then compare against one of the two values assigned to it, or both. Further, a data processing device for carrying out the aforementioned methods is provided. The data processing device may optionally be a Reduced Instruction Set Computer, RISC, processor and, in this case an ARM processor, and, if an ARM processor is provided, the ARM processor may support ARM BTI and ARM GCS. The data processing device may optionally be a Complex Instruction Set Computer, CISC, processor, optionally an Intel x86-64 instruction set processor, wherein the Intel x86-64 processor supports Indirect Branch Tracking, IBT, and Control-flow Enforcement Technology, CET.
[0092] Further, a computer program is provided, the computer program comprising instructions which, when the program is executed by a computer, cause the computer to carry out the steps mentioned for the methods above.
[0093] The presently disclosed methods have several advantages over the prior art. It offers improved efficiency for hardware-assisted CFI with legacy / standard CPU cores, especially with ARM architectures. Further, it provides a significantly improved security level, over Pointer Authentication Code, PAC-based default forward CFI solutions. A shadow-stack and fine-grained forward
[0094] CFI scheme eliminates the PAC risk of replaying integrity MACs and moves forward CFI from a type-based solution to an exact solution. It can also be implemented on standard ARM hardware as a compiler extension.
[0095] The foregoing description is merely examples of specific implementations of this application, but are not intended to limit the protection scope of this application. Any variation or replacement readily figured out by a person skilled in the art within the technical scope disclosed in this application shall fall within the protection scope of this application. Therefore, the protection scope of this application shall be subject to the protection scope of the claims.
Claims
CLAIMS1. A computer-implemented method of implementing forward control flow integrity for indirectly called functions, comprising: assigning (SI), at a compile time, a shadow stack target identification, shadow stack target ID, to each of indirectly called functions; placing (S2), at a call site, each shadow stack target ID of the indirectly called functions on a shadow stack (105); and adding (S3) instructions to each of the indirectly called functions at the compile time, wherein the instructions comprise: loading (S31) the shadow stack target ID of a respective indirectly called function from the shadow stack (105); setting (S32) an own target identification, target ID, of the respective indirectly called function; comparing (S33) the shadow stack target ID and the own target ID and aborting program execution in case of a mismatch.
2. The method of claim 1, wherein each of the shadow stack target ID and the own target ID comprises a group ID and an individual ID, wherein the group ID refers to a set of indirectly called functions and the individual ID refers to one specific indirectly called function, and wherein indirectly called function are called either via their group ID or individual ID or via both their group ID and individual ID, and wherein at least one of the group ID or the individual ID are compared, wherein if both group ID and individual ID are compared, the program is aborted in case there is a mismatch for each of the two comparisons.
3. The method of any one of claims 1 to 2, wherein the shadow stack target ID and the own target ID are assigned as ordinal values or as hashes of a code of the function.
4. The method of any one of claims 1 to 3, wherein each of the indirectly called functions is executed from the start of the respective indirectly called function.
5. The method of any one of claims 1 to 4, wherein adding the instructions to each of the indirectly called functions comprises adding the instructions to a function preamble of each of the indirectly called functions.
6. The method of any one of claims 1 to 5, wherein the method is carried out on an ARM processor.
7. The method of claim 6, wherein each of the indirectly called functions is executed from the start of the respective indirectly called function via ARM Branch Target Identification, BTI.
8. The method of any one of claims 6 to 7, wherein the shadow stack (105) is an ARM Guarded Control Stack, GCS.
9. The method of any one of claims 6 to 8, wherein loading from the shadow stack (105) comprises using Guarded Control Stack Push, GCSPUSH and / or Guarded Control Stack Pop, GCSPOP.
10. The method of any one of claims 6 to 8, wherein loading from the shadow stack (105) comprises using direct memory read.
11. A data processing device comprising means for carrying out the method of any of claims 1 to 10.
12. The data processing device of claim 11 , wherein the data processing device comprises a Reduced Instruction Set Computer, RISC, processor and wherein the RISC processor is an ARM processor.
13. The data processing device of claim 11, wherein the data processing device is a Complex Instruction Set Computer, CISC, processor.
14. The data processing device of claim 13, wherein the data processing device is an Intel x86-64 instruction set processor, wherein the Intel x86-64 processor supports Indirect Branch Tracking, IBT, and Control-flow Enforcement Technology, CET.
15. A computer program comprising instructions which, when the program is executed by a computer, cause the computer to carry out the steps of the method of any one of claims 1 to 10.
Citation Information
Patent Citations
Control flow integrity to prevent potential leakage of sensitive data to adversaries
US20230418934A1
User-level exception-based invocation of software instrumentation handlers
US20240095063A1
Control flow integrity
WO2023169654A1