From: Isaku Yamahata Date: Wed, 10 Dec 2008 06:39:47 +0000 (+0900) Subject: IA64: fix efi_emulate_set_virtual_address_map() X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14034 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=4ad4b780a8c7f7e775c59970dffe1a15f6c1abe8;p=xen.git 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 --- diff --git a/xen/arch/ia64/xen/fw_emul.c b/xen/arch/ia64/xen/fw_emul.c index 3b64bd14d4..ca878b362b 100644 --- a/xen/arch/ia64/xen/fw_emul.c +++ b/xen/arch/ia64/xen/fw_emul.c @@ -1334,6 +1334,10 @@ efi_emulate_set_virtual_address_map( efi_desc_size = sizeof(efi_memory_desc_t); for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { + struct page_info *efi_runtime_page = NULL; + struct page_info *fpswa_inf_page = NULL; + struct page_info *fw_table_page = NULL; + if (copy_from_user(&entry, p, sizeof(efi_memory_desc_t))) { printk ("efi_emulate_set_virtual_address_map: copy_from_user() fault. addr=0x%p\n", p); return EFI_UNSUPPORTED; @@ -1343,6 +1347,27 @@ efi_emulate_set_virtual_address_map( if (md->type != EFI_PAL_CODE) continue; + /* get pages to prevend them from being freed + * during touching them. + * those entres are in [FW_TABLES_BASE_PADDR, ...] + * see dom_fw.h for its layout. + */ + efi_runtime_page = virt_to_page(efi_runtime); + fpswa_inf_page = virt_to_page(fpswa_inf); + fw_table_page = virt_to_page( + domain_mpa_to_imva(d, FW_TABLES_BASE_PADDR)); + if (get_page(efi_runtime_page, d) == 0) + return EFI_INVALID_PARAMETER; + if (get_page(fpswa_inf_page, d) == 0) { + put_page(efi_runtime_page); + return EFI_INVALID_PARAMETER; + } + if (get_page(fw_table_page, d) == 0) { + put_page(fpswa_inf_page); + put_page(efi_runtime_page); + return EFI_INVALID_PARAMETER; + } + #define EFI_HYPERCALL_PATCH_TO_VIRT(tgt,call) \ do { \ vfn = (unsigned long *) domain_mpa_to_imva(d, tgt); \ @@ -1365,6 +1390,10 @@ efi_emulate_set_virtual_address_map( *vfn++ = FW_HYPERCALL_FPSWA_PATCH_INDEX * 16UL + md->virt_addr; *vfn = 0; fpswa_inf->fpswa = (void *) (FW_HYPERCALL_FPSWA_ENTRY_INDEX * 16UL + md->virt_addr); + + put_page(fw_table_page); + put_page(fpswa_inf_page); + put_page(efi_runtime_page); break; }