1/* 2 * arch/sh/kernel/vsyscall/vsyscall.c 3 * 4 * Copyright (C) 2006 Paul Mundt 5 * 6 * vDSO randomization 7 * Copyright(C) 2005-2006, Red Hat, Inc., Ingo Molnar 8 * 9 * This file is subject to the terms and conditions of the GNU General Public 10 * License. See the file "COPYING" in the main directory of this archive 11 * for more details. 12 */ 13#include <linux/mm.h> 14#include <linux/kernel.h> 15#include <linux/init.h> 16#include <linux/gfp.h> 17#include <linux/module.h> 18#include <linux/elf.h> 19#include <linux/sched.h> 20#include <linux/err.h> 21 22/* 23 * Should the kernel map a VDSO page into processes and pass its 24 * address down to glibc upon exec()? 25 */ 26unsigned int __read_mostly vdso_enabled = 1; 27EXPORT_SYMBOL_GPL(vdso_enabled); 28 29static int __init vdso_setup(char *s) 30{ 31 vdso_enabled = simple_strtoul(s, NULL, 0); 32 return 1; 33} 34__setup("vdso=", vdso_setup); 35 36/* 37 * These symbols are defined by vsyscall.o to mark the bounds 38 * of the ELF DSO images included therein. 39 */ 40extern const char vsyscall_trapa_start, vsyscall_trapa_end; 41static struct page *syscall_pages[1]; 42 43int __init vsyscall_init(void) 44{ 45 void *syscall_page = (void *)get_zeroed_page(GFP_ATOMIC); 46 syscall_pages[0] = virt_to_page(syscall_page); 47 48 49 memcpy(syscall_page, 50 &vsyscall_trapa_start, 51 &vsyscall_trapa_end - &vsyscall_trapa_start); 52 53 return 0; 54} 55 56/* Setup a VMA at program startup for the vsyscall page */ 57int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) 58{ 59 struct mm_struct *mm = current->mm; 60 unsigned long addr; 61 int ret; 62 63 down_write(&mm->mmap_sem); 64 addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0); 65 if (IS_ERR_VALUE(addr)) { 66 ret = addr; 67 goto up_fail; 68 } 69 70 ret = install_special_mapping(mm, addr, PAGE_SIZE, 71 VM_READ | VM_EXEC | 72 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC | 73 VM_ALWAYSDUMP, 74 syscall_pages); 75 if (unlikely(ret)) 76 goto up_fail; 77 78 current->mm->context.vdso = (void *)addr; 79 80up_fail: 81 up_write(&mm->mmap_sem); 82 return ret; 83} 84 85const char *arch_vma_name(struct vm_area_struct *vma) 86{ 87 if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) 88 return "[vdso]"; 89 90 return NULL; 91} 92 93struct vm_area_struct *get_gate_vma(struct task_struct *task) 94{ 95 return NULL; 96} 97 98int in_gate_area(struct task_struct *task, unsigned long address) 99{ 100 return 0; 101} 102 103int in_gate_area_no_task(unsigned long address) 104{ 105 return 0; 106} 107