[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v3 2/4] xen/x86: introduce self modifying code test



On Thu, Dec 14, 2023 at 02:57:11PM +0100, Jan Beulich wrote:
> On 14.12.2023 14:47, Roger Pau Monné wrote:
> > On Thu, Dec 14, 2023 at 12:55:22PM +0100, Jan Beulich wrote:
> >> On 14.12.2023 11:17, Roger Pau Monne wrote:
> >>> --- a/xen/arch/x86/setup.c
> >>> +++ b/xen/arch/x86/setup.c
> >>> @@ -58,6 +58,7 @@
> >>>  #include <asm/microcode.h>
> >>>  #include <asm/prot-key.h>
> >>>  #include <asm/pv/domain.h>
> >>> +#include <asm/test-smoc.h>
> >>>  
> >>>  /* opt_nosmp: If true, secondary processors are ignored. */
> >>>  static bool __initdata opt_nosmp;
> >>> @@ -1951,6 +1952,8 @@ void asmlinkage __init noreturn 
> >>> __start_xen(unsigned long mbi_p)
> >>>  
> >>>      alternative_branches();
> >>>  
> >>> +    test_smoc(XEN_SYSCTL_TEST_SMOC_ALL, NULL);
> >>
> >> I realize I'm at risk of causing scope creep, but I'd still like to at
> >> least ask: As further self-tests are added, we likely don't want to
> >> alter __start_xen() every time. Should there perhaps better be a wrapper
> >> (going forward: multiple ones, depending on the time tests want invoking),
> >> together with a Kconfig control to allow suppressing all of these tests in
> >> at least release builds?
> > 
> > Right now I only had in mind that livepatch related tests won't be
> > executed as part of the call in __start_xen(), but all the other ones
> > would, and hence wasn't expecting the code to change from the form in
> > the next patch.
> 
> Well, I was thinking of there more stuff appearing in test/, not self-
> modifying-code related, and hence needing further test_*() alongside.
> test_smoc().

Oh, I see.  I think it might be best to introduce such wrapper when we
have at least 2 different self tests?  Otherwise it would be weird IMO
to have another function (ie: execute_self_tests()?) that's just a
wrapper around test_smoc().

> >>> --- /dev/null
> >>> +++ b/xen/arch/x86/test/smoc.c
> >>> @@ -0,0 +1,68 @@
> >>> +/* SPDX-License-Identifier: GPL-2.0 */
> >>> +
> >>> +#include <xen/errno.h>
> >>> +
> >>> +#include <asm/alternative.h>
> >>> +#include <asm/cpufeature.h>
> >>> +#include <asm/test-smoc.h>
> >>> +
> >>> +static bool cf_check test_insn_replacement(void)
> >>> +{
> >>> +#define EXPECTED_VALUE 2
> >>> +    unsigned int r = ~EXPECTED_VALUE;
> >>> +
> >>> +    alternative_io("", "mov %1, %0", X86_FEATURE_ALWAYS,
> >>> +                   "+r" (r), "i" (EXPECTED_VALUE));
> >>> +
> >>> +    return r == EXPECTED_VALUE;
> >>> +#undef EXPECTED_VALUE
> >>> +}
> >>> +
> >>> +int test_smoc(uint32_t selection, uint32_t *results)
> >>> +{
> >>> +    struct {
> >>> +        unsigned int mask;
> >>> +        bool (*test)(void);
> >>> +        const char *name;
> >>> +    } static const tests[] = {
> >>> +        { XEN_SYSCTL_TEST_SMOC_INSN_REPL, &test_insn_replacement,
> >>> +          "alternative instruction replacement" },
> >>> +    };
> >>> +    unsigned int i;
> >>> +
> >>> +    if ( selection & ~XEN_SYSCTL_TEST_SMOC_ALL )
> >>> +        return -EINVAL;
> >>> +
> >>> +    if ( results )
> >>> +        *results = 0;
> >>> +
> >>> +    printk(XENLOG_INFO "Checking Self Modify Code\n");
> >>> +
> >>> +    for ( i = 0; i < ARRAY_SIZE(tests); i++ )
> >>> +    {
> >>> +        if ( !(selection & tests[i].mask) )
> >>> +            continue;
> >>> +
> >>> +        if ( tests[i].test() )
> >>> +        {
> >>> +            if ( results )
> >>> +                *results |= tests[i].mask;
> >>> +            continue;
> >>> +        }
> >>> +
> >>> +        add_taint(TAINT_ERROR_SMOC);
> >>> +        printk(XENLOG_ERR "%s test failed\n", tests[i].name);
> >>
> >> Do we really want both of these even when coming here from the sysctl?
> > 
> > So only print the messages if system_state < SYS_STATE_active?
> 
> Yes. Nor tainting the system.

OK.

> >>> --- a/xen/common/kernel.c
> >>> +++ b/xen/common/kernel.c
> >>> @@ -386,13 +386,14 @@ char *print_tainted(char *str)
> >>>  {
> >>>      if ( tainted )
> >>>      {
> >>> -        snprintf(str, TAINT_STRING_MAX_LEN, "Tainted: %c%c%c%c%c%c",
> >>> +        snprintf(str, TAINT_STRING_MAX_LEN, "Tainted: %c%c%c%c%c%c%c",
> >>>                   tainted & TAINT_MACHINE_INSECURE ? 'I' : ' ',
> >>>                   tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
> >>>                   tainted & TAINT_SYNC_CONSOLE ? 'C' : ' ',
> >>>                   tainted & TAINT_ERROR_INJECT ? 'E' : ' ',
> >>>                   tainted & TAINT_HVM_FEP ? 'H' : ' ',
> >>> -                 tainted & TAINT_CPU_OUT_OF_SPEC ? 'S' : ' ');
> >>> +                 tainted & TAINT_CPU_OUT_OF_SPEC ? 'S' : ' ',
> >>> +                 tainted & TAINT_ERROR_SMOC ? 'A' : ' ');
> >>
> >> How well is this going to scale as other selftests are added? IOW should
> >> this taint really be self-modifying-code-specific?
> > 
> > I'm afraid I'm not sure I'm following.  Would you instead like to make
> > the taint per-test selectable?
> 
> The other way around actually: Taint generally for failed selftests,
> not just for the self-modifying-code one (which ends up being the only
> one right now).

So the suggestion would be to use TAINT_ERROR_SELFTEST instead of
TAINT_ERROR_SMOC?  I can do that, but it might also be more
appropriate when there are more self tests.

Thanks, Roger.



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.