From 62f6d3620e91ea7bf3e9698a98245dc0b4e6a4d5 Mon Sep 17 00:00:00 2001 From: Corey Henderson Date: Sat, 30 Aug 2014 18:56:00 -0400 Subject: [PATCH] Make sure each symbol address doesn't start with a OP_JMP_REL32 instruction This patch makes kpatch_link_object run through all the verify steps before it attempts to patch them. On failure, there is no need to call unlink (although unlink is called on the return path anyway - but I'll tackle that problem another day) so add the err_verify jump point. We also now check the start of the symbol address for the 0xe9 OP_JMP_REL32 instruction. This may not be the best place to do it, but it's the soonest place I could find that I could add the check without doing any major rewrites. --- kmod/core/core.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/kmod/core/core.c b/kmod/core/core.c index e17234b1a..0ec9c80ad 100644 --- a/kmod/core/core.c +++ b/kmod/core/core.c @@ -706,10 +706,6 @@ static int kpatch_link_object(struct kpatch_module *kpmod, object->mod = mod; } - ret = kpatch_write_relocations(kpmod, object); - if (ret) - goto err_unlink; - list_for_each_entry(func, &object->funcs, list) { /* calculate actual old location */ @@ -717,7 +713,7 @@ static int kpatch_link_object(struct kpatch_module *kpmod, ret = kpatch_verify_symbol_match(func->name, func->old_addr); if (ret) - goto err_unlink; + goto err_verify; } else { unsigned long old_addr; old_addr = kpatch_find_module_symbol(mod, func->name); @@ -725,11 +721,26 @@ static int kpatch_link_object(struct kpatch_module *kpmod, pr_err("unable to find symbol '%s' in module '%s\n", func->name, mod->name); ret = -EINVAL; - goto err_unlink; + goto err_verify; } func->old_addr = old_addr; } + /* does this function start with OP_JMP_REL32? */ + if (*(u8 *)func->old_addr == 0xe9) { + pr_err("symbol '%s' at address 0x%lx starts with a OP_JMP_REL32\n", func->name, func->old_addr); + ret = -EINVAL; + goto err_verify; + } + + } + + ret = kpatch_write_relocations(kpmod, object); + if (ret) + goto err_unlink; + + list_for_each_entry(func, &object->funcs, list) { + /* add to ftrace filter and register handler if needed */ ret = kpatch_ftrace_add_func(func->old_addr); if (ret) @@ -741,6 +752,7 @@ static int kpatch_link_object(struct kpatch_module *kpmod, err_unlink: kpatch_unlink_object(object); +err_verify: return ret; }