Dear Xen-Devel team,

we discovered a bug regarding undefined behaviour in the FPU emulation
unit.

if ( !s->rex_prefix )
{
        /* Convert 32-bit real/vm86 to 32-bit prot format. */
        unsigned int fip = fpstate.env.mode.real.fip_lo +
                                           (fpstate.env.mode.real.fip_hi << 16);
        unsigned int fdp = fpstate.env.mode.real.fdp_lo +
                                           (fpstate.env.mode.real.fdp_hi << 16);
        unsigned int fop = fpstate.env.mode.real.fop;

        fpstate.env.mode.prot.fip = fip & 0xf;
        fpstate.env.mode.prot.fcs = fip >> 4;
        fpstate.env.mode.prot.fop = fop;
        fpstate.env.mode.prot.fdp = fdp & 0xf;
        fpstate.env.mode.prot.fds = fdp >> 4;
}

It occurs at arch/x86/arch/x86/x86_emulate/blk.c:85 of the v4.20.0
release during the bit shift and can be triggered using the attached xtf
test. We are not aware of any security consequences.
Simply shifting by 4 should do the trick in my opinion.

Similar code resides in the same file in lines 87, 125 and 127.
The attached xtf test is run for hvm32.

~Fabian
#include <xtf.h>

const char test_title[] = "PoC-FPU-UBSan";

bool test_needs_fep = true;

void test_main(void)
{
    uint8_t fpu_env[28];

    /* To trigger UBSAN oout of bounds shift */
    memset(fpu_env, 0xFF, sizeof(fpu_env));

    asm volatile("movl %%cr0, %%ebx;"
                 "andl $0xFFFFFFFE, %%ebx;"
                 "movl %%ebx, %%cr0;"
                 "ud2;"
                 ".ascii \"xen\";"
                 "fldenv (%0)"
                 :
                 : "r"(fpu_env)
                 : "memory"
                 );

}

Reply via email to