ext/oci8/oci8lib.c in ruby-oci8-2.2.13 vs ext/oci8/oci8lib.c in ruby-oci8-2.2.14

- old
+ new

@@ -7,10 +7,11 @@ #ifdef HAVE_RUBY_THREAD_H #include <ruby/thread.h> #endif #if defined(HAVE_PLTHOOK) && !defined(WIN32) #include <dlfcn.h> +#include <sys/mman.h> #include "plthook.h" #endif ID oci8_id_at_last_error; ID oci8_id_get; @@ -133,10 +134,12 @@ unsigned int pos = 0; const char *name; void **addr; const char *prefix; size_t prefix_len; + int prot; + size_t page_size = sysconf(_SC_PAGESIZE); #ifdef RTLD_FIRST flags |= RTLD_FIRST; /* for macOS */ #endif @@ -159,11 +162,11 @@ if (prefix == NULL) { dlclose(handle); plthook_close(ph); return; } - while (plthook_enum(ph, &pos, &name, &addr) == 0) { + while (plthook_enum_with_prot(ph, &pos, &name, &addr, &prot) == 0) { void *funcaddr; if (prefix_len != 0) { if (strncmp(name, prefix, prefix_len) != 0) { continue; } @@ -177,10 +180,20 @@ if (funcaddr != NULL && *addr != funcaddr) { /* If libclntsh.so exports and imports same functions, their * PLT entries are forcedly modified to point to itself not * to use functions in other libraries. */ +#define ALIGN_ADDR(addr) ((void*)((size_t)(addr) & ~(page_size - 1))) + if ((prot & PROT_WRITE) == 0) { + /* when the region containing addr isn't writable, make it writable temporarily */ + if (mprotect(ALIGN_ADDR(addr), page_size, PROT_READ | PROT_WRITE) != 0) { + continue; + } + } *addr = funcaddr; + if ((prot & PROT_WRITE) == 0) { + mprotect(ALIGN_ADDR(addr), page_size, prot); + } } } plthook_close(ph); dlclose(handle); }