mirror of
https://github.com/dynup/kpatch
synced 2025-04-11 03:31:20 +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;
|
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)
|
int rela_equal(struct rela *rela1, struct rela *rela2)
|
||||||
{
|
{
|
||||||
|
char *prefix1, *prefix2;
|
||||||
|
|
||||||
if (rela1->type != rela2->type ||
|
if (rela1->type != rela2->type ||
|
||||||
rela1->offset != rela2->offset)
|
rela1->offset != rela2->offset)
|
||||||
return 0;
|
return 0;
|
||||||
@ -525,9 +556,18 @@ int rela_equal(struct rela *rela1, struct rela *rela2)
|
|||||||
!strcmp(rela1->string, rela2->string))
|
!strcmp(rela1->string, rela2->string))
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
if (strcmp(rela1->sym->name, rela2->sym->name))
|
if (rela1->addend != rela2->addend)
|
||||||
return 0;
|
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;
|
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) {
|
list_for_each_entry(sec2, seclist2, list) {
|
||||||
if (strcmp(sec1->name, sec2->name))
|
if (strcmp(sec1->name, sec2->name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (special_static_prefix(sec1->secsym))
|
||||||
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Group sections must match exactly to be correlated.
|
* Group sections must match exactly to be correlated.
|
||||||
* Changed group sections are currently not supported.
|
* 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)
|
sym1->type != sym2->type)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (special_static_prefix(sym1))
|
||||||
|
continue;
|
||||||
|
|
||||||
/* group section symbols must have correlated sections */
|
/* group section symbols must have correlated sections */
|
||||||
if (sym1->sec &&
|
if (sym1->sec &&
|
||||||
sym1->sec->sh.sh_type == SHT_GROUP &&
|
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
|
* 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
|
* can arbitrarily change. Try to rename the patched version of the symbol to
|
||||||
* match the base version and then correlate them.
|
* match the base version and then correlate them.
|
||||||
*/
|
*/
|
||||||
@ -891,6 +938,9 @@ void kpatch_correlate_static_local_variables(struct kpatch_elf *base,
|
|||||||
sym->twin)
|
sym->twin)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (special_static_prefix(sym))
|
||||||
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The static variables in the __verbose section contain
|
* The static variables in the __verbose section contain
|
||||||
* debugging information specific to the patched object and
|
* debugging information specific to the patched object and
|
||||||
@ -1032,7 +1082,8 @@ void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
|
|||||||
int add_off;
|
int add_off;
|
||||||
|
|
||||||
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) ||
|
||||||
|
is_debug_section(sec))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
list_for_each_entry(rela, &sec->relas, list) {
|
list_for_each_entry(rela, &sec->relas, list) {
|
||||||
@ -1159,10 +1210,14 @@ void kpatch_verify_patchability(struct kpatch_elf *kelf)
|
|||||||
errs++;
|
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 &&
|
if (sec->include && sec->status != NEW &&
|
||||||
(!strncmp(sec->name, ".data", 5) ||
|
(!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",
|
log_normal("data section %s selected for inclusion\n",
|
||||||
sec->name);
|
sec->name);
|
||||||
errs++;
|
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