Skip to content

Fix Intel CET / SHSTK support in fibers #14027

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: PHP-8.3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
fail-fast: false
matrix:
branch: ${{ fromJson(needs.GENERATE_MATRIX.outputs.branches) }}
configuration_parameters: ['']
configuration_parameters: ['CFLAGS="-fcf-protection=full" LDFLAGS="-Wl,-z,cet-report=error"']
debug: [true, false]
name: ['']
run_tests_parameters: ['']
Expand Down Expand Up @@ -112,12 +112,16 @@ jobs:
uses: ./.github/actions/setup-x64
- name: Test
uses: ./.github/actions/test-linux
env:
GLIBC_TUNABLES: 'glibc.cpu.hwcaps=SHSTK'
with:
runTestsParameters: >-
${{ matrix.run_tests_parameters }}
idleCpu: ${{ matrix.asan && 'true' || 'false' }}
- name: Test Tracing JIT
uses: ./.github/actions/test-linux
env:
GLIBC_TUNABLES: 'glibc.cpu.hwcaps=SHSTK'
with:
jitType: tracing
runTestsParameters: >-
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ jobs:
configurationParameters: >-
--${{ matrix.debug && 'enable' || 'disable' }}-debug
--${{ matrix.zts && 'enable' || 'disable' }}-zts
${{ matrix.asan && 'CFLAGS="-fsanitize=undefined,address -fno-sanitize=function -DZEND_TRACK_ARENA_ALLOC" LDFLAGS="-fsanitize=undefined,address -fno-sanitize=function" CC=clang CXX=clang++ --disable-opcache-jit' || '' }}
${{ matrix.asan && 'CFLAGS="-fsanitize=undefined,address -fno-sanitize=function -DZEND_TRACK_ARENA_ALLOC" LDFLAGS="-fsanitize=undefined,address -fno-sanitize=function" CC=clang CXX=clang++ --disable-opcache-jit' || 'CFLAGS="-fcf-protection=full" LDFLAGS="-Wl,-z,cet-report=error"' }}
skipSlow: ${{ matrix.asan }}
- name: make
run: make -j$(/usr/bin/nproc) >/dev/null
Expand All @@ -123,6 +123,8 @@ jobs:
if: matrix.asan == false
uses: ./.github/actions/test-linux
- name: Test ${{ matrix.asan && 'OpCache' || 'Tracing JIT' }}
env:
GLIBC_TUNABLES: ${{ !matrix.asan && 'glibc.cpu.hwcaps=SHSTK' || '' }}
uses: ./.github/actions/test-linux
with:
jitType: ${{ matrix.asan && 'disable' || 'tracing' }}
Expand Down
8 changes: 0 additions & 8 deletions Zend/asm/jump_x86_64_sysv_elf_gas.S
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,6 @@ jump_fcontext:
movq %rbx, 0x30(%rsp) /* save RBX */
movq %rbp, 0x38(%rsp) /* save RBP */

#if BOOST_CONTEXT_SHADOW_STACK
/* grow the stack to reserve space for shadow stack pointer(SSP) */
leaq -0x8(%rsp), %rsp
/* read the current SSP and store it */
rdsspq %rcx
movq %rcx, (%rsp)
#endif

#if BOOST_CONTEXT_SHADOW_STACK
/* grow the stack to reserve space for shadow stack pointer(SSP) */
leaq -0x8(%rsp), %rsp
Expand Down
29 changes: 0 additions & 29 deletions Zend/asm/make_x86_64_sysv_elf_gas.S
Original file line number Diff line number Diff line change
Expand Up @@ -88,35 +88,6 @@ make_fcontext:
/* will be entered after context-function returns */
movq %rcx, 0x38(%rax)

#if BOOST_CONTEXT_SHADOW_STACK
/* Populate the shadow stack and normal stack */
/* get original SSP */
rdsspq %r8
/* restore new shadow stack */
rstorssp -0x8(%r9)
/* save the restore token on the original shadow stack */
saveprevssp
/* push the address of "jmp trampoline" to the new shadow stack */
/* as well as the stack */
call 1f
jmp trampoline
1:
/* save address of "jmp trampoline" as return-address */
/* for context-function */
pop 0x38(%rax)
/* Get the new SSP. */
rdsspq %r9
/* restore original shadow stack */
rstorssp -0x8(%r8)
/* save the restore token on the new shadow stack. */
saveprevssp

/* reserve space for the new SSP */
leaq -0x8(%rax), %rax
/* save the new SSP to this fcontext */
movq %r9, (%rax)
#endif

#if BOOST_CONTEXT_SHADOW_STACK
/* Populate the shadow stack */

Expand Down
14 changes: 7 additions & 7 deletions Zend/zend_fibers.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,14 @@
#endif

# if defined __CET__
# include <sys/syscall.h>
# include <unistd.h>
# include <cet.h>
# 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
Expand Down Expand Up @@ -264,15 +268,11 @@ 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 */
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);
Expand Down
11 changes: 9 additions & 2 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1331,11 +1331,18 @@ fi
dnl Check whether syscall to create shadow stack exists, should be a better way, but...
AC_CACHE_CHECK([whether syscall to create shadow stack exists], ac_cv_syscall_shadow_stack_exists,
[AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <sys/syscall.h>
#include <unistd.h>
#include <sys/mman.h>
#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;
Expand Down
Loading