All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/5] mremap fix/cleanups
@ 2015-07-01 23:02 Oleg Nesterov
  2015-07-01 23:03 ` [PATCH v2 1/5] mremap: don't leak new_vma if f_op->mremap() fails Oleg Nesterov
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Oleg Nesterov @ 2015-07-01 23:02 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Benjamin LaHaise, David Rientjes, Hugh Dickins, Jeff Moyer,
	Kirill Shutemov, Pavel Emelyanov, linux-kernel

Actually this is resend, not v2. Added the acks I got from David
(thanks!).

2/5 (acked by Pavel and Kirill) was sent separately and ignored
too, I think it fits this series.

(and I think that the recently added arch_remap() hook is not
 the right thing, we can remove it with these changes).

Andrew, should I resend the

	[PATCH 0/3] special_mapping_fault() is broken
	http://marc.info/?l=linux-kernel&m=143492093907585

series too?

Oleg.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 1/5] mremap: don't leak new_vma if f_op->mremap() fails
  2015-07-01 23:02 [PATCH v2 0/5] mremap fix/cleanups Oleg Nesterov
@ 2015-07-01 23:03 ` Oleg Nesterov
  2015-07-01 23:03 ` [PATCH v2 2/5] mm: move ->mremap() from file_operations to vm_operations_struct Oleg Nesterov
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Oleg Nesterov @ 2015-07-01 23:03 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Benjamin LaHaise, David Rientjes, Hugh Dickins, Jeff Moyer,
	Kirill Shutemov, Pavel Emelyanov, linux-kernel

move_vma() can't just return if f_op->mremap() fails, we should
unmap the new vma like we do if move_page_tables() fails. To avoid
the code duplication this patch moves the "move entries back" under
the new "if (err)" branch.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: David Rientjes <rientjes@google.com>
---
 mm/mremap.c |   16 +++++++---------
 1 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/mm/mremap.c b/mm/mremap.c
index a7c93ec..f54a43f 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -276,6 +276,12 @@ static unsigned long move_vma(struct vm_area_struct *vma,
 	moved_len = move_page_tables(vma, old_addr, new_vma, new_addr, old_len,
 				     need_rmap_locks);
 	if (moved_len < old_len) {
+		err = -ENOMEM;
+	} else if (vma->vm_file && vma->vm_file->f_op->mremap) {
+		err = vma->vm_file->f_op->mremap(vma->vm_file, new_vma);
+	}
+
+	if (unlikely(err)) {
 		/*
 		 * On error, move entries back from new area to old,
 		 * which will succeed since page tables still there,
@@ -286,16 +292,8 @@ static unsigned long move_vma(struct vm_area_struct *vma,
 		vma = new_vma;
 		old_len = new_len;
 		old_addr = new_addr;
-		new_addr = -ENOMEM;
+		new_addr = err;
 	} else {
-		if (vma->vm_file && vma->vm_file->f_op->mremap) {
-			err = vma->vm_file->f_op->mremap(vma->vm_file, new_vma);
-			if (err < 0) {
-				move_page_tables(new_vma, new_addr, vma,
-						 old_addr, moved_len, true);
-				return err;
-			}
-		}
 		arch_remap(mm, old_addr, old_addr + old_len,
 			   new_addr, new_addr + new_len);
 	}
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 2/5] mm: move ->mremap() from file_operations to vm_operations_struct
  2015-07-01 23:02 [PATCH v2 0/5] mremap fix/cleanups Oleg Nesterov
  2015-07-01 23:03 ` [PATCH v2 1/5] mremap: don't leak new_vma if f_op->mremap() fails Oleg Nesterov
@ 2015-07-01 23:03 ` Oleg Nesterov
  2015-07-01 23:03 ` [PATCH v2 3/5] mremap: don't do mm_populate(new_addr) on failure Oleg Nesterov
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Oleg Nesterov @ 2015-07-01 23:03 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Benjamin LaHaise, David Rientjes, Hugh Dickins, Jeff Moyer,
	Kirill Shutemov, Pavel Emelyanov, linux-kernel

vma->vm_ops->mremap() looks more natural and clean in move_vma(), and
this way ->mremap() can have more users. Say, vdso.

While at it, s/aio_ring_remap/aio_ring_mremap/.

Note: this is the minimal change before ->mremap() finds another user
in file_operations; this method should have more arguments, and it can
be used to kill arch_remap().

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Pavel Emelyanov <xemul@parallels.com>
Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
---
 fs/aio.c           |   25 ++++++++++++++++---------
 include/linux/fs.h |    1 -
 include/linux/mm.h |    1 +
 mm/mremap.c        |    4 ++--
 4 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/fs/aio.c b/fs/aio.c
