1212#include <linux/binfmts.h>
1313#include <linux/err.h>
1414#include <asm/page.h>
15+ #include <asm/vdso.h>
16+
1517#ifdef CONFIG_GENERIC_TIME_VSYSCALL
1618#include <vdso/datapage.h>
1719#else
18- #include <asm/vdso.h>
20+ struct vdso_data {
21+ };
1922#endif
2023
2124extern char vdso_start [], vdso_end [];
2225
26+ enum vvar_pages {
27+ VVAR_DATA_PAGE_OFFSET ,
28+ VVAR_NR_PAGES ,
29+ };
30+
31+ #define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT)
32+
2333static unsigned int vdso_pages __ro_after_init ;
2434static struct page * * vdso_pagelist __ro_after_init ;
2535
@@ -38,7 +48,7 @@ static int __init vdso_init(void)
3848
3949 vdso_pages = (vdso_end - vdso_start ) >> PAGE_SHIFT ;
4050 vdso_pagelist =
41- kcalloc (vdso_pages + 1 , sizeof (struct page * ), GFP_KERNEL );
51+ kcalloc (vdso_pages + VVAR_NR_PAGES , sizeof (struct page * ), GFP_KERNEL );
4252 if (unlikely (vdso_pagelist == NULL )) {
4353 pr_err ("vdso: pagelist allocation failed\n" );
4454 return - ENOMEM ;
@@ -63,38 +73,41 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
6373 unsigned long vdso_base , vdso_len ;
6474 int ret ;
6575
66- vdso_len = (vdso_pages + 1 ) << PAGE_SHIFT ;
76+ BUILD_BUG_ON (VVAR_NR_PAGES != __VVAR_PAGES );
77+
78+ vdso_len = (vdso_pages + VVAR_NR_PAGES ) << PAGE_SHIFT ;
79+
80+ if (mmap_write_lock_killable (mm ))
81+ return - EINTR ;
6782
68- mmap_write_lock (mm );
6983 vdso_base = get_unmapped_area (NULL , 0 , vdso_len , 0 , 0 );
7084 if (IS_ERR_VALUE (vdso_base )) {
7185 ret = vdso_base ;
7286 goto end ;
7387 }
7488
75- /*
76- * Put vDSO base into mm struct. We need to do this before calling
77- * install_special_mapping or the perf counter mmap tracking code
78- * will fail to recognise it as a vDSO (since arch_vma_name fails).
79- */
80- mm -> context .vdso = (void * )vdso_base ;
89+ mm -> context .vdso = NULL ;
90+ ret = install_special_mapping (mm , vdso_base , VVAR_SIZE ,
91+ (VM_READ | VM_MAYREAD ), & vdso_pagelist [vdso_pages ]);
92+ if (unlikely (ret ))
93+ goto end ;
8194
8295 ret =
83- install_special_mapping (mm , vdso_base , vdso_pages << PAGE_SHIFT ,
96+ install_special_mapping (mm , vdso_base + VVAR_SIZE ,
97+ vdso_pages << PAGE_SHIFT ,
8498 (VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC ),
8599 vdso_pagelist );
86100
87- if (unlikely (ret )) {
88- mm -> context .vdso = NULL ;
101+ if (unlikely (ret ))
89102 goto end ;
90- }
91103
92- vdso_base += (vdso_pages << PAGE_SHIFT );
93- ret = install_special_mapping (mm , vdso_base , PAGE_SIZE ,
94- (VM_READ | VM_MAYREAD ), & vdso_pagelist [vdso_pages ]);
104+ /*
105+ * Put vDSO base into mm struct. We need to do this before calling
106+ * install_special_mapping or the perf counter mmap tracking code
107+ * will fail to recognise it as a vDSO (since arch_vma_name fails).
108+ */
109+ mm -> context .vdso = (void * )vdso_base + VVAR_SIZE ;
95110
96- if (unlikely (ret ))
97- mm -> context .vdso = NULL ;
98111end :
99112 mmap_write_unlock (mm );
100113 return ret ;
@@ -105,7 +118,7 @@ const char *arch_vma_name(struct vm_area_struct *vma)
105118 if (vma -> vm_mm && (vma -> vm_start == (long )vma -> vm_mm -> context .vdso ))
106119 return "[vdso]" ;
107120 if (vma -> vm_mm && (vma -> vm_start ==
108- (long )vma -> vm_mm -> context .vdso + PAGE_SIZE ))
121+ (long )vma -> vm_mm -> context .vdso - VVAR_SIZE ))
109122 return "[vdso_data]" ;
110123 return NULL ;
111124}
0 commit comments