[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2 3/7] x86/alternative: Walk all replacements during self tests
When self tests are active, walk all alternative replacements with x86_decode_lite(). This checks that we can decode all instructions, and also lets us check that disp8's don't leave the replacement block as such a case will definitely malfunction. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Reviewed-by: Jan Beulich <JBeulich@xxxxxxxx> --- CC: Jan Beulich <JBeulich@xxxxxxxx> CC: Roger Pau Monné <roger.pau@xxxxxxxxxx> v2: * Rebase over API changes in patch 1 * Use +%lu and drop casts * Swap to CONFIG_SELF_TESTS --- xen/arch/x86/alternative.c | 52 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/xen/arch/x86/alternative.c b/xen/arch/x86/alternative.c index 1ba35cb9ede9..2dc759abd858 100644 --- a/xen/arch/x86/alternative.c +++ b/xen/arch/x86/alternative.c @@ -15,6 +15,7 @@ #include <asm/traps.h> #include <asm/nmi.h> #include <asm/nops.h> +#include <asm/x86_emulate.h> #include <xen/livepatch.h> #define MAX_PATCH_LEN (255-1) @@ -490,6 +491,57 @@ static void __init _alternative_instructions(bool force) void __init alternative_instructions(void) { arch_init_ideal_nops(); + + /* + * Walk all replacement instructions with x86_decode_lite(). This checks + * both that we can decode all instructions within the replacement, and + * that any near branch with a disp8 stays within the alternative itself. + */ + if ( IS_ENABLED(CONFIG_SELF_TESTS) ) + { + struct alt_instr *a; + + for ( a = __alt_instructions; + a < __alt_instructions_end; ++a ) + { + void *repl = ALT_REPL_PTR(a); + void *ip = repl, *end = ip + a->repl_len; + + if ( !a->repl_len ) + continue; + + for ( x86_decode_lite_t res; ip < end; ip += res.len ) + { + const int8_t *d8; + const void *target; + + res = x86_decode_lite(ip, end); + + if ( res.len == 0 ) + { + printk("Alt for %ps [%*ph]\n", + ALT_ORIG_PTR(a), a->repl_len, repl); + panic(" Unable to decode instruction at +%lu in alternative\n", + ip - repl); + } + + if ( res.rel_sz != 1 ) + continue; + + d8 = res.rel; + target = ip + res.len + *d8; + + if ( target < repl || target > end ) + { + printk("Alt for %ps [%*ph]\n", + ALT_ORIG_PTR(a), a->repl_len, repl); + panic(" 'JMP/Jcc disp8' at +%lu leaves alternative block\n", + ip - repl); + } + } + } + } + _alternative_instructions(false); } -- 2.39.5
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |