[PATCH 1/2] arm64: mm: detect bad __create_mapping uses

Mark Rutland mark.rutland at arm.com
Mon Nov 23 03:21:51 PST 2015


On Mon, Nov 23, 2015 at 11:01:51AM +0000, Steve Capper wrote:
> On 20 November 2015 at 17:05, Mark Rutland <mark.rutland at arm.com> wrote:
> > On Fri, Nov 20, 2015 at 04:13:28PM +0000, Steve Capper wrote:
> >> On 20 November 2015 at 15:35, Mark Rutland <mark.rutland at arm.com> wrote:
> >> > If a caller of __create_mapping provides a PA and VA which have
> >> > different sub-page offsets, it is not clear which offset they expect to
> >> > apply to the mapping, and is indicative of a bad caller.
> >> >
> >> > Disallow calls with differing sub-page offsets, and WARN when they are
> >> > encountered, so that we can detect and fix such cases.
> >> >
> >> > Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> >> > Cc: Ard Biesheuvel <ard.biesheuvel at linaro.org>
> >> > Cc: Catalin Marinas <caralin.marinas at arm.com>
> >> > Cc: Laura Abbott <labbott at fedoraproject.org>
> >> > Cc: Steve Capper <steve.capper at linaro.org>
> >> > Cc: Will Deacon <will.deacon at arm.com>
> >> > ---
> >> >  arch/arm64/mm/mmu.c | 7 +++++++
> >> >  1 file changed, 7 insertions(+)
> >> >
> >> > diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> >> > index e3f563c..3b06afa 100644
> >> > --- a/arch/arm64/mm/mmu.c
> >> > +++ b/arch/arm64/mm/mmu.c
> >> > @@ -300,6 +300,13 @@ static void  __create_mapping(struct mm_struct *mm, pgd_t *pgd,
> >> >  {
> >> >         unsigned long addr, length, end, next;
> >> >
> >> > +       /*
> >> > +        * If the virtual and physical address don't have the same offset
> >> > +        * within a page, we cannot map the region as the caller expects.
> >> > +        */
> >> > +       if (WARN_ON((phys ^ virt) & ~PAGE_MASK))
> >> > +               return;
> >> > +
> >>
> >> Do we want any subpage offsets in our virt and phys?
> >
> > Yes.
> >
> > For instance, when mapping EFI regions (which exist at 4K granularity)
> > on a 64K page kernel, per [1]. The spec requires that any regions in the
> > same 64K page can be mapped using the same attributes, so it's fine to
> > map at 64K granularity.
> 
> Thanks Mark,
> I didn't know that was allowed, now I do :-).
> These two patches now make perfect sense.
> 
> >
> > We already try to cater for this in __create_mapping where we fix up the
> > base and size:
> >
> >         addr = virt & PAGE_MASK;
> >         length = PAGE_ALIGN(size + (virt & ~PAGE_MASK));
> >
> > I will add a middle paragraph to the commit message:
> >
> >         In some cases, the region we wish to map may validly have a
> >         sub-page offset in the physical and virtual adddresses. For
> >         example, EFI runtime regions have 4K granularity, yet may be
> >         mapped by a 64K page kernel. So long as the physical and virtual
> >         offsets are the same, the region will be mapped at the expected
> >         VAs.
> >
> > Does that sound OK?
> 
> s/adddresses/addresses/
> Otherwise that looks great, thanks.

Good spot. Fixed.

> >> If we have sub page bits in phys won't that start flipping on bits in
> >> the page table entries?
> >
> > In all cases where we use phys, we either shift phys right by PAGE_SHIFT
> > (in __populate_init_pte vi __phys_to_pfn) which clears those bits, or we
> > first check it is sufficiently aligned for that level of table (and
> > hence the low bits are all zero). Patch 2 fixes a bug related to the
> > latter case.
> >
> >> What about something like:
> >> if (WARN_ON((phys | virt) & ~PAGE_MASK))
> >
> > Per the above, that would break the EFI code in [1].
> 
> Agreed.
> 
> I was toying with suggesting we warn for any phys/virt bit set below
> bit #12 (i.e. anything smaller than 4K alignment), that would probably
> just increase complexity with little appreciable gain though.

I'm not sure either way, to be honest. We might want to use it in an
ioremap-like manner to map small objects.

For instance, we use create_mapping to map the DTB in fixmap_remap_fdt,
and the DTB itself is only guaranteed to be 8-byte aligned. However,
fixmap_remap_fdt has to handle the sub-page offset explicitly either
way, either adding it to the fixmap slot's virtual address or
subtracting it from the physical base when it makes the call.

> For both patches (with the extra paragraph above added to the commit log):
> Reviewed-by: Steve Capper <steve.capper at linaro.org>

I take it you mean with the paragraph added to this patch, not to both
patches?

Thanks,
Mark.



More information about the linux-arm-kernel mailing list