From b7d56babad41b4b86e905951967675a7459a40a5 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Sun, 21 Apr 2024 13:46:54 +0200 Subject: [PATCH 1/2] Fix map_shadow_stack syscall number * Syscall number for map_shadow_stack has changed since initial support was added. * Use SYS_map_shadow_stack instead of hard-coded number when possible --- Zend/zend_fibers.c | 8 ++++++-- configure.ac | 11 +++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 4173a870b0e0..9cdfde6f39ad 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -69,10 +69,14 @@ #endif # if defined __CET__ +# include +# include # include # define SHSTK_ENABLED (__CET__ & 0x2) # define BOOST_CONTEXT_SHADOW_STACK (SHSTK_ENABLED && SHADOW_STACK_SYSCALL) -# define __NR_map_shadow_stack 451 +# ifndef SYS_map_shadow_stack +# define SYS_map_shadow_stack 453 +# endif # ifndef SHADOW_STACK_SET_TOKEN # define SHADOW_STACK_SET_TOKEN 0x1 #endif @@ -283,7 +287,7 @@ static zend_fiber_stack *zend_fiber_stack_allocate(size_t size) /* issue syscall to create shadow stack for the new fcontext */ /* SHADOW_STACK_SET_TOKEN option will put "restore token" on the new shadow stack */ - stack->ss_base = (void *)syscall(__NR_map_shadow_stack, 0, stack->ss_size, SHADOW_STACK_SET_TOKEN); + stack->ss_base = (void *)syscall(SYS_map_shadow_stack, 0, stack->ss_size, SHADOW_STACK_SET_TOKEN); if (stack->ss_base == MAP_FAILED) { zend_throw_exception_ex(NULL, 0, "Fiber shadow stack allocate failed: mmap failed: %s (%d)", strerror(errno), errno); diff --git a/configure.ac b/configure.ac index b5dcf0da17f8..201b706f10db 100644 --- a/configure.ac +++ b/configure.ac @@ -1294,11 +1294,18 @@ fi AC_CACHE_CHECK([whether syscall to create shadow stack exists], [php_cv_have_shadow_stack_syscall], [AC_RUN_IFELSE([AC_LANG_SOURCE([ +#include #include #include +#ifndef SYS_map_shadow_stack +# define SYS_map_shadow_stack 453 +#endif +#ifndef SHADOW_STACK_SET_TOKEN +# define SHADOW_STACK_SET_TOKEN 0x1 +#endif int main(void) { - /* test if syscall 451, i.e., map_shadow_stack is available */ - void* base = (void *)syscall(451, 0, 0x20000, 0x1); + /* test if map_shadow_stack is available */ + void* base = (void *)syscall(SYS_map_shadow_stack, 0, 0x20000, SHADOW_STACK_SET_TOKEN); if (base != (void*)-1) { munmap(base, 0x20000); return 0; From 2e1771e8d66d3997f9fa58a3a658ebd1d6537087 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Sun, 21 Apr 2024 13:48:22 +0200 Subject: [PATCH 2/2] Increase SHSTK stack size The shadow stack may need as much space as the fiber stack in the worse case, so allocate a shadow stack the same size as the fiber stack. This matches what the kernel does for the main stack. --- Zend/zend_fibers.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 9cdfde6f39ad..aed96c8d3acc 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -279,11 +279,7 @@ static zend_fiber_stack *zend_fiber_stack_allocate(size_t size) stack->size = stack_size; #if !defined(ZEND_FIBER_UCONTEXT) && BOOST_CONTEXT_SHADOW_STACK - /* shadow stack saves ret address only, need less space */ - stack->ss_size= stack_size >> 5; - - /* align shadow stack to 8 bytes. */ - stack->ss_size = (stack->ss_size + 7) & ~7; + stack->ss_size = stack_size; /* issue syscall to create shadow stack for the new fcontext */ /* SHADOW_STACK_SET_TOKEN option will put "restore token" on the new shadow stack */