index 480440f..c122624 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -308,15 +308,9 @@ static void aio_free_ring(struct kioctx *ctx)
 	}
 }
 
-static int aio_ring_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	vma->vm_flags |= VM_DONTEXPAND;
-	vma->vm_ops = &generic_file_vm_ops;
-	return 0;
-}
-
-static int aio_ring_remap(struct file *file, struct vm_area_struct *vma)
+static int aio_ring_mremap(struct vm_area_struct *vma)
 {
+	struct file *file = vma->vm_file;
 	struct mm_struct *mm = vma->vm_mm;
 	struct kioctx_table *table;
 	int i, res = -EINVAL;
@@ -342,9 +336,22 @@ static int aio_ring_remap(struct file *file, struct vm_area_struct *vma)
 	return res;
 }
 
+static const struct vm_operations_struct aio_ring_vm_ops = {
+	.mremap		= aio_ring_mremap,
+	.fault		= filemap_fault,
+	.map_pages	= filemap_map_pages,
+	.page_mkwrite	= filemap_page_mkwrite,
+};
+
+static int aio_ring_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	vma->vm_flags |= VM_DONTEXPAND;
+	vma->vm_ops = &aio_ring_vm_ops;
+	return 0;
+}
+
 static const struct file_operations aio_ring_fops = {
 	.mmap = aio_ring_mmap,
-	.mremap = aio_ring_remap,
 };
 
 #if IS_ENABLED(CONFIG_MIGRATION)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 35ec87e..42aac09 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1582,7 +1582,6 @@ struct file_operations {
 	long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
 	long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
 	int (*mmap) (struct file *, struct vm_area_struct *);
-	int (*mremap)(struct file *, struct vm_area_struct *);
 	int (*open) (struct inode *, struct file *);
 	int (*flush) (struct file *, fl_owner_t id);
 	int (*release) (struct inode *, struct file *);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 0755b9f..bb51ced 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -244,6 +244,7 @@ struct vm_fault {
 struct vm_operations_struct {
 	void (*open)(struct vm_area_struct * area);
 	void (*close)(struct vm_area_struct * area);
+	int (*mremap)(struct vm_area_struct * area);
 	int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);
 	void (*map_pages)(struct vm_area_struct *vma, struct vm_fault *vmf);
 
diff --git a/mm/mremap.c b/mm/mremap.c
index f54a43f..3310378 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -277,8 +277,8 @@ static unsigned long move_vma(struct vm_area_struct *vma,
 				     need_rmap_locks);
 	if (moved_len < old_len) {
 		err = -ENOMEM;
-	} else if (vma->vm_file && vma->vm_file->f_op->mremap) {
-		err = vma->vm_file->f_op->mremap(vma->vm_file, new_vma);
+	} else if (vma->vm_ops && vma->vm_ops->mremap) {
+		err = vma->vm_ops->mremap(new_vma);
 	}
 
 	if (unlikely(err)) {
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 3/5] mremap: don't do mm_populate(new_addr) on failure
  2015-07-01 23:02 [PATCH v2 0/5] mremap fix/cleanups Oleg Nesterov
  2015-07-01 23:03 ` [PATCH v2 1/5] mremap: don't leak new_vma if f_op->mremap() fails Oleg Nesterov
  2015-07-01 23:03 ` [PATCH v2 2/5] mm: move ->mremap() from file_operations to vm_operations_struct Oleg Nesterov
@ 2015-07-01 23:03 ` Oleg Nesterov
  2015-07-01 23:03 ` [PATCH v2 4/5] mremap: don't do uneccesary checks if new_len == old_len Oleg Nesterov
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Oleg Nesterov @ 2015-07-01 23:03 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Benjamin LaHaise, David Rientjes, Hugh Dickins, Jeff Moyer,
	Kirill Shutemov, Pavel Emelyanov, linux-kernel

move_vma() sets *locked even if move_page_tables() or ->mremap()
fails, change sys_mremap() to check "ret & ~PAGE_MASK".

I think we should simply remove the VM_LOCKED code in move_vma(),
that is why this patch doesn't change move_vma(). But this needs
more cleanups.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: David Rientjes <rientjes@google.com>
---
 mm/mremap.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/mm/mremap.c b/mm/mremap.c
index 3310378..7dcf7b4 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -578,8 +578,10 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
 		ret = move_vma(vma, addr, old_len, new_len, new_addr, &locked);
 	}
 out:
