]> granicus.if.org Git - php/commitdiff
Keep JIT region executable under ZTS
authorDylan K. Taylor <dktapps@pmmp.io>
Mon, 11 Jan 2021 22:39:14 +0000 (22:39 +0000)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 19 Jan 2021 09:25:42 +0000 (10:25 +0100)
When one thread tries to compile a script, another thread may
already be executing JITed code. In this case we can't make the
memory non-executable.

This violates the W^X principle, but doesn't seem to be avoidable
for ZTS builds for now. The same problem does not exist for NTS,
as it's a different process executing there, which has it's own
memory protection mapping.

Closes GH-6595.

ext/opcache/jit/zend_jit.c

index a983a818a9ee0a2b652a7ae6e798ee622c449310..1306bb36ba015b0b693483173205d9a34b72dd11 100644 (file)
@@ -3962,15 +3962,24 @@ 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) {
+               int opts = PROT_READ | PROT_WRITE;
+#ifdef ZTS
+               /* Another thread may be executing JITed code. */
+               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_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);