[PATCH 1/2] livepatch: Add a new function to verify the address and name match for extra module

From: Minfei Huang
Date: Sun Apr 12 2015 - 09:21:37 EST


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 <minfei.huang@xxxxxxxxxxx>
---
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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/