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);
}