ruby-oci8 2.2.12 → 2.2.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/NEWS +18 -0
- data/docs/hanging-after-inactivity.md +1 -1
- data/ext/oci8/extconf.rb +1 -0
- data/ext/oci8/oci8.c +2 -2
- data/ext/oci8/oci8.h +6 -5
- data/ext/oci8/oci8lib.c +0 -21
- data/ext/oci8/oraconf.rb +4 -0
- data/ext/oci8/oradate.c +0 -11
- data/ext/oci8/plthook_elf.c +312 -183
- data/ext/oci8/plthook_osx.c +649 -91
- data/ext/oci8/plthook_win32.c +39 -25
- data/lib/oci8/oracle_version.rb +9 -1
- data/lib/oci8/version.rb +1 -1
- data/lib/oci8.rb +2 -0
- data/test/test_metadata.rb +1 -0
- data/test/test_oranumber.rb +3 -1
- data/test/test_package_type.rb +10 -4
- metadata +3 -3
data/ext/oci8/plthook_elf.c
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
/* -*- indent-tabs-mode: nil -*-
|
2
2
|
*
|
3
|
-
* plthook_elf.c --
|
3
|
+
* plthook_elf.c -- implementation of plthook for ELF format
|
4
4
|
*
|
5
5
|
* URL: https://github.com/kubo/plthook
|
6
6
|
*
|
7
7
|
* ------------------------------------------------------
|
8
8
|
*
|
9
|
-
* Copyright 2013-
|
9
|
+
* Copyright 2013-2019 Kubo Takehiro <kubo@jiubao.org>
|
10
10
|
*
|
11
11
|
* Redistribution and use in source and binary forms, with or without modification, are
|
12
12
|
* permitted provided that the following conditions are met:
|
@@ -50,6 +50,7 @@
|
|
50
50
|
#include <dlfcn.h>
|
51
51
|
#ifdef __sun
|
52
52
|
#include <sys/auxv.h>
|
53
|
+
#include <procfs.h>
|
53
54
|
#define ELF_TARGET_ALL
|
54
55
|
#endif /* __sun */
|
55
56
|
#ifdef __FreeBSD__
|
@@ -61,6 +62,10 @@
|
|
61
62
|
#include <link.h>
|
62
63
|
#include "plthook.h"
|
63
64
|
|
65
|
+
#if defined __UCLIBC__ && !defined RTLD_NOLOAD
|
66
|
+
#define RTLD_NOLOAD 0
|
67
|
+
#endif
|
68
|
+
|
64
69
|
#ifndef __GNUC__
|
65
70
|
#define __attribute__(arg)
|
66
71
|
#endif
|
@@ -75,46 +80,66 @@
|
|
75
80
|
|
76
81
|
#if defined __x86_64__ || defined __x86_64
|
77
82
|
#define R_JUMP_SLOT R_X86_64_JUMP_SLOT
|
78
|
-
#define Elf_Plt_Rel Elf_Rela
|
79
|
-
#define PLT_DT_REL DT_RELA
|
80
83
|
#define R_GLOBAL_DATA R_X86_64_GLOB_DAT
|
81
84
|
#elif defined __i386__ || defined __i386
|
82
85
|
#define R_JUMP_SLOT R_386_JMP_SLOT
|
83
|
-
#define Elf_Plt_Rel Elf_Rel
|
84
|
-
#define PLT_DT_REL DT_REL
|
85
86
|
#define R_GLOBAL_DATA R_386_GLOB_DAT
|
87
|
+
#define USE_REL
|
86
88
|
#elif defined __arm__ || defined __arm
|
87
89
|
#define R_JUMP_SLOT R_ARM_JUMP_SLOT
|
88
|
-
#define
|
90
|
+
#define R_GLOBAL_DATA R_ARM_GLOB_DAT
|
91
|
+
#define USE_REL
|
89
92
|
#elif defined __aarch64__ || defined __aarch64 /* ARM64 */
|
90
93
|
#define R_JUMP_SLOT R_AARCH64_JUMP_SLOT
|
91
|
-
#define
|
94
|
+
#define R_GLOBAL_DATA R_AARCH64_GLOB_DAT
|
92
95
|
#elif defined __powerpc64__
|
93
96
|
#define R_JUMP_SLOT R_PPC64_JMP_SLOT
|
94
|
-
#define
|
97
|
+
#define R_GLOBAL_DATA R_PPC64_GLOB_DAT
|
95
98
|
#elif defined __powerpc__
|
96
99
|
#define R_JUMP_SLOT R_PPC_JMP_SLOT
|
97
|
-
#define
|
100
|
+
#define R_GLOBAL_DATA R_PPC_GLOB_DAT
|
101
|
+
#elif defined __riscv
|
102
|
+
#define R_JUMP_SLOT R_RISCV_JUMP_SLOT
|
103
|
+
#if __riscv_xlen == 32
|
104
|
+
#define R_GLOBAL_DATA R_RISCV_32
|
105
|
+
#elif __riscv_xlen == 64
|
106
|
+
#define R_GLOBAL_DATA R_RISCV_64
|
107
|
+
#else
|
108
|
+
#error unsupported RISCV implementation
|
109
|
+
#endif
|
98
110
|
#elif 0 /* disabled because not tested */ && (defined __sparcv9 || defined __sparc_v9__)
|
99
111
|
#define R_JUMP_SLOT R_SPARC_JMP_SLOT
|
100
|
-
#define Elf_Plt_Rel Elf_Rela
|
101
112
|
#elif 0 /* disabled because not tested */ && (defined __sparc || defined __sparc__)
|
102
113
|
#define R_JUMP_SLOT R_SPARC_JMP_SLOT
|
103
|
-
#define Elf_Plt_Rel Elf_Rela
|
104
114
|
#elif 0 /* disabled because not tested */ && (defined __ia64 || defined __ia64__)
|
105
115
|
#define R_JUMP_SLOT R_IA64_IPLTMSB
|
106
|
-
#define Elf_Plt_Rel Elf_Rela
|
107
116
|
#else
|
108
117
|
#error unsupported OS
|
109
118
|
#endif
|
110
119
|
|
120
|
+
#ifdef USE_REL
|
121
|
+
#define Elf_Plt_Rel Elf_Rel
|
122
|
+
#define PLT_DT_REL DT_REL
|
123
|
+
#define PLT_DT_RELSZ DT_RELSZ
|
124
|
+
#define PLT_DT_RELENT DT_RELENT
|
125
|
+
#else
|
126
|
+
#define Elf_Plt_Rel Elf_Rela
|
127
|
+
#define PLT_DT_REL DT_RELA
|
128
|
+
#define PLT_DT_RELSZ DT_RELASZ
|
129
|
+
#define PLT_DT_RELENT DT_RELAENT
|
130
|
+
#endif
|
131
|
+
|
111
132
|
#if defined __LP64__
|
112
133
|
#ifndef ELF_CLASS
|
113
134
|
#define ELF_CLASS ELFCLASS64
|
114
135
|
#endif
|
115
136
|
#define SIZE_T_FMT "lu"
|
116
137
|
#define ELF_WORD_FMT "u"
|
138
|
+
#ifdef __ANDROID__
|
139
|
+
#define ELF_XWORD_FMT "llu"
|
140
|
+
#else
|
117
141
|
#define ELF_XWORD_FMT "lu"
|
142
|
+
#endif
|
118
143
|
#define ELF_SXWORD_FMT "ld"
|
119
144
|
#define Elf_Half Elf64_Half
|
120
145
|
#define Elf_Xword Elf64_Xword
|
@@ -162,43 +187,65 @@
|
|
162
187
|
#endif
|
163
188
|
#endif /* __LP64__ */
|
164
189
|
|
165
|
-
#if defined(PT_GNU_RELRO) && !defined(__sun)
|
166
|
-
#define SUPPORT_RELRO /* RELRO (RELocation Read-Only) */
|
167
|
-
#if !defined(DF_1_NOW) && defined(DF_1_BIND_NOW)
|
168
|
-
#define DF_1_NOW DF_1_BIND_NOW
|
169
|
-
#endif
|
170
|
-
#endif
|
171
|
-
|
172
190
|
struct plthook {
|
173
191
|
const Elf_Sym *dynsym;
|
174
192
|
const char *dynstr;
|
175
193
|
size_t dynstr_size;
|
176
194
|
const char *plt_addr_base;
|
177
|
-
const Elf_Plt_Rel *
|
178
|
-
size_t
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
const char *relro_end;
|
195
|
+
const Elf_Plt_Rel *rela_plt;
|
196
|
+
size_t rela_plt_cnt;
|
197
|
+
#ifdef R_GLOBAL_DATA
|
198
|
+
const Elf_Plt_Rel *rela_dyn;
|
199
|
+
size_t rela_dyn_cnt;
|
183
200
|
#endif
|
184
201
|
};
|
185
202
|
|
186
203
|
static char errmsg[512];
|
187
|
-
|
188
|
-
#ifdef SUPPORT_RELRO
|
189
204
|
static size_t page_size;
|
190
|
-
#
|
205
|
+
#define ALIGN_ADDR(addr) ((void*)((size_t)(addr) & ~(page_size - 1)))
|
191
206
|
|
192
207
|
static int plthook_open_executable(plthook_t **plthook_out);
|
193
208
|
static int plthook_open_shared_library(plthook_t **plthook_out, const char *filename);
|
194
209
|
static const Elf_Dyn *find_dyn_by_tag(const Elf_Dyn *dyn, Elf_Sxword tag);
|
195
|
-
#ifdef SUPPORT_RELRO
|
196
|
-
static int set_relro_members(plthook_t *plthook, struct link_map *lmap);
|
197
|
-
#endif
|
198
210
|
static int plthook_open_real(plthook_t **plthook_out, struct link_map *lmap);
|
211
|
+
#if defined __FreeBSD__ || defined __sun
|
199
212
|
static int check_elf_header(const Elf_Ehdr *ehdr);
|
213
|
+
#endif
|
200
214
|
static void set_errmsg(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2)));
|
201
215
|
|
216
|
+
#if defined __ANDROID__ || defined __UCLIBC__
|
217
|
+
struct dl_iterate_data {
|
218
|
+
char* addr;
|
219
|
+
struct link_map lmap;
|
220
|
+
};
|
221
|
+
|
222
|
+
static int dl_iterate_cb(struct dl_phdr_info *info, size_t size, void *cb_data)
|
223
|
+
{
|
224
|
+
struct dl_iterate_data *data = (struct dl_iterate_data*)cb_data;
|
225
|
+
Elf_Half idx = 0;
|
226
|
+
|
227
|
+
for (idx = 0; idx < info->dlpi_phnum; ++idx) {
|
228
|
+
const Elf_Phdr *phdr = &info->dlpi_phdr[idx];
|
229
|
+
char* base = (char*)info->dlpi_addr + phdr->p_vaddr;
|
230
|
+
if (base <= data->addr && data->addr < base + phdr->p_memsz) {
|
231
|
+
break;
|
232
|
+
}
|
233
|
+
}
|
234
|
+
if (idx == info->dlpi_phnum) {
|
235
|
+
return 0;
|
236
|
+
}
|
237
|
+
for (idx = 0; idx < info->dlpi_phnum; ++idx) {
|
238
|
+
const Elf_Phdr *phdr = &info->dlpi_phdr[idx];
|
239
|
+
if (phdr->p_type == PT_DYNAMIC) {
|
240
|
+
data->lmap.l_addr = info->dlpi_addr;
|
241
|
+
data->lmap.l_ld = (Elf_Dyn*)(info->dlpi_addr + phdr->p_vaddr);
|
242
|
+
return 1;
|
243
|
+
}
|
244
|
+
}
|
245
|
+
return 0;
|
246
|
+
}
|
247
|
+
#endif
|
248
|
+
|
202
249
|
int plthook_open(plthook_t **plthook_out, const char *filename)
|
203
250
|
{
|
204
251
|
*plthook_out = NULL;
|
@@ -211,6 +258,27 @@ int plthook_open(plthook_t **plthook_out, const char *filename)
|
|
211
258
|
|
212
259
|
int plthook_open_by_handle(plthook_t **plthook_out, void *hndl)
|
213
260
|
{
|
261
|
+
#if defined __ANDROID__ || defined __UCLIBC__
|
262
|
+
const static char *symbols[] = {
|
263
|
+
"__INIT_ARRAY__",
|
264
|
+
"_end",
|
265
|
+
"_start"
|
266
|
+
};
|
267
|
+
size_t i;
|
268
|
+
|
269
|
+
if (hndl == NULL) {
|
270
|
+
set_errmsg("NULL handle");
|
271
|
+
return PLTHOOK_FILE_NOT_FOUND;
|
272
|
+
}
|
273
|
+
for (i = 0; i < sizeof(symbols)/sizeof(symbols[0]); i++) {
|
274
|
+
char *addr = dlsym(hndl, symbols[i]);
|
275
|
+
if (addr != NULL) {
|
276
|
+
return plthook_open_by_address(plthook_out, addr - 1);
|
277
|
+
}
|
278
|
+
}
|
279
|
+
set_errmsg("Could not find an address in the specified handle.");
|
280
|
+
return PLTHOOK_INTERNAL_ERROR;
|
281
|
+
#else
|
214
282
|
struct link_map *lmap = NULL;
|
215
283
|
|
216
284
|
if (hndl == NULL) {
|
@@ -222,12 +290,22 @@ int plthook_open_by_handle(plthook_t **plthook_out, void *hndl)
|
|
222
290
|
return PLTHOOK_FILE_NOT_FOUND;
|
223
291
|
}
|
224
292
|
return plthook_open_real(plthook_out, lmap);
|
293
|
+
#endif
|
225
294
|
}
|
226
295
|
|
227
296
|
int plthook_open_by_address(plthook_t **plthook_out, void *address)
|
228
297
|
{
|
229
298
|
#if defined __FreeBSD__
|
230
299
|
return PLTHOOK_NOT_IMPLEMENTED;
|
300
|
+
#elif defined __ANDROID__ || defined __UCLIBC__
|
301
|
+
struct dl_iterate_data data = {0,};
|
302
|
+
data.addr = address;
|
303
|
+
dl_iterate_phdr(dl_iterate_cb, &data);
|
304
|
+
if (data.lmap.l_ld == NULL) {
|
305
|
+
set_errmsg("Could not find memory region containing address %p", address);
|
306
|
+
return PLTHOOK_INTERNAL_ERROR;
|
307
|
+
}
|
308
|
+
return plthook_open_real(plthook_out, &data.lmap);
|
231
309
|
#else
|
232
310
|
Dl_info info;
|
233
311
|
struct link_map *lmap = NULL;
|
@@ -243,7 +321,9 @@ int plthook_open_by_address(plthook_t **plthook_out, void *address)
|
|
243
321
|
|
244
322
|
static int plthook_open_executable(plthook_t **plthook_out)
|
245
323
|
{
|
246
|
-
#if defined
|
324
|
+
#if defined __ANDROID__ || defined __UCLIBC__
|
325
|
+
return plthook_open_shared_library(plthook_out, NULL);
|
326
|
+
#elif defined __linux__
|
247
327
|
return plthook_open_real(plthook_out, _r_debug.r_map);
|
248
328
|
#elif defined __sun
|
249
329
|
const char *auxv_file = "/proc/self/auxv";
|
@@ -280,12 +360,21 @@ static int plthook_open_executable(plthook_t **plthook_out)
|
|
280
360
|
static int plthook_open_shared_library(plthook_t **plthook_out, const char *filename)
|
281
361
|
{
|
282
362
|
void *hndl = dlopen(filename, RTLD_LAZY | RTLD_NOLOAD);
|
363
|
+
#if defined __ANDROID__ || defined __UCLIBC__
|
364
|
+
int rv;
|
365
|
+
#else
|
283
366
|
struct link_map *lmap = NULL;
|
367
|
+
#endif
|
284
368
|
|
285
369
|
if (hndl == NULL) {
|
286
370
|
set_errmsg("dlopen error: %s", dlerror());
|
287
371
|
return PLTHOOK_FILE_NOT_FOUND;
|
288
372
|
}
|
373
|
+
#if defined __ANDROID__ || defined __UCLIBC__
|
374
|
+
rv = plthook_open_by_handle(plthook_out, hndl);
|
375
|
+
dlclose(hndl);
|
376
|
+
return rv;
|
377
|
+
#else
|
289
378
|
if (dlinfo(hndl, RTLD_DI_LINKMAP, &lmap) != 0) {
|
290
379
|
set_errmsg("dlinfo error");
|
291
380
|
dlclose(hndl);
|
@@ -293,6 +382,7 @@ static int plthook_open_shared_library(plthook_t **plthook_out, const char *file
|
|
293
382
|
}
|
294
383
|
dlclose(hndl);
|
295
384
|
return plthook_open_real(plthook_out, lmap);
|
385
|
+
#endif
|
296
386
|
}
|
297
387
|
|
298
388
|
static const Elf_Dyn *find_dyn_by_tag(const Elf_Dyn *dyn, Elf_Sxword tag)
|
@@ -306,47 +396,79 @@ static const Elf_Dyn *find_dyn_by_tag(const Elf_Dyn *dyn, Elf_Sxword tag)
|
|
306
396
|
return NULL;
|
307
397
|
}
|
308
398
|
|
309
|
-
#ifdef
|
310
|
-
|
311
|
-
static const char *get_mapped_file(const void *address, char *buf, int *err)
|
399
|
+
#ifdef __linux__
|
400
|
+
static int get_memory_permission(void *address)
|
312
401
|
{
|
313
402
|
unsigned long addr = (unsigned long)address;
|
314
403
|
FILE *fp;
|
404
|
+
char buf[PATH_MAX];
|
405
|
+
char perms[5];
|
406
|
+
int bol = 1;
|
315
407
|
|
316
408
|
fp = fopen("/proc/self/maps", "r");
|
317
409
|
if (fp == NULL) {
|
318
410
|
set_errmsg("failed to open /proc/self/maps");
|
319
|
-
|
320
|
-
return NULL;
|
411
|
+
return 0;
|
321
412
|
}
|
322
413
|
while (fgets(buf, PATH_MAX, fp) != NULL) {
|
323
414
|
unsigned long start, end;
|
324
|
-
int
|
415
|
+
int eol = (strchr(buf, '\n') != NULL);
|
416
|
+
if (bol) {
|
417
|
+
/* The fgets reads from the beginning of a line. */
|
418
|
+
if (!eol) {
|
419
|
+
/* The next fgets reads from the middle of the same line. */
|
420
|
+
bol = 0;
|
421
|
+
}
|
422
|
+
} else {
|
423
|
+
/* The fgets reads from the middle of a line. */
|
424
|
+
if (eol) {
|
425
|
+
/* The next fgets reads from the beginning of a line. */
|
426
|
+
bol = 1;
|
427
|
+
}
|
428
|
+
continue;
|
429
|
+
}
|
325
430
|
|
326
|
-
sscanf(buf, "%lx-%lx
|
327
|
-
if (offset == 0) {
|
431
|
+
if (sscanf(buf, "%lx-%lx %4s", &start, &end, perms) != 3) {
|
328
432
|
continue;
|
329
433
|
}
|
330
|
-
if (start
|
331
|
-
|
332
|
-
|
333
|
-
|
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;
|
334
440
|
}
|
335
|
-
if (
|
336
|
-
|
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;
|
337
457
|
}
|
338
|
-
p[strlen(p) - 1] = '\0'; /* remove '\n' */
|
339
458
|
fclose(fp);
|
340
|
-
return
|
459
|
+
return prot;
|
341
460
|
}
|
342
461
|
}
|
343
462
|
fclose(fp);
|
344
|
-
set_errmsg("Could not find
|
345
|
-
|
346
|
-
|
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;
|
347
469
|
}
|
348
470
|
#elif defined __FreeBSD__
|
349
|
-
static
|
471
|
+
static int get_memory_permission(void *address)
|
350
472
|
{
|
351
473
|
uint64_t addr = (uint64_t)address;
|
352
474
|
struct kinfo_vmentry *top;
|
@@ -354,87 +476,78 @@ static const char *get_mapped_file(const void *address, char *buf, int *err)
|
|
354
476
|
|
355
477
|
top = kinfo_getvmmap(getpid(), &cnt);
|
356
478
|
if (top == NULL) {
|
357
|
-
|
358
|
-
|
359
|
-
return NULL;
|
479
|
+
set_errmsg("failed to call kinfo_getvmmap()\n");
|
480
|
+
return 0;
|
360
481
|
}
|
361
482
|
for (i = 0; i < cnt; i++) {
|
362
483
|
struct kinfo_vmentry *kve = top + i;
|
363
484
|
|
364
|
-
if (kve->kve_start
|
365
|
-
|
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
|
+
}
|
366
499
|
free(top);
|
367
|
-
return
|
500
|
+
return prot;
|
368
501
|
}
|
369
502
|
}
|
370
503
|
free(top);
|
371
|
-
set_errmsg("Could not find
|
372
|
-
|
373
|
-
return NULL;
|
374
|
-
}
|
375
|
-
#else
|
376
|
-
static const char *get_mapped_file(const void *address, char *buf, int *err)
|
377
|
-
{
|
378
|
-
set_errmsg("Could not find a mapped file reagion containing %p", address);
|
379
|
-
*err = PLTHOOK_INTERNAL_ERROR;
|
380
|
-
return NULL;
|
504
|
+
set_errmsg("Could not find memory region containing %p", (void*)addr);
|
505
|
+
return 0;
|
381
506
|
}
|
382
|
-
#
|
383
|
-
|
384
|
-
static int
|
507
|
+
#elif defined(__sun)
|
508
|
+
#define NUM_MAPS 20
|
509
|
+
static int get_memory_permission(void *address)
|
385
510
|
{
|
386
|
-
|
387
|
-
const char *fname;
|
511
|
+
unsigned long addr = (unsigned long)address;
|
388
512
|
FILE *fp;
|
389
|
-
|
390
|
-
|
391
|
-
int rv;
|
392
|
-
|
393
|
-
if (lmap->l_name[0] == '/') {
|
394
|
-
fname = lmap->l_name;
|
395
|
-
} else {
|
396
|
-
int err;
|
513
|
+
prmap_t maps[NUM_MAPS];
|
514
|
+
size_t num;
|
397
515
|
|
398
|
-
|
399
|
-
if (fname == NULL) {
|
400
|
-
return err;
|
401
|
-
}
|
402
|
-
}
|
403
|
-
fp = fopen(fname, "r");
|
516
|
+
fp = fopen("/proc/self/map", "r");
|
404
517
|
if (fp == NULL) {
|
405
|
-
set_errmsg("failed to open
|
406
|
-
return
|
407
|
-
}
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
plthook->relro_start = plthook->plt_addr_base + phdr.p_vaddr;
|
431
|
-
plthook->relro_end = plthook->relro_start + phdr.p_memsz;
|
432
|
-
break;
|
518
|
+
set_errmsg("failed to open /proc/self/map");
|
519
|
+
return 0;
|
520
|
+
}
|
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];
|
525
|
+
|
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
|
+
}
|
433
543
|
}
|
434
544
|
}
|
435
545
|
fclose(fp);
|
546
|
+
set_errmsg("Could not find memory region containing %p", (void*)addr);
|
436
547
|
return 0;
|
437
548
|
}
|
549
|
+
#else
|
550
|
+
#error Unsupported platform
|
438
551
|
#endif
|
439
552
|
|
440
553
|
static int plthook_open_real(plthook_t **plthook_out, struct link_map *lmap)
|
@@ -443,13 +556,26 @@ static int plthook_open_real(plthook_t **plthook_out, struct link_map *lmap)
|
|
443
556
|
const Elf_Dyn *dyn;
|
444
557
|
const char *dyn_addr_base = NULL;
|
445
558
|
|
559
|
+
if (page_size == 0) {
|
560
|
+
page_size = sysconf(_SC_PAGESIZE);
|
561
|
+
}
|
562
|
+
|
446
563
|
#if defined __linux__
|
447
564
|
plthook.plt_addr_base = (char*)lmap->l_addr;
|
565
|
+
#if defined __riscv
|
566
|
+
const Elf_Ehdr *ehdr = (const Elf_Ehdr*)lmap->l_addr;
|
567
|
+
if (ehdr->e_type == ET_DYN) {
|
568
|
+
dyn_addr_base = (const char*)lmap->l_addr;
|
569
|
+
}
|
570
|
+
#endif
|
571
|
+
#if defined __ANDROID__ || defined __UCLIBC__
|
572
|
+
dyn_addr_base = (const char*)lmap->l_addr;
|
573
|
+
#endif
|
448
574
|
#elif defined __FreeBSD__ || defined __sun
|
449
575
|
const Elf_Ehdr *ehdr = (const Elf_Ehdr*)lmap->l_addr;
|
450
|
-
int
|
451
|
-
if (
|
452
|
-
return
|
576
|
+
int rv_ = check_elf_header(ehdr);
|
577
|
+
if (rv_ != 0) {
|
578
|
+
return rv_;
|
453
579
|
}
|
454
580
|
if (ehdr->e_type == ET_DYN) {
|
455
581
|
dyn_addr_base = (const char*)lmap->l_addr;
|
@@ -496,62 +622,48 @@ static int plthook_open_real(plthook_t **plthook_out, struct link_map *lmap)
|
|
496
622
|
|
497
623
|
/* get .rela.plt or .rel.plt section */
|
498
624
|
dyn = find_dyn_by_tag(lmap->l_ld, DT_JMPREL);
|
499
|
-
|
500
|
-
|
501
|
-
if (dyn == NULL) {
|
502
|
-
/* get .rela.dyn or .rel.dyn section */
|
503
|
-
dyn = find_dyn_by_tag(lmap->l_ld, PLT_DT_REL);
|
504
|
-
plthook.r_type = R_GLOBAL_DATA;
|
505
|
-
}
|
506
|
-
#endif
|
507
|
-
if (dyn == NULL) {
|
508
|
-
set_errmsg("failed to find DT_JMPREL");
|
509
|
-
return PLTHOOK_INTERNAL_ERROR;
|
510
|
-
}
|
511
|
-
plthook.plt = (const Elf_Plt_Rel *)(dyn_addr_base + dyn->d_un.d_ptr);
|
512
|
-
|
513
|
-
if (plthook.r_type == R_JUMP_SLOT) {
|
514
|
-
/* get total size of .rela.plt or .rel.plt */
|
625
|
+
if (dyn != NULL) {
|
626
|
+
plthook.rela_plt = (const Elf_Plt_Rel *)(dyn_addr_base + dyn->d_un.d_ptr);
|
515
627
|
dyn = find_dyn_by_tag(lmap->l_ld, DT_PLTRELSZ);
|
516
628
|
if (dyn == NULL) {
|
517
629
|
set_errmsg("failed to find DT_PLTRELSZ");
|
518
630
|
return PLTHOOK_INTERNAL_ERROR;
|
519
631
|
}
|
520
|
-
|
521
|
-
|
522
|
-
#ifdef
|
523
|
-
|
524
|
-
|
525
|
-
|
632
|
+
plthook.rela_plt_cnt = dyn->d_un.d_val / sizeof(Elf_Plt_Rel);
|
633
|
+
}
|
634
|
+
#ifdef R_GLOBAL_DATA
|
635
|
+
/* get .rela.dyn or .rel.dyn section */
|
636
|
+
dyn = find_dyn_by_tag(lmap->l_ld, PLT_DT_REL);
|
637
|
+
if (dyn != NULL) {
|
526
638
|
size_t total_size, elem_size;
|
527
639
|
|
528
|
-
|
640
|
+
plthook.rela_dyn = (const Elf_Plt_Rel *)(dyn_addr_base + dyn->d_un.d_ptr);
|
641
|
+
dyn = find_dyn_by_tag(lmap->l_ld, PLT_DT_RELSZ);
|
529
642
|
if (dyn == NULL) {
|
530
|
-
set_errmsg("failed to find
|
643
|
+
set_errmsg("failed to find PLT_DT_RELSZ");
|
531
644
|
return PLTHOOK_INTERNAL_ERROR;
|
532
645
|
}
|
533
646
|
total_size = dyn->d_un.d_ptr;
|
534
647
|
|
535
|
-
dyn = find_dyn_by_tag(lmap->l_ld,
|
648
|
+
dyn = find_dyn_by_tag(lmap->l_ld, PLT_DT_RELENT);
|
536
649
|
if (dyn == NULL) {
|
537
|
-
set_errmsg("failed to find
|
650
|
+
set_errmsg("failed to find PLT_DT_RELENT");
|
538
651
|
return PLTHOOK_INTERNAL_ERROR;
|
539
652
|
}
|
540
653
|
elem_size = dyn->d_un.d_ptr;
|
541
|
-
plthook.
|
542
|
-
#endif
|
654
|
+
plthook.rela_dyn_cnt = total_size / elem_size;
|
543
655
|
}
|
656
|
+
#endif
|
544
657
|
|
545
|
-
#ifdef
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
}
|
658
|
+
#ifdef R_GLOBAL_DATA
|
659
|
+
if (plthook.rela_plt == NULL && plthook.rela_dyn == NULL) {
|
660
|
+
set_errmsg("failed to find either of DT_JMPREL and DT_REL");
|
661
|
+
return PLTHOOK_INTERNAL_ERROR;
|
662
|
+
}
|
663
|
+
#else
|
664
|
+
if (plthook.rela_plt == NULL) {
|
665
|
+
set_errmsg("failed to find DT_JMPREL");
|
666
|
+
return PLTHOOK_INTERNAL_ERROR;
|
555
667
|
}
|
556
668
|
#endif
|
557
669
|
|
@@ -564,6 +676,7 @@ static int plthook_open_real(plthook_t **plthook_out, struct link_map *lmap)
|
|
564
676
|
return 0;
|
565
677
|
}
|
566
678
|
|
679
|
+
#if defined __FreeBSD__ || defined __sun
|
567
680
|
static int check_elf_header(const Elf_Ehdr *ehdr)
|
568
681
|
{
|
569
682
|
static const unsigned short s = 1;
|
@@ -610,26 +723,44 @@ static int check_elf_header(const Elf_Ehdr *ehdr)
|
|
610
723
|
}
|
611
724
|
return 0;
|
612
725
|
}
|
726
|
+
#endif
|
727
|
+
|
728
|
+
static int check_rel(const plthook_t *plthook, const Elf_Plt_Rel *plt, Elf_Xword r_type, const char **name_out, void ***addr_out)
|
729
|
+
{
|
730
|
+
if (ELF_R_TYPE(plt->r_info) == r_type) {
|
731
|
+
size_t idx = ELF_R_SYM(plt->r_info);
|
732
|
+
idx = plthook->dynsym[idx].st_name;
|
733
|
+
if (idx + 1 > plthook->dynstr_size) {
|
734
|
+
set_errmsg("too big section header string table index: %" SIZE_T_FMT, idx);
|
735
|
+
return PLTHOOK_INVALID_FILE_FORMAT;
|
736
|
+
}
|
737
|
+
*name_out = plthook->dynstr + idx;
|
738
|
+
*addr_out = (void**)(plthook->plt_addr_base + plt->r_offset);
|
739
|
+
return 0;
|
740
|
+
}
|
741
|
+
return -1;
|
742
|
+
}
|
613
743
|
|
614
744
|
int plthook_enum(plthook_t *plthook, unsigned int *pos, const char **name_out, void ***addr_out)
|
615
745
|
{
|
616
|
-
while (*pos < plthook->
|
617
|
-
const Elf_Plt_Rel *plt = plthook->
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
if (idx + 1 > plthook->dynstr_size) {
|
623
|
-
set_errmsg("too big section header string table index: %" SIZE_T_FMT, idx);
|
624
|
-
return PLTHOOK_INVALID_FILE_FORMAT;
|
625
|
-
}
|
626
|
-
*name_out = plthook->dynstr + idx;
|
627
|
-
*addr_out = (void**)(plthook->plt_addr_base + plt->r_offset);
|
628
|
-
(*pos)++;
|
629
|
-
return 0;
|
746
|
+
while (*pos < plthook->rela_plt_cnt) {
|
747
|
+
const Elf_Plt_Rel *plt = plthook->rela_plt + *pos;
|
748
|
+
int rv = check_rel(plthook, plt, R_JUMP_SLOT, name_out, addr_out);
|
749
|
+
(*pos)++;
|
750
|
+
if (rv >= 0) {
|
751
|
+
return rv;
|
630
752
|
}
|
753
|
+
}
|
754
|
+
#ifdef R_GLOBAL_DATA
|
755
|
+
while (*pos < plthook->rela_plt_cnt + plthook->rela_dyn_cnt) {
|
756
|
+
const Elf_Plt_Rel *plt = plthook->rela_dyn + (*pos - plthook->rela_plt_cnt);
|
757
|
+
int rv = check_rel(plthook, plt, R_GLOBAL_DATA, name_out, addr_out);
|
631
758
|
(*pos)++;
|
759
|
+
if (rv >= 0) {
|
760
|
+
return rv;
|
761
|
+
}
|
632
762
|
}
|
763
|
+
#endif
|
633
764
|
*name_out = NULL;
|
634
765
|
*addr_out = NULL;
|
635
766
|
return EOF;
|
@@ -650,26 +781,24 @@ int plthook_replace(plthook_t *plthook, const char *funcname, void *funcaddr, vo
|
|
650
781
|
while ((rv = plthook_enum(plthook, &pos, &name, &addr)) == 0) {
|
651
782
|
if (strncmp(name, funcname, funcnamelen) == 0) {
|
652
783
|
if (name[funcnamelen] == '\0' || name[funcnamelen] == '@') {
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
784
|
+
int prot = get_memory_permission(addr);
|
785
|
+
if (prot == 0) {
|
786
|
+
return PLTHOOK_INTERNAL_ERROR;
|
787
|
+
}
|
788
|
+
if (!(prot & PROT_WRITE)) {
|
789
|
+
if (mprotect(ALIGN_ADDR(addr), page_size, PROT_READ | PROT_WRITE) != 0) {
|
790
|
+
set_errmsg("Could not change the process memory permission at %p: %s",
|
791
|
+
ALIGN_ADDR(addr), strerror(errno));
|
660
792
|
return PLTHOOK_INTERNAL_ERROR;
|
661
793
|
}
|
662
794
|
}
|
663
|
-
#endif
|
664
795
|
if (oldfunc) {
|
665
796
|
*oldfunc = *addr;
|
666
797
|
}
|
667
798
|
*addr = funcaddr;
|
668
|
-
|
669
|
-
|
670
|
-
mprotect(maddr, page_size, PROT_READ);
|
799
|
+
if (!(prot & PROT_WRITE)) {
|
800
|
+
mprotect(ALIGN_ADDR(addr), page_size, prot);
|
671
801
|
}
|
672
|
-
#endif
|
673
802
|
return 0;
|
674
803
|
}
|
675
804
|
}
|