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.