ruby-oci8 2.2.13 → 2.2.14

Sign up to get free protection for your applications and to get access to all the features.
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