Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix appsec tests in 8.1-8.3 #2974

Merged
merged 1 commit into from
Nov 28, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading