From: Stefani Seibold Date: Mon, 17 Mar 2014 22:22:13 +0000 (+0100) Subject: x86, vdso32: handle 32 bit vDSO larger one page X-Git-Tag: v3.15-rc1~129^2~7 X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=commitdiff_plain;h=4e40112c4ff6a577dd06d92b2a54cdf06265bf74;p=linux.git x86, vdso32: handle 32 bit vDSO larger one page This patch enables 32 bit vDSO which are larger than a page. Signed-off-by: Stefani Seibold Link: http://lkml.kernel.org/r/1395094933-14252-14-git-send-email-stefani@seibold.net Signed-off-by: H. Peter Anvin --- diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c index e10abdf4cc10..5b4aaefb6b42 100644 --- a/arch/x86/vdso/vdso32-setup.c +++ b/arch/x86/vdso/vdso32-setup.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -69,7 +70,8 @@ __setup_param("vdso=", vdso32_setup, vdso_setup, 0); EXPORT_SYMBOL_GPL(vdso_enabled); #endif -static struct page *vdso32_pages[1]; +static struct page **vdso32_pages; +static unsigned int vdso32_size; #ifdef CONFIG_X86_64 @@ -115,11 +117,10 @@ void enable_sep_cpu(void) int __init sysenter_setup(void) { - void *vdso_page = (void *)get_zeroed_page(GFP_ATOMIC); + void *vdso_pages; const void *vdso; size_t vdso_len; - - vdso32_pages[0] = virt_to_page(vdso_page); + unsigned int i; if (vdso32_syscall()) { vdso = &vdso32_syscall_start; @@ -132,8 +133,15 @@ int __init sysenter_setup(void) vdso_len = &vdso32_int80_end - &vdso32_int80_start; } - memcpy(vdso_page, vdso, vdso_len); - patch_vdso32(vdso_page, vdso_len); + vdso32_size = (vdso_len + PAGE_SIZE - 1) / PAGE_SIZE; + vdso32_pages = kmalloc(sizeof(*vdso32_pages) * vdso32_size, GFP_ATOMIC); + vdso_pages = kmalloc(VDSO_OFFSET(vdso32_size), GFP_ATOMIC); + + for(i = 0; i != vdso32_size; ++i) + vdso32_pages[i] = virt_to_page(vdso_pages + VDSO_OFFSET(i)); + + memcpy(vdso_pages, vdso, vdso_len); + patch_vdso32(vdso_pages, vdso_len); return 0; } @@ -169,7 +177,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) */ ret = install_special_mapping(mm, addr, - VDSO_OFFSET(VDSO_PAGES - VDSO_PREV_PAGES), + VDSO_OFFSET(vdso32_size), VM_READ|VM_EXEC| VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, vdso32_pages);