mirror of
https://github.com/dynup/kpatch
synced 2025-04-01 22:48:08 +00:00
Merge pull request #412 from jpoimboe/key-warned
support for__key and __warned special static local vars
This commit is contained in:
commit
93398c21ca
@ -514,8 +514,39 @@ struct kpatch_elf *kpatch_elf_open(const char *name)
|
||||
return kelf;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function detects whether the given symbol is a "special" static local
|
||||
* variable (for lack of a better term). If so, it returns the variable's
|
||||
* prefix string (with the trailing number removed).
|
||||
*
|
||||
* Special static local variables should never be correlated and should always
|
||||
* be included if they are referenced by an included function.
|
||||
*/
|
||||
char *special_static_prefix(struct symbol *sym)
|
||||
{
|
||||
if (!sym)
|
||||
return NULL;
|
||||
|
||||
if (sym->type == STT_OBJECT &&
|
||||
sym->bind == STB_LOCAL) {
|
||||
if (!strncmp(sym->name, "__key.", 6))
|
||||
return "__key.";
|
||||
|
||||
if (!strncmp(sym->name, "__warned.", 9))
|
||||
return "__warned.";
|
||||
}
|
||||
|
||||
if (sym->type == STT_SECTION &&
|
||||
!strncmp(sym->name, ".bss.__key.", 11))
|
||||
return ".bss.__key.";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int rela_equal(struct rela *rela1, struct rela *rela2)
|
||||
{
|
||||
char *prefix1, *prefix2;
|
||||
|
||||
if (rela1->type != rela2->type ||
|
||||
rela1->offset != rela2->offset)
|
||||
return 0;
|
||||
@ -525,9 +556,18 @@ int rela_equal(struct rela *rela1, struct rela *rela2)
|
||||
!strcmp(rela1->string, rela2->string))
|
||||
return 1;
|
||||
} else {
|
||||
if (strcmp(rela1->sym->name, rela2->sym->name))
|
||||
if (rela1->addend != rela2->addend)
|
||||
return 0;
|
||||
if (rela1->addend == rela2->addend)
|
||||
|
||||
prefix1 = special_static_prefix(rela1->sym);
|
||||
if (prefix1) {
|
||||
prefix2 = special_static_prefix(rela2->sym);
|
||||
if (!prefix2)
|
||||
return 0;
|
||||
return !strcmp(prefix1, prefix2);
|
||||
}
|
||||
|
||||
if (!strcmp(rela1->sym->name, rela2->sym->name))
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -675,6 +715,10 @@ 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;
|
||||
|
||||
if (special_static_prefix(sec1->secsym))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Group sections must match exactly to be correlated.
|
||||
* Changed group sections are currently not supported.
|
||||
@ -705,6 +749,9 @@ void kpatch_correlate_symbols(struct list_head *symlist1, struct list_head *syml
|
||||
sym1->type != sym2->type)
|
||||
continue;
|
||||
|
||||
if (special_static_prefix(sym1))
|
||||
continue;
|
||||
|
||||
/* group section symbols must have correlated sections */
|
||||
if (sym1->sec &&
|
||||
sym1->sec->sh.sh_type == SHT_GROUP &&
|
||||
@ -874,7 +921,7 @@ void kpatch_rename_mangled_functions(struct kpatch_elf *base,
|
||||
|
||||
/*
|
||||
* gcc renames static local variables by appending a period and a number. For
|
||||
* example, __key could be renamed to __key.31452. Unfortunately this number
|
||||
* example, __foo could be renamed to __foo.31452. Unfortunately this number
|
||||
* can arbitrarily change. Try to rename the patched version of the symbol to
|
||||
* match the base version and then correlate them.
|
||||
*/
|
||||
@ -891,6 +938,9 @@ void kpatch_correlate_static_local_variables(struct kpatch_elf *base,
|
||||
sym->twin)
|
||||
continue;
|
||||
|
||||
if (special_static_prefix(sym))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* The static variables in the __verbose section contain
|
||||
* debugging information specific to the patched object and
|
||||
@ -1032,7 +1082,8 @@ void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
|
||||
int add_off;
|
||||
|
||||
list_for_each_entry(sec, &kelf->sections, list) {
|
||||
if (!is_rela_section(sec))
|
||||
if (!is_rela_section(sec) ||
|
||||
is_debug_section(sec))
|
||||
continue;
|
||||
|
||||
list_for_each_entry(rela, &sec->relas, list) {
|
||||
@ -1159,10 +1210,14 @@ void kpatch_verify_patchability(struct kpatch_elf *kelf)
|
||||
errs++;
|
||||
}
|
||||
|
||||
/* ensure we aren't including .data.* or .bss.* */
|
||||
/*
|
||||
* ensure we aren't including .data.* or .bss.*
|
||||
* (.data.unlikely is ok b/c it only has __warned vars)
|
||||
*/
|
||||
if (sec->include && sec->status != NEW &&
|
||||
(!strncmp(sec->name, ".data", 5) ||
|
||||
!strncmp(sec->name, ".bss", 4))) {
|
||||
!strncmp(sec->name, ".bss", 4)) &&
|
||||
strcmp(sec->name, ".data.unlikely")) {
|
||||
log_normal("data section %s selected for inclusion\n",
|
||||
sec->name);
|
||||
errs++;
|
||||
|
23
test/integration/special-static.patch
Normal file
23
test/integration/special-static.patch
Normal file
@ -0,0 +1,23 @@
|
||||
Index: src/kernel/fork.c
|
||||
===================================================================
|
||||
--- src.orig/kernel/fork.c
|
||||
+++ src/kernel/fork.c
|
||||
@@ -1029,10 +1029,18 @@ static void posix_cpu_timers_init_group(
|
||||
INIT_LIST_HEAD(&sig->cpu_timers[2]);
|
||||
}
|
||||
|
||||
+void kpatch_foo(void)
|
||||
+{
|
||||
+ if (!jiffies)
|
||||
+ printk("kpatch copy signal\n");
|
||||
+}
|
||||
+
|
||||
static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
|
||||
{
|
||||
struct signal_struct *sig;
|
||||
|
||||
+ kpatch_foo();
|
||||
+
|
||||
if (clone_flags & CLONE_THREAD)
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user