mirror of
https://github.com/dynup/kpatch
synced 2025-05-10 03:47:56 +00:00
review changes for module support PR
Signed-off-by: Seth Jennings <sjenning@redhat.com>
This commit is contained in:
parent
5b62d5f169
commit
15b22cf01b
@ -473,15 +473,20 @@ static int kpatch_verify_symbol_match(char *name, unsigned long addr)
|
|||||||
|
|
||||||
static unsigned long kpatch_find_module_symbol(struct module *mod, char *name)
|
static unsigned long kpatch_find_module_symbol(struct module *mod, char *name)
|
||||||
{
|
{
|
||||||
char buf[255], *pos;
|
char buf[KSYM_SYMBOL_LEN];
|
||||||
|
|
||||||
|
/* check total string length for overrun */
|
||||||
|
if (strlen(mod->name) + strlen(name) + 1 >= KSYM_SYMBOL_LEN) {
|
||||||
|
pr_err("buffer overrun finding symbol '%s' in module '%s'\n",
|
||||||
|
name, mod->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* encode symbol name as "mod->name:name" */
|
/* encode symbol name as "mod->name:name" */
|
||||||
strcpy(buf, mod->name);
|
strcpy(buf, mod->name);
|
||||||
pos = buf + strlen(mod->name);
|
strcat(buf, ":");
|
||||||
*pos++ = ':';
|
strcat(buf, name);
|
||||||
strcpy(pos, name);
|
|
||||||
|
|
||||||
pr_notice("looking up '%s'\n", buf);
|
|
||||||
return kallsyms_lookup_name(buf);
|
return kallsyms_lookup_name(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,7 +498,7 @@ static int kpatch_write_relocations(struct kpatch_module *kpmod)
|
|||||||
unsigned long core = (unsigned long)kpmod->mod->module_core;
|
unsigned long core = (unsigned long)kpmod->mod->module_core;
|
||||||
unsigned long core_ro_size = kpmod->mod->core_ro_size;
|
unsigned long core_ro_size = kpmod->mod->core_ro_size;
|
||||||
unsigned long core_size = kpmod->mod->core_size;
|
unsigned long core_size = kpmod->mod->core_size;
|
||||||
unsigned long old_addr;
|
unsigned long src_addr;
|
||||||
struct module *mod;
|
struct module *mod;
|
||||||
|
|
||||||
for (i = 0; i < kpmod->dynrelas_nr; i++) {
|
for (i = 0; i < kpmod->dynrelas_nr; i++) {
|
||||||
@ -504,17 +509,19 @@ static int kpatch_write_relocations(struct kpatch_module *kpmod)
|
|||||||
ret = kpatch_verify_symbol_match(dynrela->name, dynrela->src);
|
ret = kpatch_verify_symbol_match(dynrela->name, dynrela->src);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
old_addr = dynrela->src;
|
src_addr = dynrela->src;
|
||||||
} else {
|
} else {
|
||||||
/* module, dynrela->src is not right */
|
/* module, dynrela->src is not right */
|
||||||
mod = find_module(dynrela->objname);
|
mod = find_module(dynrela->objname);
|
||||||
if (!mod) {
|
if (!mod) {
|
||||||
pr_err("unable to find module\n");
|
pr_err("unable to find module '%s'\n",
|
||||||
|
dynrela->objname);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
old_addr = kpatch_find_module_symbol(mod, dynrela->name);
|
src_addr = kpatch_find_module_symbol(mod, dynrela->name);
|
||||||
if (!old_addr) {
|
if (!src_addr) {
|
||||||
pr_err("unable to find symbol\n");
|
pr_err("unable to find symbol '%s' in module '%s'\n",
|
||||||
|
dynrela->name, mod->name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -522,20 +529,20 @@ static int kpatch_write_relocations(struct kpatch_module *kpmod)
|
|||||||
switch (dynrela->type) {
|
switch (dynrela->type) {
|
||||||
case R_X86_64_PC32:
|
case R_X86_64_PC32:
|
||||||
loc = dynrela->dest;
|
loc = dynrela->dest;
|
||||||
val = (u32)(old_addr + dynrela->addend -
|
val = (u32)(src_addr + dynrela->addend -
|
||||||
dynrela->dest);
|
dynrela->dest);
|
||||||
size = 4;
|
size = 4;
|
||||||
break;
|
break;
|
||||||
case R_X86_64_32S:
|
case R_X86_64_32S:
|
||||||
loc = dynrela->dest;
|
loc = dynrela->dest;
|
||||||
val = (s32)old_addr + dynrela->addend;
|
val = (s32)src_addr + dynrela->addend;
|
||||||
size = 4;
|
size = 4;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk("unsupported rela type %ld for "
|
printk("unsupported rela type %ld for "
|
||||||
"0x%lx <- 0x%lx at index %d\n",
|
"0x%lx <- 0x%lx at index %d\n",
|
||||||
dynrela->type, dynrela->dest,
|
dynrela->type, dynrela->dest,
|
||||||
old_addr, i);
|
src_addr, i);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -567,19 +574,18 @@ static int kpatch_write_relocations(struct kpatch_module *kpmod)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kpatch_calculate_old_addr(struct kpatch_func *func)
|
static int kpatch_calculate_old_addr(struct kpatch_func *func)
|
||||||
{
|
{
|
||||||
struct module *module;
|
struct module *module;
|
||||||
|
|
||||||
if (!strcmp(func->patch->objname, "vmlinux")) {
|
if (!strcmp(func->patch->objname, "vmlinux")) {
|
||||||
func->old_addr = func->patch->old_offset;
|
func->old_addr = func->patch->old_offset;
|
||||||
func->mod = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
module = find_module(func->patch->objname);
|
module = find_module(func->patch->objname);
|
||||||
if (!module) {
|
if (!module) {
|
||||||
pr_err("patch contains code for an module that is not loaded\n");
|
pr_err("patch contains code for a module that is not loaded\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,7 +615,7 @@ int kpatch_register(struct kpatch_module *kpmod, bool replace)
|
|||||||
if (!kpmod->internal)
|
if (!kpmod->internal)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
funcs = kmalloc(sizeof(*funcs) * num_funcs, GFP_KERNEL);
|
funcs = kzalloc(sizeof(*funcs) * num_funcs, GFP_KERNEL);
|
||||||
if (!funcs) {
|
if (!funcs) {
|
||||||
kfree(kpmod->internal);
|
kfree(kpmod->internal);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
Loading…
Reference in New Issue
Block a user