fix review comments

Signed-off-by: Seth Jennings <sjenning@redhat.com>
This commit is contained in:
Seth Jennings 2014-05-15 13:25:27 -05:00
parent 880e271841
commit e1177e3a03
5 changed files with 41 additions and 25 deletions

1
.gitignore vendored
View File

@ -7,7 +7,6 @@
*.swp *.swp
.tmp_versions .tmp_versions
Module.symvers Module.symvers
kpatch-build/lookup.o
kpatch-build/lookup kpatch-build/lookup
kpatch-build/create-diff-object kpatch-build/create-diff-object
man/kpatch.1.gz man/kpatch.1.gz

View File

@ -472,13 +472,13 @@ int kpatch_register(struct kpatch_module *kpmod, bool replace)
dynrela->type, dynrela->dest, dynrela->type, dynrela->dest,
dynrela->src, i); dynrela->src, i);
ret = -EINVAL; ret = -EINVAL;
goto err_up; goto err_put;
} }
set_memory_rw((unsigned long)loc & PAGE_MASK, 1); set_memory_rw((unsigned long)loc & PAGE_MASK, 1);
ret = probe_kernel_write(loc, &val, size); ret = probe_kernel_write(loc, &val, size);
set_memory_ro((unsigned long)loc & PAGE_MASK, 1); set_memory_ro((unsigned long)loc & PAGE_MASK, 1);
if (ret) if (ret)
goto err_up; goto err_put;
} }
for (i = 0; i < num_funcs; i++) { for (i = 0; i < num_funcs; i++) {
@ -597,6 +597,7 @@ err_unregister:
kpatch_num_registered--; kpatch_num_registered--;
err_rollback: err_rollback:
kpatch_remove_funcs_from_filter(funcs, num_funcs); kpatch_remove_funcs_from_filter(funcs, num_funcs);
err_put:
module_put(kpmod->mod); module_put(kpmod->mod);
err_up: err_up:
up(&kpatch_mutex); up(&kpatch_mutex);

View File

@ -7,9 +7,6 @@ TARGETS = create-diff-object
all: $(TARGETS) all: $(TARGETS)
%: %.c
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
create-diff-object: create-diff-object.c list.h lookup.c lookup.h create-diff-object: create-diff-object.c list.h lookup.c lookup.h
$(CC) $(CFLAGS) create-diff-object.c lookup.c -o $@ $(LDFLAGS) $(CC) $(CFLAGS) create-diff-object.c lookup.c -o $@ $(LDFLAGS)

View File

@ -1366,7 +1366,7 @@ void kpatch_create_patches_sections(struct kpatch_elf *kelf,
/* allocate section resources */ /* allocate section resources */
ALLOC_LINK(sec, &kelf->sections); ALLOC_LINK(sec, &kelf->sections);
size = nr * sizeof(*patches); size = nr * sizeof(*patches);
patches = malloc(nr * sizeof(*patches)); patches = malloc(size);
if (!patches) if (!patches)
ERROR("malloc"); ERROR("malloc");
sec->name = ".kpatch.patches"; sec->name = ".kpatch.patches";
@ -1410,7 +1410,7 @@ void kpatch_create_patches_sections(struct kpatch_elf *kelf,
find_section_by_name(&kelf->sections, ".symtab")->index; find_section_by_name(&kelf->sections, ".symtab")->index;
relasec->sh.sh_info = sec->index; relasec->sh.sh_info = sec->index;
/* populate text section */ /* populate sections */
index = 0; index = 0;
list_for_each_entry(sym, &kelf->symbols, list) { list_for_each_entry(sym, &kelf->symbols, list) {
if (sym->type == STT_FUNC && sym->sec->include) { if (sym->type == STT_FUNC && sym->sec->include) {
@ -1433,7 +1433,11 @@ void kpatch_create_patches_sections(struct kpatch_elf *kelf,
patches[index].old_size = result.size; patches[index].old_size = result.size;
patches[index].new_size = sym->sym.st_size; patches[index].new_size = sym->sym.st_size;
/* add entry in rela list */ /*
* Add a relocation that will populate
* the patches[index].new_addr field at
* module load time.
*/
ALLOC_LINK(rela, &relasec->relas); ALLOC_LINK(rela, &relasec->relas);
rela->sym = sym; rela->sym = sym;
rela->type = R_X86_64_64; rela->type = R_X86_64_64;
@ -1480,7 +1484,7 @@ void kpatch_create_dynamic_rela_sections(struct kpatch_elf *kelf,
/* allocate section resources */ /* allocate section resources */
ALLOC_LINK(sec, &kelf->sections); ALLOC_LINK(sec, &kelf->sections);
size = nr * sizeof(*dynrelas); size = nr * sizeof(*dynrelas);
dynrelas = malloc(nr * sizeof(*dynrelas)); dynrelas = malloc(size);
if (!dynrelas) if (!dynrelas)
ERROR("malloc"); ERROR("malloc");
sec->name = ".kpatch.dynrelas"; sec->name = ".kpatch.dynrelas";
@ -1524,7 +1528,7 @@ void kpatch_create_dynamic_rela_sections(struct kpatch_elf *kelf,
find_section_by_name(&kelf->sections, ".symtab")->index; find_section_by_name(&kelf->sections, ".symtab")->index;
relasec->sh.sh_info = sec->index; relasec->sh.sh_info = sec->index;
/* populate text section (reuse sec for iterator here) */ /* populate sections (reuse sec for iterator here) */
index = 0; index = 0;
list_for_each_entry(sec, &kelf->sections, list) { list_for_each_entry(sec, &kelf->sections, list) {
if (!is_rela_section(sec)) if (!is_rela_section(sec))
@ -1575,7 +1579,12 @@ void kpatch_create_dynamic_rela_sections(struct kpatch_elf *kelf,
ERROR("size mismatch in dynrelas sections"); ERROR("size mismatch in dynrelas sections");
} }
void kpatch_strip_non_included_syms(struct lookup_table *table, /*
* This function strips out symbols that were referenced by changed rela
* sections, but the rela entries that referenced them were converted to
* dynrelas and are no longer needed.
*/
void kpatch_strip_unneeded_syms(struct lookup_table *table,
struct kpatch_elf *kelf) struct kpatch_elf *kelf)
{ {
struct symbol *sym, *safe; struct symbol *sym, *safe;
@ -1666,9 +1675,6 @@ void kpatch_write_output_elf(struct kpatch_elf *kelf, Elf *elf, char *outfile)
/* add changed sections */ /* add changed sections */
list_for_each_entry(sec, &kelf->sections, list) { list_for_each_entry(sec, &kelf->sections, list) {
if (is_rela_section(sec))
kpatch_rebuild_rela_section_data(sec);
scn = elf_newscn(elfout); scn = elf_newscn(elfout);
if (!scn) if (!scn)
ERROR("elf_newscn"); ERROR("elf_newscn");
@ -1756,6 +1762,7 @@ int main(int argc, char *argv[])
struct arguments arguments; struct arguments arguments;
int num_changed; int num_changed;
struct lookup_table *vmlinux; struct lookup_table *vmlinux;
struct section *sec;
struct symbol *sym; struct symbol *sym;
char *hint; char *hint;
@ -1825,7 +1832,7 @@ int main(int argc, char *argv[])
} }
kpatch_create_patches_sections(kelf_out, vmlinux, hint); kpatch_create_patches_sections(kelf_out, vmlinux, hint);
kpatch_create_dynamic_rela_sections(kelf_out, vmlinux, hint); kpatch_create_dynamic_rela_sections(kelf_out, vmlinux, hint);
kpatch_strip_non_included_syms(vmlinux, kelf_out); kpatch_strip_unneeded_syms(vmlinux, kelf_out);
kpatch_create_shstrtab(kelf_out); kpatch_create_shstrtab(kelf_out);
kpatch_create_strtab(kelf_out); kpatch_create_strtab(kelf_out);
@ -1834,6 +1841,12 @@ int main(int argc, char *argv[])
if (arguments.inventory) if (arguments.inventory)
kpatch_write_inventory_file(kelf_out, outfile); kpatch_write_inventory_file(kelf_out, outfile);
/* rebuild the rela section data buffers from their relas lists */
list_for_each_entry(sec, &kelf_out->sections, list)
if (is_rela_section(sec))
kpatch_rebuild_rela_section_data(sec);
kpatch_write_output_elf(kelf_out, kelf_patched->elf, outfile); kpatch_write_output_elf(kelf_out, kelf_patched->elf, outfile);
return 0; return 0;

View File

@ -140,7 +140,7 @@ void lookup_close(struct lookup_table *table)
int lookup_local_symbol(struct lookup_table *table, char *name, char *hint, int lookup_local_symbol(struct lookup_table *table, char *name, char *hint,
struct lookup_result *result) struct lookup_result *result)
{ {
struct symbol *sym; struct symbol *sym, *match = NULL;
int i; int i;
char *curfile = NULL; char *curfile = NULL;
@ -151,18 +151,24 @@ int lookup_local_symbol(struct lookup_table *table, char *name, char *hint,
curfile = sym->name; curfile = sym->name;
continue; /* begin hint file symbols */ continue; /* begin hint file symbols */
} else if (curfile) } else if (curfile)
break; /* end hint file symbols */ curfile = NULL; /* end hint file symbols */
} }
if (!curfile) if (!curfile)
continue; continue;
if (sym->bind == STB_LOCAL && !strcmp(sym->name, name)) { if (sym->bind == STB_LOCAL && !strcmp(sym->name, name)) {
result->value = sym->value; if (match)
result->size = sym->size; /* dup file+symbol, unresolvable ambiguity */
return 0; return 1;
match = sym;
} }
} }
if (!match)
return 1; return 1;
result->value = match->value;
result->size = match->size;
return 0;
} }
int lookup_global_symbol(struct lookup_table *table, char *name, int lookup_global_symbol(struct lookup_table *table, char *name,