@@ -23,13 +23,21 @@ struct vdso_data {
2323#endif
2424
2525extern char vdso_start [], vdso_end [];
26+ #ifdef CONFIG_COMPAT
27+ extern char compat_vdso_start [], compat_vdso_end [];
28+ #endif
2629
2730enum vvar_pages {
2831 VVAR_DATA_PAGE_OFFSET ,
2932 VVAR_TIMENS_PAGE_OFFSET ,
3033 VVAR_NR_PAGES ,
3134};
3235
36+ enum rv_vdso_map {
37+ RV_VDSO_MAP_VVAR ,
38+ RV_VDSO_MAP_VDSO ,
39+ };
40+
3341#define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT)
3442
3543/*
@@ -52,12 +60,6 @@ struct __vdso_info {
5260 struct vm_special_mapping * cm ;
5361};
5462
55- static struct __vdso_info vdso_info __ro_after_init = {
56- .name = "vdso" ,
57- .vdso_code_start = vdso_start ,
58- .vdso_code_end = vdso_end ,
59- };
60-
6163static int vdso_mremap (const struct vm_special_mapping * sm ,
6264 struct vm_area_struct * new_vma )
6365{
@@ -66,37 +68,33 @@ static int vdso_mremap(const struct vm_special_mapping *sm,
6668 return 0 ;
6769}
6870
69- static int __init __vdso_init (void )
71+ static void __init __vdso_init (struct __vdso_info * vdso_info )
7072{
7173 unsigned int i ;
7274 struct page * * vdso_pagelist ;
7375 unsigned long pfn ;
7476
75- if (memcmp (vdso_info .vdso_code_start , "\177ELF" , 4 )) {
76- pr_err ("vDSO is not a valid ELF object!\n" );
77- return - EINVAL ;
78- }
77+ if (memcmp (vdso_info -> vdso_code_start , "\177ELF" , 4 ))
78+ panic ("vDSO is not a valid ELF object!\n" );
7979
80- vdso_info . vdso_pages = (
81- vdso_info . vdso_code_end -
82- vdso_info . vdso_code_start ) >>
80+ vdso_info -> vdso_pages = (
81+ vdso_info -> vdso_code_end -
82+ vdso_info -> vdso_code_start ) >>
8383 PAGE_SHIFT ;
8484
85- vdso_pagelist = kcalloc (vdso_info . vdso_pages ,
85+ vdso_pagelist = kcalloc (vdso_info -> vdso_pages ,
8686 sizeof (struct page * ),
8787 GFP_KERNEL );
8888 if (vdso_pagelist == NULL )
89- return - ENOMEM ;
89+ panic ( "vDSO kcalloc failed!\n" ) ;
9090
9191 /* Grab the vDSO code pages. */
92- pfn = sym_to_pfn (vdso_info . vdso_code_start );
92+ pfn = sym_to_pfn (vdso_info -> vdso_code_start );
9393
94- for (i = 0 ; i < vdso_info . vdso_pages ; i ++ )
94+ for (i = 0 ; i < vdso_info -> vdso_pages ; i ++ )
9595 vdso_pagelist [i ] = pfn_to_page (pfn + i );
9696
97- vdso_info .cm -> pages = vdso_pagelist ;
98-
99- return 0 ;
97+ vdso_info -> cm -> pages = vdso_pagelist ;
10098}
10199
102100#ifdef CONFIG_TIME_NS
@@ -116,13 +114,14 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
116114{
117115 struct mm_struct * mm = task -> mm ;
118116 struct vm_area_struct * vma ;
117+ struct __vdso_info * vdso_info = mm -> context .vdso_info ;
119118
120119 mmap_read_lock (mm );
121120
122121 for (vma = mm -> mmap ; vma ; vma = vma -> vm_next ) {
123122 unsigned long size = vma -> vm_end - vma -> vm_start ;
124123
125- if (vma_is_special_mapping (vma , vdso_info . dm ))
124+ if (vma_is_special_mapping (vma , vdso_info -> dm ))
126125 zap_page_range (vma , vma -> vm_start , size );
127126 }
128127
@@ -187,11 +186,6 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
187186 return vmf_insert_pfn (vma , vmf -> address , pfn );
188187}
189188
190- enum rv_vdso_map {
191- RV_VDSO_MAP_VVAR ,
192- RV_VDSO_MAP_VDSO ,
193- };
194-
195189static struct vm_special_mapping rv_vdso_maps [] __ro_after_init = {
196190 [RV_VDSO_MAP_VVAR ] = {
197191 .name = "[vvar]" ,
@@ -203,25 +197,46 @@ static struct vm_special_mapping rv_vdso_maps[] __ro_after_init = {
203197 },
204198};
205199
200+ static struct __vdso_info vdso_info __ro_after_init = {
201+ .name = "vdso" ,
202+ .vdso_code_start = vdso_start ,
203+ .vdso_code_end = vdso_end ,
204+ .dm = & rv_vdso_maps [RV_VDSO_MAP_VVAR ],
205+ .cm = & rv_vdso_maps [RV_VDSO_MAP_VDSO ],
206+ };
207+
208+ #ifdef CONFIG_COMPAT
209+ static struct __vdso_info compat_vdso_info __ro_after_init = {
210+ .name = "compat_vdso" ,
211+ .vdso_code_start = compat_vdso_start ,
212+ .vdso_code_end = compat_vdso_end ,
213+ .dm = & rv_vdso_maps [RV_VDSO_MAP_VVAR ],
214+ .cm = & rv_vdso_maps [RV_VDSO_MAP_VDSO ],
215+ };
216+ #endif
217+
206218static int __init vdso_init (void )
207219{
208- vdso_info .dm = & rv_vdso_maps [RV_VDSO_MAP_VVAR ];
209- vdso_info .cm = & rv_vdso_maps [RV_VDSO_MAP_VDSO ];
220+ __vdso_init (& vdso_info );
221+ #ifdef CONFIG_COMPAT
222+ __vdso_init (& compat_vdso_info );
223+ #endif
210224
211- return __vdso_init () ;
225+ return 0 ;
212226}
213227arch_initcall (vdso_init );
214228
215229static int __setup_additional_pages (struct mm_struct * mm ,
216230 struct linux_binprm * bprm ,
217- int uses_interp )
231+ int uses_interp ,
232+ struct __vdso_info * vdso_info )
218233{
219234 unsigned long vdso_base , vdso_text_len , vdso_mapping_len ;
220235 void * ret ;
221236
222237 BUILD_BUG_ON (VVAR_NR_PAGES != __VVAR_PAGES );
223238
224- vdso_text_len = vdso_info . vdso_pages << PAGE_SHIFT ;
239+ vdso_text_len = vdso_info -> vdso_pages << PAGE_SHIFT ;
225240 /* Be sure to map the data page */
226241 vdso_mapping_len = vdso_text_len + VVAR_SIZE ;
227242
@@ -232,16 +247,18 @@ static int __setup_additional_pages(struct mm_struct *mm,
232247 }
233248
234249 ret = _install_special_mapping (mm , vdso_base , VVAR_SIZE ,
235- (VM_READ | VM_MAYREAD | VM_PFNMAP ), vdso_info . dm );
250+ (VM_READ | VM_MAYREAD | VM_PFNMAP ), vdso_info -> dm );
236251 if (IS_ERR (ret ))
237252 goto up_fail ;
238253
239254 vdso_base += VVAR_SIZE ;
240255 mm -> context .vdso = (void * )vdso_base ;
256+ mm -> context .vdso_info = (void * )vdso_info ;
257+
241258 ret =
242259 _install_special_mapping (mm , vdso_base , vdso_text_len ,
243260 (VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC ),
244- vdso_info . cm );
261+ vdso_info -> cm );
245262
246263 if (IS_ERR (ret ))
247264 goto up_fail ;
@@ -253,6 +270,24 @@ static int __setup_additional_pages(struct mm_struct *mm,
253270 return PTR_ERR (ret );
254271}
255272
273+ #ifdef CONFIG_COMPAT
274+ int compat_arch_setup_additional_pages (struct linux_binprm * bprm ,
275+ int uses_interp )
276+ {
277+ struct mm_struct * mm = current -> mm ;
278+ int ret ;
279+
280+ if (mmap_write_lock_killable (mm ))
281+ return - EINTR ;
282+
283+ ret = __setup_additional_pages (mm , bprm , uses_interp ,
284+ & compat_vdso_info );
285+ mmap_write_unlock (mm );
286+
287+ return ret ;
288+ }
289+ #endif
290+
256291int arch_setup_additional_pages (struct linux_binprm * bprm , int uses_interp )
257292{
258293 struct mm_struct * mm = current -> mm ;
@@ -261,7 +296,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
261296 if (mmap_write_lock_killable (mm ))
262297 return - EINTR ;
263298
264- ret = __setup_additional_pages (mm , bprm , uses_interp );
299+ ret = __setup_additional_pages (mm , bprm , uses_interp , & vdso_info );
265300 mmap_write_unlock (mm );
266301
267302 return ret ;
0 commit comments