diff options
-rw-r--r-- | arch/x86_64/ia32/syscall32.c | 59 | ||||
-rw-r--r-- | include/asm-x86_64/proto.h | 1 |
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[]; | |||
18 | extern unsigned char syscall32_sysenter[], syscall32_sysenter_end[]; | 18 | extern unsigned char syscall32_sysenter[], syscall32_sysenter_end[]; |
19 | extern int sysctl_vsyscall32; | 19 | extern int sysctl_vsyscall32; |
20 | 20 | ||
21 | char *syscall32_page; | 21 | static struct page *syscall32_pages[1]; |
22 | static int use_sysenter = -1; | 22 | static int use_sysenter = -1; |
23 | 23 | ||
24 | static struct page * | ||
25 | syscall32_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 */ | ||
33 | static void syscall32_vma_close(struct vm_area_struct *vma) | ||
34 | { | ||
35 | } | ||
36 | |||
37 | static struct vm_operations_struct syscall32_vm_ops = { | ||
38 | .close = syscall32_vma_close, | ||
39 | .nopage = syscall32_nopage, | ||
40 | }; | ||
41 | |||
42 | struct linux_binprm; | 24 | struct 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 */ |
45 | int syscall32_setup_pages(struct linux_binprm *bprm, int exstack) | 27 | int 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 | ||
85 | const char *arch_vma_name(struct vm_area_struct *vma) | 51 | const 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 | ||
93 | static int __init init_syscall32(void) | 59 | static 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); | |||
81 | extern void __show_regs(struct pt_regs * regs); | 81 | extern void __show_regs(struct pt_regs * regs); |
82 | extern void show_regs(struct pt_regs * regs); | 82 | extern void show_regs(struct pt_regs * regs); |
83 | 83 | ||
84 | extern char *syscall32_page; | ||
85 | extern void syscall32_cpu_init(void); | 84 | extern void syscall32_cpu_init(void); |
86 | 85 | ||
87 | extern void setup_node_bootmem(int nodeid, unsigned long start, unsigned long end); | 86 | extern void setup_node_bootmem(int nodeid, unsigned long start, unsigned long end); |