|
Michel Lind |
de7e84 |
From f1ad9d71e677ae94de4b9efeb137ad34a7d10e6a Mon Sep 17 00:00:00 2001
|
|
Michel Lind |
de7e84 |
From: Pete Swain <swine@google.com>
|
|
Michel Lind |
de7e84 |
Date: Fri, 31 May 2024 15:17:46 -0700
|
|
Michel Lind |
de7e84 |
Subject: [PATCH 100/118] create-diff-object: avoid reloc-type collisions on
|
|
Michel Lind |
de7e84 |
elf.h constants
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
The elf.h reloc-type constants are not unique across archs, for example:
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
#define R_PPC64_REL24 10 /* PC relative 26 bit */
|
|
Michel Lind |
de7e84 |
#define R_X86_64_32 10 /* Direct 32 bit zero extended */
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
so to avoid any unexpected aliasing, guard all R_arch_type refs with a
|
|
Michel Lind |
de7e84 |
check on kelf->arch, or a global default arch set from the first elf
|
|
Michel Lind |
de7e84 |
encountered.
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
Closes: #1356 ("Do we need more robust archeticture protection")
|
|
Michel Lind |
de7e84 |
Signed-off-by: Pete Swain <swine@google.com>
|
|
Michel Lind |
de7e84 |
Signed-off-by: Mihails Strasuns <mstrasun@amazon.com>
|
|
Michel Lind |
de7e84 |
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
|
|
Michel Lind |
de7e84 |
---
|
|
Michel Lind |
de7e84 |
kpatch-build/create-diff-object.c | 77 ++++++++++++++++++-----------
|
|
Michel Lind |
de7e84 |
kpatch-build/create-kpatch-module.c | 3 ++
|
|
Michel Lind |
de7e84 |
kpatch-build/kpatch-elf.c | 24 ++++++++-
|
|
Michel Lind |
de7e84 |
kpatch-build/kpatch-elf.h | 3 ++
|
|
Michel Lind |
de7e84 |
4 files changed, 77 insertions(+), 30 deletions(-)
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
--- a/kpatch-build/create-diff-object.c
|
|
Michel Lind |
de7e84 |
+++ b/kpatch-build/create-diff-object.c
|
|
Michel Lind |
de7e84 |
@@ -215,6 +215,8 @@ static bool is_gcc6_localentry_bundled_s
|
|
Michel Lind |
de7e84 |
*/
|
|
Michel Lind |
de7e84 |
static struct rela *toc_rela(const struct rela *rela)
|
|
Michel Lind |
de7e84 |
{
|
|
Michel Lind |
de7e84 |
+ if (!is_arch(PPC64))
|
|
Michel Lind |
de7e84 |
+ return (struct rela *)rela;
|
|
Michel Lind |
de7e84 |
if (rela->type != R_PPC64_TOC16_HA &&
|
|
Michel Lind |
de7e84 |
rela->type != R_PPC64_TOC16_LO_DS)
|
|
Michel Lind |
de7e84 |
return (struct rela *)rela;
|
|
Michel Lind |
de7e84 |
@@ -1623,7 +1625,7 @@ static void kpatch_replace_sections_syms
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
if (is_text_section(relasec->base) &&
|
|
Michel Lind |
de7e84 |
!is_text_section(sym->sec) &&
|
|
Michel Lind |
de7e84 |
- rela->type == R_X86_64_32S &&
|
|
Michel Lind |
de7e84 |
+ is_arch(X86_64) && rela->type == R_X86_64_32S &&
|
|
Michel Lind |
de7e84 |
rela->addend == (long)sym->sec->sh.sh_size &&
|
|
Michel Lind |
de7e84 |
end == (long)sym->sec->sh.sh_size) {
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
@@ -3241,12 +3243,23 @@ static int function_ptr_rela(const struc
|
|
Michel Lind |
de7e84 |
{
|
|
Michel Lind |
de7e84 |
const struct rela *rela_toc = toc_rela(rela);
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
+ switch (def_arch()) {
|
|
Michel Lind |
de7e84 |
+ case PPC64:
|
|
Michel Lind |
de7e84 |
+ if (rela->type != R_PPC64_TOC16_HA &&
|
|
Michel Lind |
de7e84 |
+ rela->type != R_PPC64_TOC16_LO_DS)
|
|
Michel Lind |
de7e84 |
+ return false;
|
|
Michel Lind |
de7e84 |
+ break;
|
|
Michel Lind |
de7e84 |
+ case X86_64:
|
|
Michel Lind |
de7e84 |
+ if (rela->type != R_X86_64_32S)
|
|
Michel Lind |
de7e84 |
+ return false;
|
|
Michel Lind |
de7e84 |
+ break;
|
|
Michel Lind |
de7e84 |
+ default:
|
|
Michel Lind |
de7e84 |
+ break;
|
|
Michel Lind |
de7e84 |
+ }
|
|
Michel Lind |
de7e84 |
+
|
|
Michel Lind |
de7e84 |
return (rela_toc && rela_toc->sym->type == STT_FUNC &&
|
|
Michel Lind |
de7e84 |
!rela_toc->sym->parent &&
|
|
Michel Lind |
de7e84 |
- rela_toc->addend == (int)rela_toc->sym->sym.st_value &&
|
|
Michel Lind |
de7e84 |
- (rela->type == R_X86_64_32S ||
|
|
Michel Lind |
de7e84 |
- rela->type == R_PPC64_TOC16_HA ||
|
|
Michel Lind |
de7e84 |
- rela->type == R_PPC64_TOC16_LO_DS));
|
|
Michel Lind |
de7e84 |
+ rela_toc->addend == (int)rela_toc->sym->sym.st_value);
|
|
Michel Lind |
de7e84 |
}
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
static bool need_klp_reloc(struct kpatch_elf *kelf, struct lookup_table *table,
|
|
Michel Lind |
de7e84 |
@@ -3261,32 +3274,38 @@ static bool need_klp_reloc(struct kpatch
|
|
Michel Lind |
de7e84 |
* These references are treated specially by the module loader and
|
|
Michel Lind |
de7e84 |
* should never be converted to klp relocations.
|
|
Michel Lind |
de7e84 |
*/
|
|
Michel Lind |
de7e84 |
- if (rela->type == R_PPC64_REL16_HA || rela->type == R_PPC64_REL16_LO ||
|
|
Michel Lind |
de7e84 |
- rela->type == R_PPC64_ENTRY)
|
|
Michel Lind |
de7e84 |
- return false;
|
|
Michel Lind |
de7e84 |
+ switch (kelf->arch) {
|
|
Michel Lind |
de7e84 |
+ case PPC64:
|
|
Michel Lind |
de7e84 |
+ if (rela->type == R_PPC64_REL16_HA || rela->type == R_PPC64_REL16_LO ||
|
|
Michel Lind |
de7e84 |
+ rela->type == R_PPC64_ENTRY)
|
|
Michel Lind |
de7e84 |
+ return false;
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
- /* v5.13+ kernels use relative jump labels */
|
|
Michel Lind |
de7e84 |
- if (rela->type == R_PPC64_REL64 && strcmp(relasec->name, ".rela__jump_table"))
|
|
Michel Lind |
de7e84 |
- return false;
|
|
Michel Lind |
de7e84 |
+ /* v5.13+ kernels use relative jump labels */
|
|
Michel Lind |
de7e84 |
+ if (rela->type == R_PPC64_REL64 && strcmp(relasec->name, ".rela__jump_table"))
|
|
Michel Lind |
de7e84 |
+ return false;
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
- /*
|
|
Michel Lind |
de7e84 |
- * On powerpc, the function prologue generated by GCC 6 has the
|
|
Michel Lind |
de7e84 |
- * sequence:
|
|
Michel Lind |
de7e84 |
- *
|
|
Michel Lind |
de7e84 |
- * .globl my_func
|
|
Michel Lind |
de7e84 |
- * .type my_func, @function
|
|
Michel Lind |
de7e84 |
- * .quad .TOC.-my_func
|
|
Michel Lind |
de7e84 |
- * my_func:
|
|
Michel Lind |
de7e84 |
- * .reloc ., R_PPC64_ENTRY ; optional
|
|
Michel Lind |
de7e84 |
- * ld r2,-8(r12)
|
|
Michel Lind |
de7e84 |
- * add r2,r2,r12
|
|
Michel Lind |
de7e84 |
- * .localentry my_func, .-my_func
|
|
Michel Lind |
de7e84 |
- *
|
|
Michel Lind |
de7e84 |
- * The R_PPC64_ENTRY is optional and its symbol might have an empty
|
|
Michel Lind |
de7e84 |
- * name. Leave it as a normal rela.
|
|
Michel Lind |
de7e84 |
- */
|
|
Michel Lind |
de7e84 |
- if (rela->type == R_PPC64_ENTRY)
|
|
Michel Lind |
de7e84 |
- return false;
|
|
Michel Lind |
de7e84 |
+ /*
|
|
Michel Lind |
de7e84 |
+ * On powerpc, the function prologue generated by GCC 6 has the
|
|
Michel Lind |
de7e84 |
+ * sequence:
|
|
Michel Lind |
de7e84 |
+ *
|
|
Michel Lind |
de7e84 |
+ * .globl my_func
|
|
Michel Lind |
de7e84 |
+ * .type my_func, @function
|
|
Michel Lind |
de7e84 |
+ * .quad .TOC.-my_func
|
|
Michel Lind |
de7e84 |
+ * my_func:
|
|
Michel Lind |
de7e84 |
+ * .reloc ., R_PPC64_ENTRY ; optional
|
|
Michel Lind |
de7e84 |
+ * ld r2,-8(r12)
|
|
Michel Lind |
de7e84 |
+ * add r2,r2,r12
|
|
Michel Lind |
de7e84 |
+ * .localentry my_func, .-my_func
|
|
Michel Lind |
de7e84 |
+ *
|
|
Michel Lind |
de7e84 |
+ * The R_PPC64_ENTRY is optional and its symbol might have an empty
|
|
Michel Lind |
de7e84 |
+ * name. Leave it as a normal rela.
|
|
Michel Lind |
de7e84 |
+ */
|
|
Michel Lind |
de7e84 |
+ if (rela->type == R_PPC64_ENTRY)
|
|
Michel Lind |
de7e84 |
+ return false;
|
|
Michel Lind |
de7e84 |
+ break;
|
|
Michel Lind |
de7e84 |
+ default:
|
|
Michel Lind |
de7e84 |
+ break;
|
|
Michel Lind |
de7e84 |
+ }
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
/*
|
|
Michel Lind |
de7e84 |
* Allow references to core module symbols to remain as normal
|
|
Michel Lind |
de7e84 |
--- a/kpatch-build/create-kpatch-module.c
|
|
Michel Lind |
de7e84 |
+++ b/kpatch-build/create-kpatch-module.c
|
|
Michel Lind |
de7e84 |
@@ -58,6 +58,9 @@ static void create_dynamic_rela_sections
|
|
Michel Lind |
de7e84 |
dynsec = create_section_pair(kelf, ".kpatch.dynrelas", sizeof(*dynrelas), nr);
|
|
Michel Lind |
de7e84 |
dynrelas = dynsec->data->d_buf;
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
+ if (kelf->arch != X86_64)
|
|
Michel Lind |
de7e84 |
+ return;
|
|
Michel Lind |
de7e84 |
+
|
|
Michel Lind |
de7e84 |
for (index = 0; index < nr; index++) {
|
|
Michel Lind |
de7e84 |
offset = index * (unsigned int)sizeof(*krelas);
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
--- a/kpatch-build/kpatch-elf.c
|
|
Michel Lind |
de7e84 |
+++ b/kpatch-build/kpatch-elf.c
|
|
Michel Lind |
de7e84 |
@@ -38,6 +38,26 @@
|
|
Michel Lind |
de7e84 |
* Helper functions
|
|
Michel Lind |
de7e84 |
******************/
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
+static enum architecture current_arch;
|
|
Michel Lind |
de7e84 |
+
|
|
Michel Lind |
de7e84 |
+enum architecture def_arch(void)
|
|
Michel Lind |
de7e84 |
+{
|
|
Michel Lind |
de7e84 |
+ return current_arch;
|
|
Michel Lind |
de7e84 |
+}
|
|
Michel Lind |
de7e84 |
+
|
|
Michel Lind |
de7e84 |
+bool is_arch(enum architecture arch)
|
|
Michel Lind |
de7e84 |
+{
|
|
Michel Lind |
de7e84 |
+ return current_arch == arch;
|
|
Michel Lind |
de7e84 |
+}
|
|
Michel Lind |
de7e84 |
+
|
|
Michel Lind |
de7e84 |
+void set_arch(enum architecture arch)
|
|
Michel Lind |
de7e84 |
+{
|
|
Michel Lind |
de7e84 |
+ if (!arch || (current_arch && arch != current_arch))
|
|
Michel Lind |
de7e84 |
+ ERROR("inconsistent ELF arch: setting %d but already %d",
|
|
Michel Lind |
de7e84 |
+ arch, current_arch);
|
|
Michel Lind |
de7e84 |
+ current_arch = arch;
|
|
Michel Lind |
de7e84 |
+}
|
|
Michel Lind |
de7e84 |
+
|
|
Michel Lind |
de7e84 |
char *status_str(enum status status)
|
|
Michel Lind |
de7e84 |
{
|
|
Michel Lind |
de7e84 |
switch(status) {
|
|
Michel Lind |
de7e84 |
@@ -594,8 +614,10 @@ struct kpatch_elf *kpatch_elf_open(const
|
|
Michel Lind |
de7e84 |
kelf->arch = S390;
|
|
Michel Lind |
de7e84 |
break;
|
|
Michel Lind |
de7e84 |
default:
|
|
Michel Lind |
de7e84 |
- ERROR("Unsupported target architecture");
|
|
Michel Lind |
de7e84 |
+ ERROR("Unsupported target architecture: e_machine %x",
|
|
Michel Lind |
de7e84 |
+ ehdr.e_machine);
|
|
Michel Lind |
de7e84 |
}
|
|
Michel Lind |
de7e84 |
+ set_arch(kelf->arch);
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
kpatch_create_section_list(kelf);
|
|
Michel Lind |
de7e84 |
kpatch_create_symbol_list(kelf);
|
|
Michel Lind |
de7e84 |
--- a/kpatch-build/kpatch-elf.h
|
|
Michel Lind |
de7e84 |
+++ b/kpatch-build/kpatch-elf.h
|
|
Michel Lind |
de7e84 |
@@ -159,6 +159,9 @@ int offset_of_string(struct list_head *l
|
|
Michel Lind |
de7e84 |
long rela_target_offset(struct kpatch_elf *kelf, struct section *relasec,
|
|
Michel Lind |
de7e84 |
struct rela *rela);
|
|
Michel Lind |
de7e84 |
unsigned int insn_length(struct kpatch_elf *kelf, void *addr);
|
|
Michel Lind |
de7e84 |
+enum architecture def_arch(void);
|
|
Michel Lind |
de7e84 |
+void set_arch(enum architecture);
|
|
Michel Lind |
de7e84 |
+bool is_arch(enum architecture);
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
#ifndef R_PPC64_ENTRY
|
|
Michel Lind |
de7e84 |
#define R_PPC64_ENTRY 118
|