Fix #81679: Tracing JIT crashes on reattaching

When a new process reattaches to OPcache, tracing JIT causes segfaults,
because each new process allocates its own `zend_jit_traces` and
`zend_jit_exit_groups` in SHM, although these need to be shared between
all processes.

We solve that by only allocating these structs for the first process,
and store the pointers in `accel_shared_globals`, so we can reassign
them when a new process reattaches.

Closes GH-7776.
This commit is contained in:
Christoph M. Becker 2021-12-15 11:47:44 +01:00
parent cd8e6f5f7b
commit 49380b59d2
No known key found for this signature in database
GPG Key ID: D66C9593118BCCB6
4 changed files with 33 additions and 13 deletions

3
NEWS
View File

@ -15,6 +15,9 @@ PHP NEWS
. Fixed bug GH-7765 (php_oci_cleanup_global_handles segfaults at second
call). (cmb)
- OPcache:
. Fixed bug #81679 (Tracing JIT crashes on reattaching). (cmb)
- PDO_PGSQL:
. Fixed error message allocation of PDO PgSQL. (SATO Kentaro)

View File

@ -285,6 +285,10 @@ typedef struct _zend_accel_shared_globals {
/* uninitialized HashTable Support */
uint32_t uninitialized_bucket[-HT_MIN_MASK];
/* Tracing JIT */
void *jit_traces;
const void **jit_exit_groups;
/* Interned Strings Support (must be the last element) */
zend_string_table interned_strings;
} zend_accel_shared_globals;

View File

@ -4390,7 +4390,7 @@ ZEND_EXT_API int zend_jit_startup(void *buf, size_t size, zend_bool reattached)
#endif
}
if (zend_jit_trace_startup() != SUCCESS) {
if (zend_jit_trace_startup(reattached) != SUCCESS) {
return FAILURE;
}

View File

@ -48,20 +48,33 @@ static zend_always_inline const char *zend_jit_trace_star_desc(uint8_t trace_fla
}
}
static int zend_jit_trace_startup(void)
static int zend_jit_trace_startup(zend_bool reattached)
{
zend_jit_traces = (zend_jit_trace_info*)zend_shared_alloc(sizeof(zend_jit_trace_info) * JIT_G(max_root_traces));
if (!zend_jit_traces) {
return FAILURE;
if (!reattached) {
zend_jit_traces = (zend_jit_trace_info*)zend_shared_alloc(sizeof(zend_jit_trace_info) * JIT_G(max_root_traces));
if (!zend_jit_traces) {
return FAILURE;
}
zend_jit_exit_groups = (const void**)zend_shared_alloc(sizeof(void*) * (ZEND_JIT_TRACE_MAX_EXITS/ZEND_JIT_EXIT_POINTS_PER_GROUP));
if (!zend_jit_exit_groups) {
return FAILURE;
}
ZEND_JIT_TRACE_NUM = 1;
ZEND_JIT_COUNTER_NUM = 0;
ZEND_JIT_EXIT_NUM = 0;
ZEND_JIT_EXIT_COUNTERS = 0;
ZCSG(jit_traces) = zend_jit_traces;
ZCSG(jit_exit_groups) = zend_jit_exit_groups;
} else {
zend_jit_traces = ZCSG(jit_traces);
if (!zend_jit_traces) {
return FAILURE;
}
zend_jit_exit_groups = ZCSG(jit_exit_groups);
if (!zend_jit_exit_groups) {
return FAILURE;
}
}
zend_jit_exit_groups = (const void**)zend_shared_alloc(sizeof(void*) * (ZEND_JIT_TRACE_MAX_EXITS/ZEND_JIT_EXIT_POINTS_PER_GROUP));
if (!zend_jit_exit_groups) {
return FAILURE;
}
ZEND_JIT_TRACE_NUM = 1;
ZEND_JIT_COUNTER_NUM = 0;
ZEND_JIT_EXIT_NUM = 0;
ZEND_JIT_EXIT_COUNTERS = 0;
memset(&dummy_op_array, 0, sizeof(dummy_op_array));
dummy_op_array.fn_flags = ZEND_ACC_DONE_PASS_TWO;