In order to restrict the patch, we can verify the provided function
address and name match. Now we have can only verify the vmlinux function
name and address.

Add a new function to verify extra module function name and address. The
patch would not be patched, if the function name and address are not
matched.

Signed-off-by: Minfei Huang <[email protected]>
---
 kernel/livepatch/core.c | 54 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 38 insertions(+), 16 deletions(-)

diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 3f9f1d6..ff42c29 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -196,12 +196,16 @@ static int klp_find_object_symbol(const char *objname, 
const char *name,
 }
 
 struct klp_verify_args {
+       const char *objname;
        const char *name;
        const unsigned long addr;
 };
 
-static int klp_verify_callback(void *data, const char *name,
-                              struct module *mod, unsigned long addr)
+typedef int (*klp_verify_callback)(void *data, const char *name,
+               struct module *mod, unsigned long addr);
+
+static int klp_verify_vmlinux_callback(void *data, const char *name,
+               struct module *mod, unsigned long addr)
 {
        struct klp_verify_args *args = data;
 
@@ -213,18 +217,38 @@ static int klp_verify_callback(void *data, const char 
*name,
        return 0;
 }
 
-static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
+static int klp_verify_module_callback(void *data, const char *name,
+               struct module *mod, unsigned long addr)
+{
+       struct klp_verify_args *args = data;
+
+       if (!mod || !args->objname)
+               return 0;
+
+       if (!strcmp(args->objname, mod->name) &&
+           !strcmp(args->name, name) &&
+           args->addr == addr)
+               return 1;
+
+       return 0;
+}
+
+static int klp_verify_symbol(const char *objname, const char *name,
+               unsigned long addr)
 {
        struct klp_verify_args args = {
+               .objname = objname,
                .name = name,
                .addr = addr,
        };
+       klp_verify_callback fn = objname ?
+               klp_verify_module_callback : klp_verify_vmlinux_callback;
 
-       if (kallsyms_on_each_symbol(klp_verify_callback, &args))
+       if (kallsyms_on_each_symbol(fn, &args))
                return 0;
 
-       pr_err("symbol '%s' not found at specified address 0x%016lx, kernel 
mismatch?\n",
-               name, addr);
+       pr_err("symbol '%s' not found at specified address 0x%016lx, %s 
mismatch?\n",
+                       name, addr, objname ? objname : "kernel");
        return -EINVAL;
 }
 
@@ -238,12 +262,12 @@ static int klp_find_verify_func_addr(struct klp_object 
*obj,
        func->old_addr = 0;
 #endif
 
-       if (!func->old_addr || klp_is_module(obj))
-               ret = klp_find_object_symbol(obj->name, func->old_name,
-                                            &func->old_addr);
+       if (func->old_addr)
+               ret = klp_verify_symbol(obj->name, func->old_name,
+                               func->old_addr);
        else
-               ret = klp_verify_vmlinux_symbol(func->old_name,
-                                               func->old_addr);
+               ret = klp_find_object_symbol(obj->name, func->old_name,
+                               &func->old_addr);
 
        return ret;
 }
@@ -285,10 +309,8 @@ static int klp_write_object_relocations(struct module 
*pmod,
 
        for (reloc = obj->relocs; reloc->name; reloc++) {
                if (!klp_is_module(obj)) {
-                       ret = klp_verify_vmlinux_symbol(reloc->name,
+                       ret = klp_verify_symbol(NULL, reloc->name,
                                                        reloc->val);
-                       if (ret)
-                               return ret;
                } else {
                        /* module, reloc->val needs to be discovered */
                        if (reloc->external)
@@ -299,9 +321,9 @@ static int klp_write_object_relocations(struct module *pmod,
                                ret = klp_find_object_symbol(obj->mod->name,
                                                             reloc->name,
                                                             &reloc->val);
-                       if (ret)
-                               return ret;
                }
+               if (ret)
+                       return ret;
                ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc,
                                             reloc->val + reloc->addend);
                if (ret) {
-- 
2.2.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to