1/* 2 * Copyright (C) 2011 Richard Weinberger <richrd@nod.at> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8 9#include <linux/slab.h> 10#include <linux/sched.h> 11#include <linux/mm.h> 12#include <asm/page.h> 13#include <linux/init.h> 14 15static unsigned int __read_mostly vdso_enabled = 1; 16unsigned long um_vdso_addr; 17 18extern unsigned long task_size; 19extern char vdso_start[], vdso_end[]; 20 21static struct page **vdsop; 22 23static int __init init_vdso(void) 24{ 25 struct page *um_vdso; 26 27 BUG_ON(vdso_end - vdso_start > PAGE_SIZE); 28 29 um_vdso_addr = task_size - PAGE_SIZE; 30 31 vdsop = kmalloc(sizeof(struct page *), GFP_KERNEL); 32 if (!vdsop) 33 goto oom; 34 35 um_vdso = alloc_page(GFP_KERNEL); 36 if (!um_vdso) { 37 kfree(vdsop); 38 39 goto oom; 40 } 41 42 copy_page(page_address(um_vdso), vdso_start); 43 *vdsop = um_vdso; 44 45 return 0; 46 47oom: 48 printk(KERN_ERR "Cannot allocate vdso\n"); 49 vdso_enabled = 0; 50 51 return -ENOMEM; 52} 53subsys_initcall(init_vdso); 54 55int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) 56{ 57 int err; 58 struct mm_struct *mm = current->mm; 59 60 if (!vdso_enabled) 61 return 0; 62 63 down_write(&mm->mmap_sem); 64 65 err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE, 66 VM_READ|VM_EXEC| 67 VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, 68 vdsop); 69 70 up_write(&mm->mmap_sem); 71 72 return err; 73} 74