x86/alternatives: Fix ALTERNATIVE_2 padding generation properly
authorBorislav Petkov <bp@suse.de>
Sat, 4 Apr 2015 13:34:43 +0000 (15:34 +0200)
committerIngo Molnar <mingo@kernel.org>
Sat, 4 Apr 2015 13:58:23 +0000 (15:58 +0200)
commitdbe4058a6a44af4ca5d146aebe01b0a1f9b7fd2a
tree99afa890af32c6c129417823087ffcdc62ddfedb
parent6b51311c976593fb7311322b1647a912cd456ec4
x86/alternatives: Fix ALTERNATIVE_2 padding generation properly

Quentin caught a corner case with the generation of instruction
padding in the ALTERNATIVE_2 macro: if len(orig_insn) <
len(alt1) < len(alt2), then not enough padding gets added and
that is not good(tm) as we could overwrite the beginning of the
next instruction.

Luckily, at the time of this writing, we don't have
ALTERNATIVE_2() invocations which have that problem and even if
we did, a simple fix would be to prepend the instructions with
enough prefixes so that that corner case doesn't happen.

However, best it would be if we fixed it properly. See below for
a simple, abstracted example of what we're doing.

So what we ended up doing is, we compute the

max(len(alt1), len(alt2)) - len(orig_insn)

and feed that value to the .skip gas directive. The max() cannot
have conditionals due to gas limitations, thus the fancy integer
math.

With this patch, all ALTERNATIVE_2 sites get padded correctly;
generating obscure test cases pass too:

  #define alt_max_short(a, b)    ((a) ^ (((a) ^ (b)) & -(-((a) < (b)))))

  #define gen_skip(orig, alt1, alt2, marker) \
   .skip -((alt_max_short(alt1, alt2) - (orig)) > 0) * \
   (alt_max_short(alt1, alt2) - (orig)),marker

   .pushsection .text, "ax"
  .globl main
  main:
   gen_skip(1, 2, 4, 0x09)
   gen_skip(4, 1, 2, 0x10)
   ...
   .popsection

Thanks to Quentin for catching it and double-checking the fix!

Reported-by: Quentin Casasnovas <quentin.casasnovas@oracle.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20150404133443.GE21152@pd.tnic
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/include/asm/alternative-asm.h
arch/x86/include/asm/alternative.h
arch/x86/kernel/alternative.c