lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <02957e4c-6752-4039-bcc5-c00b971ad0aa@lucifer.local>
Date:   Wed, 11 Oct 2023 07:34:47 +0100
From:   Lorenzo Stoakes <lstoakes@...il.com>
To:     "Liam R. Howlett" <Liam.Howlett@...cle.com>, linux-mm@...ck.org,
        linux-kernel@...r.kernel.org,
        Andrew Morton <akpm@...ux-foundation.org>,
        Alexander Viro <viro@...iv.linux.org.uk>,
        Christian Brauner <brauner@...nel.org>,
        Vlastimil Babka <vbabka@...e.cz>, linux-fsdevel@...r.kernel.org
Subject: Re: [PATCH v2 2/5] mm: abstract the vma_merge()/split_vma() pattern
 for mprotect() et al.

On Tue, Oct 10, 2023 at 10:14:52PM -0400, Liam R. Howlett wrote:
> * Lorenzo Stoakes <lstoakes@...il.com> [231009 16:53]:
> > mprotect() and other functions which change VMA parameters over a range
> > each employ a pattern of:-
> >
> > 1. Attempt to merge the range with adjacent VMAs.
> > 2. If this fails, and the range spans a subset of the VMA, split it
> >    accordingly.
> >
> > This is open-coded and duplicated in each case. Also in each case most of
> > the parameters passed to vma_merge() remain the same.
> >
> > Create a new function, vma_modify(), which abstracts this operation,
> > accepting only those parameters which can be changed.
> >
> > To avoid the mess of invoking each function call with unnecessary
> > parameters, create inline wrapper functions for each of the modify
> > operations, parameterised only by what is required to perform the action.
> >
> > Note that the userfaultfd_release() case works even though it does not
> > split VMAs - since start is set to vma->vm_start and end is set to
> > vma->vm_end, the split logic does not trigger.
> >
> > In addition, since we calculate pgoff to be equal to vma->vm_pgoff + (start
> > - vma->vm_start) >> PAGE_SHIFT, and start - vma->vm_start will be 0 in this
> > instance, this invocation will remain unchanged.
> >
> > Signed-off-by: Lorenzo Stoakes <lstoakes@...il.com>
> > ---
> >  fs/userfaultfd.c   | 69 +++++++++++++++-------------------------------
> >  include/linux/mm.h | 60 ++++++++++++++++++++++++++++++++++++++++
> >  mm/madvise.c       | 32 ++++++---------------
> >  mm/mempolicy.c     | 22 +++------------
> >  mm/mlock.c         | 27 +++++-------------
> >  mm/mmap.c          | 45 ++++++++++++++++++++++++++++++
> >  mm/mprotect.c      | 35 +++++++----------------
> >  7 files changed, 157 insertions(+), 133 deletions(-)
> >
> > diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
> > index a7c6ef764e63..ba44a67a0a34 100644
> > --- a/fs/userfaultfd.c
> > +++ b/fs/userfaultfd.c
> > @@ -927,11 +927,10 @@ static int userfaultfd_release(struct inode *inode, struct file *file)
> >  			continue;
> >  		}
> >  		new_flags = vma->vm_flags & ~__VM_UFFD_FLAGS;
> > -		prev = vma_merge(&vmi, mm, prev, vma->vm_start, vma->vm_end,
> > -				 new_flags, vma->anon_vma,
> > -				 vma->vm_file, vma->vm_pgoff,
> > -				 vma_policy(vma),
> > -				 NULL_VM_UFFD_CTX, anon_vma_name(vma));
> > +		prev = vma_modify_flags_uffd(&vmi, prev, vma, vma->vm_start,
> > +					     vma->vm_end, new_flags,
> > +					     NULL_VM_UFFD_CTX);
> > +
> >  		if (prev) {
> >  			vma = prev;
> >  		} else {
> > @@ -1331,7 +1330,6 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
> >  	unsigned long start, end, vma_end;
> >  	struct vma_iterator vmi;
> >  	bool wp_async = userfaultfd_wp_async_ctx(ctx);
> > -	pgoff_t pgoff;
> >
> >  	user_uffdio_register = (struct uffdio_register __user *) arg;
> >
> > @@ -1484,28 +1482,17 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
> >  		vma_end = min(end, vma->vm_end);
> >
> >  		new_flags = (vma->vm_flags & ~__VM_UFFD_FLAGS) | vm_flags;
> > -		pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
> > -		prev = vma_merge(&vmi, mm, prev, start, vma_end, new_flags,
> > -				 vma->anon_vma, vma->vm_file, pgoff,
> > -				 vma_policy(vma),
> > -				 ((struct vm_userfaultfd_ctx){ ctx }),
> > -				 anon_vma_name(vma));
> > -		if (prev) {
> > -			/* vma_merge() invalidated the mas */
> > -			vma = prev;
> > -			goto next;
> > -		}
> > -		if (vma->vm_start < start) {
> > -			ret = split_vma(&vmi, vma, start, 1);
> > -			if (ret)
> > -				break;
> > -		}
> > -		if (vma->vm_end > end) {
> > -			ret = split_vma(&vmi, vma, end, 0);
> > -			if (ret)
> > -				break;
> > +		prev = vma_modify_flags_uffd(&vmi, prev, vma, start, vma_end,
> > +					     new_flags,
> > +					     (struct vm_userfaultfd_ctx){ctx});
> > +		if (IS_ERR(prev)) {
> > +			ret = PTR_ERR(prev);
> > +			break;
> >  		}
> > -	next:
> > +
> > +		if (prev)
> > +			vma = prev; /* vma_merge() invalidated the mas */
>
> This is a stale comment.  The maple state is in the vma iterator, which
> is passed through.  I missed this on the vma iterator conversion.

Ack, this was coincidentally removed in v3 so this is already resolved.

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