Hi Ralf, On Thu, Sep 01, 2016 at 01:04:25PM +0100, James Hogan wrote: > The page structures associated with the vDSO pages in the kernel image > are calculated using virt_to_page(), which uses __pa() under the hood to > find the pfn associated with the virtual address. The vDSO data pointers > however point to kernel symbols, so __pa_symbol() should really be used > instead. > > Since there is no equivalent to virt_to_page() which uses __pa_symbol(), > fix init_vdso_image() to work directly with pfns, calculated with > PHYS_PFN(__pa_symbol(...)). > > This issue broke the Malta Enhanced Virtual Addressing (EVA) > configuration which has a non-default implementation of __pa_symbol(). > This is because it uses a physical alias so that the kernel executes > from KSeg0 (VA 0x80000000 -> PA 0x00000000), while RAM is provided to > the kernel in the KUSeg range (VA 0x00000000 -> PA 0x80000000) which > uses the same underlying RAM. > > Since there are no page structures associated with the low physical > address region, some arbitrary kernel memory would be interpreted as a > page structure for the vDSO pages and badness ensues. > > Fixes: ebb5e78cc634 ("MIPS: Initial implementation of a VDSO") > Signed-off-by: James Hogan <james.hogan@xxxxxxxxxx> > Cc: Ralf Baechle <ralf@xxxxxxxxxxxxxx> > Cc: Leonid Yegoshin <leonid.yegoshin@xxxxxxxxxx> > Cc: linux-mips@xxxxxxxxxxxxxx > Cc: <stable@xxxxxxxxxxxxxxx> # 4.4.x- > --- > arch/mips/kernel/vdso.c | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) > > diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c > index 9abe447a4b48..e4a8d8846eac 100644 > --- a/arch/mips/kernel/vdso.c > +++ b/arch/mips/kernel/vdso.c > @@ -39,16 +39,16 @@ static struct vm_special_mapping vdso_vvar_mapping = { > static void __init init_vdso_image(struct mips_vdso_image *image) > { > unsigned long num_pages, i; > + unsigned long data_pfn; > > BUG_ON(!PAGE_ALIGNED(image->data)); > BUG_ON(!PAGE_ALIGNED(image->size)); > > num_pages = image->size / PAGE_SIZE; > > - for (i = 0; i < num_pages; i++) { > - image->mapping.pages[i] = > - virt_to_page(image->data + (i * PAGE_SIZE)); > - } > + data_pfn = PHYS_PFN(__pa_symbol(image->data)); Actually PHYS_PFN() was only added in v4.5, and we need this patch applied as far back as v4.4, so I'll send a v2 using __phys_to_pfn() instead. Cheers James
Attachment:
signature.asc
Description: Digital signature