aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86_64/ia32/syscall32.c59
-rw-r--r--include/asm-x86_64/proto.h1
2 files changed, 13 insertions, 47 deletions
diff --git a/arch/x86_64/ia32/syscall32.c b/arch/x86_64/ia32/syscall32.c
index 59f1fa155915..568ff0df89e7 100644
--- a/arch/x86_64/ia32/syscall32.c
+++ b/arch/x86_64/ia32/syscall32.c
@@ -18,68 +18,34 @@ extern unsigned char syscall32_syscall[], syscall32_syscall_end[];
18extern unsigned char syscall32_sysenter[], syscall32_sysenter_end[]; 18extern unsigned char syscall32_sysenter[], syscall32_sysenter_end[];
19extern int sysctl_vsyscall32; 19extern int sysctl_vsyscall32;
20 20
21char *syscall32_page; 21static struct page *syscall32_pages[1];
22static int use_sysenter = -1; 22static int use_sysenter = -1;
23 23
24static struct page *
25syscall32_nopage(struct vm_area_struct *vma, unsigned long adr, int *type)
26{
27 struct page *p = virt_to_page(adr - vma->vm_start + syscall32_page);
28 get_page(p);
29 return p;
30}
31
32/* Prevent VMA merging */
33static void syscall32_vma_close(struct vm_area_struct *vma)
34{
35}
36
37static struct vm_operations_struct syscall32_vm_ops = {
38 .close = syscall32_vma_close,
39 .nopage = syscall32_nopage,
40};
41
42struct linux_binprm; 24struct linux_binprm;
43 25
44/* Setup a VMA at program startup for the vsyscall page */ 26/* Setup a VMA at program startup for the vsyscall page */
45int syscall32_setup_pages(struct linux_binprm *bprm, int exstack) 27int syscall32_setup_pages(struct linux_binprm *bprm, int exstack)
46{ 28{
47 int npages = (VSYSCALL32_END - VSYSCALL32_BASE) >> PAGE_SHIFT;
48 struct vm_area_struct *vma;
49 struct mm_struct *mm = current->mm; 29 struct mm_struct *mm = current->mm;
50 int ret; 30 int ret;
51 31
52 vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); 32 down_write(&mm->mmap_sem);
53 if (!vma)
54 return -ENOMEM;
55
56 memset(vma, 0, sizeof(struct vm_area_struct));
57 /* Could randomize here */
58 vma->vm_start = VSYSCALL32_BASE;
59 vma->vm_end = VSYSCALL32_END;
60 /* MAYWRITE to allow gdb to COW and set breakpoints */
61 vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE;
62 /* 33 /*
34 * MAYWRITE to allow gdb to COW and set breakpoints
35 *
63 * Make sure the vDSO gets into every core dump. 36 * Make sure the vDSO gets into every core dump.
64 * Dumping its contents makes post-mortem fully interpretable later 37 * Dumping its contents makes post-mortem fully interpretable later
65 * without matching up the same kernel and hardware config to see 38 * without matching up the same kernel and hardware config to see
66 * what PC values meant. 39 * what PC values meant.
67 */ 40 */
68 vma->vm_flags |= VM_ALWAYSDUMP; 41 /* Could randomize here */
69 vma->vm_flags |= mm->def_flags; 42 ret = install_special_mapping(mm, VSYSCALL32_BASE, PAGE_SIZE,
70 vma->vm_page_prot = protection_map[vma->vm_flags & 7]; 43 VM_READ|VM_EXEC|
71 vma->vm_ops = &syscall32_vm_ops; 44 VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
72 vma->vm_mm = mm; 45 VM_ALWAYSDUMP,
73 46 syscall32_pages);
74 down_write(&mm->mmap_sem);
75 if ((ret = insert_vm_struct(mm, vma))) {
76 up_write(&mm->mmap_sem);
77 kmem_cache_free(vm_area_cachep, vma);
78 return ret;
79 }
80 mm->total_vm += npages;
81 up_write(&mm->mmap_sem); 47 up_write(&mm->mmap_sem);
82 return 0; 48 return ret;
83} 49}
84 50
85const char *arch_vma_name(struct vm_area_struct *vma) 51const char *arch_vma_name(struct vm_area_struct *vma)
@@ -92,9 +58,10 @@ const char *arch_vma_name(struct vm_area_struct *vma)
92 58
93static int __init init_syscall32(void) 59static int __init init_syscall32(void)
94{ 60{
95 syscall32_page = (void *)get_zeroed_page(GFP_KERNEL); 61 char *syscall32_page = (void *)get_zeroed_page(GFP_KERNEL);
96 if (!syscall32_page) 62 if (!syscall32_page)
97 panic("Cannot allocate syscall32 page"); 63 panic("Cannot allocate syscall32 page");
64 syscall32_pages[0] = virt_to_page(syscall32_page);
98 if (use_sysenter > 0) { 65 if (use_sysenter > 0) {
99 memcpy(syscall32_page, syscall32_sysenter, 66 memcpy(syscall32_page, syscall32_sysenter,
100 syscall32_sysenter_end - syscall32_sysenter); 67 syscall32_sysenter_end - syscall32_sysenter);
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
index 6d324b838972..a6d2ff5c69b7 100644
--- a/include/asm-x86_64/proto.h
+++ b/include/asm-x86_64/proto.h
@@ -81,7 +81,6 @@ extern void swap_low_mappings(void);
81extern void __show_regs(struct pt_regs * regs); 81extern void __show_regs(struct pt_regs * regs);
82extern void show_regs(struct pt_regs * regs); 82extern void show_regs(struct pt_regs * regs);
83 83
84extern char *syscall32_page;
85extern void syscall32_cpu_init(void); 84extern void syscall32_cpu_init(void);
86 85
87extern void setup_node_bootmem(int nodeid, unsigned long start, unsigned long end); 86extern void setup_node_bootmem(int nodeid, unsigned long start, unsigned long end);