From 6cd74df69115e4cf258c0a05d6e59a83c43d1db9 Mon Sep 17 00:00:00 2001 From: Yossi Itigin Date: Tue, 20 Jun 2017 17:42:26 +0300 Subject: [PATCH] UCM: Use correct pointer for original 'free' when patching plt. If using just 'free' as-is, it would point to free@plt which would jump to ucm_free and result in infinite recursion. Instead, use whatever free@plt was jumping to originally. --- src/ucm/malloc/malloc_hook.c | 2 ++ src/ucm/util/reloc.c | 28 +++++++++++++++------------- src/ucm/util/reloc.h | 1 + 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/ucm/malloc/malloc_hook.c b/src/ucm/malloc/malloc_hook.c index ec59246b81a..7b756ed0fcc 100644 --- a/src/ucm/malloc/malloc_hook.c +++ b/src/ucm/malloc/malloc_hook.c @@ -664,6 +664,8 @@ ucs_status_t ucm_malloc_install(int events) ucm_debug("installing malloc relocations"); ucm_malloc_populate_glibc_cache(); ucm_malloc_install_symbols(ucm_malloc_symbol_patches); + ucs_assert(ucm_malloc_symbol_patches[0].value == ucm_free); + ucm_malloc_hook_state.free = ucm_malloc_symbol_patches[0].prev_value; ucm_malloc_hook_state.install_state |= UCM_MALLOC_INSTALLED_MALL_SYMS; } } else { diff --git a/src/ucm/util/reloc.c b/src/ucm/util/reloc.c index 6001eb91907..cce6493fabd 100644 --- a/src/ucm/util/reloc.c +++ b/src/ucm/util/reloc.c @@ -37,12 +37,13 @@ typedef struct ucm_auxv { long value; } UCS_S_PACKED ucm_auxv_t; + typedef struct ucm_reloc_dl_iter_context { - const char *symbol; - void *newvalue; - ucs_status_t status; + ucm_reloc_patch_t *patch; + ucs_status_t status; } ucm_reloc_dl_iter_context_t; + /* List of patches to be applied to additional libraries */ static UCS_LIST_HEAD(ucm_reloc_patch_list); static void * (*ucm_reloc_orig_dlopen)(const char *, int) = NULL; @@ -142,7 +143,7 @@ static int ucm_reloc_get_aux_phsize() static ucs_status_t ucm_reloc_modify_got(ElfW(Addr) base, const ElfW(Phdr) *phdr, const char *phname, - int phnum, int phsize, const char *symbol, void *newvalue) + int phnum, int phsize, ucm_reloc_patch_t *patch) { ElfW(Phdr) *dphdr; ElfW(Rela) *reloc; @@ -183,11 +184,11 @@ ucm_reloc_modify_got(ElfW(Addr) base, const ElfW(Phdr) *phdr, const char *phname /* Find matching symbol and replace it */ for (reloc = jmprel; (void*)reloc < jmprel + pltrelsz; ++reloc) { elf_sym = (char*)strtab + symtab[ELF64_R_SYM(reloc->r_info)].st_name; - if (!strcmp(symbol, elf_sym)) { + if (!strcmp(patch->symbol, elf_sym)) { entry = (void *)(base + reloc->r_offset); - ucm_trace("'%s' entry in '%s' is at %p", symbol, basename(phname), - entry); + ucm_trace("'%s' entry in '%s' is at %p", patch->symbol, + basename(phname), entry); page = (void *)((intptr_t)entry & ~(page_size - 1)); ret = mprotect(page, page_size, PROT_READ|PROT_WRITE); @@ -195,7 +196,8 @@ ucm_reloc_modify_got(ElfW(Addr) base, const ElfW(Phdr) *phdr, const char *phname ucm_error("failed to modify GOT page %p to rw: %m", page); return UCS_ERR_UNSUPPORTED; } - *entry = newvalue; + patch->prev_value = *entry; + *entry = patch->value; break; } } @@ -217,7 +219,7 @@ static int ucm_reloc_phdr_iterator(struct dl_phdr_info *info, size_t size, void ctx->status = ucm_reloc_modify_got(info->dlpi_addr, info->dlpi_phdr, info->dlpi_name, info->dlpi_phnum, - phsize, ctx->symbol, ctx->newvalue); + phsize, ctx->patch); if (ctx->status == UCS_OK) { return 0; /* continue iteration and patch all objects */ } else { @@ -229,9 +231,8 @@ static int ucm_reloc_phdr_iterator(struct dl_phdr_info *info, size_t size, void static ucs_status_t ucm_reloc_apply_patch(ucm_reloc_patch_t *patch) { ucm_reloc_dl_iter_context_t ctx = { - .symbol = patch->symbol, - .newvalue = patch->value, - .status = UCS_OK + .patch = patch, + .status = UCS_OK }; /* Avoid locks here because we don't modify ELF data structures. @@ -239,7 +240,8 @@ static ucs_status_t ucm_reloc_apply_patch(ucm_reloc_patch_t *patch) */ (void)dl_iterate_phdr(ucm_reloc_phdr_iterator, &ctx); if (ctx.status == UCS_OK) { - ucm_debug("modified '%s' to %p", ctx.symbol, ctx.newvalue); + ucm_debug("modified '%s' from %p to %p", patch->symbol, + patch->prev_value, patch->value); } return ctx.status; } diff --git a/src/ucm/util/reloc.h b/src/ucm/util/reloc.h index f80e464e0bb..36b1f0c1338 100644 --- a/src/ucm/util/reloc.h +++ b/src/ucm/util/reloc.h @@ -20,6 +20,7 @@ typedef struct ucm_reloc_patch { const char *symbol; void *value; + void *prev_value; ucs_list_link_t list; } ucm_reloc_patch_t;