Re: [PATCH v7 03/19] gup: Turn fault_in_pages_{readable,writeable} into fault_in_{readable,writeable}
From: Matthew Wilcox
Date: Tue Sep 28 2021 - 12:42:01 EST
On Tue, Sep 28, 2021 at 05:02:43PM +0200, Andreas Gruenbacher wrote:
> On Fri, Sep 3, 2021 at 4:57 PM Filipe Manana <fdmanana@xxxxxxxxx> wrote:
> > On Fri, Aug 27, 2021 at 5:52 PM Andreas Gruenbacher <agruenba@xxxxxxxxxx> wrote:
> > > +size_t fault_in_writeable(char __user *uaddr, size_t size)
> > > +{
> > > + char __user *start = uaddr, *end;
> > > +
> > > + if (unlikely(size == 0))
> > > + return 0;
> > > + if (!PAGE_ALIGNED(uaddr)) {
> > > + if (unlikely(__put_user(0, uaddr) != 0))
> > > + return size;
> > > + uaddr = (char __user *)PAGE_ALIGN((unsigned long)uaddr);
> > > + }
> > > + end = (char __user *)PAGE_ALIGN((unsigned long)start + size);
> > > + if (unlikely(end < start))
> > > + end = NULL;
> > > + while (uaddr != end) {
> > > + if (unlikely(__put_user(0, uaddr) != 0))
> > > + goto out;
> > > + uaddr += PAGE_SIZE;
> >
> > Won't we loop endlessly or corrupt some unwanted page when 'end' was
> > set to NULL?
>
> What do you mean? We set 'end' to NULL when start + size < start
> exactly so that the loop will stop when uaddr wraps around.
But think about x86-64. The virtual address space (unless you have 5
level PTs) looks like:
[0, 2^47) userspace
[2^47, 2^64 - 2^47) hole
[2^64 - 2^47, 2^64) kernel space
If we try to copy from the hole we'll get some kind of fault (I forget
the details). We have to stop at the top of userspace.