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

[Xen-devel] Ping: [PATCH v3] x86emul/fuzz: add a state sanity checking function



>>> On 02.04.19 at 15:01,  wrote:
> This is to accompany sanitize_input(). Just like for initial state we
> want to have state between two emulated insns sane, at least as far as
> assumptions in the main emulator go. Do minimal checking after segment
> register, CR, and MSR writes, and roll back to the old value in case of
> failure (raising #GP(0) at the same time).
> 
> In the particular case observed, a CR0 write clearing CR0.PE was
> followed by a VEX-encoded insn, which the decoder accepts based on
> guest address size, restricting things just outside of the 64-bit case
> (real and virtual modes don't allow VEX-encoded insns). Subsequently
> _get_fpu() would then assert that CR0.PE must be set (and EFLAGS.VM
> clear) when trying to invoke YMM, ZMM, or OPMASK state.
> 
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
> ---
> v3: Rename helper function to check_state().
> v2: Correct placement of new declaration in fuzz_write_segment().
> 
> --- a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
> +++ b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
> @@ -76,6 +76,8 @@ static inline bool input_read(struct fuz
>      return true;
>  }
>  
> +static bool check_state(struct x86_emulate_ctxt *ctxt);
> +
>  static const char* const x86emul_return_string[] = {
>      [X86EMUL_OKAY] = "X86EMUL_OKAY",
>      [X86EMUL_UNHANDLEABLE] = "X86EMUL_UNHANDLEABLE",
> @@ -424,8 +426,19 @@ static int fuzz_write_segment(
>      rc = maybe_fail(ctxt, "write_segment", true);
>  
>      if ( rc == X86EMUL_OKAY )
> +    {
> +        struct segment_register old = c->segments[seg];
> +
>          c->segments[seg] = *reg;
>  
> +        if ( !check_state(ctxt) )
> +        {
> +            c->segments[seg] = old;
> +            x86_emul_hw_exception(13 /* #GP */, 0, ctxt);
> +            rc = X86EMUL_EXCEPTION;
> +        }
> +    }
> +
>      return rc;
>  }
>  
> @@ -452,6 +465,7 @@ static int fuzz_write_cr(
>  {
>      struct fuzz_state *s = ctxt->data;
>      struct fuzz_corpus *c = s->corpus;
> +    unsigned long old;
>      int rc;
>  
>      if ( reg >= ARRAY_SIZE(c->cr) )
> @@ -461,9 +475,17 @@ static int fuzz_write_cr(
>      if ( rc != X86EMUL_OKAY )
>          return rc;
>  
> +    old = c->cr[reg];
>      c->cr[reg] = val;
>  
> -    return X86EMUL_OKAY;
> +    if ( !check_state(ctxt) )
> +    {
> +        c->cr[reg] = old;
> +        x86_emul_hw_exception(13 /* #GP */, 0, ctxt);
> +        rc = X86EMUL_EXCEPTION;
> +    }
> +
> +    return rc;
>  }
>  
>  #define fuzz_read_xcr emul_test_read_xcr
> @@ -561,7 +583,16 @@ static int fuzz_write_msr(
>      {
>          if ( msr_index[idx] == reg )
>          {
> +            uint64_t old = c->msr[idx];
> +
>              c->msr[idx] = val;
> +
> +            if ( !check_state(ctxt) )
> +            {
> +                c->msr[idx] = old;
> +                break;
> +            }
> +
>              return X86EMUL_OKAY;
>          }
>      }
> @@ -811,6 +842,30 @@ static void sanitize_input(struct x86_em
>      }
>  }
>  
> +/*
> + * Call this function from hooks potentially altering machine state into
> + * something that's not architecturally valid, yet which - as per above -
> + * the emulator relies on.
> + */
> +static bool check_state(struct x86_emulate_ctxt *ctxt)
> +{
> +    const struct fuzz_state *s = ctxt->data;
> +    const struct fuzz_corpus *c = s->corpus;
> +    const struct cpu_user_regs *regs = &c->regs;
> +
> +    if ( long_mode_active(ctxt) && !(c->cr[0] & X86_CR0_PG) )
> +        return false;
> +
> +    if ( (c->cr[0] & X86_CR0_PG) && !(c->cr[0] & X86_CR0_PE) )
> +        return false;
> +
> +    if ( (regs->rflags & X86_EFLAGS_VM) &&
> +         (c->segments[x86_seg_cs].db || c->segments[x86_seg_ss].db) )
> +        return false;
> +
> +    return true;
> +}
> +
>  int LLVMFuzzerInitialize(int *argc, char ***argv)
>  {
>      if ( !emul_test_init() )
> 
> 
> 
> 





_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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