Skip to content

Commit

Permalink
Fix appsec tests in 8.1-8.3
Browse files Browse the repository at this point in the history
The use of pipe() creates an extra file descriptor which makes the
helper unable to find the correct pipe file descriptor. While this could
perhaps be improved by telling the helper explicitly the id of the
correct file descriptor, it's probably better to swap write() calls of
reading invalid addresses with mincore().
  • Loading branch information
cataphract committed Nov 22, 2024
1 parent 35d1665 commit 627c44a
Showing 1 changed file with 38 additions and 11 deletions.
49 changes: 38 additions & 11 deletions zend_abstract_interface/jit_utils/jit_blacklist.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,6 @@ typedef union _zend_op_trace_info {

#define ZEND_OP_TRACE_INFO(opline, offset) \
((zend_op_trace_info*)(((char*)opline) + offset))

#ifndef _WIN32
static int dd_probe_pipes[2];
#endif
#endif

#define ZEND_FUNC_INFO(op_array) \
Expand All @@ -107,9 +103,6 @@ static void zai_jit_find_opcache_handle(void *ext) {

// opcache startup NULLs its handle. MINIT is executed before extension startup.
void zai_jit_minit(void) {
#if PHP_VERSION_ID < 80400 && !defined(_WIN32)
pipe(dd_probe_pipes);
#endif
zend_llist_apply(&zend_extensions, zai_jit_find_opcache_handle);
}

Expand Down Expand Up @@ -185,6 +178,42 @@ int zai_get_zend_func_rid(zend_op_array *op_array) {
return zend_func_info_rid;
}

#if defined(__linux__) && (defined(__x86_64__) || defined(__aarch64__)) && PHP_VERSION_ID < 80400
static bool is_mapped(void *addr, size_t size) {
uintptr_t page_size = sysconf(_SC_PAGESIZE);
assert(size <= page_size);
uintptr_t page_addr = ((uintptr_t)addr & ~(page_size - 1));
unsigned char vec;

uintptr_t last_page_addr = ((uintptr_t)(addr + size - 1) & ~(page_size - 1));

#ifdef __x86_64__
#define SYS_mincore 0x1B
#else // aarch64
#define SYS_mincore 0xE8
#endif

again:
if (syscall(SYS_mincore, page_addr, page_size, &vec) == 0) {
if (page_addr == last_page_addr) {
return true;
} else {
page_addr = last_page_addr;
goto again;
}
} else if (errno == EFAULT || errno == ENOMEM) {
return false;
} else {
// we don't know... asume true
#ifdef ZEND_DEBUG
abort();
#else
return true;
#endif
}
}
#endif

void zai_jit_blacklist_function_inlining(zend_op_array *op_array) {
#if PHP_VERSION_ID >= 80400
if (opcache_handle) {
Expand All @@ -210,14 +239,12 @@ void zai_jit_blacklist_function_inlining(zend_op_array *op_array) {

size_t offset = jit_extension->offset;

#ifndef _WIN32
#if defined(__linux__) && (defined(__x86_64__) || defined(__aarch64__))
// check whether the op_trace_info is actually readable or EFAULTing
// we can't trust opcache too much here...
char dummy_buf[sizeof(zend_op_trace_info)];
if (write(dd_probe_pipes[1], ZEND_OP_TRACE_INFO(opline, offset), sizeof(zend_op_trace_info)) < 0) {
if (!is_mapped(ZEND_OP_TRACE_INFO(opline, offset), sizeof(zend_op_trace_info))) {
return;
}
read(dd_probe_pipes[0], dummy_buf, sizeof(zend_op_trace_info));
#endif

if (!(ZEND_OP_TRACE_INFO(opline, offset)->trace_flags & ZEND_JIT_TRACE_BLACKLISTED)) {
Expand Down

0 comments on commit 627c44a

Please sign in to comment.