ruby-oci8 2.2.13 → 2.2.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1db88cf1bfe7291cc597bd695db32ea0e730734650c3bdfd40b9295663d0ac5e
4
- data.tar.gz: 96f6b1b9fff2ba6067421d588495298cb14b5d42aa1fe7d4257c18431fdca654
3
+ metadata.gz: 1e144a61c64f6856db08e6e473ac4531dd008c967bad30f48bf6a6852c7fc623
4
+ data.tar.gz: e35589ae71e41de3d0b77ca04dfa4bc0aa761272915c5e4d2cabcb955b4923d8
5
5
  SHA512:
6
- metadata.gz: da88c45ce3e73abb6cf30ad9633286204c3869a7b5e5f8e5acaeb90a824f7bb91d842c7da807e4639ff6993cf6d2bae96f9f5fe8cd64144f836eeca61c7fc85f
7
- data.tar.gz: '088b13f4df8245aa95abdb2e2bf744c2088fa3fe87ffd5ffcdfedf0b43a724630d9a3603468269e6bf5790c4480d4e85a79a28af4db18bd05310b39c7dafed74'
6
+ metadata.gz: 474b19d0d1a92f1cd52e0b12babeff15c4ccdeb076a3b523b61ad8d7fdc9b0bab99715af698b83cf841b114880f111e727f0dbd8e583ca4263b30fb28a2621f7
7
+ data.tar.gz: '079389be6f6662ae81795da0c0e4c7ba81bee27a1724032cf2c7de652f5282d0201d4f3ffec9eaa6e74d2e068abb96097912d3417d5c65cb084ed02c51e6d89b'
data/NEWS CHANGED
@@ -1,5 +1,13 @@
1
1
  # @markup markdown
2
2
 
3
+ 2.2.14 (2024-08-06)
4
+ ===================
5
+
6
+ Fixed issues
7
+ ------------
8
+
9
+ - Fix SIGSEGV when nokogiri is loaded before oci8 (GH-263 - Linux only)
10
+
3
11
  2.2.13 (2024-07-27)
4
12
  ===================
5
13
 
data/ext/oci8/oci8lib.c CHANGED
@@ -9,6 +9,7 @@
9
9
  #endif
10
10
  #if defined(HAVE_PLTHOOK) && !defined(WIN32)
11
11
  #include <dlfcn.h>
12
+ #include <sys/mman.h>
12
13
  #include "plthook.h"
13
14
  #endif
14
15
 
@@ -135,6 +136,8 @@ static void rebind_internal_symbols(void)
135
136
  void **addr;
136
137
  const char *prefix;
137
138
  size_t prefix_len;
139
+ int prot;
140
+ size_t page_size = sysconf(_SC_PAGESIZE);
138
141
 
139
142
  #ifdef RTLD_FIRST
140
143
  flags |= RTLD_FIRST; /* for macOS */
@@ -161,7 +164,7 @@ static void rebind_internal_symbols(void)
161
164
  plthook_close(ph);
162
165
  return;
163
166
  }
