Skip to content

Commit 3092eb4

Browse files
guoren83palmer-dabbelt
authored andcommitted
riscv: compat: vdso: Add setup additional pages implementation
Reconstruct __setup_additional_pages() by appending vdso info pointer argument to meet compat_vdso_info requirement. And change vm_special_mapping *dm, *cm initialization into static. Signed-off-by: Guo Ren <[email protected]> Signed-off-by: Guo Ren <[email protected]> Reviewed-by: Palmer Dabbelt <[email protected]> Tested-by: Heiko Stuebner <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 0715372 commit 3092eb4

File tree

3 files changed

+76
-35
lines changed

3 files changed

+76
-35
lines changed

arch/riscv/include/asm/elf.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,5 +130,10 @@ do { if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
130130
typedef compat_ulong_t compat_elf_greg_t;
131131
typedef compat_elf_greg_t compat_elf_gregset_t[ELF_NGREG];
132132

133+
extern int compat_arch_setup_additional_pages(struct linux_binprm *bprm,
134+
int uses_interp);
135+
#define compat_arch_setup_additional_pages \
136+
compat_arch_setup_additional_pages
137+
133138
#endif /* CONFIG_COMPAT */
134139
#endif /* _ASM_RISCV_ELF_H */

arch/riscv/include/asm/mmu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ typedef struct {
1616
atomic_long_t id;
1717
#endif
1818
void *vdso;
19+
void *vdso_info;
1920
#ifdef CONFIG_SMP
2021
/* A local icache flush is needed before user execution can resume. */
2122
cpumask_t icache_stale_mask;

arch/riscv/kernel/vdso.c

Lines changed: 70 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,21 @@ struct vdso_data {
2323
#endif
2424

2525
extern char vdso_start[], vdso_end[];
26+
#ifdef CONFIG_COMPAT
27+
extern char compat_vdso_start[], compat_vdso_end[];
28+
#endif
2629

2730
enum 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-
6163
static 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-
195189
static 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+
206218
static 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
}
213227
arch_initcall(vdso_init);
214228

215229
static 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+
256291
int 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

Comments
 (0)