mirror of https://github.com/dynup/kpatch
kmod/core: Skip relocations of already altered instructions
When a patch module is loaded, the kernel facilities like alternatives and paravirt may alter some of its instructions. This happens before Kpatch core module is notified and tries to apply dynrelas to it. If an instruction to apply a dynrela to has already been changed by these facilities, an incorrect instruction might be written as a result. The core module now detects such conditions and does not apply dynrela to the changed instructions. Suggested by Josh Poimboeuf in the discussion of https://github.com/dynup/kpatch/issues/580. Changes in v.2: * Used pr_notice to give more emphasis to the messages. * Added an explanation message. Signed-off-by: Evgenii Shatokhin <eshatokhin@virtuozzo.com>
This commit is contained in:
parent
7eda8dab6d
commit
8dac9d0871
|
@ -43,6 +43,7 @@
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/kallsyms.h>
|
#include <linux/kallsyms.h>
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
|
#include <linux/string.h>
|
||||||
#include <asm/stacktrace.h>
|
#include <asm/stacktrace.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include "kpatch.h"
|
#include "kpatch.h"
|
||||||
|
@ -650,6 +651,19 @@ static int kpatch_write_relocations(struct kpatch_module *kpmod,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip it if the instruction to be relocated has been
|
||||||
|
* changed already (paravirt or alternatives may do this).
|
||||||
|
*/
|
||||||
|
if (memchr_inv((void *)loc, 0, size)) {
|
||||||
|
pr_notice("Skipped dynrela for %s (0x%lx <- 0x%lx): the instruction has been changed already.\n",
|
||||||
|
dynrela->name, dynrela->dest, dynrela->src);
|
||||||
|
pr_notice_once(
|
||||||
|
"This is not necessarily a bug but it may indicate in some cases "
|
||||||
|
"that the binary patch does not handle paravirt operations, alternatives or the like properly.\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_SET_MODULE_RONX
|
#ifdef CONFIG_DEBUG_SET_MODULE_RONX
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
|
||||||
if (loc < core + kpmod->mod->core_layout.ro_size)
|
if (loc < core + kpmod->mod->core_layout.ro_size)
|
||||||
|
|
Loading…
Reference in New Issue