Skip to content

Commit 11e86dc

Browse files
author
Ingo Molnar
committed
x86/paravirt: Detect over-sized patching bugs in paravirt_patch_call()
paravirt_patch_call() currently handles patching failures inconsistently: we generate a warning in the retpoline case, but don't in other cases where we might end up with a non-working kernel as well. So just convert it all to a BUG_ON(), these patching calls are *not* supposed to fail, and if they do we want to know it immediately. This also makes the kernel smaller and removes an #ifdef ugly. I tried it with a richly paravirt-enabled kernel and no patching bugs were detected. Cc: Andy Lutomirski <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Brian Gerst <[email protected]> Cc: Denys Vlasenko <[email protected]> Cc: H. Peter Anvin <[email protected]> Cc: Juergen Gross <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent 2777cae commit 11e86dc

File tree

1 file changed

+8
-8
lines changed

1 file changed

+8
-8
lines changed

arch/x86/kernel/paravirt.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,21 @@ struct branch {
7373
static unsigned paravirt_patch_call(void *insnbuf, const void *target,
7474
unsigned long addr, unsigned len)
7575
{
76+
const int call_len = 5;
7677
struct branch *b = insnbuf;
77-
unsigned long delta = (unsigned long)target - (addr+5);
78+
unsigned long delta = (unsigned long)target - (addr+call_len);
7879

79-
if (len < 5) {
80-
#ifdef CONFIG_RETPOLINE
81-
WARN_ONCE(1, "Failing to patch indirect CALL in %ps\n", (void *)addr);
82-
#endif
83-
return len; /* call too long for patch site */
80+
if (len < call_len) {
81+
pr_warn("paravirt: Failed to patch indirect CALL at %ps\n", (void *)addr);
82+
/* Kernel might not be viable if patching fails, bail out: */
83+
BUG_ON(1);
8484
}
8585

8686
b->opcode = 0xe8; /* call */
8787
b->delta = delta;
88-
BUILD_BUG_ON(sizeof(*b) != 5);
88+
BUILD_BUG_ON(sizeof(*b) != call_len);
8989

90-
return 5;
90+
return call_len;
9191
}
9292

9393
#ifdef CONFIG_PARAVIRT_XXL

0 commit comments

Comments
 (0)