ia64/xen-unstable

changeset 18872:3acca92b9597

IA64: fix efi_emulate_set_virtual_address_map()

get_page() before touching guest pages.
Otherwise pages may be freed during those operations.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Isaku Yamahata <yamahata@valinux.co.jp>
date Wed Dec 10 15:39:47 2008 +0900 (2008-12-10)
parents e239a47180fb
children a86a4ddd8b2b
files xen/arch/ia64/xen/fw_emul.c
line diff
     1.1 --- a/xen/arch/ia64/xen/fw_emul.c	Wed Dec 10 15:39:46 2008 +0900
     1.2 +++ b/xen/arch/ia64/xen/fw_emul.c	Wed Dec 10 15:39:47 2008 +0900
     1.3 @@ -1334,6 +1334,10 @@ efi_emulate_set_virtual_address_map(
     1.4  	efi_desc_size = sizeof(efi_memory_desc_t);
     1.5  
     1.6  	for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
     1.7 +		struct page_info *efi_runtime_page = NULL;
     1.8 +		struct page_info *fpswa_inf_page = NULL;
     1.9 +		struct page_info *fw_table_page = NULL;
    1.10 +		
    1.11  		if (copy_from_user(&entry, p, sizeof(efi_memory_desc_t))) {
    1.12  			printk ("efi_emulate_set_virtual_address_map: copy_from_user() fault. addr=0x%p\n", p);
    1.13  			return EFI_UNSUPPORTED;
    1.14 @@ -1343,6 +1347,27 @@ efi_emulate_set_virtual_address_map(
    1.15                  if (md->type != EFI_PAL_CODE)
    1.16                          continue;
    1.17  
    1.18 +		/* get pages to prevend them from being freed 
    1.19 +		 * during touching them.
    1.20 +		 * those entres are in [FW_TABLES_BASE_PADDR, ...]
    1.21 +		 * see dom_fw.h for its layout.
    1.22 +		 */
    1.23 +		efi_runtime_page = virt_to_page(efi_runtime);
    1.24 +		fpswa_inf_page = virt_to_page(fpswa_inf);
    1.25 +		fw_table_page = virt_to_page(
    1.26 +			domain_mpa_to_imva(d, FW_TABLES_BASE_PADDR));
    1.27 +		if (get_page(efi_runtime_page, d) == 0)
    1.28 +			return EFI_INVALID_PARAMETER;
    1.29 +		if (get_page(fpswa_inf_page, d) == 0) {
    1.30 +			put_page(efi_runtime_page);
    1.31 +			return EFI_INVALID_PARAMETER;
    1.32 +		}
    1.33 +		if (get_page(fw_table_page, d) == 0) {
    1.34 +			put_page(fpswa_inf_page);
    1.35 +			put_page(efi_runtime_page);
    1.36 +			return EFI_INVALID_PARAMETER;
    1.37 +		}
    1.38 +
    1.39  #define EFI_HYPERCALL_PATCH_TO_VIRT(tgt,call) \
    1.40  	do { \
    1.41  		vfn = (unsigned long *) domain_mpa_to_imva(d, tgt); \
    1.42 @@ -1365,6 +1390,10 @@ efi_emulate_set_virtual_address_map(
    1.43  		*vfn++ = FW_HYPERCALL_FPSWA_PATCH_INDEX * 16UL + md->virt_addr;
    1.44  		*vfn   = 0;
    1.45  		fpswa_inf->fpswa = (void *) (FW_HYPERCALL_FPSWA_ENTRY_INDEX * 16UL + md->virt_addr);
    1.46 +
    1.47 +		put_page(fw_table_page);
    1.48 +		put_page(fpswa_inf_page);
    1.49 +		put_page(efi_runtime_page);
    1.50  		break;
    1.51  	}
    1.52