-	if (ret & ~PAGE_MASK)
+	if (ret & ~PAGE_MASK) {
 		vm_unacct_memory(charged);
+		locked = 0;
+	}
 	up_write(&current->mm->mmap_sem);
 	if (locked && new_len > old_len)
 		mm_populate(new_addr + old_len, new_len - old_len);
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 4/5] mremap: don't do uneccesary checks if new_len == old_len
  2015-07-01 23:02 [PATCH v2 0/5] mremap fix/cleanups Oleg Nesterov
                   ` (2 preceding siblings ...)
  2015-07-01 23:03 ` [PATCH v2 3/5] mremap: don't do mm_populate(new_addr) on failure Oleg Nesterov
@ 2015-07-01 23:03 ` Oleg Nesterov
  2015-07-01 23:03 ` [PATCH v2 5/5] mremap: simplify the "overlap" check in mremap_to() Oleg Nesterov
  2015-07-15 23:34 ` [PATCH v2 0/5] mremap fix/cleanups David Rientjes
  5 siblings, 0 replies; 8+ messages in thread
From: Oleg Nesterov @ 2015-07-01 23:03 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Benjamin LaHaise, David Rientjes, Hugh Dickins, Jeff Moyer,
	Kirill Shutemov, Pavel Emelyanov, linux-kernel

The "new_len > old_len" branch in vma_to_resize() looks very confusing.
It only covers the VM_DONTEXPAND/pgoff checks but everything below is
equally unneeded if new_len == old_len.

Change this code to return if "new_len == old_len", new_len < old_len
is not possible, otherwise the code below is wrong anyway.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: David Rientjes <rientjes@google.com>
---
 mm/mremap.c |   21 +++++++++++----------
 1 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/mm/mremap.c b/mm/mremap.c
index 7dcf7b4..d3f42be 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -346,6 +346,7 @@ static struct vm_area_struct *vma_to_resize(unsigned long addr,
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma = find_vma(mm, addr);
+	unsigned long pgoff;
 
 	if (!vma || vma->vm_start > addr)
 		return ERR_PTR(-EFAULT);
@@ -357,17 +358,17 @@ static struct vm_area_struct *vma_to_resize(unsigned long addr,
 	if (old_len > vma->vm_end - addr)
 		return ERR_PTR(-EFAULT);
 
+	if (new_len == old_len)
+		return vma;
+
 	/* Need to be careful about a growing mapping */
-	if (new_len > old_len) {
-		unsigned long pgoff;
-
-		if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP))
-			return ERR_PTR(-EFAULT);
-		pgoff = (addr - vma->vm_start) >> PAGE_SHIFT;
-		pgoff += vma->vm_pgoff;
-		if (pgoff + (new_len >> PAGE_SHIFT) < pgoff)
-			return ERR_PTR(-EINVAL);
-	}
+	pgoff = (addr - vma->vm_start) >> PAGE_SHIFT;
+	pgoff += vma->vm_pgoff;
+	if (pgoff + (new_len >> PAGE_SHIFT) < pgoff)
+		return ERR_PTR(-EINVAL);
+
+	if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP))
+		return ERR_PTR(-EFAULT);
 
 	if (vma->vm_flags & VM_LOCKED) {
 		unsigned long locked, lock_limit;
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 5/5] mremap: simplify the "overlap" check in mremap_to()
  2015-07-01 23:02 [PATCH v2 0/5] mremap fix/cleanups Oleg Nesterov
                   ` (3 preceding siblings ...)
  2015-07-01 23:03 ` [PATCH v2 4/5] mremap: don't do uneccesary checks if new_len == old_len Oleg Nesterov
@ 2015-07-01 23:03 ` Oleg Nesterov
  2015-07-15 23:34 ` [PATCH v2 0/5] mremap fix/cleanups David Rientjes
  5 siblings, 0 replies; 8+ messages in thread
From: Oleg Nesterov @ 2015-07-01 23:03 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Benjamin LaHaise, David Rientjes, Hugh Dickins, Jeff Moyer,
	Kirill Shutemov, Pavel Emelyanov, linux-kernel

Minor, but this check is overcomplicated. Two half-intervals do NOT
overlap if END1 <= START2 || END2 <= START1, mremap_to() just needs
to negate this check.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: David Rientjes <rientjes@google.com>
---
 mm/mremap.c |    9 ++-------
 1 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/mm/mremap.c b/mm/mremap.c
index d3f42be..5a71cce 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -407,13 +407,8 @@ static unsigned long mremap_to(unsigned long addr, unsigned long old_len,
 	if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len)
 		goto out;
 
-	/* Check if the location we're moving into overlaps the
-	 * old location at all, and fail if it does.
-	 */
-	if ((new_addr <= addr) && (new_addr+new_len) > addr)
-		goto out;
-
-	if ((addr <= new_addr) && (addr+old_len) > new_addr)
+	/* Ensure the old/new locations do not overlap */
+	if (addr + old_len > new_addr && new_addr + new_len > addr)
 		goto out;
 
 	ret = do_munmap(mm, new_addr, new_len);
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 0/5] mremap fix/cleanups
  2015-07-01 23:02 [PATCH v2 0/5] mremap fix/cleanups Oleg Nesterov
                   ` (4 preceding siblings ...)
  2015-07-01 23:03 ` [PATCH v2 5/5] mremap: simplify the "overlap" check in mremap_to() Oleg Nesterov
@ 2015-07-15 23:34 ` David Rientjes
  2015-07-15 23:46   ` Andrew Morton
  5 siblings, 1 reply; 8+ messages in thread
From: David Rientjes @ 2015-07-15 23:34 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Andrew Morton, Benjamin LaHaise, Hugh Dickins, Jeff Moyer,
	Kirill Shutemov, Pavel Emelyanov, linux-kernel

On Thu, 2 Jul 2015, Oleg Nesterov wrote:

> Actually this is resend, not v2. Added the acks I got from David
> (thanks!).
> 
> 2/5 (acked by Pavel and Kirill) was sent separately and ignored
> too, I think it fits this series.
> 
> (and I think that the recently added arch_remap() hook is not
>  the right thing, we can remove it with these changes).
> 

This series applies cleanly to next-20150715 and has acks, was it deferred 
for some reason?

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 0/5] mremap fix/cleanups
  2015-07-15 23:34 ` [PATCH v2 0/5] mremap fix/cleanups David Rientjes
