Commit 6890acac authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'objtool_urgent_for_v5.15_rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull objtool fixes from Borislav Petkov:

 - Update section headers before the respective relocations to not
   trigger a safety check in elftoolchain's implementation of libelf

 - Do not add garbage data to the .rela.orc_unwind_ip section

* tag 'objtool_urgent_for_v5.15_rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  objtool: Update section header before relocations
  objtool: Check for gelf_update_rel[a] failures
parents f644750c 86e1e054
...@@ -508,6 +508,7 @@ int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset, ...@@ -508,6 +508,7 @@ int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
list_add_tail(&reloc->list, &sec->reloc->reloc_list); list_add_tail(&reloc->list, &sec->reloc->reloc_list);
elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc)); elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
sec->reloc->sh.sh_size += sec->reloc->sh.sh_entsize;
sec->reloc->changed = true; sec->reloc->changed = true;
return 0; return 0;
...@@ -977,63 +978,63 @@ static struct section *elf_create_reloc_section(struct elf *elf, ...@@ -977,63 +978,63 @@ static struct section *elf_create_reloc_section(struct elf *elf,
} }
} }
static int elf_rebuild_rel_reloc_section(struct section *sec, int nr) static int elf_rebuild_rel_reloc_section(struct section *sec)
{ {
struct reloc *reloc; struct reloc *reloc;
int idx = 0, size; int idx = 0;
void *buf; void *buf;
/* Allocate a buffer for relocations */ /* Allocate a buffer for relocations */
size = nr * sizeof(GElf_Rel); buf = malloc(sec->sh.sh_size);
buf = malloc(size);
if (!buf) { if (!buf) {
perror("malloc"); perror("malloc");
return -1; return -1;
} }
sec->data->d_buf = buf; sec->data->d_buf = buf;
sec->data->d_size = size; sec->data->d_size = sec->sh.sh_size;
sec->data->d_type = ELF_T_REL; sec->data->d_type = ELF_T_REL;
sec->sh.sh_size = size;
idx = 0; idx = 0;
list_for_each_entry(reloc, &sec->reloc_list, list) { list_for_each_entry(reloc, &sec->reloc_list, list) {
reloc->rel.r_offset = reloc->offset; reloc->rel.r_offset = reloc->offset;
reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type); reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
gelf_update_rel(sec->data, idx, &reloc->rel); if (!gelf_update_rel(sec->data, idx, &reloc->rel)) {
WARN_ELF("gelf_update_rel");
return -1;
}
idx++; idx++;
} }
return 0; return 0;
} }
static int elf_rebuild_rela_reloc_section(struct section *sec, int nr) static int elf_rebuild_rela_reloc_section(struct section *sec)
{ {
struct reloc *reloc; struct reloc *reloc;
int idx = 0, size; int idx = 0;
void *buf; void *buf;
/* Allocate a buffer for relocations with addends */ /* Allocate a buffer for relocations with addends */
size = nr * sizeof(GElf_Rela); buf = malloc(sec->sh.sh_size);
buf = malloc(size);
if (!buf) { if (!buf) {
perror("malloc"); perror("malloc");
return -1; return -1;
} }
sec->data->d_buf = buf; sec->data->d_buf = buf;
sec->data->d_size = size; sec->data->d_size = sec->sh.sh_size;
sec->data->d_type = ELF_T_RELA; sec->data->d_type = ELF_T_RELA;
sec->sh.sh_size = size;
idx = 0; idx = 0;
list_for_each_entry(reloc, &sec->reloc_list, list) { list_for_each_entry(reloc, &sec->reloc_list, list) {
reloc->rela.r_offset = reloc->offset; reloc->rela.r_offset = reloc->offset;
reloc->rela.r_addend = reloc->addend; reloc->rela.r_addend = reloc->addend;
reloc->rela.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type); reloc->rela.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
gelf_update_rela(sec->data, idx, &reloc->rela); if (!gelf_update_rela(sec->data, idx, &reloc->rela)) {
WARN_ELF("gelf_update_rela");
return -1;
}
idx++; idx++;
} }
...@@ -1042,16 +1043,9 @@ static int elf_rebuild_rela_reloc_section(struct section *sec, int nr) ...@@ -1042,16 +1043,9 @@ static int elf_rebuild_rela_reloc_section(struct section *sec, int nr)
static int elf_rebuild_reloc_section(struct elf *elf, struct section *sec) static int elf_rebuild_reloc_section(struct elf *elf, struct section *sec)
{ {
struct reloc *reloc;
int nr;
nr = 0;
list_for_each_entry(reloc, &sec->reloc_list, list)
nr++;
switch (sec->sh.sh_type) { switch (sec->sh.sh_type) {
case SHT_REL: return elf_rebuild_rel_reloc_section(sec, nr); case SHT_REL: return elf_rebuild_rel_reloc_section(sec);
case SHT_RELA: return elf_rebuild_rela_reloc_section(sec, nr); case SHT_RELA: return elf_rebuild_rela_reloc_section(sec);
default: return -1; default: return -1;
} }
} }
...@@ -1111,12 +1105,6 @@ int elf_write(struct elf *elf) ...@@ -1111,12 +1105,6 @@ int elf_write(struct elf *elf)
/* Update changed relocation sections and section headers: */ /* Update changed relocation sections and section headers: */
list_for_each_entry(sec, &elf->sections, list) { list_for_each_entry(sec, &elf->sections, list) {
if (sec->changed) { if (sec->changed) {
if (sec->base &&
elf_rebuild_reloc_section(elf, sec)) {
WARN("elf_rebuild_reloc_section");
return -1;
}
s = elf_getscn(elf->elf, sec->idx); s = elf_getscn(elf->elf, sec->idx);
if (!s) { if (!s) {
WARN_ELF("elf_getscn"); WARN_ELF("elf_getscn");
...@@ -1127,6 +1115,12 @@ int elf_write(struct elf *elf) ...@@ -1127,6 +1115,12 @@ int elf_write(struct elf *elf)
return -1; return -1;
} }
if (sec->base &&
elf_rebuild_reloc_section(elf, sec)) {
WARN("elf_rebuild_reloc_section");
return -1;
}
sec->changed = false; sec->changed = false;
elf->changed = true; elf->changed = true;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment