From 270d30655e3ad329b06baa48feb5ac657feb1001 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 11 Jan 2021 22:39:14 +0000 Subject: [PATCH 1/2] Fixed JIT segfault on ZTS this happens when one thread tries to compile a script while another thread is already executing some code. This was discovered while updating my fork of ext-pthreads to PHP 8.0. --- ext/opcache/jit/zend_jit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index a983a818a9ee0..02d8868483ff4 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -3962,7 +3962,7 @@ ZEND_EXT_API void zend_jit_unprotect(void) { #ifdef HAVE_MPROTECT if (!(JIT_G(debug) & (ZEND_JIT_DEBUG_GDB|ZEND_JIT_DEBUG_PERF_DUMP))) { - if (mprotect(dasm_buf, dasm_size, PROT_READ | PROT_WRITE) != 0) { + if (mprotect(dasm_buf, dasm_size, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) { fprintf(stderr, "mprotect() failed [%d] %s\n", errno, strerror(errno)); } } @@ -3970,7 +3970,7 @@ ZEND_EXT_API void zend_jit_unprotect(void) if (!(JIT_G(debug) & (ZEND_JIT_DEBUG_GDB|ZEND_JIT_DEBUG_PERF_DUMP))) { DWORD old; - if (!VirtualProtect(dasm_buf, dasm_size, PAGE_READWRITE, &old)) { + if (!VirtualProtect(dasm_buf, dasm_size, PAGE_EXECUTE_READWRITE, &old)) { DWORD err = GetLastError(); char *msg = php_win32_error_to_msg(err); fprintf(stderr, "VirtualProtect() failed [%u] %s\n", err, msg); From b235664cbc652c88797c729b4797a83614d668f5 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 18 Jan 2021 14:56:54 +0000 Subject: [PATCH 2/2] Limit RWX usage to ZTS only NTS is not affected because only one thread will be running code in any process at a time. --- ext/opcache/jit/zend_jit.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 02d8868483ff4..c46b86dcca2d3 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -3962,15 +3962,23 @@ ZEND_EXT_API void zend_jit_unprotect(void) { #ifdef HAVE_MPROTECT if (!(JIT_G(debug) & (ZEND_JIT_DEBUG_GDB|ZEND_JIT_DEBUG_PERF_DUMP))) { - if (mprotect(dasm_buf, dasm_size, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) { + int opts = PROT_READ | PROT_WRITE; +#ifdef ZTS + opts |= PROT_EXEC; +#endif + if (mprotect(dasm_buf, dasm_size, opts) != 0) { fprintf(stderr, "mprotect() failed [%d] %s\n", errno, strerror(errno)); } } #elif _WIN32 if (!(JIT_G(debug) & (ZEND_JIT_DEBUG_GDB|ZEND_JIT_DEBUG_PERF_DUMP))) { - DWORD old; - - if (!VirtualProtect(dasm_buf, dasm_size, PAGE_EXECUTE_READWRITE, &old)) { + DWORD old, new; +#ifdef ZTS + new = PAGE_EXECUTE_READWRITE; +#else + new = PAGE_READWRITE; +#endif + if (!VirtualProtect(dasm_buf, dasm_size, new, &old)) { DWORD err = GetLastError(); char *msg = php_win32_error_to_msg(err); fprintf(stderr, "VirtualProtect() failed [%u] %s\n", err, msg);