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 +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
|