164
- while (plthook_enum(ph, &pos, &name, &addr) == 0) {
167
+ while (plthook_enum_with_prot(ph, &pos, &name, &addr, &prot) == 0) {
165
168
  void *funcaddr;
166
169
  if (prefix_len != 0) {
167
170
  if (strncmp(name, prefix, prefix_len) != 0) {
@@ -179,7 +182,17 @@ static void rebind_internal_symbols(void)
179
182
  * PLT entries are forcedly modified to point to itself not
180
183
  * to use functions in other libraries.
181
184
  */
185
+ #define ALIGN_ADDR(addr) ((void*)((size_t)(addr) & ~(page_size - 1)))
186
+ if ((prot & PROT_WRITE) == 0) {
187
+ /* when the region containing addr isn't writable, make it writable temporarily */
188
+ if (mprotect(ALIGN_ADDR(addr), page_size, PROT_READ | PROT_WRITE) != 0) {
189
+ continue;
190
+ }
191
+ }
182
192
  *addr = funcaddr;
193
+ if ((prot & PROT_WRITE) == 0) {
194
+ mprotect(ALIGN_ADDR(addr), page_size, prot);
195
+ }
183
196
  }
184
197
  }
185
198
  plthook_close(ph);
data/ext/oci8/plthook.h CHANGED
@@ -59,8 +59,14 @@ int plthook_replace(plthook_t *plthook, const char *funcname, void *funcaddr, vo
59
59
  void plthook_close(plthook_t *plthook);
60
60
  const char *plthook_error(void);
61
61
 
62
+ /* enumerate entries with memory protection information (bitwise-OR of PROT_READ, PROT_WRITE and PROT_EXEC)
63
+ *
64
+ * source: plthook_elf.c and plthook_osx.c
65
+ */
66
+ int plthook_enum_with_prot(plthook_t *plthook, unsigned int *pos, const char **name_out, void ***addr_out, int *prot);
67
+
62
68
  #ifdef __cplusplus
63
- }; /* extern "C" */
69
+ } /* extern "C" */
64
70
  #endif
65
71
 
66
72
  #endif
@@ -187,6 +187,14 @@
187
187
  #endif
188
188
  #endif /* __LP64__ */
189
189
 
190
+ typedef struct mem_prot {
191
+ size_t start;
192
+ size_t end;
193
+ int prot;
194
+ } mem_prot_t;
195
+
196
+ #define NUM_MEM_PROT 20
197
+
190
198
  struct plthook {
191
199
  const Elf_Sym *dynsym;
192
200
  const char *dynstr;
@@ -198,6 +206,7 @@ struct plthook {
198
206
  const Elf_Plt_Rel *rela_dyn;
199
207
  size_t rela_dyn_cnt;
200
208
  #endif
209
+ mem_prot_t mem_prot[NUM_MEM_PROT];
201
210
  };
202
211
 
203
212
  static char errmsg[512];
@@ -207,7 +216,15 @@ static size_t page_size;
207
216
  static int plthook_open_executable(plthook_t **plthook_out);
208
217
  static int plthook_open_shared_library(plthook_t **plthook_out, const char *filename);
209
218
  static const Elf_Dyn *find_dyn_by_tag(const Elf_Dyn *dyn, Elf_Sxword tag);
219
+
220
+ typedef struct mem_prot_iter mem_prot_iter_t;
221
+ static int mem_prot_begin(mem_prot_iter_t *iter);
222
+ static int mem_prot_next(mem_prot_iter_t *iter, mem_prot_t *mem_prot);
223
+ static void mem_prot_end(mem_prot_iter_t *iter);
224
+
210
225
  static int plthook_open_real(plthook_t **plthook_out, struct link_map *lmap);
226
+ static int plthook_set_mem_prot(plthook_t *plthook);
227
+ static int plthook_get_mem_prot(plthook_t *plthook, void *addr);
211
228
  #if defined __FreeBSD__ || defined __sun
212
229
  static int check_elf_header(const Elf_Ehdr *ehdr);
213
230
  #endif
@@ -397,22 +414,29 @@ static const Elf_Dyn *find_dyn_by_tag(const Elf_Dyn *dyn, Elf_Sxword tag)
397
414
  }
398
415
 
399
416
  #ifdef __linux__
400
- static int get_memory_permission(void *address)
401
- {
402
- unsigned long addr = (unsigned long)address;
417
+ struct mem_prot_iter {
403
418
  FILE *fp;
404
- char buf[PATH_MAX];
405
- char perms[5];
406
- int bol = 1;
419
+ };
407
420
 
408
- fp = fopen("/proc/self/maps", "r");
409
- if (fp == NULL) {
421
+ static int mem_prot_begin(mem_prot_iter_t *iter)
422
+ {
423
+ iter->fp = fopen("/proc/self/maps", "r");
424
+ if (iter->fp == NULL) {
410
425
  set_errmsg("failed to open /proc/self/maps");
411
- return 0;
426
+ return -1;
412
427
  }
413
- while (fgets(buf, PATH_MAX, fp) != NULL) {
428
+ return 0;
429
+ }
430
+
431
+ static int mem_prot_next(mem_prot_iter_t *iter, mem_prot_t *mem_prot)
432
+ {
433
+ char buf[PATH_MAX];
434
+ char perms[5];
435
+ int bol = 1; /* beginnng of line */
436
+
437
+ while (fgets(buf, PATH_MAX, iter->fp) != NULL) {
414
438
  unsigned long start, end;
415
- int eol = (strchr(buf, '\n') != NULL);
439
+ int eol = (strchr(buf, '\n') != NULL); /* end of line */
416
440
  if (bol) {
417
441
  /* The fgets reads from the beginning of a line. */
418
442
  if (!eol) {
@@ -431,121 +455,126 @@ static int get_memory_permission(void *address)
431
455
  if (sscanf(buf, "%lx-%lx %4s", &start, &end, perms) != 3) {
432
456
  continue;
433
457
  }
434
- if (start <= addr && addr < end) {
435
- int prot = 0;
436
- if (perms[0] == 'r') {
437
- prot |= PROT_READ;
438
- } else if (perms[0] != '-') {
439
- goto unknown_perms;
440
- }
441
- if (perms[1] == 'w') {
442
- prot |= PROT_WRITE;
443
- } else if (perms[1] != '-') {
444
- goto unknown_perms;
445
- }
446
- if (perms[2] == 'x') {
447
- prot |= PROT_EXEC;
448
- } else if (perms[2] != '-') {
449
- goto unknown_perms;
450
- }
451
- if (perms[3] != 'p') {
452
- goto unknown_perms;
453
- }
454
- if (perms[4] != '\0') {
455
- perms[4] = '\0';
456
- goto unknown_perms;
457
- }
458
- fclose(fp);
459
- return prot;
458
+ mem_prot->start = start;
459
+ mem_prot->end = end;
460
+ mem_prot->prot = 0;
461
+ if (perms[0] == 'r') {
462
+ mem_prot->prot |= PROT_READ;
463
+ }
464
+ if (perms[1] == 'w') {
465
+ mem_prot->prot |= PROT_WRITE;
460
466
  }
467
+ if (perms[2] == 'x') {
468
+ mem_prot->prot |= PROT_EXEC;
469
+ }
470
+ return 0;
461
471
  }
462
- fclose(fp);
463
- set_errmsg("Could not find memory region containing %p", (void*)addr);
464
- return 0;
465
- unknown_perms:
466
- fclose(fp);
467
- set_errmsg("Unexcepted memory permission %s at %p", perms, (void*)addr);
468
- return 0;
472
+ return -1;
469
473
  }
470
- #elif defined __FreeBSD__
471
- static int get_memory_permission(void *address)
474
+
475
+ static void mem_prot_end(mem_prot_iter_t *iter)
472
476
  {
473
- uint64_t addr = (uint64_t)address;
474
- struct kinfo_vmentry *top;
475
- int i, cnt;
477
+ if (iter->fp != NULL) {
478
+ fclose(iter->fp);
479
+ }
480
+ }
481
+ #elif defined __FreeBSD__
482
+ struct mem_prot_iter {
483
+ struct kinfo_vmentry *kve;
484
+ int idx;
485
+ int num;
486
+ };
476
487
 
477
- top = kinfo_getvmmap(getpid(), &cnt);
478
- if (top == NULL) {
488
+ static int mem_prot_begin(mem_prot_iter_t *iter)
489
+ {
490
+ iter->kve = kinfo_getvmmap(getpid(), &iter->num);
491
+ if (iter->kve == NULL) {
479
492
  set_errmsg("failed to call kinfo_getvmmap()\n");
480
- return 0;
493
+ return -1;
481
494
  }
482
- for (i = 0; i < cnt; i++) {
483
- struct kinfo_vmentry *kve = top + i;
495
+ iter->idx = 0;
496
+ return 0;
497
+ }
484
498
 
485
- if (kve->kve_start <= addr && addr < kve->kve_end) {
486
- int prot = 0;
487
- if (kve->kve_protection & KVME_PROT_READ) {
488
- prot |= PROT_READ;
489
- }
490
- if (kve->kve_protection & KVME_PROT_WRITE) {
491
- prot |= PROT_WRITE;
492
- }
493
- if (kve->kve_protection & KVME_PROT_EXEC) {
494
- prot |= PROT_EXEC;
495
- }
496
- if (prot == 0) {
497
- set_errmsg("Unknown kve_protection 0x%x at %p", kve->kve_protection, (void*)addr);
498
- }
499
- free(top);
500
- return prot;
501
- }
499
+ static int mem_prot_next(mem_prot_iter_t *iter, mem_prot_t *mem_prot)
500
+ {
501
+ if (iter->idx >= iter->num) {
502
+ return -1;
503
+ }
504
+ struct kinfo_vmentry *kve = &iter->kve[iter->idx++];
505
+ mem_prot->start = kve->kve_start;
506
+ mem_prot->end = kve->kve_end;
507
+ mem_prot->prot = 0;
508
+ if (kve->kve_protection & KVME_PROT_READ) {
509
+ mem_prot->prot |= PROT_READ;
510
+ }
511
+ if (kve->kve_protection & KVME_PROT_WRITE) {
512
+ mem_prot->prot |= PROT_WRITE;
513
+ }
514
+ if (kve->kve_protection & KVME_PROT_EXEC) {
515
+ mem_prot->prot |= PROT_EXEC;
502
516
  }
503
- free(top);
504
- set_errmsg("Could not find memory region containing %p", (void*)addr);
505
517
  return 0;
506
518
  }
507
- #elif defined(__sun)
508
- #define NUM_MAPS 20
509
- static int get_memory_permission(void *address)
519
+
520
+ static void mem_prot_end(mem_prot_iter_t *iter)
510
521
  {
511
- unsigned long addr = (unsigned long)address;
522
+ if (iter->kve != NULL) {
523
+ free(iter->kve);
524
+ }
525
+ }
526
+ #elif defined(__sun)
527
+ struct mem_prot_iter {
512
528
  FILE *fp;
513
- prmap_t maps[NUM_MAPS];
529
+ prmap_t maps[20];
530
+ size_t idx;
514
531
  size_t num;
532
+ };
515
533
 
516
- fp = fopen("/proc/self/map", "r");
517
- if (fp == NULL) {
534
+ static int mem_prot_begin(mem_prot_iter_t *iter)
535
+ {
536
+ iter->fp = fopen("/proc/self/map", "r");
537
+ if (iter->fp == NULL) {
518
538
  set_errmsg("failed to open /proc/self/map");
519
- return 0;
539
+ return -1;
520
540
  }
521
- while ((num = fread(maps, sizeof(prmap_t), NUM_MAPS, fp)) > 0) {
522
- size_t i;
523
- for (i = 0; i < num; i++) {
524
- prmap_t *map = &maps[i];
541
+ iter->idx = iter->num = 0;
542
+ return 0;
543
+ }
525
544
 
526
- if (map->pr_vaddr <= addr && addr < map->pr_vaddr + map->pr_size) {
527
- int prot = 0;
528
- if (map->pr_mflags & MA_READ) {
529
- prot |= PROT_READ;
530
- }
531
- if (map->pr_mflags & MA_WRITE) {
532
- prot |= PROT_WRITE;
533
- }
534
- if (map->pr_mflags & MA_EXEC) {
535
- prot |= PROT_EXEC;
536
- }
537
- if (prot == 0) {
538
- set_errmsg("Unknown pr_mflags 0x%x at %p", map->pr_mflags, (void*)addr);
539
- }
540
- fclose(fp);
541
- return prot;
542
- }
545
+ static int mem_prot_next(mem_prot_iter_t *iter, mem_prot_t *mem_prot)
546
+ {
547
+ prmap_t *map;
548
+
549
+ if (iter->idx == iter->num) {
550
+ iter->num = fread(iter->maps, sizeof(iter->maps[0]), sizeof(iter->maps) / sizeof(iter->maps[0]), iter->fp);
551
+ if (iter->num == 0) {
552
+ return -1;
543
553
  }
554
+ iter->idx = 0;
555
+ }
556
+ map = &iter->maps[iter->idx++];
557
+ mem_prot->start = map->pr_vaddr;
558
+ mem_prot->end = map->pr_vaddr + map->pr_size;
559
+ mem_prot->prot = 0;
560
+ if (map->pr_mflags & MA_READ) {
561
+ mem_prot->prot |= PROT_READ;
562
+ }
563
+ if (map->pr_mflags & MA_WRITE) {
564
+ mem_prot->prot |= PROT_WRITE;
565
+ }
566
+ if (map->pr_mflags & MA_EXEC) {
567
+ mem_prot->prot |= PROT_EXEC;
544
568
  }
545
- fclose(fp);
546
- set_errmsg("Could not find memory region containing %p", (void*)addr);
547
569
  return 0;
548
570
  }
571
+
572
+ static void mem_prot_end(mem_prot_iter_t *iter)
573
+ {
574
+ if (iter->fp != NULL) {
575
+ fclose(iter->fp);
576
+ }
577
+ }
549
578
  #else
550
579
  #error Unsupported platform
551
580
  #endif
@@ -572,7 +601,11 @@ static int plthook_open_real(plthook_t **plthook_out, struct link_map *lmap)
572
601
  dyn_addr_base = (const char*)lmap->l_addr;
573
602
  #endif
574
603
  #elif defined __FreeBSD__ || defined __sun
604
+ #if __FreeBSD__ >= 13
605
+ const Elf_Ehdr *ehdr = (const Elf_Ehdr*)lmap->l_base;
606
+ #else
575
607
  const Elf_Ehdr *ehdr = (const Elf_Ehdr*)lmap->l_addr;
608
+ #endif
576
609
  int rv_ = check_elf_header(ehdr);
577
610
  if (rv_ != 0) {
578
611
  return rv_;
@@ -666,6 +699,9 @@ static int plthook_open_real(plthook_t **plthook_out, struct link_map *lmap)
666
699
  return PLTHOOK_INTERNAL_ERROR;
667
700
  }
668
701
  #endif
702
+ if (plthook_set_mem_prot(&plthook)) {
703
+ return PLTHOOK_INTERNAL_ERROR;
704
+ }
669
705
 
670
706
  *plthook_out = malloc(sizeof(plthook_t));
671
707
  if (*plthook_out == NULL) {
@@ -676,6 +712,53 @@ static int plthook_open_real(plthook_t **plthook_out, struct link_map *lmap)
676
712
  return 0;
677
713
  }
678
714
 
715
+ static int plthook_set_mem_prot(plthook_t *plthook)
716
+ {
717
+ unsigned int pos = 0;
718
+ const char *name;
719
+ void **addr;
720
+ size_t start = (size_t)-1;
721
+ size_t end = 0;
722
+ mem_prot_iter_t iter;
723
+ mem_prot_t mem_prot;
724
+ int idx = 0;
725
+
726
+ while (plthook_enum(plthook, &pos, &name, &addr) == 0) {
727
+ if (start > (size_t)addr) {
728
+ start = (size_t)addr;
729
+ }
730
+ if (end < (size_t)addr) {
731
+ end = (size_t)addr;
732
+ }
733
+ }
734
+ end++;
735
+
736
+ if (mem_prot_begin(&iter) != 0) {
737
+ return PLTHOOK_INTERNAL_ERROR;
738
+ }
739
+ while (mem_prot_next(&iter, &mem_prot) == 0 && idx < NUM_MEM_PROT) {
740
+ if (mem_prot.prot != 0 && mem_prot.start < end && start < mem_prot.end) {
741
+ plthook->mem_prot[idx++] = mem_prot;
742
+ }
743
+ }
744
+ mem_prot_end(&iter);
745
+ return 0;
746
+ }
747
+
748
+ static int plthook_get_mem_prot(plthook_t *plthook, void *addr)
749
+ {
750
+ mem_prot_t *ptr = plthook->mem_prot;
751
+ mem_prot_t *end = ptr + NUM_MEM_PROT;
752
+
753
+ while (ptr < end && ptr->prot != 0) {
754
+ if (ptr->start <= (size_t)addr && (size_t)addr < ptr->end) {
755
+ return ptr->prot;
756
+ }
757
+ ++ptr;
758
+ }
759
+ return 0;
760
+ }
761
+
679
762
  #if defined __FreeBSD__ || defined __sun
680
763
  static int check_elf_header(const Elf_Ehdr *ehdr)
681
764
  {
@@ -742,12 +825,20 @@ static int check_rel(const plthook_t *plthook, const Elf_Plt_Rel *plt, Elf_Xword
742
825
  }
743
826
 
744
827
  int plthook_enum(plthook_t *plthook, unsigned int *pos, const char **name_out, void ***addr_out)
828
+ {
829
+ return plthook_enum_with_prot(plthook, pos, name_out, addr_out, NULL);
830
+ }
831
+
832
+ int plthook_enum_with_prot(plthook_t *plthook, unsigned int *pos, const char **name_out, void ***addr_out, int *prot)
745
833
  {
746
834
  while (*pos < plthook->rela_plt_cnt) {
747
835
  const Elf_Plt_Rel *plt = plthook->rela_plt + *pos;
748
836
  int rv = check_rel(plthook, plt, R_JUMP_SLOT, name_out, addr_out);
749
837
  (*pos)++;
750
838
  if (rv >= 0) {
839
+ if (rv == 0 && prot != NULL) {
840
+ *prot = plthook_get_mem_prot(plthook, *addr_out);
841
+ }
751
842
  return rv;
752
843
  }
753
844
  }
@@ -757,6 +848,9 @@ int plthook_enum(plthook_t *plthook, unsigned int *pos, const char **name_out, v
757
848
  int rv = check_rel(plthook, plt, R_GLOBAL_DATA, name_out, addr_out);
758
849
  (*pos)++;
759
850
  if (rv >= 0) {
851
+ if (rv == 0 && prot != NULL) {
852
+ *prot = plthook_get_mem_prot(plthook, *addr_out);
853
+ }
760
854
  return rv;
761
855
  }
762
856
  }
@@ -781,8 +875,10 @@ int plthook_replace(plthook_t *plthook, const char *funcname, void *funcaddr, vo
781
875
  while ((rv = plthook_enum(plthook, &pos, &name, &addr)) == 0) {
782
876
  if (strncmp(name, funcname, funcnamelen) == 0) {
783
877
  if (name[funcnamelen] == '\0' || name[funcnamelen] == '@') {
784
- int prot = get_memory_permission(addr);
878
+ int prot = plthook_get_mem_prot(plthook, addr);
785
879
  if (prot == 0) {
880
+ set_errmsg("Could not get the process memory permission at %p",
881
+ ALIGN_ADDR(addr));
786
882
  return PLTHOOK_INTERNAL_ERROR;
787
883
  }
788
884
  if (!(prot & PROT_WRITE)) {
@@ -41,6 +41,7 @@
41
41
  #include <inttypes.h>
42
42
  #include <dlfcn.h>
43
43
  #include <errno.h>
44
+ #include <mach/mach.h>
44
45
  #include <mach-o/dyld.h>
45
46
  #include <sys/mman.h>
46
47
  #include <mach-o/fixup-chains.h>
@@ -152,9 +153,17 @@ typedef struct {
152
153
  void **addr;
153
154
  } bind_address_t;
154
155
 
156
+ typedef struct mem_prot {
157
+ size_t start;
158
+ size_t end;
159
+ int prot;
160
+ } mem_prot_t;
161
+
162
+ #define NUM_MEM_PROT 100
163
+
155
164
  struct plthook {
156
165
  unsigned int num_entries;
157
- int readonly_segment;
166
+ mem_prot_t mem_prot[NUM_MEM_PROT];
158
167
  bind_address_t entries[1]; /* This must be the last. */
159
168
  };
160
169
 
@@ -174,6 +183,8 @@ static int plthook_open_real(plthook_t **plthook_out, uint32_t image_idx, const
174
183
  static unsigned int set_bind_addrs(data_t *d, uint32_t lazy_bind_off, uint32_t lazy_bind_size);
175
184
  static void set_bind_addr(data_t *d, unsigned int *idx, const char *sym_name, int seg_index, int seg_offset);
176
185
  static int read_chained_fixups(data_t *d, const struct mach_header *mh, const char *image_name);
186
+ static int set_mem_prot(plthook_t *plthook);
187
+ static int get_mem_prot(plthook_t *plthook, void *addr);
177
188
 
178
189
  static void set_errmsg(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2)));
179
190
 
@@ -511,6 +522,7 @@ static int plthook_open_real(plthook_t **plthook_out, uint32_t image_idx, const
511
522
  data.plthook->num_entries = nbind;
512
523
  set_bind_addrs(&data, lazy_bind_off, lazy_bind_size);
513
524
  }
525
+ set_mem_prot(data.plthook);
514
526
 
515
527
  *plthook_out = data.plthook;
516
528
  return 0;
@@ -666,7 +678,6 @@ static int read_chained_fixups(data_t *d, const struct mach_header *mh, const ch
666
678
  goto cleanup;
667
679
  }
668
680
  d->plthook->num_entries = header->imports_count;
669
- d->plthook->readonly_segment = 1;
670
681
 
671
682
  switch (header->imports_format) {
672
683
  case DYLD_CHAINED_IMPORT:
@@ -967,7 +978,64 @@ cleanup:
967
978
  return rv;
968
979
  }
969
980
 
981
+ static int set_mem_prot(plthook_t *plthook)
982
+ {
983
+ unsigned int pos = 0;
984
+ const char *name;
985
+ void **addr;
986
+ size_t start = (size_t)-1;
987
+ size_t end = 0;
988
+ mach_port_t task = mach_task_self();
989
+ vm_address_t vm_addr = 0;
990
+ vm_size_t vm_size;
991
+ vm_region_basic_info_data_64_t info;
992
+ mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
993
+ memory_object_name_t object = 0;
994
+ int idx = 0;
995
+
996
+ while (plthook_enum(plthook, &pos, &name, &addr) == 0) {
997
+ if (start > (size_t)addr) {
998
+ start = (size_t)addr;
999
+ }
1000
+ if (end < (size_t)addr) {
1001
+ end = (size_t)addr;
1002
+ }
1003
+ }
1004
+ end++;
1005
+
1006
+ while (vm_region_64(task, &vm_addr, &vm_size, VM_REGION_BASIC_INFO_64, (vm_region_info_t)&info, &info_count, &object) == KERN_SUCCESS) {
1007
+ mem_prot_t mem_prot = {vm_addr, vm_addr + vm_size, info.protection & (PROT_READ | PROT_WRITE | PROT_EXEC)};
1008
+ if (mem_prot.prot != 0 && mem_prot.start < end && start < mem_prot.end) {
1009
+ plthook->mem_prot[idx++] = mem_prot;
1010
+ if (idx == NUM_MEM_PROT) {
1011
+ break;
1012
+ }
1013
+ }
1014
+ vm_addr += vm_size;
1015
+ }
1016
+ return 0;
1017
+ }
1018
+
1019
+ static int get_mem_prot(plthook_t *plthook, void *addr)
1020
+ {
1021
+ mem_prot_t *ptr = plthook->mem_prot;
1022
+ mem_prot_t *end = ptr + NUM_MEM_PROT;
1023
+
1024
+ while (ptr < end && ptr->prot != 0) {
1025
+ if (ptr->start <= (size_t)addr && (size_t)addr < ptr->end) {
1026
+ return ptr->prot;
1027
+ }
1028
+ ++ptr;
1029
+ }
1030
+ return 0;
1031
+ }
1032
+
970
1033
  int plthook_enum(plthook_t *plthook, unsigned int *pos, const char **name_out, void ***addr_out)
1034
+ {
1035
+ return plthook_enum_with_prot(plthook, pos, name_out, addr_out, NULL);
1036
+ }
1037
+
1038
+ int plthook_enum_with_prot(plthook_t *plthook, unsigned int *pos, const char **name_out, void ***addr_out, int *prot)
971
1039
  {
972
1040
  if (*pos >= plthook->num_entries) {
973
1041
  *name_out = NULL;
@@ -977,6 +1045,9 @@ int plthook_enum(plthook_t *plthook, unsigned int *pos, const char **name_out, v
977
1045
  *name_out = plthook->entries[*pos].name;
978
1046
  *addr_out = plthook->entries[*pos].addr;
979
1047
  (*pos)++;
1048
+ if (prot != NULL) {
1049
+ *prot = get_mem_prot(plthook, *addr_out);
1050
+ }
980
1051
  return 0;
981
1052
  }
982
1053
 
@@ -1020,7 +1091,12 @@ matched:
1020
1091
  if (oldfunc) {
1021
1092
  *oldfunc = *addr;
1022
1093
  }
1023
- if (plthook->readonly_segment) {
1094
+ int prot = get_mem_prot(plthook, addr);
1095
+ if (prot == 0) {
1096
+ set_errmsg("Could not get the process memory permission at %p", addr);
1097
+ return PLTHOOK_INTERNAL_ERROR;
1098
+ }
1099
+ if (!(prot & PROT_WRITE)) {
1024
1100
  size_t page_size = sysconf(_SC_PAGESIZE);
1025
1101
  void *base = (void*)((size_t)addr & ~(page_size - 1));
1026
1102
  if (mprotect(base, page_size, PROT_READ | PROT_WRITE) != 0) {
@@ -1028,7 +1104,7 @@ matched:
1028
1104
  return PLTHOOK_INTERNAL_ERROR;
1029
1105
  }
1030
1106
  *addr = funcaddr;
1031
- mprotect(base, page_size, PROT_READ);
1107
+ mprotect(base, page_size, prot);
1032
1108
  } else {
1033
1109
  *addr = funcaddr;
1034
1110
  }
data/lib/oci8/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class OCI8
2
- VERSION = "2.2.13"
2
+ VERSION = "2.2.14"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-oci8
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.13
4
+ version: 2.2.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kubo Takehiro
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-27 00:00:00.000000000 Z
11
+ date: 2024-08-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: 'ruby-oci8 is a ruby interface for Oracle using OCI8 API. It is available
14
14
  with Oracle 10g or later including Oracle Instant Client.
@@ -152,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
152
152
  - !ruby/object:Gem::Version
153
153
  version: '0'
154
154
  requirements: []
155
- rubygems_version: 3.4.10
155
+ rubygems_version: 3.5.5
156
156
  signing_key:
157
157
  specification_version: 4
158
158
  summary: Ruby interface for Oracle using OCI8 API