|
@@ -203,45 +203,6 @@ static int klp_find_object_symbol(const char *objname, const char *name,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
-struct klp_verify_args {
|
|
|
- const char *name;
|
|
|
- const unsigned long addr;
|
|
|
-};
|
|
|
-
|
|
|
-static int klp_verify_callback(void *data, const char *name,
|
|
|
- struct module *mod, unsigned long addr)
|
|
|
-{
|
|
|
- struct klp_verify_args *args = data;
|
|
|
-
|
|
|
- if (!mod &&
|
|
|
- !strcmp(args->name, name) &&
|
|
|
- args->addr == addr)
|
|
|
- return 1;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
|
|
|
-{
|
|
|
- struct klp_verify_args args = {
|
|
|
- .name = name,
|
|
|
- .addr = addr,
|
|
|
- };
|
|
|
- int ret;
|
|
|
-
|
|
|
- mutex_lock(&module_mutex);
|
|
|
- ret = kallsyms_on_each_symbol(klp_verify_callback, &args);
|
|
|
- mutex_unlock(&module_mutex);
|
|
|
-
|
|
|
- if (!ret) {
|
|
|
- pr_err("symbol '%s' not found at specified address 0x%016lx, kernel mismatch?\n",
|
|
|
- name, addr);
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* external symbols are located outside the parent object (where the parent
|
|
|
* object is either vmlinux or the kmod being patched).
|
|
@@ -272,6 +233,7 @@ static int klp_write_object_relocations(struct module *pmod,
|
|
|
struct klp_object *obj)
|
|
|
{
|
|
|
int ret;
|
|
|
+ unsigned long val;
|
|
|
struct klp_reloc *reloc;
|
|
|
|
|
|
if (WARN_ON(!klp_is_object_loaded(obj)))
|
|
@@ -281,35 +243,27 @@ static int klp_write_object_relocations(struct module *pmod,
|
|
|
return -EINVAL;
|
|
|
|
|
|
for (reloc = obj->relocs; reloc->name; reloc++) {
|
|
|
- if (!klp_is_module(obj)) {
|
|
|
-
|
|
|
-#if defined(CONFIG_RANDOMIZE_BASE)
|
|
|
- /* If KASLR has been enabled, adjust old value accordingly */
|
|
|
- if (kaslr_enabled())
|
|
|
- reloc->val += kaslr_offset();
|
|
|
-#endif
|
|
|
- ret = klp_verify_vmlinux_symbol(reloc->name,
|
|
|
- reloc->val);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
- } else {
|
|
|
- /* module, reloc->val needs to be discovered */
|
|
|
- if (reloc->external)
|
|
|
- ret = klp_find_external_symbol(pmod,
|
|
|
- reloc->name,
|
|
|
- &reloc->val);
|
|
|
- else
|
|
|
- ret = klp_find_object_symbol(obj->mod->name,
|
|
|
- reloc->name,
|
|
|
- 0, &reloc->val);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
- }
|
|
|
+ /* discover the address of the referenced symbol */
|
|
|
+ if (reloc->external) {
|
|
|
+ if (reloc->sympos > 0) {
|
|
|
+ pr_err("non-zero sympos for external reloc symbol '%s' is not supported\n",
|
|
|
+ reloc->name);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ ret = klp_find_external_symbol(pmod, reloc->name, &val);
|
|
|
+ } else
|
|
|
+ ret = klp_find_object_symbol(obj->name,
|
|
|
+ reloc->name,
|
|
|
+ reloc->sympos,
|
|
|
+ &val);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc,
|
|
|
- reloc->val + reloc->addend);
|
|
|
+ val + reloc->addend);
|
|
|
if (ret) {
|
|
|
pr_err("relocation failed for symbol '%s' at 0x%016lx (%d)\n",
|
|
|
- reloc->name, reloc->val, ret);
|
|
|
+ reloc->name, val, ret);
|
|
|
return ret;
|
|
|
}
|
|
|
}
|