[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen stable-4.14] x86/irq: fix infinite loop in irq_move_cleanup_interrupt
commit d785e076b36111899ef9ee2340f2da9375afc9f5 Author: Roger Pau Monné <roger.pau@xxxxxxxxxx> AuthorDate: Tue Dec 15 14:14:34 2020 +0100 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Tue Dec 15 14:14:34 2020 +0100 x86/irq: fix infinite loop in irq_move_cleanup_interrupt If Xen enters irq_move_cleanup_interrupt with a dynamic vector below IRQ_MOVE_CLEANUP_VECTOR pending in IRR (0x20 or 0x21) that's also designated for a cleanup it will enter a loop where irq_move_cleanup_interrupt continuously sends a cleanup IPI (vector 0x22) to itself while waiting for the vector with lower priority to be injected - which will never happen because IRQ_MOVE_CLEANUP_VECTOR takes precedence and it's always injected first. Fix this by making sure vectors below IRQ_MOVE_CLEANUP_VECTOR are marked as used and thus not available for APs. Also add some logic to assert and prevent irq_move_cleanup_interrupt from entering such an infinite loop, albeit that should never happen given the current code. This is XSA-356 / CVE-2020-29567. Fixes: 3fba06ba9f8 ('x86/IRQ: re-use legacy vector ranges on APs') Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx> master commit: ca85682e8c16361fdf3814c9b25a2ec3ff4f8bed master date: 2020-12-15 13:42:16 +0100 --- xen/arch/x86/irq.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index 8d1f9a9fc6..37c86283cc 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -441,8 +441,15 @@ int __init init_irq_data(void) set_bit(HYPERCALL_VECTOR, used_vectors); #endif - /* IRQ_MOVE_CLEANUP_VECTOR used for clean up vectors */ - set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors); + /* + * Mark vectors up to the cleanup one as used, to prevent an infinite loop + * invoking irq_move_cleanup_interrupt. + */ + BUILD_BUG_ON(IRQ_MOVE_CLEANUP_VECTOR < FIRST_DYNAMIC_VECTOR); + for ( vector = FIRST_DYNAMIC_VECTOR; + vector <= IRQ_MOVE_CLEANUP_VECTOR; + vector++ ) + __set_bit(vector, used_vectors); return 0; } @@ -727,10 +734,6 @@ void irq_move_cleanup_interrupt(struct cpu_user_regs *regs) { unsigned vector, me; - /* This interrupt should not nest inside others. */ - BUILD_BUG_ON(APIC_PRIO_CLASS(IRQ_MOVE_CLEANUP_VECTOR) != - APIC_PRIO_CLASS(FIRST_DYNAMIC_VECTOR)); - ack_APIC_irq(); me = smp_processor_id(); @@ -774,6 +777,11 @@ void irq_move_cleanup_interrupt(struct cpu_user_regs *regs) */ if ( irr & (1u << (vector % 32)) ) { + if ( vector < IRQ_MOVE_CLEANUP_VECTOR ) + { + ASSERT_UNREACHABLE(); + goto unlock; + } send_IPI_self(IRQ_MOVE_CLEANUP_VECTOR); TRACE_3D(TRC_HW_IRQ_MOVE_CLEANUP_DELAY, irq, vector, smp_processor_id()); -- generated by git-patchbot for /home/xen/git/xen.git#stable-4.14
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |