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 +4 -4
- data/NEWS +8 -0
- data/ext/oci8/oci8lib.c +14 -1
- data/ext/oci8/plthook.h +7 -1
- data/ext/oci8/plthook_elf.c +201 -105
- data/ext/oci8/plthook_osx.c +80 -4
- data/lib/oci8/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e144a61c64f6856db08e6e473ac4531dd008c967bad30f48bf6a6852c7fc623
|
4
|
+
data.tar.gz: e35589ae71e41de3d0b77ca04dfa4bc0aa761272915c5e4d2cabcb955b4923d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz: '
|
6
|
+
metadata.gz: 474b19d0d1a92f1cd52e0b12babeff15c4ccdeb076a3b523b61ad8d7fdc9b0bab99715af698b83cf841b114880f111e727f0dbd8e583ca4263b30fb28a2621f7
|
7
|
+
data.tar.gz: '079389be6f6662ae81795da0c0e4c7ba81bee27a1724032cf2c7de652f5282d0201d4f3ffec9eaa6e74d2e068abb96097912d3417d5c65cb084ed02c51e6d89b'
|
data/NEWS
CHANGED
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 (
|
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
|
-
}
|
69
|
+
} /* extern "C" */
|
64
70
|
#endif
|
65
71
|
|
66
72
|
#endif
|
data/ext/oci8/plthook_elf.c
CHANGED
@@ -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
|
-
|
401
|
-
{
|
402
|
-
unsigned long addr = (unsigned long)address;
|
417
|
+
struct mem_prot_iter {
|
403
418
|
FILE *fp;
|
404
|
-
|
405
|
-
char perms[5];
|
406
|
-
int bol = 1;
|
419
|
+
};
|
407
420
|
|
408
|
-
|
409
|
-
|
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
|
426
|
+
return -1;
|
412
427
|
}
|
413
|
-
|
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
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
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
|
-
|
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
|
-
|
471
|
-
static
|
474
|
+
|
475
|
+
static void mem_prot_end(mem_prot_iter_t *iter)
|
472
476
|
{
|
473
|
-
|
474
|
-
|
475
|
-
|
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
|
-
|
478
|
-
|
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
|
493
|
+
return -1;
|
481
494
|
}
|
482
|
-
|
483
|
-
|
495
|
+
iter->idx = 0;
|
496
|
+
return 0;
|
497
|
+
}
|
484
498
|
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
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
|
-
|
508
|
-
|
509
|
-
static int get_memory_permission(void *address)
|
519
|
+
|
520
|
+
static void mem_prot_end(mem_prot_iter_t *iter)
|
510
521
|
{
|
511
|
-
|
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[
|
529
|
+
prmap_t maps[20];
|
530
|
+
size_t idx;
|
514
531
|
size_t num;
|
532
|
+
};
|
515
533
|
|
516
|
-
|
517
|
-
|
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
|
539
|
+
return -1;
|
520
540
|
}
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
prmap_t *map = &maps[i];
|
541
|
+
iter->idx = iter->num = 0;
|
542
|
+
return 0;
|
543
|
+
}
|
525
544
|
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
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 =
|
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)) {
|
data/ext/oci8/plthook_osx.c
CHANGED
@@ -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
|
-
|
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
|
-
|
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,
|
1107
|
+
mprotect(base, page_size, prot);
|
1032
1108
|
} else {
|
1033
1109
|
*addr = funcaddr;
|
1034
1110
|
}
|
data/lib/oci8/version.rb
CHANGED
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.
|
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-
|
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.
|
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
|