@ 2015-07-15 23:46   ` Andrew Morton
  0 siblings, 0 replies; 8+ messages in thread
From: Andrew Morton @ 2015-07-15 23:46 UTC (permalink / raw)
  To: David Rientjes
  Cc: Oleg Nesterov, Benjamin LaHaise, Hugh Dickins, Jeff Moyer,
	Kirill Shutemov, Pavel Emelyanov, linux-kernel

On Wed, 15 Jul 2015 16:34:35 -0700 (PDT) David Rientjes <rientjes@google.com> wrote:

> On Thu, 2 Jul 2015, Oleg Nesterov wrote:
> 
> > Actually this is resend, not v2. Added the acks I got from David
> > (thanks!).
> > 
> > 2/5 (acked by Pavel and Kirill) was sent separately and ignored
> > too, I think it fits this series.
> > 
> > (and I think that the recently added arch_remap() hook is not
> >  the right thing, we can remove it with these changes).
> > 
> 
> This series applies cleanly to next-20150715 and has acks, was it deferred 
> for some reason?

I applied

mremap-dont-leak-new_vma-if-f_op-mremap-fails.patch
mm-move-mremap-from-file_operations-to-vm_operations_struct.patch
mremap-dont-do-mm_populatenew_addr-on-failure.patch
mremap-dont-do-uneccesary-checks-if-new_len-==-old_len.patch
mremap-simplify-the-overlap-check-in-mremap_to.patch

Check spam folder ;)

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2015-07-15 23:46 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-01 23:02 [PATCH v2 0/5] mremap fix/cleanups Oleg Nesterov
2015-07-01 23:03 ` [PATCH v2 1/5] mremap: don't leak new_vma if f_op->mremap() fails Oleg Nesterov
2015-07-01 23:03 ` [PATCH v2 2/5] mm: move ->mremap() from file_operations to vm_operations_struct Oleg Nesterov
2015-07-01 23:03 ` [PATCH v2 3/5] mremap: don't do mm_populate(new_addr) on failure Oleg Nesterov
2015-07-01 23:03 ` [PATCH v2 4/5] mremap: don't do uneccesary checks if new_len == old_len Oleg Nesterov
2015-07-01 23:03 ` [PATCH v2 5/5] mremap: simplify the "overlap" check in mremap_to() Oleg Nesterov
2015-07-15 23:34 ` [PATCH v2 0/5] mremap fix/cleanups David Rientjes
2015-07-15 23:46   ` Andrew Morton

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.