ia64/xen-unstable

changeset 16286:42e032f52371

[IA64] Fix ia64_sal_get_state_info() emulation bug

It is possible to double-free the sal queue entry when multiple
ia64_sal_get_state_info() from Dom0 are called simultaniously.
In the worst case, the kernel might panic.

Signed-off-by: Kazuhiro Suzuki <kaz@jp.fujitsu.com>
author Alex Williamson <alex.williamson@hp.com>
date Thu Nov 01 08:50:03 2007 -0600 (2007-11-01)
parents a07288a84785
children b235b68a0f4f
files xen/arch/ia64/xen/fw_emul.c
line diff
     1.1 --- a/xen/arch/ia64/xen/fw_emul.c	Tue Oct 30 15:34:44 2007 -0600
     1.2 +++ b/xen/arch/ia64/xen/fw_emul.c	Thu Nov 01 08:50:03 2007 -0600
     1.3 @@ -242,6 +242,8 @@ sal_emulator (long index, unsigned long 
     1.4  			}
     1.5  			e = list_entry(sal_queue[in1].next,
     1.6  			               sal_queue_entry_t, list);
     1.7 +
     1.8 +			list_del(&e->list);
     1.9  			spin_unlock_irqrestore(&sal_queue_lock, flags);
    1.10  
    1.11  			IA64_SAL_DEBUG("SAL_GET_STATE_INFO(%s <= %s) "
    1.12 @@ -277,10 +279,12 @@ sal_emulator (long index, unsigned long 
    1.13  			r9 = arg.ret;
    1.14  			status = arg.status;
    1.15  			if (r9 == 0) {
    1.16 +				xfree(e);
    1.17 +			} else {
    1.18 +				/* Re-add the entry to sal_queue */
    1.19  				spin_lock_irqsave(&sal_queue_lock, flags);
    1.20 -				list_del(&e->list);
    1.21 +				list_add(&e->list, &sal_queue[in1]);
    1.22  				spin_unlock_irqrestore(&sal_queue_lock, flags);
    1.23 -				xfree(e);
    1.24  			}
    1.25  		} else {
    1.26  			status = IA64_SAL_NO_INFORMATION_AVAILABLE;
    1.27 @@ -316,10 +320,10 @@ sal_emulator (long index, unsigned long 
    1.28  			               "on CPU#%d.\n",
    1.29  			               rec_name[e->sal_info_type],
    1.30  			               rec_name[in1], e->cpuid);
    1.31 -			
    1.32  
    1.33  			arg.type = e->sal_info_type;
    1.34  			arg.status = 0;
    1.35 +
    1.36  			if (e->cpuid == smp_processor_id()) {
    1.37  				IA64_SAL_DEBUG("SAL_CLEAR_STATE_INFO: local\n");
    1.38  				clear_state_info_on(&arg);