From 040a37d3f15932924d75f2c9fb3e503004af986a Mon Sep 17 00:00:00 2001 From: Chen Date: Tue, 26 Apr 2022 01:58:22 -0700 Subject: [PATCH] Add IBT support for fiber Indirect Branch Tracking (IBT) is part of Intel's Control-Flow Enforcement Technology (CET). IBT is hardware based, forward edge Control-Flow-Integrity mechanism where any indirect CALL/JMP must target an ENDBR instruction or suffer #CP. This commit adds IBT support for fiber: 1. Add endbr32/64 in assembly 2. Inform compiler jump_fcontext may return via indirect branch Furthermore: gcc support CET since v8.1 and set it to default since gcc 11. That is, the ELF header of sapi/cli/php has a property named IBT. However, such property is lost since PHP8.1 because the assembly introduced by Fiber. This commit also fixes this. Closes GH-8339 Signed-off-by: Chen, Hu Co-authored-by: Christoph M. Becker --- NEWS | 3 +++ Zend/asm/jump_x86_64_sysv_elf_gas.S | 6 ++++++ Zend/asm/make_x86_64_sysv_elf_gas.S | 8 ++++++++ Zend/zend_fibers.c | 2 +- Zend/zend_portability.h | 6 ++++++ 5 files changed, 24 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 142a467f344..81ce7e26648 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.1.8 +- Core: + . Fixed bug GH-8338 (Intel CET is disabled unintentionally). (Chen, Hu) + - MBString: . mb_detect_encoding recognizes all letters in Czech alphabet (alexdowad) . mb_detect_encoding recognizes all letters in Hungarian alphabet (alexdowad) diff --git a/Zend/asm/jump_x86_64_sysv_elf_gas.S b/Zend/asm/jump_x86_64_sysv_elf_gas.S index 0c4a1a39eb8..c675c8c774c 100644 --- a/Zend/asm/jump_x86_64_sysv_elf_gas.S +++ b/Zend/asm/jump_x86_64_sysv_elf_gas.S @@ -24,12 +24,18 @@ * * ****************************************************************************************/ +# if defined __CET__ +# include +# else +# define _CET_ENDBR +# endif .file "jump_x86_64_sysv_elf_gas.S" .text .globl jump_fcontext .type jump_fcontext,@function .align 16 jump_fcontext: + _CET_ENDBR leaq -0x38(%rsp), %rsp /* prepare stack */ #if !defined(BOOST_USE_TSX) diff --git a/Zend/asm/make_x86_64_sysv_elf_gas.S b/Zend/asm/make_x86_64_sysv_elf_gas.S index 0ef37569a02..d422c6972df 100644 --- a/Zend/asm/make_x86_64_sysv_elf_gas.S +++ b/Zend/asm/make_x86_64_sysv_elf_gas.S @@ -24,12 +24,18 @@ * * ****************************************************************************************/ +# if defined __CET__ +# include +# else +# define _CET_ENDBR +# endif .file "make_x86_64_sysv_elf_gas.S" .text .globl make_fcontext .type make_fcontext,@function .align 16 make_fcontext: + _CET_ENDBR /* first arg of make_fcontext() == top of context-stack */ movq %rdi, %rax @@ -66,11 +72,13 @@ make_fcontext: trampoline: /* store return address on stack */ /* fix stack alignment */ + _CET_ENDBR push %rbp /* jump to context-function */ jmp *%rbx finish: + _CET_ENDBR /* exit code is zero */ xorq %rdi, %rdi /* exit application */ diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index dd06f86ae8d..1fec85528fb 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -141,7 +141,7 @@ typedef struct { /* These functions are defined in assembler files provided by boost.context (located in "Zend/asm"). */ extern void *make_fcontext(void *sp, size_t size, void (*fn)(boost_context_data)); -extern boost_context_data jump_fcontext(void *to, zend_fiber_transfer *transfer); +extern ZEND_INDIRECT_RETURN boost_context_data jump_fcontext(void *to, zend_fiber_transfer *transfer); #endif ZEND_API zend_class_entry *zend_ce_fiber; diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index 6ad9f1b1db2..74f8be3c1a2 100644 --- a/Zend/zend_portability.h +++ b/Zend/zend_portability.h @@ -679,4 +679,10 @@ extern "C++" { # define ZEND_VOIDP(ptr) (ptr) #endif +#if defined(__GNUC__) && ZEND_GCC_VERSION >= 9000 +# define ZEND_INDIRECT_RETURN __attribute__((__indirect_return__)) +#else +# define ZEND_INDIRECT_RETURN +#endif + #endif /* ZEND_PORTABILITY_H */