Skip to content

Commit

Permalink
Merge pull request #2974 from DataDog/glopes/fix-appsec-test-pipe
Browse files Browse the repository at this point in the history
Fix appsec tests in 8.1-8.3
  • Loading branch information
cataphract authored Nov 28, 2024
2 parents 76bb60b + 21dcf99 commit 0c6532b
Showing 1 changed file with 63 additions and 12 deletions.
75 changes: 63 additions & 12 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,68 @@ 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));
uintptr_t last_page_addr = ((uintptr_t)(addr + size - 1) & ~(page_size - 1));

unsigned char vec[2];
#ifdef __x86_64__
#define SYS_mincore 0x1B
#else // aarch64
#define SYS_mincore 0xE8
#endif

int retries = 5;
again:
if (syscall(SYS_mincore, page_addr, (1 + (page_addr != last_page_addr)) * page_size, &vec) == 0) {
return true;
} else if (errno == EFAULT || errno == ENOMEM) {
return false;
} else if (errno == EAGAIN) {
if (retries-- > 0) {
goto again;
}
return true;
} else {
// we don't know... assume true
#ifdef ZEND_DEBUG
abort();
#else
return true;
#endif
}
}
#elif defined(__APPLE__) && PHP_VERSION_ID < 80400
#include <mach/mach.h>
static bool is_mapped(void *addr, size_t size) {
mach_port_t task = mach_task_self();
vm_address_t address = (vm_address_t)addr;

while (address < (vm_address_t)addr + size) {
__auto_type a = address;
vm_size_t region_size;
vm_region_basic_info_data_64_t info;
kern_return_t kr = vm_region_64(task, &address, &region_size, VM_REGION_BASIC_INFO, (vm_region_info_t)&info,
&(mach_msg_type_number_t){VM_REGION_BASIC_INFO_COUNT_64}, &(memory_object_name_t){0});

if (kr != KERN_SUCCESS || !(info.protection & VM_PROT_READ)) {
return false;
}

address += region_size;
}

return true;
}
#else
static inline bool is_mapped(...) {
return true;
}
#endif

void zai_jit_blacklist_function_inlining(zend_op_array *op_array) {
#if PHP_VERSION_ID >= 80400
if (opcache_handle) {
Expand All @@ -210,15 +265,11 @@ void zai_jit_blacklist_function_inlining(zend_op_array *op_array) {

size_t offset = jit_extension->offset;

#ifndef _WIN32
// 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)) {
bool is_protected_memory = false;
Expand Down

0 comments on commit 0c6532b

Please sign in to comment.