133 lines
4.1 KiB
Diff
133 lines
4.1 KiB
Diff
|
|
From b9ae8a1ea14d46b3f4ba887fb10f9898c6f5cc53 Mon Sep 17 00:00:00 2001
|
||
|
|
From: ningyu <ningyu9@huawei.com>
|
||
|
|
Date: Sat, 11 May 2024 08:06:58 +0000
|
||
|
|
Subject: [PATCH 19/20] 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
|
||
|
|
|