mirror of
https://github.com/dynup/kpatch
synced 2024-12-28 08:12:01 +00:00
add correlation and compare support for GROUP sections
GROUP section are rare and are a mechanism in the ELF to indicated that certain groups of section must be included or excluded (stripped) together. It is valid to have more than one of these section with the same ".group" name. This currently messes up the section correlation code with correlates based solely on name. This commit adds additional correlation criteria for GROUP sections; namely, the section content must be the same. Changing of groups sections (i.e. reindexing of the section indexes the GROUP section includes in their section data) is not supported and will result in a "new/changed section not included" error. Signed-off-by: Seth Jennings <sjenning@redhat.com>
This commit is contained in:
parent
2990bb790a
commit
bf86555e06
@ -101,6 +101,7 @@ struct section {
|
||||
enum status status;
|
||||
int include;
|
||||
int ignore;
|
||||
int grouped;
|
||||
union {
|
||||
struct { /* if (is_rela_section()) */
|
||||
struct section *base;
|
||||
@ -681,6 +682,17 @@ void kpatch_correlate_sections(struct list_head *seclist1, struct list_head *sec
|
||||
list_for_each_entry(sec2, seclist2, list) {
|
||||
if (strcmp(sec1->name, sec2->name))
|
||||
continue;
|
||||
/*
|
||||
* Group sections must match exactly to be correlated.
|
||||
* Changed group sections are currently not supported.
|
||||
*/
|
||||
if (sec1->sh.sh_type == SHT_GROUP) {
|
||||
if (sec1->data->d_size != sec2->data->d_size)
|
||||
continue;
|
||||
if (memcmp(sec1->data->d_buf, sec2->data->d_buf,
|
||||
sec1->data->d_size))
|
||||
continue;
|
||||
}
|
||||
sec1->twin = sec2;
|
||||
sec2->twin = sec1;
|
||||
/* set initial status, might change */
|
||||
@ -698,6 +710,11 @@ void kpatch_correlate_symbols(struct list_head *symlist1, struct list_head *syml
|
||||
list_for_each_entry(sym2, symlist2, list) {
|
||||
if (!strcmp(sym1->name, sym2->name) &&
|
||||
sym1->type == sym2->type) {
|
||||
/* group section symbols must have correlated sections */
|
||||
if (sym1->sec &&
|
||||
sym1->sec->sh.sh_type == SHT_GROUP &&
|
||||
sym1->sec->twin != sym2->sec)
|
||||
continue;
|
||||
sym1->twin = sym2;
|
||||
sym2->twin = sym1;
|
||||
/* set initial status, might change */
|
||||
@ -742,6 +759,31 @@ void kpatch_check_program_headers(Elf *elf)
|
||||
DIFF_FATAL("ELF contains program header");
|
||||
}
|
||||
|
||||
|
||||
void kpatch_mark_grouped_sections(struct kpatch_elf *kelf)
|
||||
{
|
||||
struct section *groupsec, *sec;
|
||||
unsigned int *data, *end;
|
||||
|
||||
list_for_each_entry(groupsec, &kelf->sections, list) {
|
||||
if (groupsec->sh.sh_type != SHT_GROUP)
|
||||
continue;
|
||||
data = groupsec->data->d_buf;
|
||||
end = groupsec->data->d_buf + groupsec->data->d_size;
|
||||
data++; /* skip first flag word (e.g. GRP_COMDAT) */
|
||||
while (data < end) {
|
||||
sec = find_section_by_index(&kelf->sections, *data);
|
||||
if (!sec)
|
||||
ERROR("group section not found");
|
||||
sec->grouped = 1;
|
||||
log_debug("marking section %s (%d) as grouped\n",
|
||||
sec->name, sec->index);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* When gcc makes compiler optimizations which affect a function's calling
|
||||
* interface, it mangles the function's name. For example, sysctl_print_dir is
|
||||
@ -1066,6 +1108,17 @@ void kpatch_verify_patchability(struct kpatch_elf *kelf)
|
||||
errs++;
|
||||
}
|
||||
|
||||
if (sec->status == CHANGED && sec->grouped) {
|
||||
log_normal("changed section %s is part of a section group\n",
|
||||
sec->name);
|
||||
errs++;
|
||||
}
|
||||
|
||||
if (sec->sh.sh_type == SHT_GROUP && sec->status == NEW) {
|
||||
log_normal("new/changed group sections are not supported\n");
|
||||
errs++;
|
||||
}
|
||||
|
||||
/* ensure we aren't including .data.* or .bss.* */
|
||||
if (sec->include &&
|
||||
(!strncmp(sec->name, ".data", 5) ||
|
||||
@ -2516,6 +2569,7 @@ int main(int argc, char *argv[])
|
||||
kpatch_check_program_headers(kelf_base->elf);
|
||||
kpatch_check_program_headers(kelf_patched->elf);
|
||||
|
||||
kpatch_mark_grouped_sections(kelf_patched);
|
||||
kpatch_replace_sections_syms(kelf_base);
|
||||
kpatch_replace_sections_syms(kelf_patched);
|
||||
kpatch_rename_mangled_functions(kelf_base, kelf_patched);
|
||||
|
Loading…
Reference in New Issue
Block a user