Skip to content

Commit d53b5c0

Browse files
avaginctmarinas
authored andcommitted
arm64/vdso: use the fault callback to map vvar pages
Currently the vdso has no awareness of time namespaces, which may apply distinct offsets to processes in different namespaces. To handle this within the vdso, we'll need to expose a per-namespace data page. As a preparatory step, this patch separates the vdso data page from the code pages, and has it faulted in via its own fault callback. Subsquent patches will extend this to support distinct pages per time namespace. The vvar vma has to be installed with the VM_PFNMAP flag to handle faults via its vma fault callback. Signed-off-by: Andrei Vagin <[email protected]> Reviewed-by: Vincenzo Frascino <[email protected]> Reviewed-by: Dmitry Safonov <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]>
1 parent 9ebcfad commit d53b5c0

File tree

1 file changed

+15
-10
lines changed

1 file changed

+15
-10
lines changed

arch/arm64/kernel/vdso.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -107,29 +107,32 @@ static int __vdso_init(enum vdso_abi abi)
107107
vdso_info[abi].vdso_code_start) >>
108108
PAGE_SHIFT;
109109

110-
/* Allocate the vDSO pagelist, plus a page for the data. */
111-
vdso_pagelist = kcalloc(vdso_info[abi].vdso_pages + 1,
110+
vdso_pagelist = kcalloc(vdso_info[abi].vdso_pages,
112111
sizeof(struct page *),
113112
GFP_KERNEL);
114113
if (vdso_pagelist == NULL)
115114
return -ENOMEM;
116115

117-
/* Grab the vDSO data page. */
118-
vdso_pagelist[0] = phys_to_page(__pa_symbol(vdso_data));
119-
120-
121116
/* Grab the vDSO code pages. */
122117
pfn = sym_to_pfn(vdso_info[abi].vdso_code_start);
123118

124119
for (i = 0; i < vdso_info[abi].vdso_pages; i++)
125-
vdso_pagelist[i + 1] = pfn_to_page(pfn + i);
120+
vdso_pagelist[i] = pfn_to_page(pfn + i);
126121

127-
vdso_info[abi].dm->pages = &vdso_pagelist[0];
128-
vdso_info[abi].cm->pages = &vdso_pagelist[1];
122+
vdso_info[abi].cm->pages = vdso_pagelist;
129123

130124
return 0;
131125
}
132126

127+
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
128+
struct vm_area_struct *vma, struct vm_fault *vmf)
129+
{
130+
if (vmf->pgoff == 0)
131+
return vmf_insert_pfn(vma, vmf->address,
132+
sym_to_pfn(vdso_data));
133+
return VM_FAULT_SIGBUS;
134+
}
135+
133136
static int __setup_additional_pages(enum vdso_abi abi,
134137
struct mm_struct *mm,
135138
struct linux_binprm *bprm,
@@ -150,7 +153,7 @@ static int __setup_additional_pages(enum vdso_abi abi,
150153
}
151154

152155
ret = _install_special_mapping(mm, vdso_base, PAGE_SIZE,
153-
VM_READ|VM_MAYREAD,
156+
VM_READ|VM_MAYREAD|VM_PFNMAP,
154157
vdso_info[abi].dm);
155158
if (IS_ERR(ret))
156159
goto up_fail;
@@ -206,6 +209,7 @@ static struct vm_special_mapping aarch32_vdso_maps[] = {
206209
#ifdef CONFIG_COMPAT_VDSO
207210
[AA32_MAP_VVAR] = {
208211
.name = "[vvar]",
212+
.fault = vvar_fault,
209213
},
210214
[AA32_MAP_VDSO] = {
211215
.name = "[vdso]",
@@ -371,6 +375,7 @@ enum aarch64_map {
371375
static struct vm_special_mapping aarch64_vdso_maps[] __ro_after_init = {
372376
[AA64_MAP_VVAR] = {
373377
.name = "[vvar]",
378+
.fault = vvar_fault,
374379
},
375380
[AA64_MAP_VDSO] = {
376381
.name = "[vdso]",

0 commit comments

Comments
 (0)