From b9ae8a1ea14d46b3f4ba887fb10f9898c6f5cc53 Mon Sep 17 00:00:00 2001 From: ningyu Date: Sat, 11 May 2024 08:06:58 +0000 Subject: [PATCH] upatch-manage: Fixed the core dump issue after applying hot patches to nginx on x86_64 architecture. For non-dynamic library elf, do not place the global variables in the GOT table --- upatch-manage/arch/x86_64/resolve.c | 16 ++++++++++++--- upatch-manage/upatch-elf.c | 32 +++++++++++++++++++++++++++-- upatch-manage/upatch-elf.h | 5 ++++- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/upatch-manage/arch/x86_64/resolve.c b/upatch-manage/arch/x86_64/resolve.c index 45261dd..5432b20 100644 --- a/upatch-manage/arch/x86_64/resolve.c +++ b/upatch-manage/arch/x86_64/resolve.c @@ -123,10 +123,20 @@ unsigned long insert_got_table(struct upatch_elf *uelf, struct object_file *obj, goto out; } - elf_addr = setup_got_table(uelf, jmp_addr, tls_addr); + if (uelf->relf->info.is_dyn && !uelf->relf->info.is_pie) { + elf_addr = setup_got_table(uelf, jmp_addr, tls_addr); + + log_debug("0x%lx: jmp_addr=0x%lx\n", elf_addr, jmp_addr); + + } else { + /* + * For non-dynamic library files, global variables are not placed in the GOT table + */ + elf_addr = jmp_addr; + log_debug("For non-dynamic library: jmp_addr=0x%lx\n", jmp_addr); + } - log_debug("0x%lx: jmp_addr=0x%lx\n", elf_addr, jmp_addr); out: return elf_addr; -} \ No newline at end of file +} diff --git a/upatch-manage/upatch-elf.c b/upatch-manage/upatch-elf.c index 02444eb..78c7fd7 100644 --- a/upatch-manage/upatch-elf.c +++ b/upatch-manage/upatch-elf.c @@ -132,6 +132,31 @@ int upatch_init(struct upatch_elf *uelf, const char *name) return 0; } +static bool is_pie_elf(struct running_elf *relf) +{ + GElf_Shdr *shdr = &relf->info.shdrs[relf->index.dynamic]; + GElf_Dyn *dyns = (void *)relf->info.hdr + shdr->sh_offset; + if (relf->index.dynamic == 0) { + return false; + } + for (Elf64_Xword i = 0; i < shdr->sh_size / sizeof(GElf_Dyn); i++) { + log_debug("Syminfo %lx, %lx\n", dyns[i].d_tag, dyns[i].d_un.d_val); + if (dyns[i].d_tag == DT_FLAGS_1) { + if ((dyns[i].d_un.d_val & DF_1_PIE) != 0) + return true; + break; + } + } + return false; +} + +static bool is_dyn_elf(struct running_elf *relf) +{ + GElf_Ehdr *ehdr = relf->info.hdr; + + return ehdr->e_type == ET_DYN; +} + int binary_init(struct running_elf *relf, const char *name) { int ret = open_elf(&relf->info, name); @@ -156,7 +181,8 @@ int binary_init(struct running_elf *relf, const char *name) relf->dynstrtab = (char *)relf->info.hdr + relf->info.shdrs[relf->info.shdrs[i].sh_link].sh_offset; } else if (relf->info.shdrs[i].sh_type == SHT_DYNAMIC) { - /* Currently, we don't utilize it */ + log_debug("Found section '%s', idx=%d\n", DYNAMIC_NAME, i); + relf->index.dynamic = i; } else if (streql(sec_name, PLT_RELA_NAME) && relf->info.shdrs[i].sh_type == SHT_RELA) { log_debug("Found section '%s', idx=%d\n", PLT_RELA_NAME, i); @@ -177,7 +203,9 @@ int binary_init(struct running_elf *relf, const char *name) break; } } - + + relf->info.is_pie = is_pie_elf(relf); + relf->info.is_dyn = is_dyn_elf(relf); return 0; } diff --git a/upatch-manage/upatch-elf.h b/upatch-manage/upatch-elf.h index fe68b7e..481fec9 100644 --- a/upatch-manage/upatch-elf.h +++ b/upatch-manage/upatch-elf.h @@ -30,6 +30,7 @@ #define SYMTAB_NAME ".symtab" #define DYNSYM_NAME ".dynsym" +#define DYNAMIC_NAME ".dynamic" #define GOT_RELA_NAME ".rela.dyn" #define PLT_RELA_NAME ".rela.plt" #define BUILD_ID_NAME ".note.gnu.build-id" @@ -95,6 +96,8 @@ struct elf_info { char *shstrtab; unsigned int num_build_id; + bool is_pie; + bool is_dyn; }; struct running_elf { @@ -111,7 +114,7 @@ struct running_elf { struct { unsigned int sym, str; unsigned int rela_dyn, rela_plt; - unsigned int dynsym, dynstr; + unsigned int dynsym, dynstr, dynamic; } index; /* load bias, used to handle ASLR */ -- 2.34.1