x86/mm: PV superpage handling lacks sanity checks MMUEXT_{,UN}MARK_SUPER fail to check the input MFN for validity before dereferencing pointers into the superpage frame table. get_superpage() has a similar issue. This is XSA-167. Reported-by: Qinghao Tang Signed-off-by: Jan Beulich Acked-by: Ian Campbell --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -2624,6 +2624,9 @@ int get_superpage(unsigned long mfn, str ASSERT(opt_allow_superpage); + if ( !mfn_valid(mfn | (L1_PAGETABLE_ENTRIES - 1)) ) + return -EINVAL; + spage = mfn_to_spage(mfn); y = spage->type_info; do { @@ -3401,42 +3404,26 @@ long do_mmuext_op( } case MMUEXT_MARK_SUPER: + case MMUEXT_UNMARK_SUPER: { unsigned long mfn = op.arg1.mfn; - if ( unlikely(d != pg_owner) ) - rc = -EPERM; - else if ( mfn & (L1_PAGETABLE_ENTRIES-1) ) - { - MEM_LOG("Unaligned superpage reference mfn %lx", mfn); - okay = 0; - } - else if ( !opt_allow_superpage ) + if ( !opt_allow_superpage ) { MEM_LOG("Superpages disallowed"); rc = -ENOSYS; } - else - rc = mark_superpage(mfn_to_spage(mfn), d); - break; - } - - case MMUEXT_UNMARK_SUPER: - { - unsigned long mfn = op.arg1.mfn; - - if ( unlikely(d != pg_owner) ) + else if ( unlikely(d != pg_owner) ) rc = -EPERM; - else if ( mfn & (L1_PAGETABLE_ENTRIES-1) ) + else if ( mfn & (L1_PAGETABLE_ENTRIES - 1) ) { MEM_LOG("Unaligned superpage reference mfn %lx", mfn); - okay = 0; - } - else if ( !opt_allow_superpage ) - { - MEM_LOG("Superpages disallowed"); - rc = -ENOSYS; + rc = -EINVAL; } + else if ( !mfn_valid(mfn | (L1_PAGETABLE_ENTRIES - 1)) ) + rc = -EINVAL; + else if ( op.cmd == MMUEXT_MARK_SUPER ) + rc = mark_superpage(mfn_to_spage(mfn), d); else rc = unmark_superpage(mfn_to_spage(mfn)); break;