All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] mm: audit find_vma() callers
@ 2014-04-20  2:26 ` Davidlohr Bueso
  0 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-20  2:26 UTC (permalink / raw)
  To: akpm; +Cc: zeus, aswin, davidlohr, linux-mm, linux-kernel

Ensure find_vma() callers do so with the mmap_sem held. 

I'm sure there are a few more places left to fix, but 
this is a pretty good start. Following the call chain,
some users become all tangled up, but I believe these
fixes are correct. Furthermore, the bulk of the callers
of find_vma are in a lot of functions where it is well
known that the mmap_sem is taken way before, such as
get_unmapped_area() family.

Please note that none of the patches are tested.

Thanks!

  blackfin/ptrace: call find_vma with the mmap_sem held
  m68k: call find_vma with the mmap_sem held in sys_cacheflush()
  mips: call find_vma with the mmap_sem held
  arc: call find_vma with the mmap_sem held
  drivers/misc/sgi-gru/grufault.c: call find_vma with the mmap_sem held
  drm/exynos: call find_vma with the mmap_sem held

 arch/arc/kernel/troubleshoot.c          |  7 ++++---
 arch/blackfin/kernel/ptrace.c           |  8 ++++++--
 arch/m68k/kernel/sys_m68k.c             | 18 ++++++++++++------
 arch/mips/kernel/traps.c                |  2 ++
 arch/mips/mm/c-octeon.c                 |  2 ++
 drivers/gpu/drm/exynos/exynos_drm_g2d.c |  6 ++++++
 drivers/misc/sgi-gru/grufault.c         | 13 +++++++++----
 7 files changed, 41 insertions(+), 15 deletions(-)

-- 
1.8.1.4


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

* [PATCH 0/6] mm: audit find_vma() callers
@ 2014-04-20  2:26 ` Davidlohr Bueso
  0 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-20  2:26 UTC (permalink / raw)
  To: akpm; +Cc: zeus, aswin, davidlohr, linux-mm, linux-kernel

Ensure find_vma() callers do so with the mmap_sem held. 

I'm sure there are a few more places left to fix, but 
this is a pretty good start. Following the call chain,
some users become all tangled up, but I believe these
fixes are correct. Furthermore, the bulk of the callers
of find_vma are in a lot of functions where it is well
known that the mmap_sem is taken way before, such as
get_unmapped_area() family.

Please note that none of the patches are tested.

Thanks!

  blackfin/ptrace: call find_vma with the mmap_sem held
  m68k: call find_vma with the mmap_sem held in sys_cacheflush()
  mips: call find_vma with the mmap_sem held
  arc: call find_vma with the mmap_sem held
  drivers/misc/sgi-gru/grufault.c: call find_vma with the mmap_sem held
  drm/exynos: call find_vma with the mmap_sem held

 arch/arc/kernel/troubleshoot.c          |  7 ++++---
 arch/blackfin/kernel/ptrace.c           |  8 ++++++--
 arch/m68k/kernel/sys_m68k.c             | 18 ++++++++++++------
 arch/mips/kernel/traps.c                |  2 ++
 arch/mips/mm/c-octeon.c                 |  2 ++
 drivers/gpu/drm/exynos/exynos_drm_g2d.c |  6 ++++++
 drivers/misc/sgi-gru/grufault.c         | 13 +++++++++----
 7 files changed, 41 insertions(+), 15 deletions(-)

-- 
1.8.1.4

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* [PATCH 1/6] blackfin/ptrace: call find_vma with the mmap_sem held
  2014-04-20  2:26 ` Davidlohr Bueso
@ 2014-04-20  2:26   ` Davidlohr Bueso
  -1 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-20  2:26 UTC (permalink / raw)
  To: akpm
  Cc: zeus, aswin, davidlohr, linux-mm, linux-kernel, Steven Miao,
	adi-buildroot-devel

Performing vma lookups without taking the mm->mmap_sem is asking
for trouble. While doing the search, the vma in question can be
modified or even removed before returning to the caller. Take the
lock (shared) in order to avoid races while iterating through the
vmacache and/or rbtree.

This patch is completely *untested*.

Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
Cc: Steven Miao <realmz6@gmail.com>
Cc: adi-buildroot-devel@lists.sourceforge.net
---
 arch/blackfin/kernel/ptrace.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index e1f88e0..8b8fe67 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -117,6 +117,7 @@ put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
 int
 is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long len)
 {
+	bool valid;
 	struct vm_area_struct *vma;
 	struct sram_list_struct *sraml;
 
@@ -124,9 +125,12 @@ is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long
 	if (start + len < start)
 		return -EIO;
 
+	down_read(&child->mm->mmap_sem);
 	vma = find_vma(child->mm, start);
-	if (vma && start >= vma->vm_start && start + len <= vma->vm_end)
-			return 0;
+	valid = vma && start >= vma->vm_start && start + len <= vma->vm_end;
+	up_read(&child->mm->mmap_sem);
+	if (valid)
+		return 0;
 
 	for (sraml = child->mm->context.sram_list; sraml; sraml = sraml->next)
 		if (start >= (unsigned long)sraml->addr
-- 
1.8.1.4


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

* [PATCH 1/6] blackfin/ptrace: call find_vma with the mmap_sem held
@ 2014-04-20  2:26   ` Davidlohr Bueso
  0 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-20  2:26 UTC (permalink / raw)
  To: akpm
  Cc: zeus, aswin, davidlohr, linux-mm, linux-kernel, Steven Miao,
	adi-buildroot-devel

Performing vma lookups without taking the mm->mmap_sem is asking
for trouble. While doing the search, the vma in question can be
modified or even removed before returning to the caller. Take the
lock (shared) in order to avoid races while iterating through the
vmacache and/or rbtree.

This patch is completely *untested*.

Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
Cc: Steven Miao <realmz6@gmail.com>
Cc: adi-buildroot-devel@lists.sourceforge.net
---
 arch/blackfin/kernel/ptrace.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index e1f88e0..8b8fe67 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -117,6 +117,7 @@ put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
 int
 is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long len)
 {
+	bool valid;
 	struct vm_area_struct *vma;
 	struct sram_list_struct *sraml;
 
@@ -124,9 +125,12 @@ is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long
 	if (start + len < start)
 		return -EIO;
 
+	down_read(&child->mm->mmap_sem);
 	vma = find_vma(child->mm, start);
-	if (vma && start >= vma->vm_start && start + len <= vma->vm_end)
-			return 0;
+	valid = vma && start >= vma->vm_start && start + len <= vma->vm_end;
+	up_read(&child->mm->mmap_sem);
+	if (valid)
+		return 0;
 
 	for (sraml = child->mm->context.sram_list; sraml; sraml = sraml->next)
 		if (start >= (unsigned long)sraml->addr
-- 
1.8.1.4

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* [PATCH 2/6] m68k: call find_vma with the mmap_sem held in sys_cacheflush()
  2014-04-20  2:26 ` Davidlohr Bueso
@ 2014-04-20  2:26   ` Davidlohr Bueso
  -1 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-20  2:26 UTC (permalink / raw)
  To: akpm
  Cc: zeus, aswin, davidlohr, linux-mm, linux-kernel,
	Geert Uytterhoeven, linux-m68k

Performing vma lookups without taking the mm->mmap_sem is asking
for trouble. While doing the search, the vma in question can be
modified or even removed before returning to the caller. Take the
lock (shared) in order to avoid races while iterating through
the vmacache and/or rbtree.

This patch is completely *untested*.

Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: linux-m68k@lists.linux-m68k.org
---
 arch/m68k/kernel/sys_m68k.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 3a480b3..d2263a0 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
 asmlinkage int
 sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 {
-	struct vm_area_struct *vma;
 	int ret = -EINVAL;
 
 	if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
@@ -389,16 +388,23 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 		if (!capable(CAP_SYS_ADMIN))
 			goto out;
 	} else {
+		struct vm_area_struct *vma;
+		bool invalid;
+
+		/* Check for overflow.  */
+		if (addr + len < addr)
+			goto out;
+
 		/*
 		 * Verify that the specified address region actually belongs
 		 * to this process.
 		 */
-		vma = find_vma (current->mm, addr);
 		ret = -EINVAL;
-		/* Check for overflow.  */
-		if (addr + len < addr)
-			goto out;
-		if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
+		down_read(&current->mm->mmap_sem);
+		vma = find_vma(current->mm, addr);
+		invalid = !vma || addr < vma->vm_start || addr + len > vma->vm_end;
+		up_read(&current->mm->mmap_sem);
+		if (invalid)
 			goto out;
 	}
 
-- 
1.8.1.4


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

* [PATCH 2/6] m68k: call find_vma with the mmap_sem held in sys_cacheflush()
  2014-04-20  2:26 ` Davidlohr Bueso
                   ` (2 preceding siblings ...)
  (?)
@ 2014-04-20  2:26 ` Davidlohr Bueso
  -1 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-20  2:26 UTC (permalink / raw)
  To: akpm
  Cc: zeus, aswin, davidlohr, linux-mm, linux-kernel,
	Geert Uytterhoeven, linux-m68k

Performing vma lookups without taking the mm->mmap_sem is asking
for trouble. While doing the search, the vma in question can be
modified or even removed before returning to the caller. Take the
lock (shared) in order to avoid races while iterating through
the vmacache and/or rbtree.

This patch is completely *untested*.

Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: linux-m68k@lists.linux-m68k.org
---
 arch/m68k/kernel/sys_m68k.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 3a480b3..d2263a0 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
 asmlinkage int
 sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 {
-	struct vm_area_struct *vma;
 	int ret = -EINVAL;
 
 	if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
@@ -389,16 +388,23 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 		if (!capable(CAP_SYS_ADMIN))
 			goto out;
 	} else {
+		struct vm_area_struct *vma;
+		bool invalid;
+
+		/* Check for overflow.  */
+		if (addr + len < addr)
+			goto out;
+
 		/*
 		 * Verify that the specified address region actually belongs
 		 * to this process.
 		 */
-		vma = find_vma (current->mm, addr);
 		ret = -EINVAL;
-		/* Check for overflow.  */
-		if (addr + len < addr)
-			goto out;
-		if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
+		down_read(&current->mm->mmap_sem);
+		vma = find_vma(current->mm, addr);
+		invalid = !vma || addr < vma->vm_start || addr + len > vma->vm_end;
+		up_read(&current->mm->mmap_sem);
+		if (invalid)
 			goto out;
 	}
 
-- 
1.8.1.4

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

* [PATCH 2/6] m68k: call find_vma with the mmap_sem held in sys_cacheflush()
@ 2014-04-20  2:26   ` Davidlohr Bueso
  0 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-20  2:26 UTC (permalink / raw)
  To: akpm
  Cc: zeus, aswin, davidlohr, linux-mm, linux-kernel,
	Geert Uytterhoeven, linux-m68k

Performing vma lookups without taking the mm->mmap_sem is asking
for trouble. While doing the search, the vma in question can be
modified or even removed before returning to the caller. Take the
lock (shared) in order to avoid races while iterating through
the vmacache and/or rbtree.

This patch is completely *untested*.

Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: linux-m68k@lists.linux-m68k.org
---
 arch/m68k/kernel/sys_m68k.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 3a480b3..d2263a0 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
 asmlinkage int
 sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 {
-	struct vm_area_struct *vma;
 	int ret = -EINVAL;
 
 	if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
@@ -389,16 +388,23 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 		if (!capable(CAP_SYS_ADMIN))
 			goto out;
 	} else {
+		struct vm_area_struct *vma;
+		bool invalid;
+
+		/* Check for overflow.  */
+		if (addr + len < addr)
+			goto out;
+
 		/*
 		 * Verify that the specified address region actually belongs
 		 * to this process.
 		 */
-		vma = find_vma (current->mm, addr);
 		ret = -EINVAL;
-		/* Check for overflow.  */
-		if (addr + len < addr)
-			goto out;
-		if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
+		down_read(&current->mm->mmap_sem);
+		vma = find_vma(current->mm, addr);
+		invalid = !vma || addr < vma->vm_start || addr + len > vma->vm_end;
+		up_read(&current->mm->mmap_sem);
+		if (invalid)
 			goto out;
 	}
 
-- 
1.8.1.4

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* [PATCH 3/6] mips: call find_vma with the mmap_sem held
  2014-04-20  2:26 ` Davidlohr Bueso
@ 2014-04-20  2:26   ` Davidlohr Bueso
  -1 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-20  2:26 UTC (permalink / raw)
  To: akpm
  Cc: zeus, aswin, davidlohr, linux-mm, linux-kernel, Ralf Baechle, linux-mips

Performing vma lookups without taking the mm->mmap_sem is asking
for trouble. While doing the search, the vma in question can be
modified or even removed before returning to the caller. Take the
lock (exclusively) in order to avoid races while iterating through
the vmacache and/or rbtree.

Updates two functions:
  - process_fpemu_return()
  - cteon_flush_cache_sigtramp()

This patch is completely *untested*.

Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
---
 arch/mips/kernel/traps.c | 2 ++
 arch/mips/mm/c-octeon.c  | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 074e857..c51bd20 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -712,10 +712,12 @@ int process_fpemu_return(int sig, void __user *fault_addr)
 		si.si_addr = fault_addr;
 		si.si_signo = sig;
 		if (sig == SIGSEGV) {
+			down_read(&current->mm->mmap_sem);
 			if (find_vma(current->mm, (unsigned long)fault_addr))
 				si.si_code = SEGV_ACCERR;
 			else
 				si.si_code = SEGV_MAPERR;
+			up_read(&current->mm->mmap_sem);
 		} else {
 			si.si_code = BUS_ADRERR;
 		}
diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c
index f41a5c5..05b1d7c 100644
--- a/arch/mips/mm/c-octeon.c
+++ b/arch/mips/mm/c-octeon.c
@@ -137,8 +137,10 @@ static void octeon_flush_cache_sigtramp(unsigned long addr)
 {
 	struct vm_area_struct *vma;
 
+	down_read(&current->mm->mmap_sem);
 	vma = find_vma(current->mm, addr);
 	octeon_flush_icache_all_cores(vma);
+	up_read(&current->mm->mmap_sem);
 }
 
 
-- 
1.8.1.4


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

* [PATCH 3/6] mips: call find_vma with the mmap_sem held
@ 2014-04-20  2:26   ` Davidlohr Bueso
  0 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-20  2:26 UTC (permalink / raw)
  To: akpm
  Cc: zeus, aswin, davidlohr, linux-mm, linux-kernel, Ralf Baechle, linux-mips

Performing vma lookups without taking the mm->mmap_sem is asking
for trouble. While doing the search, the vma in question can be
modified or even removed before returning to the caller. Take the
lock (exclusively) in order to avoid races while iterating through
the vmacache and/or rbtree.

Updates two functions:
  - process_fpemu_return()
  - cteon_flush_cache_sigtramp()

This patch is completely *untested*.

Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
---
 arch/mips/kernel/traps.c | 2 ++
 arch/mips/mm/c-octeon.c  | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 074e857..c51bd20 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -712,10 +712,12 @@ int process_fpemu_return(int sig, void __user *fault_addr)
 		si.si_addr = fault_addr;
 		si.si_signo = sig;
 		if (sig == SIGSEGV) {
+			down_read(&current->mm->mmap_sem);
 			if (find_vma(current->mm, (unsigned long)fault_addr))
 				si.si_code = SEGV_ACCERR;
 			else
 				si.si_code = SEGV_MAPERR;
+			up_read(&current->mm->mmap_sem);
 		} else {
 			si.si_code = BUS_ADRERR;
 		}
diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c
index f41a5c5..05b1d7c 100644
--- a/arch/mips/mm/c-octeon.c
+++ b/arch/mips/mm/c-octeon.c
@@ -137,8 +137,10 @@ static void octeon_flush_cache_sigtramp(unsigned long addr)
 {
 	struct vm_area_struct *vma;
 
+	down_read(&current->mm->mmap_sem);
 	vma = find_vma(current->mm, addr);
 	octeon_flush_icache_all_cores(vma);
+	up_read(&current->mm->mmap_sem);
 }
 
 
-- 
1.8.1.4

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* [PATCH 4/6] arc: call find_vma with the mmap_sem held
  2014-04-20  2:26 ` Davidlohr Bueso
@ 2014-04-20  2:26   ` Davidlohr Bueso
  -1 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-20  2:26 UTC (permalink / raw)
  To: akpm; +Cc: zeus, aswin, davidlohr, linux-mm, linux-kernel, Vineet Gupta

Performing vma lookups without taking the mm->mmap_sem is asking
for trouble. While doing the search, the vma in question can be
modified or even removed before returning to the caller. Take the
lock (shared) in order to avoid races while iterating through
the vmacache and/or rbtree.

This patch is completely *untested*.

Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
Cc: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/kernel/troubleshoot.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c
index 73a7450..3a5a5c1 100644
--- a/arch/arc/kernel/troubleshoot.c
+++ b/arch/arc/kernel/troubleshoot.c
@@ -90,7 +90,7 @@ static void show_faulting_vma(unsigned long address, char *buf)
 	/* can't use print_vma_addr() yet as it doesn't check for
 	 * non-inclusive vma
 	 */
-
+	down_read(&current->active_mm->mmap_sem);
 	vma = find_vma(current->active_mm, address);
 
 	/* check against the find_vma( ) behaviour which returns the next VMA
@@ -110,9 +110,10 @@ static void show_faulting_vma(unsigned long address, char *buf)
 			vma->vm_start < TASK_UNMAPPED_BASE ?
 				address : address - vma->vm_start,
 			nm, vma->vm_start, vma->vm_end);
-	} else {
+	} else
 		pr_info("    @No matching VMA found\n");
-	}
+
+	up_read(&current->active_mm->mmap_sem);
 }
 
 static void show_ecr_verbose(struct pt_regs *regs)
-- 
1.8.1.4


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

* [PATCH 4/6] arc: call find_vma with the mmap_sem held
@ 2014-04-20  2:26   ` Davidlohr Bueso
  0 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-20  2:26 UTC (permalink / raw)
  To: akpm; +Cc: zeus, aswin, davidlohr, linux-mm, linux-kernel, Vineet Gupta

Performing vma lookups without taking the mm->mmap_sem is asking
for trouble. While doing the search, the vma in question can be
modified or even removed before returning to the caller. Take the
lock (shared) in order to avoid races while iterating through
the vmacache and/or rbtree.

This patch is completely *untested*.

Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
Cc: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/kernel/troubleshoot.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c
index 73a7450..3a5a5c1 100644
--- a/arch/arc/kernel/troubleshoot.c
+++ b/arch/arc/kernel/troubleshoot.c
@@ -90,7 +90,7 @@ static void show_faulting_vma(unsigned long address, char *buf)
 	/* can't use print_vma_addr() yet as it doesn't check for
 	 * non-inclusive vma
 	 */
-
+	down_read(&current->active_mm->mmap_sem);
 	vma = find_vma(current->active_mm, address);
 
 	/* check against the find_vma( ) behaviour which returns the next VMA
@@ -110,9 +110,10 @@ static void show_faulting_vma(unsigned long address, char *buf)
 			vma->vm_start < TASK_UNMAPPED_BASE ?
 				address : address - vma->vm_start,
 			nm, vma->vm_start, vma->vm_end);
-	} else {
+	} else
 		pr_info("    @No matching VMA found\n");
-	}
+
+	up_read(&current->active_mm->mmap_sem);
 }
 
 static void show_ecr_verbose(struct pt_regs *regs)
-- 
1.8.1.4

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* [PATCH 5/6] drivers,sgi-gru/grufault.c: call find_vma with the mmap_sem held
  2014-04-20  2:26 ` Davidlohr Bueso
@ 2014-04-20  2:26   ` Davidlohr Bueso
  -1 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-20  2:26 UTC (permalink / raw)
  To: akpm
  Cc: zeus, aswin, davidlohr, linux-mm, linux-kernel, Dimitri,
	Sivanich <sivanich

From: Jonathan Gonzalez V <zeus@gnu.org>

Performing vma lookups without taking the mm->mmap_sem is asking
for trouble. While doing the search, the vma in question can
be modified or even removed before returning to the caller.
Take the lock in order to avoid races while iterating through
the vmacache and/or rbtree.

This patch is completely *untested*.

Signed-off-by: Jonathan Gonzalez V <zeus@gnu.org>
Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
Cc: Dimitri Sivanich <sivanich@sgi.com
---
 drivers/misc/sgi-gru/grufault.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c
index f74fc0c..15adc84 100644
--- a/drivers/misc/sgi-gru/grufault.c
+++ b/drivers/misc/sgi-gru/grufault.c
@@ -266,6 +266,7 @@ static int gru_vtop(struct gru_thread_state *gts, unsigned long vaddr,
 	unsigned long paddr;
 	int ret, ps;
 
+	down_write(&mm->mmap_sem);
 	vma = find_vma(mm, vaddr);
 	if (!vma)
 		goto inval;
@@ -277,22 +278,26 @@ static int gru_vtop(struct gru_thread_state *gts, unsigned long vaddr,
 	rmb();	/* Must/check ms_range_active before loading PTEs */
 	ret = atomic_pte_lookup(vma, vaddr, write, &paddr, &ps);
 	if (ret) {
-		if (atomic)
-			goto upm;
+		if (atomic) {
+			up_write(&mm->mmap_sem);
+			return VTOP_RETRY;
+		}
 		if (non_atomic_pte_lookup(vma, vaddr, write, &paddr, &ps))
 			goto inval;
 	}
 	if (is_gru_paddr(paddr))
 		goto inval;
+
+	up_write(&mm->mmap_sem);
+
 	paddr = paddr & ~((1UL << ps) - 1);
 	*gpa = uv_soc_phys_ram_to_gpa(paddr);
 	*pageshift = ps;
 	return VTOP_SUCCESS;
 
 inval:
+	up_write(&mm->mmap_sem);
 	return VTOP_INVALID;
-upm:
-	return VTOP_RETRY;
 }
 
 
-- 
1.8.1.4


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

* [PATCH 5/6] drivers,sgi-gru/grufault.c: call find_vma with the mmap_sem held
@ 2014-04-20  2:26   ` Davidlohr Bueso
  0 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-20  2:26 UTC (permalink / raw)
  To: akpm
  Cc: zeus, aswin, davidlohr, linux-mm, linux-kernel, Dimitri,
	Sivanich <sivanich

From: Jonathan Gonzalez V <zeus@gnu.org>

Performing vma lookups without taking the mm->mmap_sem is asking
for trouble. While doing the search, the vma in question can
be modified or even removed before returning to the caller.
Take the lock in order to avoid races while iterating through
the vmacache and/or rbtree.

This patch is completely *untested*.

Signed-off-by: Jonathan Gonzalez V <zeus@gnu.org>
Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
Cc: Dimitri Sivanich <sivanich@sgi.com
---
 drivers/misc/sgi-gru/grufault.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c
index f74fc0c..15adc84 100644
--- a/drivers/misc/sgi-gru/grufault.c
+++ b/drivers/misc/sgi-gru/grufault.c
@@ -266,6 +266,7 @@ static int gru_vtop(struct gru_thread_state *gts, unsigned long vaddr,
 	unsigned long paddr;
 	int ret, ps;
 
+	down_write(&mm->mmap_sem);
 	vma = find_vma(mm, vaddr);
 	if (!vma)
 		goto inval;
@@ -277,22 +278,26 @@ static int gru_vtop(struct gru_thread_state *gts, unsigned long vaddr,
 	rmb();	/* Must/check ms_range_active before loading PTEs */
 	ret = atomic_pte_lookup(vma, vaddr, write, &paddr, &ps);
 	if (ret) {
-		if (atomic)
-			goto upm;
+		if (atomic) {
+			up_write(&mm->mmap_sem);
+			return VTOP_RETRY;
+		}
 		if (non_atomic_pte_lookup(vma, vaddr, write, &paddr, &ps))
 			goto inval;
 	}
 	if (is_gru_paddr(paddr))
 		goto inval;
+
+	up_write(&mm->mmap_sem);
+
 	paddr = paddr & ~((1UL << ps) - 1);
 	*gpa = uv_soc_phys_ram_to_gpa(paddr);
 	*pageshift = ps;
 	return VTOP_SUCCESS;
 
 inval:
+	up_write(&mm->mmap_sem);
 	return VTOP_INVALID;
-upm:
-	return VTOP_RETRY;
 }
 
 
-- 
1.8.1.4

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* [PATCH 6/6] drm/exynos: call find_vma with the mmap_sem held
  2014-04-20  2:26 ` Davidlohr Bueso
@ 2014-04-20  2:26   ` Davidlohr Bueso
  -1 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-20  2:26 UTC (permalink / raw)
  To: akpm
  Cc: zeus, aswin, davidlohr, linux-mm, linux-kernel, Inki Dae,
	Joonyoung Shim, David Airlie, dri-devel, linux-samsung-soc

From: Jonathan Gonzalez V <zeus@gnu.org>

Performing vma lookups without taking the mm->mmap_sem is asking
for trouble. While doing the search, the vma in question can be
modified or even removed before returning to the caller. Take the
lock (exclusively) in order to avoid races while iterating through
the vmacache and/or rbtree.

This patch is completely *untested*.

Signed-off-by: Jonathan Gonzalez V <zeus@gnu.org>
Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
Cc: Inki Dae <inki.dae@samsung.com>
Cc: Joonyoung Shim <jy0922.shim@samsung.com>
Cc: David Airlie <airlied@linux.ie>
Cc: dri-devel@lists.freedesktop.org
Cc: linux-samsung-soc@vger.kernel.org
---
 drivers/gpu/drm/exynos/exynos_drm_g2d.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 6c1885e..8001587 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -467,14 +467,17 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
 		goto err_free;
 	}
 
+	down_read(&current->mm->mmap_sem);
 	vma = find_vma(current->mm, userptr);
 	if (!vma) {
+		up_read(&current->mm->mmap_sem);
 		DRM_ERROR("failed to get vm region.\n");
 		ret = -EFAULT;
 		goto err_free_pages;
 	}
 
 	if (vma->vm_end < userptr + size) {
+		up_read(&current->mm->mmap_sem);
 		DRM_ERROR("vma is too small.\n");
 		ret = -EFAULT;
 		goto err_free_pages;
@@ -482,6 +485,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
 
 	g2d_userptr->vma = exynos_gem_get_vma(vma);
 	if (!g2d_userptr->vma) {
+		up_read(&current->mm->mmap_sem);
 		DRM_ERROR("failed to copy vma.\n");
 		ret = -ENOMEM;
 		goto err_free_pages;
@@ -492,10 +496,12 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
 	ret = exynos_gem_get_pages_from_userptr(start & PAGE_MASK,
 						npages, pages, vma);
 	if (ret < 0) {
+		up_read(&current->mm->mmap_sem);
 		DRM_ERROR("failed to get user pages from userptr.\n");
 		goto err_put_vma;
 	}
 
+	up_read(&current->mm->mmap_sem);
 	g2d_userptr->pages = pages;
 
 	sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
-- 
1.8.1.4


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

* [PATCH 6/6] drm/exynos: call find_vma with the mmap_sem held
@ 2014-04-20  2:26   ` Davidlohr Bueso
  0 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-20  2:26 UTC (permalink / raw)
  To: akpm
  Cc: zeus, aswin, davidlohr, linux-mm, linux-kernel, Inki Dae,
	Joonyoung Shim, David Airlie, dri-devel, linux-samsung-soc

From: Jonathan Gonzalez V <zeus@gnu.org>

Performing vma lookups without taking the mm->mmap_sem is asking
for trouble. While doing the search, the vma in question can be
modified or even removed before returning to the caller. Take the
lock (exclusively) in order to avoid races while iterating through
the vmacache and/or rbtree.

This patch is completely *untested*.

Signed-off-by: Jonathan Gonzalez V <zeus@gnu.org>
Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
Cc: Inki Dae <inki.dae@samsung.com>
Cc: Joonyoung Shim <jy0922.shim@samsung.com>
Cc: David Airlie <airlied@linux.ie>
Cc: dri-devel@lists.freedesktop.org
Cc: linux-samsung-soc@vger.kernel.org
---
 drivers/gpu/drm/exynos/exynos_drm_g2d.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 6c1885e..8001587 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -467,14 +467,17 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
 		goto err_free;
 	}
 
+	down_read(&current->mm->mmap_sem);
 	vma = find_vma(current->mm, userptr);
 	if (!vma) {
+		up_read(&current->mm->mmap_sem);
 		DRM_ERROR("failed to get vm region.\n");
 		ret = -EFAULT;
 		goto err_free_pages;
 	}
 
 	if (vma->vm_end < userptr + size) {
+		up_read(&current->mm->mmap_sem);
 		DRM_ERROR("vma is too small.\n");
 		ret = -EFAULT;
 		goto err_free_pages;
@@ -482,6 +485,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
 
 	g2d_userptr->vma = exynos_gem_get_vma(vma);
 	if (!g2d_userptr->vma) {
+		up_read(&current->mm->mmap_sem);
 		DRM_ERROR("failed to copy vma.\n");
 		ret = -ENOMEM;
 		goto err_free_pages;
@@ -492,10 +496,12 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
 	ret = exynos_gem_get_pages_from_userptr(start & PAGE_MASK,
 						npages, pages, vma);
 	if (ret < 0) {
+		up_read(&current->mm->mmap_sem);
 		DRM_ERROR("failed to get user pages from userptr.\n");
 		goto err_put_vma;
 	}
 
+	up_read(&current->mm->mmap_sem);
 	g2d_userptr->pages = pages;
 
 	sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
-- 
1.8.1.4

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* Re: [PATCH 2/6] m68k: call find_vma with the mmap_sem held in sys_cacheflush()
  2014-04-20  2:26   ` Davidlohr Bueso
@ 2014-04-20  8:04     ` Geert Uytterhoeven
  -1 siblings, 0 replies; 40+ messages in thread
From: Geert Uytterhoeven @ 2014-04-20  8:04 UTC (permalink / raw)
  To: Davidlohr Bueso
  Cc: Andrew Morton, zeus, Aswin Chandramouleeswaran, Linux MM,
	linux-kernel, linux-m68k

Hi David,

On Sun, Apr 20, 2014 at 4:26 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
> Performing vma lookups without taking the mm->mmap_sem is asking
> for trouble. While doing the search, the vma in question can be
> modified or even removed before returning to the caller. Take the
> lock (shared) in order to avoid races while iterating through
> the vmacache and/or rbtree.

Thanks for your patch!

> This patch is completely *untested*.
>
> Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> Cc: Geert Uytterhoeven <geert@linux-m68k.org>
> Cc: linux-m68k@lists.linux-m68k.org
> ---
>  arch/m68k/kernel/sys_m68k.c | 18 ++++++++++++------
>  1 file changed, 12 insertions(+), 6 deletions(-)
>
> diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
> index 3a480b3..d2263a0 100644
> --- a/arch/m68k/kernel/sys_m68k.c
> +++ b/arch/m68k/kernel/sys_m68k.c
> @@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
>  asmlinkage int
>  sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
>  {
> -       struct vm_area_struct *vma;
>         int ret = -EINVAL;
>
>         if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
> @@ -389,16 +388,23 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
>                 if (!capable(CAP_SYS_ADMIN))
>                         goto out;
>         } else {
> +               struct vm_area_struct *vma;
> +               bool invalid;
> +
> +               /* Check for overflow.  */
> +               if (addr + len < addr)
> +                       goto out;
> +
>                 /*
>                  * Verify that the specified address region actually belongs
>                  * to this process.
>                  */
> -               vma = find_vma (current->mm, addr);
>                 ret = -EINVAL;
> -               /* Check for overflow.  */
> -               if (addr + len < addr)
> -                       goto out;
> -               if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
> +               down_read(&current->mm->mmap_sem);
> +               vma = find_vma(current->mm, addr);
> +               invalid = !vma || addr < vma->vm_start || addr + len > vma->vm_end;
> +               up_read(&current->mm->mmap_sem);
> +               if (invalid)
>                         goto out;
>         }

Shouldn't the up_read() be moved to the end of the function?
The vma may still be modified or destroyed between the call to find_vma(),
and the actual cache flush?

Am I missing something?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 2/6] m68k: call find_vma with the mmap_sem held in sys_cacheflush()
  2014-04-20  2:26   ` Davidlohr Bueso
  (?)
@ 2014-04-20  8:04   ` Geert Uytterhoeven
  -1 siblings, 0 replies; 40+ messages in thread
From: Geert Uytterhoeven @ 2014-04-20  8:04 UTC (permalink / raw)
  To: Davidlohr Bueso
  Cc: Andrew Morton, zeus, Aswin Chandramouleeswaran, Linux MM,
	linux-kernel, linux-m68k

Hi David,

On Sun, Apr 20, 2014 at 4:26 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
> Performing vma lookups without taking the mm->mmap_sem is asking
> for trouble. While doing the search, the vma in question can be
> modified or even removed before returning to the caller. Take the
> lock (shared) in order to avoid races while iterating through
> the vmacache and/or rbtree.

Thanks for your patch!

> This patch is completely *untested*.
>
> Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> Cc: Geert Uytterhoeven <geert@linux-m68k.org>
> Cc: linux-m68k@lists.linux-m68k.org
> ---
>  arch/m68k/kernel/sys_m68k.c | 18 ++++++++++++------
>  1 file changed, 12 insertions(+), 6 deletions(-)
>
> diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
> index 3a480b3..d2263a0 100644
> --- a/arch/m68k/kernel/sys_m68k.c
> +++ b/arch/m68k/kernel/sys_m68k.c
> @@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
>  asmlinkage int
>  sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
>  {
> -       struct vm_area_struct *vma;
>         int ret = -EINVAL;
>
>         if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
> @@ -389,16 +388,23 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
>                 if (!capable(CAP_SYS_ADMIN))
>                         goto out;
>         } else {
> +               struct vm_area_struct *vma;
> +               bool invalid;
> +
> +               /* Check for overflow.  */
> +               if (addr + len < addr)
> +                       goto out;
> +
>                 /*
>                  * Verify that the specified address region actually belongs
>                  * to this process.
>                  */
> -               vma = find_vma (current->mm, addr);
>                 ret = -EINVAL;
> -               /* Check for overflow.  */
> -               if (addr + len < addr)
> -                       goto out;
> -               if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
> +               down_read(&current->mm->mmap_sem);
> +               vma = find_vma(current->mm, addr);
> +               invalid = !vma || addr < vma->vm_start || addr + len > vma->vm_end;
> +               up_read(&current->mm->mmap_sem);
> +               if (invalid)
>                         goto out;
>         }

Shouldn't the up_read() be moved to the end of the function?
The vma may still be modified or destroyed between the call to find_vma(),
and the actual cache flush?

Am I missing something?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 2/6] m68k: call find_vma with the mmap_sem held in sys_cacheflush()
@ 2014-04-20  8:04     ` Geert Uytterhoeven
  0 siblings, 0 replies; 40+ messages in thread
From: Geert Uytterhoeven @ 2014-04-20  8:04 UTC (permalink / raw)
  To: Davidlohr Bueso
  Cc: Andrew Morton, zeus, Aswin Chandramouleeswaran, Linux MM,
	linux-kernel, linux-m68k

Hi David,

On Sun, Apr 20, 2014 at 4:26 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
> Performing vma lookups without taking the mm->mmap_sem is asking
> for trouble. While doing the search, the vma in question can be
> modified or even removed before returning to the caller. Take the
> lock (shared) in order to avoid races while iterating through
> the vmacache and/or rbtree.

Thanks for your patch!

> This patch is completely *untested*.
>
> Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> Cc: Geert Uytterhoeven <geert@linux-m68k.org>
> Cc: linux-m68k@lists.linux-m68k.org
> ---
>  arch/m68k/kernel/sys_m68k.c | 18 ++++++++++++------
>  1 file changed, 12 insertions(+), 6 deletions(-)
>
> diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
> index 3a480b3..d2263a0 100644
> --- a/arch/m68k/kernel/sys_m68k.c
> +++ b/arch/m68k/kernel/sys_m68k.c
> @@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
>  asmlinkage int
>  sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
>  {
> -       struct vm_area_struct *vma;
>         int ret = -EINVAL;
>
>         if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
> @@ -389,16 +388,23 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
>                 if (!capable(CAP_SYS_ADMIN))
>                         goto out;
>         } else {
> +               struct vm_area_struct *vma;
> +               bool invalid;
> +
> +               /* Check for overflow.  */
> +               if (addr + len < addr)
> +                       goto out;
> +
>                 /*
>                  * Verify that the specified address region actually belongs
>                  * to this process.
>                  */
> -               vma = find_vma (current->mm, addr);
>                 ret = -EINVAL;
> -               /* Check for overflow.  */
> -               if (addr + len < addr)
> -                       goto out;
> -               if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
> +               down_read(&current->mm->mmap_sem);
> +               vma = find_vma(current->mm, addr);
> +               invalid = !vma || addr < vma->vm_start || addr + len > vma->vm_end;
> +               up_read(&current->mm->mmap_sem);
> +               if (invalid)
>                         goto out;
>         }

Shouldn't the up_read() be moved to the end of the function?
The vma may still be modified or destroyed between the call to find_vma(),
and the actual cache flush?

Am I missing something?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* Re: [PATCH 2/6] m68k: call find_vma with the mmap_sem held in sys_cacheflush()
  2014-04-20  8:04     ` Geert Uytterhoeven
@ 2014-04-20 22:28       ` Davidlohr Bueso
  -1 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-20 22:28 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andrew Morton, zeus, Aswin Chandramouleeswaran, Linux MM,
	linux-kernel, linux-m68k

On Sun, 2014-04-20 at 10:04 +0200, Geert Uytterhoeven wrote:
> Hi David,
> 
> On Sun, Apr 20, 2014 at 4:26 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
> > Performing vma lookups without taking the mm->mmap_sem is asking
> > for trouble. While doing the search, the vma in question can be
> > modified or even removed before returning to the caller. Take the
> > lock (shared) in order to avoid races while iterating through
> > the vmacache and/or rbtree.
> 
> Thanks for your patch!
> 
> > This patch is completely *untested*.
> >
> > Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> > Cc: Geert Uytterhoeven <geert@linux-m68k.org>
> > Cc: linux-m68k@lists.linux-m68k.org
> > ---
> >  arch/m68k/kernel/sys_m68k.c | 18 ++++++++++++------
> >  1 file changed, 12 insertions(+), 6 deletions(-)
> >
> > diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
> > index 3a480b3..d2263a0 100644
> > --- a/arch/m68k/kernel/sys_m68k.c
> > +++ b/arch/m68k/kernel/sys_m68k.c
> > @@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
> >  asmlinkage int
> >  sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
> >  {
> > -       struct vm_area_struct *vma;
> >         int ret = -EINVAL;
> >
> >         if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
> > @@ -389,16 +388,23 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
> >                 if (!capable(CAP_SYS_ADMIN))
> >                         goto out;
> >         } else {
> > +               struct vm_area_struct *vma;
> > +               bool invalid;
> > +
> > +               /* Check for overflow.  */
> > +               if (addr + len < addr)
> > +                       goto out;
> > +
> >                 /*
> >                  * Verify that the specified address region actually belongs
> >                  * to this process.
> >                  */
> > -               vma = find_vma (current->mm, addr);
> >                 ret = -EINVAL;
> > -               /* Check for overflow.  */
> > -               if (addr + len < addr)
> > -                       goto out;
> > -               if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
> > +               down_read(&current->mm->mmap_sem);
> > +               vma = find_vma(current->mm, addr);
> > +               invalid = !vma || addr < vma->vm_start || addr + len > vma->vm_end;
> > +               up_read(&current->mm->mmap_sem);
> > +               if (invalid)
> >                         goto out;
> >         }
> 
> Shouldn't the up_read() be moved to the end of the function?
> The vma may still be modified or destroyed between the call to find_vma(),
> and the actual cache flush?

I don't think so. afaict the vma is only searched to check upon validity
for the address being passed. Once the sem is dropped, the call doesn't
do absolutely anything else with the returned vma.

Thanks,
Davidlohr


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

* Re: [PATCH 2/6] m68k: call find_vma with the mmap_sem held in sys_cacheflush()
  2014-04-20  8:04     ` Geert Uytterhoeven
  (?)
@ 2014-04-20 22:28     ` Davidlohr Bueso
  -1 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-20 22:28 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andrew Morton, zeus, Aswin Chandramouleeswaran, Linux MM,
	linux-kernel, linux-m68k

On Sun, 2014-04-20 at 10:04 +0200, Geert Uytterhoeven wrote:
> Hi David,
> 
> On Sun, Apr 20, 2014 at 4:26 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
> > Performing vma lookups without taking the mm->mmap_sem is asking
> > for trouble. While doing the search, the vma in question can be
> > modified or even removed before returning to the caller. Take the
> > lock (shared) in order to avoid races while iterating through
> > the vmacache and/or rbtree.
> 
> Thanks for your patch!
> 
> > This patch is completely *untested*.
> >
> > Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> > Cc: Geert Uytterhoeven <geert@linux-m68k.org>
> > Cc: linux-m68k@lists.linux-m68k.org
> > ---
> >  arch/m68k/kernel/sys_m68k.c | 18 ++++++++++++------
> >  1 file changed, 12 insertions(+), 6 deletions(-)
> >
> > diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
> > index 3a480b3..d2263a0 100644
> > --- a/arch/m68k/kernel/sys_m68k.c
> > +++ b/arch/m68k/kernel/sys_m68k.c
> > @@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
> >  asmlinkage int
> >  sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
> >  {
> > -       struct vm_area_struct *vma;
> >         int ret = -EINVAL;
> >
> >         if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
> > @@ -389,16 +388,23 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
> >                 if (!capable(CAP_SYS_ADMIN))
> >                         goto out;
> >         } else {
> > +               struct vm_area_struct *vma;
> > +               bool invalid;
> > +
> > +               /* Check for overflow.  */
> > +               if (addr + len < addr)
> > +                       goto out;
> > +
> >                 /*
> >                  * Verify that the specified address region actually belongs
> >                  * to this process.
> >                  */
> > -               vma = find_vma (current->mm, addr);
> >                 ret = -EINVAL;
> > -               /* Check for overflow.  */
> > -               if (addr + len < addr)
> > -                       goto out;
> > -               if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
> > +               down_read(&current->mm->mmap_sem);
> > +               vma = find_vma(current->mm, addr);
> > +               invalid = !vma || addr < vma->vm_start || addr + len > vma->vm_end;
> > +               up_read(&current->mm->mmap_sem);
> > +               if (invalid)
> >                         goto out;
> >         }
> 
> Shouldn't the up_read() be moved to the end of the function?
> The vma may still be modified or destroyed between the call to find_vma(),
> and the actual cache flush?

I don't think so. afaict the vma is only searched to check upon validity
for the address being passed. Once the sem is dropped, the call doesn't
do absolutely anything else with the returned vma.

Thanks,
Davidlohr

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

* Re: [PATCH 2/6] m68k: call find_vma with the mmap_sem held in sys_cacheflush()
@ 2014-04-20 22:28       ` Davidlohr Bueso
  0 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-20 22:28 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andrew Morton, zeus, Aswin Chandramouleeswaran, Linux MM,
	linux-kernel, linux-m68k

On Sun, 2014-04-20 at 10:04 +0200, Geert Uytterhoeven wrote:
> Hi David,
> 
> On Sun, Apr 20, 2014 at 4:26 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
> > Performing vma lookups without taking the mm->mmap_sem is asking
> > for trouble. While doing the search, the vma in question can be
> > modified or even removed before returning to the caller. Take the
> > lock (shared) in order to avoid races while iterating through
> > the vmacache and/or rbtree.
> 
> Thanks for your patch!
> 
> > This patch is completely *untested*.
> >
> > Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> > Cc: Geert Uytterhoeven <geert@linux-m68k.org>
> > Cc: linux-m68k@lists.linux-m68k.org
> > ---
> >  arch/m68k/kernel/sys_m68k.c | 18 ++++++++++++------
> >  1 file changed, 12 insertions(+), 6 deletions(-)
> >
> > diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
> > index 3a480b3..d2263a0 100644
> > --- a/arch/m68k/kernel/sys_m68k.c
> > +++ b/arch/m68k/kernel/sys_m68k.c
> > @@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
> >  asmlinkage int
> >  sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
> >  {
> > -       struct vm_area_struct *vma;
> >         int ret = -EINVAL;
> >
> >         if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
> > @@ -389,16 +388,23 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
> >                 if (!capable(CAP_SYS_ADMIN))
> >                         goto out;
> >         } else {
> > +               struct vm_area_struct *vma;
> > +               bool invalid;
> > +
> > +               /* Check for overflow.  */
> > +               if (addr + len < addr)
> > +                       goto out;
> > +
> >                 /*
> >                  * Verify that the specified address region actually belongs
> >                  * to this process.
> >                  */
> > -               vma = find_vma (current->mm, addr);
> >                 ret = -EINVAL;
> > -               /* Check for overflow.  */
> > -               if (addr + len < addr)
> > -                       goto out;
> > -               if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
> > +               down_read(&current->mm->mmap_sem);
> > +               vma = find_vma(current->mm, addr);
> > +               invalid = !vma || addr < vma->vm_start || addr + len > vma->vm_end;
> > +               up_read(&current->mm->mmap_sem);
> > +               if (invalid)
> >                         goto out;
> >         }
> 
> Shouldn't the up_read() be moved to the end of the function?
> The vma may still be modified or destroyed between the call to find_vma(),
> and the actual cache flush?

I don't think so. afaict the vma is only searched to check upon validity
for the address being passed. Once the sem is dropped, the call doesn't
do absolutely anything else with the returned vma.

Thanks,
Davidlohr

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* Re: [PATCH 2/6] m68k: call find_vma with the mmap_sem held in sys_cacheflush()
  2014-04-20 22:28       ` Davidlohr Bueso
@ 2014-04-21  7:52         ` Geert Uytterhoeven
  -1 siblings, 0 replies; 40+ messages in thread
From: Geert Uytterhoeven @ 2014-04-21  7:52 UTC (permalink / raw)
  To: Davidlohr Bueso
  Cc: Andrew Morton, zeus, Aswin Chandramouleeswaran, Linux MM,
	linux-kernel, linux-m68k

Hi David,

On Mon, Apr 21, 2014 at 12:28 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
> On Sun, 2014-04-20 at 10:04 +0200, Geert Uytterhoeven wrote:
>> On Sun, Apr 20, 2014 at 4:26 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
>> > Performing vma lookups without taking the mm->mmap_sem is asking
>> > for trouble. While doing the search, the vma in question can be
>> > modified or even removed before returning to the caller. Take the
>> > lock (shared) in order to avoid races while iterating through
>> > the vmacache and/or rbtree.
>>
>> Thanks for your patch!
>>
>> > This patch is completely *untested*.
>> >
>> > Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
>> > Cc: Geert Uytterhoeven <geert@linux-m68k.org>
>> > Cc: linux-m68k@lists.linux-m68k.org
>> > ---
>> >  arch/m68k/kernel/sys_m68k.c | 18 ++++++++++++------
>> >  1 file changed, 12 insertions(+), 6 deletions(-)
>> >
>> > diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
>> > index 3a480b3..d2263a0 100644
>> > --- a/arch/m68k/kernel/sys_m68k.c
>> > +++ b/arch/m68k/kernel/sys_m68k.c
>> > @@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
>> >  asmlinkage int
>> >  sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
>> >  {
>> > -       struct vm_area_struct *vma;
>> >         int ret = -EINVAL;
>> >
>> >         if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
>> > @@ -389,16 +388,23 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
>> >                 if (!capable(CAP_SYS_ADMIN))
>> >                         goto out;
>> >         } else {
>> > +               struct vm_area_struct *vma;
>> > +               bool invalid;
>> > +
>> > +               /* Check for overflow.  */
>> > +               if (addr + len < addr)
>> > +                       goto out;
>> > +
>> >                 /*
>> >                  * Verify that the specified address region actually belongs
>> >                  * to this process.
>> >                  */
>> > -               vma = find_vma (current->mm, addr);
>> >                 ret = -EINVAL;
>> > -               /* Check for overflow.  */
>> > -               if (addr + len < addr)
>> > -                       goto out;
>> > -               if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
>> > +               down_read(&current->mm->mmap_sem);
>> > +               vma = find_vma(current->mm, addr);
>> > +               invalid = !vma || addr < vma->vm_start || addr + len > vma->vm_end;
>> > +               up_read(&current->mm->mmap_sem);
>> > +               if (invalid)
>> >                         goto out;
>> >         }
>>
>> Shouldn't the up_read() be moved to the end of the function?
>> The vma may still be modified or destroyed between the call to find_vma(),
>> and the actual cache flush?
>
> I don't think so. afaict the vma is only searched to check upon validity
> for the address being passed. Once the sem is dropped, the call doesn't
> do absolutely anything else with the returned vma.

The function indeed doesn't do anything anymore with the vma itself, but
it does do something with the addr/len pair, which may no longer match
with the vma if it changes after the up_read(). I.e. the address may no longer
be valid when the cache is actually flushed.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 2/6] m68k: call find_vma with the mmap_sem held in sys_cacheflush()
  2014-04-20 22:28       ` Davidlohr Bueso
  (?)
@ 2014-04-21  7:52       ` Geert Uytterhoeven
  -1 siblings, 0 replies; 40+ messages in thread
From: Geert Uytterhoeven @ 2014-04-21  7:52 UTC (permalink / raw)
  To: Davidlohr Bueso
  Cc: Andrew Morton, zeus, Aswin Chandramouleeswaran, Linux MM,
	linux-kernel, linux-m68k

Hi David,

On Mon, Apr 21, 2014 at 12:28 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
> On Sun, 2014-04-20 at 10:04 +0200, Geert Uytterhoeven wrote:
>> On Sun, Apr 20, 2014 at 4:26 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
>> > Performing vma lookups without taking the mm->mmap_sem is asking
>> > for trouble. While doing the search, the vma in question can be
>> > modified or even removed before returning to the caller. Take the
>> > lock (shared) in order to avoid races while iterating through
>> > the vmacache and/or rbtree.
>>
>> Thanks for your patch!
>>
>> > This patch is completely *untested*.
>> >
>> > Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
>> > Cc: Geert Uytterhoeven <geert@linux-m68k.org>
>> > Cc: linux-m68k@lists.linux-m68k.org
>> > ---
>> >  arch/m68k/kernel/sys_m68k.c | 18 ++++++++++++------
>> >  1 file changed, 12 insertions(+), 6 deletions(-)
>> >
>> > diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
>> > index 3a480b3..d2263a0 100644
>> > --- a/arch/m68k/kernel/sys_m68k.c
>> > +++ b/arch/m68k/kernel/sys_m68k.c
>> > @@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
>> >  asmlinkage int
>> >  sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
>> >  {
>> > -       struct vm_area_struct *vma;
>> >         int ret = -EINVAL;
>> >
>> >         if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
>> > @@ -389,16 +388,23 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
>> >                 if (!capable(CAP_SYS_ADMIN))
>> >                         goto out;
>> >         } else {
>> > +               struct vm_area_struct *vma;
>> > +               bool invalid;
>> > +
>> > +               /* Check for overflow.  */
>> > +               if (addr + len < addr)
>> > +                       goto out;
>> > +
>> >                 /*
>> >                  * Verify that the specified address region actually belongs
>> >                  * to this process.
>> >                  */
>> > -               vma = find_vma (current->mm, addr);
>> >                 ret = -EINVAL;
>> > -               /* Check for overflow.  */
>> > -               if (addr + len < addr)
>> > -                       goto out;
>> > -               if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
>> > +               down_read(&current->mm->mmap_sem);
>> > +               vma = find_vma(current->mm, addr);
>> > +               invalid = !vma || addr < vma->vm_start || addr + len > vma->vm_end;
>> > +               up_read(&current->mm->mmap_sem);
>> > +               if (invalid)
>> >                         goto out;
>> >         }
>>
>> Shouldn't the up_read() be moved to the end of the function?
>> The vma may still be modified or destroyed between the call to find_vma(),
>> and the actual cache flush?
>
> I don't think so. afaict the vma is only searched to check upon validity
> for the address being passed. Once the sem is dropped, the call doesn't
> do absolutely anything else with the returned vma.

The function indeed doesn't do anything anymore with the vma itself, but
it does do something with the addr/len pair, which may no longer match
with the vma if it changes after the up_read(). I.e. the address may no longer
be valid when the cache is actually flushed.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 2/6] m68k: call find_vma with the mmap_sem held in sys_cacheflush()
@ 2014-04-21  7:52         ` Geert Uytterhoeven
  0 siblings, 0 replies; 40+ messages in thread
From: Geert Uytterhoeven @ 2014-04-21  7:52 UTC (permalink / raw)
  To: Davidlohr Bueso
  Cc: Andrew Morton, zeus, Aswin Chandramouleeswaran, Linux MM,
	linux-kernel, linux-m68k

Hi David,

On Mon, Apr 21, 2014 at 12:28 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
> On Sun, 2014-04-20 at 10:04 +0200, Geert Uytterhoeven wrote:
>> On Sun, Apr 20, 2014 at 4:26 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
>> > Performing vma lookups without taking the mm->mmap_sem is asking
>> > for trouble. While doing the search, the vma in question can be
>> > modified or even removed before returning to the caller. Take the
>> > lock (shared) in order to avoid races while iterating through
>> > the vmacache and/or rbtree.
>>
>> Thanks for your patch!
>>
>> > This patch is completely *untested*.
>> >
>> > Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
>> > Cc: Geert Uytterhoeven <geert@linux-m68k.org>
>> > Cc: linux-m68k@lists.linux-m68k.org
>> > ---
>> >  arch/m68k/kernel/sys_m68k.c | 18 ++++++++++++------
>> >  1 file changed, 12 insertions(+), 6 deletions(-)
>> >
>> > diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
>> > index 3a480b3..d2263a0 100644
>> > --- a/arch/m68k/kernel/sys_m68k.c
>> > +++ b/arch/m68k/kernel/sys_m68k.c
>> > @@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
>> >  asmlinkage int
>> >  sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
>> >  {
>> > -       struct vm_area_struct *vma;
>> >         int ret = -EINVAL;
>> >
>> >         if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
>> > @@ -389,16 +388,23 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
>> >                 if (!capable(CAP_SYS_ADMIN))
>> >                         goto out;
>> >         } else {
>> > +               struct vm_area_struct *vma;
>> > +               bool invalid;
>> > +
>> > +               /* Check for overflow.  */
>> > +               if (addr + len < addr)
>> > +                       goto out;
>> > +
>> >                 /*
>> >                  * Verify that the specified address region actually belongs
>> >                  * to this process.
>> >                  */
>> > -               vma = find_vma (current->mm, addr);
>> >                 ret = -EINVAL;
>> > -               /* Check for overflow.  */
>> > -               if (addr + len < addr)
>> > -                       goto out;
>> > -               if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
>> > +               down_read(&current->mm->mmap_sem);
>> > +               vma = find_vma(current->mm, addr);
>> > +               invalid = !vma || addr < vma->vm_start || addr + len > vma->vm_end;
>> > +               up_read(&current->mm->mmap_sem);
>> > +               if (invalid)
>> >                         goto out;
>> >         }
>>
>> Shouldn't the up_read() be moved to the end of the function?
>> The vma may still be modified or destroyed between the call to find_vma(),
>> and the actual cache flush?
>
> I don't think so. afaict the vma is only searched to check upon validity
> for the address being passed. Once the sem is dropped, the call doesn't
> do absolutely anything else with the returned vma.

The function indeed doesn't do anything anymore with the vma itself, but
it does do something with the addr/len pair, which may no longer match
with the vma if it changes after the up_read(). I.e. the address may no longer
be valid when the cache is actually flushed.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* Re: [PATCH 5/6] drivers,sgi-gru/grufault.c: call find_vma with the mmap_sem held
  2014-04-20  2:26   ` Davidlohr Bueso
@ 2014-04-21 13:36     ` Dimitri Sivanich
  -1 siblings, 0 replies; 40+ messages in thread
From: Dimitri Sivanich @ 2014-04-21 13:36 UTC (permalink / raw)
  To: Davidlohr Bueso
  Cc: akpm, zeus, aswin, linux-mm, linux-kernel, Dimitri,
	Sivanich <sivanich

On Sat, Apr 19, 2014 at 07:26:30PM -0700, Davidlohr Bueso wrote:
> From: Jonathan Gonzalez V <zeus@gnu.org>
> 
> Performing vma lookups without taking the mm->mmap_sem is asking
> for trouble. While doing the search, the vma in question can
> be modified or even removed before returning to the caller.
> Take the lock in order to avoid races while iterating through
> the vmacache and/or rbtree.
> 
> This patch is completely *untested*.

The mmap_sem is already taken in all paths calling gru_vtop().

The gru_intr() function takes it before calling gru_try_dropin(), from which
all calls to gru_vtop() originate.

The gru_find_lock_gts() function takes it when called from
gru_handle_user_call_os(), which then calls gru_user_dropin()->gru_try_dropin().

Nacked-by: Dimitri Sivanich <sivanich@sgi.com>

> 
> Signed-off-by: Jonathan Gonzalez V <zeus@gnu.org>
> Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> Cc: Dimitri Sivanich <sivanich@sgi.com
> ---
>  drivers/misc/sgi-gru/grufault.c | 13 +++++++++----
>  1 file changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c
> index f74fc0c..15adc84 100644
> --- a/drivers/misc/sgi-gru/grufault.c
> +++ b/drivers/misc/sgi-gru/grufault.c
> @@ -266,6 +266,7 @@ static int gru_vtop(struct gru_thread_state *gts, unsigned long vaddr,
>  	unsigned long paddr;
>  	int ret, ps;
>  
> +	down_write(&mm->mmap_sem);
>  	vma = find_vma(mm, vaddr);
>  	if (!vma)
>  		goto inval;
> @@ -277,22 +278,26 @@ static int gru_vtop(struct gru_thread_state *gts, unsigned long vaddr,
>  	rmb();	/* Must/check ms_range_active before loading PTEs */
>  	ret = atomic_pte_lookup(vma, vaddr, write, &paddr, &ps);
>  	if (ret) {
> -		if (atomic)
> -			goto upm;
> +		if (atomic) {
> +			up_write(&mm->mmap_sem);
> +			return VTOP_RETRY;
> +		}
>  		if (non_atomic_pte_lookup(vma, vaddr, write, &paddr, &ps))
>  			goto inval;
>  	}
>  	if (is_gru_paddr(paddr))
>  		goto inval;
> +
> +	up_write(&mm->mmap_sem);
> +
>  	paddr = paddr & ~((1UL << ps) - 1);
>  	*gpa = uv_soc_phys_ram_to_gpa(paddr);
>  	*pageshift = ps;
>  	return VTOP_SUCCESS;
>  
>  inval:
> +	up_write(&mm->mmap_sem);
>  	return VTOP_INVALID;
> -upm:
> -	return VTOP_RETRY;
>  }
>  
>  
> -- 
> 1.8.1.4

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

* Re: [PATCH 5/6] drivers,sgi-gru/grufault.c: call find_vma with the mmap_sem held
@ 2014-04-21 13:36     ` Dimitri Sivanich
  0 siblings, 0 replies; 40+ messages in thread
From: Dimitri Sivanich @ 2014-04-21 13:36 UTC (permalink / raw)
  To: Davidlohr Bueso
  Cc: akpm, zeus, aswin, linux-mm, linux-kernel, Dimitri,
	Sivanich <sivanich

On Sat, Apr 19, 2014 at 07:26:30PM -0700, Davidlohr Bueso wrote:
> From: Jonathan Gonzalez V <zeus@gnu.org>
> 
> Performing vma lookups without taking the mm->mmap_sem is asking
> for trouble. While doing the search, the vma in question can
> be modified or even removed before returning to the caller.
> Take the lock in order to avoid races while iterating through
> the vmacache and/or rbtree.
> 
> This patch is completely *untested*.

The mmap_sem is already taken in all paths calling gru_vtop().

The gru_intr() function takes it before calling gru_try_dropin(), from which
all calls to gru_vtop() originate.

The gru_find_lock_gts() function takes it when called from
gru_handle_user_call_os(), which then calls gru_user_dropin()->gru_try_dropin().

Nacked-by: Dimitri Sivanich <sivanich@sgi.com>

> 
> Signed-off-by: Jonathan Gonzalez V <zeus@gnu.org>
> Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> Cc: Dimitri Sivanich <sivanich@sgi.com
> ---
>  drivers/misc/sgi-gru/grufault.c | 13 +++++++++----
>  1 file changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c
> index f74fc0c..15adc84 100644
> --- a/drivers/misc/sgi-gru/grufault.c
> +++ b/drivers/misc/sgi-gru/grufault.c
> @@ -266,6 +266,7 @@ static int gru_vtop(struct gru_thread_state *gts, unsigned long vaddr,
>  	unsigned long paddr;
>  	int ret, ps;
>  
> +	down_write(&mm->mmap_sem);
>  	vma = find_vma(mm, vaddr);
>  	if (!vma)
>  		goto inval;
> @@ -277,22 +278,26 @@ static int gru_vtop(struct gru_thread_state *gts, unsigned long vaddr,
>  	rmb();	/* Must/check ms_range_active before loading PTEs */
>  	ret = atomic_pte_lookup(vma, vaddr, write, &paddr, &ps);
>  	if (ret) {
> -		if (atomic)
> -			goto upm;
> +		if (atomic) {
> +			up_write(&mm->mmap_sem);
> +			return VTOP_RETRY;
> +		}
>  		if (non_atomic_pte_lookup(vma, vaddr, write, &paddr, &ps))
>  			goto inval;
>  	}
>  	if (is_gru_paddr(paddr))
>  		goto inval;
> +
> +	up_write(&mm->mmap_sem);
> +
>  	paddr = paddr & ~((1UL << ps) - 1);
>  	*gpa = uv_soc_phys_ram_to_gpa(paddr);
>  	*pageshift = ps;
>  	return VTOP_SUCCESS;
>  
>  inval:
> +	up_write(&mm->mmap_sem);
>  	return VTOP_INVALID;
> -upm:
> -	return VTOP_RETRY;
>  }
>  
>  
> -- 
> 1.8.1.4

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* Re: [PATCH 1/6] blackfin/ptrace: call find_vma with the mmap_sem held
  2014-04-20  2:26   ` Davidlohr Bueso
@ 2014-04-22  3:07     ` Steven Miao
  -1 siblings, 0 replies; 40+ messages in thread
From: Steven Miao @ 2014-04-22  3:07 UTC (permalink / raw)
  To: Davidlohr Bueso
  Cc: Andrew Morton, zeus, aswin, linux-mm,
	open list:CAN NETWORK DRIVERS <linux-can@vger.kernel.org>,
	open list:NETWORKING DRIVERS <netdev@vger.kernel.org>,
	open list, bfin

Hi Davidlohr,

On Sun, Apr 20, 2014 at 10:26 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
> Performing vma lookups without taking the mm->mmap_sem is asking
> for trouble. While doing the search, the vma in question can be
> modified or even removed before returning to the caller. Take the
> lock (shared) in order to avoid races while iterating through the
> vmacache and/or rbtree.
Yes, mm->mmap_sem should lock here. Applied, thanks.
>
> This patch is completely *untested*.
>
> Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> Cc: Steven Miao <realmz6@gmail.com>
> Cc: adi-buildroot-devel@lists.sourceforge.net
> ---
>  arch/blackfin/kernel/ptrace.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
> index e1f88e0..8b8fe67 100644
> --- a/arch/blackfin/kernel/ptrace.c
> +++ b/arch/blackfin/kernel/ptrace.c
> @@ -117,6 +117,7 @@ put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
>  int
>  is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long len)
>  {
> +       bool valid;
>         struct vm_area_struct *vma;
>         struct sram_list_struct *sraml;
>
> @@ -124,9 +125,12 @@ is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long
>         if (start + len < start)
>                 return -EIO;
>
> +       down_read(&child->mm->mmap_sem);
>         vma = find_vma(child->mm, start);
> -       if (vma && start >= vma->vm_start && start + len <= vma->vm_end)
> -                       return 0;
> +       valid = vma && start >= vma->vm_start && start + len <= vma->vm_end;
> +       up_read(&child->mm->mmap_sem);
> +       if (valid)
> +               return 0;
>
>         for (sraml = child->mm->context.sram_list; sraml; sraml = sraml->next)
>                 if (start >= (unsigned long)sraml->addr
> --
> 1.8.1.4
>
-steven

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

* Re: [PATCH 1/6] blackfin/ptrace: call find_vma with the mmap_sem held
@ 2014-04-22  3:07     ` Steven Miao
  0 siblings, 0 replies; 40+ messages in thread
From: Steven Miao @ 2014-04-22  3:07 UTC (permalink / raw)
  To: Davidlohr Bueso
  Cc: Andrew Morton, zeus, aswin, linux-mm,
	open list:CAN NETWORK DRIVERS <linux-can@vger.kernel.org>,
	open list:NETWORKING DRIVERS <netdev@vger.kernel.org>,
	open list, bfin

Hi Davidlohr,

On Sun, Apr 20, 2014 at 10:26 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
> Performing vma lookups without taking the mm->mmap_sem is asking
> for trouble. While doing the search, the vma in question can be
> modified or even removed before returning to the caller. Take the
> lock (shared) in order to avoid races while iterating through the
> vmacache and/or rbtree.
Yes, mm->mmap_sem should lock here. Applied, thanks.
>
> This patch is completely *untested*.
>
> Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> Cc: Steven Miao <realmz6@gmail.com>
> Cc: adi-buildroot-devel@lists.sourceforge.net
> ---
>  arch/blackfin/kernel/ptrace.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
> index e1f88e0..8b8fe67 100644
> --- a/arch/blackfin/kernel/ptrace.c
> +++ b/arch/blackfin/kernel/ptrace.c
> @@ -117,6 +117,7 @@ put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
>  int
>  is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long len)
>  {
> +       bool valid;
>         struct vm_area_struct *vma;
>         struct sram_list_struct *sraml;
>
> @@ -124,9 +125,12 @@ is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long
>         if (start + len < start)
>                 return -EIO;
>
> +       down_read(&child->mm->mmap_sem);
>         vma = find_vma(child->mm, start);
> -       if (vma && start >= vma->vm_start && start + len <= vma->vm_end)
> -                       return 0;
> +       valid = vma && start >= vma->vm_start && start + len <= vma->vm_end;
> +       up_read(&child->mm->mmap_sem);
> +       if (valid)
> +               return 0;
>
>         for (sraml = child->mm->context.sram_list; sraml; sraml = sraml->next)
>                 if (start >= (unsigned long)sraml->addr
> --
> 1.8.1.4
>
-steven

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* Re: [PATCH 4/6] arc: call find_vma with the mmap_sem held
  2014-04-20  2:26   ` Davidlohr Bueso
@ 2014-04-22  6:02     ` Vineet Gupta
  -1 siblings, 0 replies; 40+ messages in thread
From: Vineet Gupta @ 2014-04-22  6:02 UTC (permalink / raw)
  To: Davidlohr Bueso, akpm; +Cc: zeus, aswin, linux-mm, linux-kernel

Hi,

On Sunday 20 April 2014 07:56 AM, Davidlohr Bueso wrote:
> Performing vma lookups without taking the mm->mmap_sem is asking
> for trouble. While doing the search, the vma in question can be
> modified or even removed before returning to the caller. Take the
> lock (shared) in order to avoid races while iterating through
> the vmacache and/or rbtree.
> 
> This patch is completely *untested*.
> 
> Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> Cc: Vineet Gupta <vgupta@synopsys.com>
> ---
>  arch/arc/kernel/troubleshoot.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c
> index 73a7450..3a5a5c1 100644
> --- a/arch/arc/kernel/troubleshoot.c
> +++ b/arch/arc/kernel/troubleshoot.c
> @@ -90,7 +90,7 @@ static void show_faulting_vma(unsigned long address, char *buf)
>  	/* can't use print_vma_addr() yet as it doesn't check for
>  	 * non-inclusive vma
>  	 */
> -
> +	down_read(&current->active_mm->mmap_sem);

Actually avoiding the lock here was intentional - atleast in the past, in case of
a crash from mmap_region() - due to our custom mmap syscall handler (not in
mainline) it would cause a double lockup.

However given that this code is now only called for user contexts [if
user_mode(regs)] above becomes moot point anyways and it would be safe to do that.

So, yes this looks good.

A minor suggestion though - can you please use a tmp for current->active_mm as
there are 3 users now in the function.

Acked-by: Vineet Gupta <vgupta@synopsys.com>

Thx
-Vineet



>  	vma = find_vma(current->active_mm, address);
>  
>  	/* check against the find_vma( ) behaviour which returns the next VMA
> @@ -110,9 +110,10 @@ static void show_faulting_vma(unsigned long address, char *buf)
>  			vma->vm_start < TASK_UNMAPPED_BASE ?
>  				address : address - vma->vm_start,
>  			nm, vma->vm_start, vma->vm_end);
> -	} else {
> +	} else
>  		pr_info("    @No matching VMA found\n");
> -	}
> +
> +	up_read(&current->active_mm->mmap_sem);
>  }
>  
>  static void show_ecr_verbose(struct pt_regs *regs)
> 


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

* Re: [PATCH 4/6] arc: call find_vma with the mmap_sem held
@ 2014-04-22  6:02     ` Vineet Gupta
  0 siblings, 0 replies; 40+ messages in thread
From: Vineet Gupta @ 2014-04-22  6:02 UTC (permalink / raw)
  To: Davidlohr Bueso, akpm; +Cc: zeus, aswin, linux-mm, linux-kernel

Hi,

On Sunday 20 April 2014 07:56 AM, Davidlohr Bueso wrote:
> Performing vma lookups without taking the mm->mmap_sem is asking
> for trouble. While doing the search, the vma in question can be
> modified or even removed before returning to the caller. Take the
> lock (shared) in order to avoid races while iterating through
> the vmacache and/or rbtree.
> 
> This patch is completely *untested*.
> 
> Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> Cc: Vineet Gupta <vgupta@synopsys.com>
> ---
>  arch/arc/kernel/troubleshoot.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c
> index 73a7450..3a5a5c1 100644
> --- a/arch/arc/kernel/troubleshoot.c
> +++ b/arch/arc/kernel/troubleshoot.c
> @@ -90,7 +90,7 @@ static void show_faulting_vma(unsigned long address, char *buf)
>  	/* can't use print_vma_addr() yet as it doesn't check for
>  	 * non-inclusive vma
>  	 */
> -
> +	down_read(&current->active_mm->mmap_sem);

Actually avoiding the lock here was intentional - atleast in the past, in case of
a crash from mmap_region() - due to our custom mmap syscall handler (not in
mainline) it would cause a double lockup.

However given that this code is now only called for user contexts [if
user_mode(regs)] above becomes moot point anyways and it would be safe to do that.

So, yes this looks good.

A minor suggestion though - can you please use a tmp for current->active_mm as
there are 3 users now in the function.

Acked-by: Vineet Gupta <vgupta@synopsys.com>

Thx
-Vineet



>  	vma = find_vma(current->active_mm, address);
>  
>  	/* check against the find_vma( ) behaviour which returns the next VMA
> @@ -110,9 +110,10 @@ static void show_faulting_vma(unsigned long address, char *buf)
>  			vma->vm_start < TASK_UNMAPPED_BASE ?
>  				address : address - vma->vm_start,
>  			nm, vma->vm_start, vma->vm_end);
> -	} else {
> +	} else
>  		pr_info("    @No matching VMA found\n");
> -	}
> +
> +	up_read(&current->active_mm->mmap_sem);
>  }
>  
>  static void show_ecr_verbose(struct pt_regs *regs)
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* Re: [PATCH 3/6] mips: call find_vma with the mmap_sem held
  2014-04-20  2:26   ` Davidlohr Bueso
@ 2014-04-22 13:25     ` Andreas Herrmann
  -1 siblings, 0 replies; 40+ messages in thread
From: Andreas Herrmann @ 2014-04-22 13:25 UTC (permalink / raw)
  To: Davidlohr Bueso
  Cc: akpm, zeus, aswin, linux-mm, linux-kernel, Ralf Baechle, linux-mips

On Sat, Apr 19, 2014 at 07:26:28PM -0700, Davidlohr Bueso wrote:
> Performing vma lookups without taking the mm->mmap_sem is asking
> for trouble. While doing the search, the vma in question can be
> modified or even removed before returning to the caller. Take the
> lock (exclusively) in order to avoid races while iterating through
> the vmacache and/or rbtree.
> 
> Updates two functions:
>   - process_fpemu_return()
>   - cteon_flush_cache_sigtramp()
> 
> This patch is completely *untested*.
> 
> Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> Cc: Ralf Baechle <ralf@linux-mips.org>
> Cc: linux-mips@linux-mips.org

Tested-by: Andreas Herrmann <andreas.herrmann@caviumnetworks.com>


Thanks,

Andreas

> ---
>  arch/mips/kernel/traps.c | 2 ++
>  arch/mips/mm/c-octeon.c  | 2 ++
>  2 files changed, 4 insertions(+)
> 
> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> index 074e857..c51bd20 100644
> --- a/arch/mips/kernel/traps.c
> +++ b/arch/mips/kernel/traps.c
> @@ -712,10 +712,12 @@ int process_fpemu_return(int sig, void __user *fault_addr)
>  		si.si_addr = fault_addr;
>  		si.si_signo = sig;
>  		if (sig == SIGSEGV) {
> +			down_read(&current->mm->mmap_sem);
>  			if (find_vma(current->mm, (unsigned long)fault_addr))
>  				si.si_code = SEGV_ACCERR;
>  			else
>  				si.si_code = SEGV_MAPERR;
> +			up_read(&current->mm->mmap_sem);
>  		} else {
>  			si.si_code = BUS_ADRERR;
>  		}
> diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c
> index f41a5c5..05b1d7c 100644
> --- a/arch/mips/mm/c-octeon.c
> +++ b/arch/mips/mm/c-octeon.c
> @@ -137,8 +137,10 @@ static void octeon_flush_cache_sigtramp(unsigned long addr)
>  {
>  	struct vm_area_struct *vma;
>  
> +	down_read(&current->mm->mmap_sem);
>  	vma = find_vma(current->mm, addr);
>  	octeon_flush_icache_all_cores(vma);
> +	up_read(&current->mm->mmap_sem);
>  }
>  
>  
> -- 
> 1.8.1.4
> 
> 

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

* Re: [PATCH 3/6] mips: call find_vma with the mmap_sem held
@ 2014-04-22 13:25     ` Andreas Herrmann
  0 siblings, 0 replies; 40+ messages in thread
From: Andreas Herrmann @ 2014-04-22 13:25 UTC (permalink / raw)
  To: Davidlohr Bueso
  Cc: akpm, zeus, aswin, linux-mm, linux-kernel, Ralf Baechle, linux-mips

On Sat, Apr 19, 2014 at 07:26:28PM -0700, Davidlohr Bueso wrote:
> Performing vma lookups without taking the mm->mmap_sem is asking
> for trouble. While doing the search, the vma in question can be
> modified or even removed before returning to the caller. Take the
> lock (exclusively) in order to avoid races while iterating through
> the vmacache and/or rbtree.
> 
> Updates two functions:
>   - process_fpemu_return()
>   - cteon_flush_cache_sigtramp()
> 
> This patch is completely *untested*.
> 
> Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> Cc: Ralf Baechle <ralf@linux-mips.org>
> Cc: linux-mips@linux-mips.org

Tested-by: Andreas Herrmann <andreas.herrmann@caviumnetworks.com>


Thanks,

Andreas

> ---
>  arch/mips/kernel/traps.c | 2 ++
>  arch/mips/mm/c-octeon.c  | 2 ++
>  2 files changed, 4 insertions(+)
> 
> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> index 074e857..c51bd20 100644
> --- a/arch/mips/kernel/traps.c
> +++ b/arch/mips/kernel/traps.c
> @@ -712,10 +712,12 @@ int process_fpemu_return(int sig, void __user *fault_addr)
>  		si.si_addr = fault_addr;
>  		si.si_signo = sig;
>  		if (sig == SIGSEGV) {
> +			down_read(&current->mm->mmap_sem);
>  			if (find_vma(current->mm, (unsigned long)fault_addr))
>  				si.si_code = SEGV_ACCERR;
>  			else
>  				si.si_code = SEGV_MAPERR;
> +			up_read(&current->mm->mmap_sem);
>  		} else {
>  			si.si_code = BUS_ADRERR;
>  		}
> diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c
> index f41a5c5..05b1d7c 100644
> --- a/arch/mips/mm/c-octeon.c
> +++ b/arch/mips/mm/c-octeon.c
> @@ -137,8 +137,10 @@ static void octeon_flush_cache_sigtramp(unsigned long addr)
>  {
>  	struct vm_area_struct *vma;
>  
> +	down_read(&current->mm->mmap_sem);
>  	vma = find_vma(current->mm, addr);
>  	octeon_flush_icache_all_cores(vma);
> +	up_read(&current->mm->mmap_sem);
>  }
>  
>  
> -- 
> 1.8.1.4
> 
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* [PATCH 7/6] media: videobuf2-dma-sg: call find_vma with the mmap_sem held
  2014-04-20  2:26 ` Davidlohr Bueso
@ 2014-04-28 18:09   ` Davidlohr Bueso
  -1 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-28 18:09 UTC (permalink / raw)
  To: akpm
  Cc: davidlohr, aswin, linux-mm, linux-kernel, Pawel Osciak,
	Marek Szyprowski, Kyungmin Park, Mauro Carvalho Chehab,
	linux-media

Performing vma lookups without taking the mm->mmap_sem is asking
for trouble. While doing the search, the vma in question can
be modified or even removed before returning to the caller.
Take the lock in order to avoid races while iterating through
the vmacache and/or rbtree.

Also do some very minor cleanup changes.

This patch is only compile tested.

Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
Cc: Pawel Osciak <pawel@osciak.com>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Mauro Carvalho Chehab <m.chehab@samsung.com>
Cc: linux-media@vger.kernel.org
---
It would seem this is the last offending user. 
v4l2 is a maze but I believe that this is needed as I don't
see the mmap_sem being taken by any callers of vb2_dma_sg_get_userptr().

 drivers/media/v4l2-core/videobuf2-dma-sg.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index c779f21..2a21100 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -168,8 +168,9 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	unsigned long first, last;
 	int num_pages_from_user;
 	struct vm_area_struct *vma;
+	struct mm_struct *mm = current->mm;
 
-	buf = kzalloc(sizeof *buf, GFP_KERNEL);
+	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
 	if (!buf)
 		return NULL;
 
@@ -178,7 +179,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	buf->offset = vaddr & ~PAGE_MASK;
 	buf->size = size;
 
-	first = (vaddr           & PAGE_MASK) >> PAGE_SHIFT;
+	first = (vaddr & PAGE_MASK) >> PAGE_SHIFT;
 	last  = ((vaddr + size - 1) & PAGE_MASK) >> PAGE_SHIFT;
 	buf->num_pages = last - first + 1;
 
@@ -187,7 +188,8 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	if (!buf->pages)
 		goto userptr_fail_alloc_pages;
 
-	vma = find_vma(current->mm, vaddr);
+	down_write(&mm->mmap_sem);
+	vma = find_vma(mm, vaddr);
 	if (!vma) {
 		dprintk(1, "no vma for address %lu\n", vaddr);
 		goto userptr_fail_find_vma;
@@ -218,7 +220,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 			buf->pages[num_pages_from_user] = pfn_to_page(pfn);
 		}
 	} else
-		num_pages_from_user = get_user_pages(current, current->mm,
+		num_pages_from_user = get_user_pages(current, mm,
 					     vaddr & PAGE_MASK,
 					     buf->num_pages,
 					     write,
@@ -233,6 +235,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 			buf->num_pages, buf->offset, size, 0))
 		goto userptr_fail_alloc_table_from_pages;
 
+	up_write(&mm->mmap_sem);
 	return buf;
 
 userptr_fail_alloc_table_from_pages:
@@ -244,6 +247,7 @@ userptr_fail_get_user_pages:
 			put_page(buf->pages[num_pages_from_user]);
 	vb2_put_vma(buf->vma);
 userptr_fail_find_vma:
+	up_write(&mm->mmap_sem);
 	kfree(buf->pages);
 userptr_fail_alloc_pages:
 	kfree(buf);
-- 
1.8.1.4




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

* [PATCH 7/6] media: videobuf2-dma-sg: call find_vma with the mmap_sem held
@ 2014-04-28 18:09   ` Davidlohr Bueso
  0 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-04-28 18:09 UTC (permalink / raw)
  To: akpm
  Cc: davidlohr, aswin, linux-mm, linux-kernel, Pawel Osciak,
	Marek Szyprowski, Kyungmin Park, Mauro Carvalho Chehab,
	linux-media

Performing vma lookups without taking the mm->mmap_sem is asking
for trouble. While doing the search, the vma in question can
be modified or even removed before returning to the caller.
Take the lock in order to avoid races while iterating through
the vmacache and/or rbtree.

Also do some very minor cleanup changes.

This patch is only compile tested.

Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
Cc: Pawel Osciak <pawel@osciak.com>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Mauro Carvalho Chehab <m.chehab@samsung.com>
Cc: linux-media@vger.kernel.org
---
It would seem this is the last offending user. 
v4l2 is a maze but I believe that this is needed as I don't
see the mmap_sem being taken by any callers of vb2_dma_sg_get_userptr().

 drivers/media/v4l2-core/videobuf2-dma-sg.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index c779f21..2a21100 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -168,8 +168,9 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	unsigned long first, last;
 	int num_pages_from_user;
 	struct vm_area_struct *vma;
+	struct mm_struct *mm = current->mm;
 
-	buf = kzalloc(sizeof *buf, GFP_KERNEL);
+	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
 	if (!buf)
 		return NULL;
 
@@ -178,7 +179,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	buf->offset = vaddr & ~PAGE_MASK;
 	buf->size = size;
 
-	first = (vaddr           & PAGE_MASK) >> PAGE_SHIFT;
+	first = (vaddr & PAGE_MASK) >> PAGE_SHIFT;
 	last  = ((vaddr + size - 1) & PAGE_MASK) >> PAGE_SHIFT;
 	buf->num_pages = last - first + 1;
 
@@ -187,7 +188,8 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	if (!buf->pages)
 		goto userptr_fail_alloc_pages;
 
-	vma = find_vma(current->mm, vaddr);
+	down_write(&mm->mmap_sem);
+	vma = find_vma(mm, vaddr);
 	if (!vma) {
 		dprintk(1, "no vma for address %lu\n", vaddr);
 		goto userptr_fail_find_vma;
@@ -218,7 +220,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 			buf->pages[num_pages_from_user] = pfn_to_page(pfn);
 		}
 	} else
-		num_pages_from_user = get_user_pages(current, current->mm,
+		num_pages_from_user = get_user_pages(current, mm,
 					     vaddr & PAGE_MASK,
 					     buf->num_pages,
 					     write,
@@ -233,6 +235,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 			buf->num_pages, buf->offset, size, 0))
 		goto userptr_fail_alloc_table_from_pages;
 
+	up_write(&mm->mmap_sem);
 	return buf;
 
 userptr_fail_alloc_table_from_pages:
@@ -244,6 +247,7 @@ userptr_fail_get_user_pages:
 			put_page(buf->pages[num_pages_from_user]);
 	vb2_put_vma(buf->vma);
 userptr_fail_find_vma:
+	up_write(&mm->mmap_sem);
 	kfree(buf->pages);
 userptr_fail_alloc_pages:
 	kfree(buf);
-- 
1.8.1.4



--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* Re: [PATCH 7/6] media: videobuf2-dma-sg: call find_vma with the mmap_sem held
  2014-04-28 18:09   ` Davidlohr Bueso
@ 2014-04-29  8:35     ` Marek Szyprowski
  -1 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2014-04-29  8:35 UTC (permalink / raw)
  To: Davidlohr Bueso, akpm
  Cc: aswin, linux-mm, linux-kernel, Pawel Osciak, Kyungmin Park,
	Mauro Carvalho Chehab, linux-media

Hello,

On 2014-04-28 20:09, Davidlohr Bueso wrote:
> Performing vma lookups without taking the mm->mmap_sem is asking
> for trouble. While doing the search, the vma in question can
> be modified or even removed before returning to the caller.
> Take the lock in order to avoid races while iterating through
> the vmacache and/or rbtree.
>
> Also do some very minor cleanup changes.
>
> This patch is only compile tested.

NACK.

mm->mmap_sem is taken by videobuf2-core to avoid AB-BA deadlock with v4l2 core lock. For more information, please check videobuf2-core.c. However you are right that this is a bit confusing and we need more comments about the place where mmap_sem is taken. Here is some background for this decision:

https://www.mail-archive.com/linux-media@vger.kernel.org/msg38599.html
http://www.spinics.net/lists/linux-media/msg40225.html

> Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> Cc: Pawel Osciak <pawel@osciak.com>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> Cc: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Mauro Carvalho Chehab <m.chehab@samsung.com>
> Cc: linux-media@vger.kernel.org
> ---
> It would seem this is the last offending user.
> v4l2 is a maze but I believe that this is needed as I don't
> see the mmap_sem being taken by any callers of vb2_dma_sg_get_userptr().
>
>   drivers/media/v4l2-core/videobuf2-dma-sg.c | 12 ++++++++----
>   1 file changed, 8 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
> index c779f21..2a21100 100644
> --- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
> +++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
> @@ -168,8 +168,9 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
>   	unsigned long first, last;
>   	int num_pages_from_user;
>   	struct vm_area_struct *vma;
> +	struct mm_struct *mm = current->mm;
>   
> -	buf = kzalloc(sizeof *buf, GFP_KERNEL);
> +	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
>   	if (!buf)
>   		return NULL;
>   
> @@ -178,7 +179,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
>   	buf->offset = vaddr & ~PAGE_MASK;
>   	buf->size = size;
>   
> -	first = (vaddr           & PAGE_MASK) >> PAGE_SHIFT;
> +	first = (vaddr & PAGE_MASK) >> PAGE_SHIFT;
>   	last  = ((vaddr + size - 1) & PAGE_MASK) >> PAGE_SHIFT;
>   	buf->num_pages = last - first + 1;
>   
> @@ -187,7 +188,8 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
>   	if (!buf->pages)
>   		goto userptr_fail_alloc_pages;
>   
> -	vma = find_vma(current->mm, vaddr);
> +	down_write(&mm->mmap_sem);
> +	vma = find_vma(mm, vaddr);
>   	if (!vma) {
>   		dprintk(1, "no vma for address %lu\n", vaddr);
>   		goto userptr_fail_find_vma;
> @@ -218,7 +220,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
>   			buf->pages[num_pages_from_user] = pfn_to_page(pfn);
>   		}
>   	} else
> -		num_pages_from_user = get_user_pages(current, current->mm,
> +		num_pages_from_user = get_user_pages(current, mm,
>   					     vaddr & PAGE_MASK,
>   					     buf->num_pages,
>   					     write,
> @@ -233,6 +235,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
>   			buf->num_pages, buf->offset, size, 0))
>   		goto userptr_fail_alloc_table_from_pages;
>   
> +	up_write(&mm->mmap_sem);
>   	return buf;
>   
>   userptr_fail_alloc_table_from_pages:
> @@ -244,6 +247,7 @@ userptr_fail_get_user_pages:
>   			put_page(buf->pages[num_pages_from_user]);
>   	vb2_put_vma(buf->vma);
>   userptr_fail_find_vma:
> +	up_write(&mm->mmap_sem);
>   	kfree(buf->pages);
>   userptr_fail_alloc_pages:
>   	kfree(buf);

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


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

* Re: [PATCH 7/6] media: videobuf2-dma-sg: call find_vma with the mmap_sem held
@ 2014-04-29  8:35     ` Marek Szyprowski
  0 siblings, 0 replies; 40+ messages in thread
From: Marek Szyprowski @ 2014-04-29  8:35 UTC (permalink / raw)
  To: Davidlohr Bueso, akpm
  Cc: aswin, linux-mm, linux-kernel, Pawel Osciak, Kyungmin Park,
	Mauro Carvalho Chehab, linux-media

Hello,

On 2014-04-28 20:09, Davidlohr Bueso wrote:
> Performing vma lookups without taking the mm->mmap_sem is asking
> for trouble. While doing the search, the vma in question can
> be modified or even removed before returning to the caller.
> Take the lock in order to avoid races while iterating through
> the vmacache and/or rbtree.
>
> Also do some very minor cleanup changes.
>
> This patch is only compile tested.

NACK.

mm->mmap_sem is taken by videobuf2-core to avoid AB-BA deadlock with v4l2 core lock. For more information, please check videobuf2-core.c. However you are right that this is a bit confusing and we need more comments about the place where mmap_sem is taken. Here is some background for this decision:

https://www.mail-archive.com/linux-media@vger.kernel.org/msg38599.html
http://www.spinics.net/lists/linux-media/msg40225.html

> Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> Cc: Pawel Osciak <pawel@osciak.com>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> Cc: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Mauro Carvalho Chehab <m.chehab@samsung.com>
> Cc: linux-media@vger.kernel.org
> ---
> It would seem this is the last offending user.
> v4l2 is a maze but I believe that this is needed as I don't
> see the mmap_sem being taken by any callers of vb2_dma_sg_get_userptr().
>
>   drivers/media/v4l2-core/videobuf2-dma-sg.c | 12 ++++++++----
>   1 file changed, 8 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
> index c779f21..2a21100 100644
> --- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
> +++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
> @@ -168,8 +168,9 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
>   	unsigned long first, last;
>   	int num_pages_from_user;
>   	struct vm_area_struct *vma;
> +	struct mm_struct *mm = current->mm;
>   
> -	buf = kzalloc(sizeof *buf, GFP_KERNEL);
> +	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
>   	if (!buf)
>   		return NULL;
>   
> @@ -178,7 +179,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
>   	buf->offset = vaddr & ~PAGE_MASK;
>   	buf->size = size;
>   
> -	first = (vaddr           & PAGE_MASK) >> PAGE_SHIFT;
> +	first = (vaddr & PAGE_MASK) >> PAGE_SHIFT;
>   	last  = ((vaddr + size - 1) & PAGE_MASK) >> PAGE_SHIFT;
>   	buf->num_pages = last - first + 1;
>   
> @@ -187,7 +188,8 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
>   	if (!buf->pages)
>   		goto userptr_fail_alloc_pages;
>   
> -	vma = find_vma(current->mm, vaddr);
> +	down_write(&mm->mmap_sem);
> +	vma = find_vma(mm, vaddr);
>   	if (!vma) {
>   		dprintk(1, "no vma for address %lu\n", vaddr);
>   		goto userptr_fail_find_vma;
> @@ -218,7 +220,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
>   			buf->pages[num_pages_from_user] = pfn_to_page(pfn);
>   		}
>   	} else
> -		num_pages_from_user = get_user_pages(current, current->mm,
> +		num_pages_from_user = get_user_pages(current, mm,
>   					     vaddr & PAGE_MASK,
>   					     buf->num_pages,
>   					     write,
> @@ -233,6 +235,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
>   			buf->num_pages, buf->offset, size, 0))
>   		goto userptr_fail_alloc_table_from_pages;
>   
> +	up_write(&mm->mmap_sem);
>   	return buf;
>   
>   userptr_fail_alloc_table_from_pages:
> @@ -244,6 +247,7 @@ userptr_fail_get_user_pages:
>   			put_page(buf->pages[num_pages_from_user]);
>   	vb2_put_vma(buf->vma);
>   userptr_fail_find_vma:
> +	up_write(&mm->mmap_sem);
>   	kfree(buf->pages);
>   userptr_fail_alloc_pages:
>   	kfree(buf);

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* Re: Linux-3.15-rcX - PowerPC Serial Console woes.
       [not found]         ` <OF5CEC4294.867C780E-ONCA257CCB.00315352-CA257CCB.003674E6@csc.com>
@ 2014-05-01 14:05           ` Geert Uytterhoeven
  0 siblings, 0 replies; 40+ messages in thread
From: Geert Uytterhoeven @ 2014-05-01 14:05 UTC (permalink / raw)
  To: Stephen N Chivers; +Cc: Chris Proctor, linux-serial

Hi Stephen

CC linux-serial

On Thu, May 1, 2014 at 11:54 AM, Stephen N Chivers <schivers@csc.com.au> wrote:
> Geert,
>
> I have a brace of PowerPC computers, most of which are
> VME Single boards (MVME5100 and MVME4100),
> but I also have some MPC8349MITX and a SAM440EP.
>
> They are all operated diskless from a file server.
>
> None of them have a graphical consoles and so as usual
> I am quite reliant on the serial console.
>
> I am having problems with the unexpected disabling of the
> serial console during the boot process.
>
> In all Linux-3.15 release candidates the serial console
> is disabled during the boot process when the OF Platform
> devices are registering.
>
> I will use the SAM440EP as an example, it is setup using
> a defaultish configuration with, 8250 uarts configured,
> serial console support, early printk, the "standardish"
> UDBG console and the OF platform devices.
>
> The disabling of the serial console leads to the loss of
> boot messages, this is ok for my present configuration as
> (fortunately) the root file system is mounted and so the
> boot messages are in /var/log/messages.
>
> The tty (ttyS0) device is around as after the machine has gone to
> run state 3, the console login prompt is present without
> problems.
>
> What is going on is:
>
> UDBG does its stuff ok. It is the console:
>
> bootconsole [udbg0] enabled
>
> The 8250 driver wakes up:
>
> Serial: 8250/16550 driver, 10 ports, IRQ sharing disabled
> serial8250.0: ttyS0 at MMIO 0xef600300 (irq = 16, base_baud = 509259) is a
> 16550A
> console [ttyS0] enabled
> console [ttyS0] enabled
> bootconsole [udbg0] disabled
> bootconsole [udbg0] disabled

Here the legacy 8250 driver takes over, as expected.

> serial8250.0: ttyS1 at MMIO 0xef600400 (irq = 17, base_baud = 509259) is a
> 16550A
> serial8250.0: ttyS2 at MMIO 0xef600500 (irq = 18, base_baud = 509259) is a
> 16550A
> serial8250.0: ttyS3 at MMIO 0xef600600 (irq = 19, base_baud = 509259) is a
> 16550A
> 0000:00:0c.0: ttyS4 at I/O 0x2000 (irq = 25, base_baud = 921600) is a
> 16550A
> 0000:00:0c.0: ttyS5 at I/O 0x2008 (irq = 25, base_baud = 921600) is a
> 16550A
>
> The OF PLATFORM devices kick and disable the serial console:
>
> console [ttyS0] disabled

Here the OF 8250 driver takes over.

> now, the OF serial devices are:
>
> ef600300.serial: ttyS0 at MMIO 0xef600300 (irq = 16, base_baud = 509259)
> is a 16550
> ef600400.serial: ttyS1 at MMIO 0xef600400 (irq = 17, base_baud = 509259)
> is a 16550
> ef600500.serial: ttyS2 at MMIO 0xef600500 (irq = 18, base_baud = 509259)
> is a 16550
> ef600600.serial: ttyS3 at MMIO 0xef600600 (irq = 19, base_baud = 509259)
> is a 16550
>
> when the devices are registered as part of the platform device probe,
> serial8250_register_8250_port in 8250_core.c finds that these devices
> match the earlier ones and so the lines that read:
>
> if (uart->port.dev)
> uart_remove_one_port(&serial8250_reg, &uart->port);
>
> are executed. Now uart_remove_one_port calls unregister_console,
> and that is where the console get disabled.
>
> In Linux-3.14 uart_remove_one_port does not call unregister_console
> and so for that release the serial console remains active.

That's correct.

It was added in commit 5f5c9ae56c38942623f69c3e6dc6ec78e4da2076
Author: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
Date:   Fri Feb 28 14:21:32 2014 +0100

    serial_core: Unregister console in uart_remove_one_port()

which fixed a crash on driver rmmod.

> Taking CONFIG_OF_PLATFORM out of the configuration fixes this
> problem. But, shouldn't serial8250_register_8250_port leave things
> as they are if the ports match? I tried a few things along those lines
> but the results are truly bad (the machine goes done to a "monitor"
> that isn't U-Boot).

I also don't like how the OF serial driver tries to unregister and
register the same port.

Currently this indeed removes the serial console, just like when doing
a driver unbind or rmmod, followed by a bind or insmod.

But this case is different, as no driver is actually unloaded.
Can you check why the register_console() in uart_configure_port() is not
called? If it's just due to a simple flag having the wrong state, perhaps
it can be fixed easily.

Is it due to port->type being reset to PORT_UNKNOWN in
uart_remove_one_port()? It seems port->type should already have the
right value when calling uart_add_one_port().

Thanks!

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 2/6] m68k: call find_vma with the mmap_sem held in sys_cacheflush()
  2014-04-21  7:52         ` Geert Uytterhoeven
@ 2014-08-07 22:44           ` Davidlohr Bueso
  -1 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-08-07 22:44 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andrew Morton, Aswin Chandramouleeswaran, Linux MM, linux-kernel,
	linux-m68k

Hi Geert,

On Mon, 2014-04-21 at 09:52 +0200, Geert Uytterhoeven wrote:
> Hi David,
> 
> On Mon, Apr 21, 2014 at 12:28 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
> > On Sun, 2014-04-20 at 10:04 +0200, Geert Uytterhoeven wrote:
> >> On Sun, Apr 20, 2014 at 4:26 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
> >> > Performing vma lookups without taking the mm->mmap_sem is asking
> >> > for trouble. While doing the search, the vma in question can be
> >> > modified or even removed before returning to the caller. Take the
> >> > lock (shared) in order to avoid races while iterating through
> >> > the vmacache and/or rbtree.
> >>
> >> Thanks for your patch!
> >>
> >> > This patch is completely *untested*.
> >> >
> >> > Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> >> > Cc: Geert Uytterhoeven <geert@linux-m68k.org>
> >> > Cc: linux-m68k@lists.linux-m68k.org
> >> > ---
> >> >  arch/m68k/kernel/sys_m68k.c | 18 ++++++++++++------
> >> >  1 file changed, 12 insertions(+), 6 deletions(-)
> >> >
> >> > diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
> >> > index 3a480b3..d2263a0 100644
> >> > --- a/arch/m68k/kernel/sys_m68k.c
> >> > +++ b/arch/m68k/kernel/sys_m68k.c
> >> > @@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
> >> >  asmlinkage int
> >> >  sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
> >> >  {
> >> > -       struct vm_area_struct *vma;
> >> >         int ret = -EINVAL;
> >> >
> >> >         if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
> >> > @@ -389,16 +388,23 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
> >> >                 if (!capable(CAP_SYS_ADMIN))
> >> >                         goto out;
> >> >         } else {
> >> > +               struct vm_area_struct *vma;
> >> > +               bool invalid;
> >> > +
> >> > +               /* Check for overflow.  */
> >> > +               if (addr + len < addr)
> >> > +                       goto out;
> >> > +
> >> >                 /*
> >> >                  * Verify that the specified address region actually belongs
> >> >                  * to this process.
> >> >                  */
> >> > -               vma = find_vma (current->mm, addr);
> >> >                 ret = -EINVAL;
> >> > -               /* Check for overflow.  */
> >> > -               if (addr + len < addr)
> >> > -                       goto out;
> >> > -               if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
> >> > +               down_read(&current->mm->mmap_sem);
> >> > +               vma = find_vma(current->mm, addr);
> >> > +               invalid = !vma || addr < vma->vm_start || addr + len > vma->vm_end;
> >> > +               up_read(&current->mm->mmap_sem);
> >> > +               if (invalid)
> >> >                         goto out;
> >> >         }
> >>
> >> Shouldn't the up_read() be moved to the end of the function?
> >> The vma may still be modified or destroyed between the call to find_vma(),
> >> and the actual cache flush?
> >
> > I don't think so. afaict the vma is only searched to check upon validity
> > for the address being passed. Once the sem is dropped, the call doesn't
> > do absolutely anything else with the returned vma.
> 
> The function indeed doesn't do anything anymore with the vma itself, but
> it does do something with the addr/len pair, which may no longer match
> with the vma if it changes after the up_read(). I.e. the address may no longer
> be valid when the cache is actually flushed.

Apologies for the delay, I completely forgot about this. 

So I wasn't sure if we *really* required to serialize the entire address
space for this operation. However, looking at other archs, sh seems to
do exactly that, so I guess, at least for safety, we should hold the
lock until we exit the function. I guess taking it as a reader enables
us to guarantee it won't be removed underneath us. So here's v2.

Thanks,
Davidlohr


8<-------------------------------------------------------------------------
From: Davidlohr Bueso <davidlohr@hp.com>
Subject: [PATCH v2] m68k: call find_vma with the mmap_sem held in sys_cacheflush()

Performing vma lookups without taking the mm->mmap_sem is asking
for trouble. While doing the search, the vma in question can be
modified or even removed before returning to the caller. Take the
lock (shared) in order to avoid races while iterating through
the vmacache and/or rbtree. In addition, this guarantees that the
address space will remain intact during the CPU flushing.

Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
---
Completely untested patch.

 arch/m68k/kernel/sys_m68k.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 3a480b3..9aa01ad 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
 asmlinkage int
 sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 {
-	struct vm_area_struct *vma;
 	int ret = -EINVAL;
 
 	if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
@@ -389,17 +388,21 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 		if (!capable(CAP_SYS_ADMIN))
 			goto out;
 	} else {
+		struct vm_area_struct *vma;
+
+		/* Check for overflow.  */
+		if (addr + len < addr)
+			goto out;
+
 		/*
 		 * Verify that the specified address region actually belongs
 		 * to this process.
 		 */
-		vma = find_vma (current->mm, addr);
 		ret = -EINVAL;
-		/* Check for overflow.  */
-		if (addr + len < addr)
-			goto out;
-		if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
-			goto out;
+		down_read(&current->mm->mmap_sem);
+		vma = find_vma(current->mm, addr);
+		if (!vma || addr < vma->vm_start || addr + len > vma->vm_end)
+			goto out_unlock;
 	}
 
 	if (CPU_IS_020_OR_030) {
@@ -429,7 +432,7 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 			__asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr));
 		}
 		ret = 0;
-		goto out;
+		goto out_unlock;
 	} else {
 	    /*
 	     * 040 or 060: don't blindly trust 'scope', someone could
@@ -446,6 +449,8 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 		ret = cache_flush_060 (addr, scope, cache, len);
 	    }
 	}
+out_unlock:
+	up_read(&current->mm->mmap_sem);
 out:
 	return ret;
 }
-- 
1.8.1.4




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

* Re: [PATCH 2/6] m68k: call find_vma with the mmap_sem held in sys_cacheflush()
  2014-04-21  7:52         ` Geert Uytterhoeven
                           ` (2 preceding siblings ...)
  (?)
@ 2014-08-07 22:44         ` Davidlohr Bueso
  -1 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-08-07 22:44 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andrew Morton, Aswin Chandramouleeswaran, Linux MM, linux-kernel,
	linux-m68k

Hi Geert,

On Mon, 2014-04-21 at 09:52 +0200, Geert Uytterhoeven wrote:
> Hi David,
> 
> On Mon, Apr 21, 2014 at 12:28 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
> > On Sun, 2014-04-20 at 10:04 +0200, Geert Uytterhoeven wrote:
> >> On Sun, Apr 20, 2014 at 4:26 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
> >> > Performing vma lookups without taking the mm->mmap_sem is asking
> >> > for trouble. While doing the search, the vma in question can be
> >> > modified or even removed before returning to the caller. Take the
> >> > lock (shared) in order to avoid races while iterating through
> >> > the vmacache and/or rbtree.
> >>
> >> Thanks for your patch!
> >>
> >> > This patch is completely *untested*.
> >> >
> >> > Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> >> > Cc: Geert Uytterhoeven <geert@linux-m68k.org>
> >> > Cc: linux-m68k@lists.linux-m68k.org
> >> > ---
> >> >  arch/m68k/kernel/sys_m68k.c | 18 ++++++++++++------
> >> >  1 file changed, 12 insertions(+), 6 deletions(-)
> >> >
> >> > diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
> >> > index 3a480b3..d2263a0 100644
> >> > --- a/arch/m68k/kernel/sys_m68k.c
> >> > +++ b/arch/m68k/kernel/sys_m68k.c
> >> > @@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
> >> >  asmlinkage int
> >> >  sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
> >> >  {
> >> > -       struct vm_area_struct *vma;
> >> >         int ret = -EINVAL;
> >> >
> >> >         if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
> >> > @@ -389,16 +388,23 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
> >> >                 if (!capable(CAP_SYS_ADMIN))
> >> >                         goto out;
> >> >         } else {
> >> > +               struct vm_area_struct *vma;
> >> > +               bool invalid;
> >> > +
> >> > +               /* Check for overflow.  */
> >> > +               if (addr + len < addr)
> >> > +                       goto out;
> >> > +
> >> >                 /*
> >> >                  * Verify that the specified address region actually belongs
> >> >                  * to this process.
> >> >                  */
> >> > -               vma = find_vma (current->mm, addr);
> >> >                 ret = -EINVAL;
> >> > -               /* Check for overflow.  */
> >> > -               if (addr + len < addr)
> >> > -                       goto out;
> >> > -               if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
> >> > +               down_read(&current->mm->mmap_sem);
> >> > +               vma = find_vma(current->mm, addr);
> >> > +               invalid = !vma || addr < vma->vm_start || addr + len > vma->vm_end;
> >> > +               up_read(&current->mm->mmap_sem);
> >> > +               if (invalid)
> >> >                         goto out;
> >> >         }
> >>
> >> Shouldn't the up_read() be moved to the end of the function?
> >> The vma may still be modified or destroyed between the call to find_vma(),
> >> and the actual cache flush?
> >
> > I don't think so. afaict the vma is only searched to check upon validity
> > for the address being passed. Once the sem is dropped, the call doesn't
> > do absolutely anything else with the returned vma.
> 
> The function indeed doesn't do anything anymore with the vma itself, but
> it does do something with the addr/len pair, which may no longer match
> with the vma if it changes after the up_read(). I.e. the address may no longer
> be valid when the cache is actually flushed.

Apologies for the delay, I completely forgot about this. 

So I wasn't sure if we *really* required to serialize the entire address
space for this operation. However, looking at other archs, sh seems to
do exactly that, so I guess, at least for safety, we should hold the
lock until we exit the function. I guess taking it as a reader enables
us to guarantee it won't be removed underneath us. So here's v2.

Thanks,
Davidlohr


8<-------------------------------------------------------------------------
From: Davidlohr Bueso <davidlohr@hp.com>
Subject: [PATCH v2] m68k: call find_vma with the mmap_sem held in sys_cacheflush()

Performing vma lookups without taking the mm->mmap_sem is asking
for trouble. While doing the search, the vma in question can be
modified or even removed before returning to the caller. Take the
lock (shared) in order to avoid races while iterating through
the vmacache and/or rbtree. In addition, this guarantees that the
address space will remain intact during the CPU flushing.

Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
---
Completely untested patch.

 arch/m68k/kernel/sys_m68k.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 3a480b3..9aa01ad 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
 asmlinkage int
 sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 {
-	struct vm_area_struct *vma;
 	int ret = -EINVAL;
 
 	if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
@@ -389,17 +388,21 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 		if (!capable(CAP_SYS_ADMIN))
 			goto out;
 	} else {
+		struct vm_area_struct *vma;
+
+		/* Check for overflow.  */
+		if (addr + len < addr)
+			goto out;
+
 		/*
 		 * Verify that the specified address region actually belongs
 		 * to this process.
 		 */
-		vma = find_vma (current->mm, addr);
 		ret = -EINVAL;
-		/* Check for overflow.  */
-		if (addr + len < addr)
-			goto out;
-		if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
-			goto out;
+		down_read(&current->mm->mmap_sem);
+		vma = find_vma(current->mm, addr);
+		if (!vma || addr < vma->vm_start || addr + len > vma->vm_end)
+			goto out_unlock;
 	}
 
 	if (CPU_IS_020_OR_030) {
@@ -429,7 +432,7 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 			__asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr));
 		}
 		ret = 0;
-		goto out;
+		goto out_unlock;
 	} else {
 	    /*
 	     * 040 or 060: don't blindly trust 'scope', someone could
@@ -446,6 +449,8 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 		ret = cache_flush_060 (addr, scope, cache, len);
 	    }
 	}
+out_unlock:
+	up_read(&current->mm->mmap_sem);
 out:
 	return ret;
 }
-- 
1.8.1.4

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

* Re: [PATCH 2/6] m68k: call find_vma with the mmap_sem held in sys_cacheflush()
@ 2014-08-07 22:44           ` Davidlohr Bueso
  0 siblings, 0 replies; 40+ messages in thread
From: Davidlohr Bueso @ 2014-08-07 22:44 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andrew Morton, Aswin Chandramouleeswaran, Linux MM, linux-kernel,
	linux-m68k

Hi Geert,

On Mon, 2014-04-21 at 09:52 +0200, Geert Uytterhoeven wrote:
> Hi David,
> 
> On Mon, Apr 21, 2014 at 12:28 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
> > On Sun, 2014-04-20 at 10:04 +0200, Geert Uytterhoeven wrote:
> >> On Sun, Apr 20, 2014 at 4:26 AM, Davidlohr Bueso <davidlohr@hp.com> wrote:
> >> > Performing vma lookups without taking the mm->mmap_sem is asking
> >> > for trouble. While doing the search, the vma in question can be
> >> > modified or even removed before returning to the caller. Take the
> >> > lock (shared) in order to avoid races while iterating through
> >> > the vmacache and/or rbtree.
> >>
> >> Thanks for your patch!
> >>
> >> > This patch is completely *untested*.
> >> >
> >> > Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
> >> > Cc: Geert Uytterhoeven <geert@linux-m68k.org>
> >> > Cc: linux-m68k@lists.linux-m68k.org
> >> > ---
> >> >  arch/m68k/kernel/sys_m68k.c | 18 ++++++++++++------
> >> >  1 file changed, 12 insertions(+), 6 deletions(-)
> >> >
> >> > diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
> >> > index 3a480b3..d2263a0 100644
> >> > --- a/arch/m68k/kernel/sys_m68k.c
> >> > +++ b/arch/m68k/kernel/sys_m68k.c
> >> > @@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
> >> >  asmlinkage int
> >> >  sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
> >> >  {
> >> > -       struct vm_area_struct *vma;
> >> >         int ret = -EINVAL;
> >> >
> >> >         if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
> >> > @@ -389,16 +388,23 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
> >> >                 if (!capable(CAP_SYS_ADMIN))
> >> >                         goto out;
> >> >         } else {
> >> > +               struct vm_area_struct *vma;
> >> > +               bool invalid;
> >> > +
> >> > +               /* Check for overflow.  */
> >> > +               if (addr + len < addr)
> >> > +                       goto out;
> >> > +
> >> >                 /*
> >> >                  * Verify that the specified address region actually belongs
> >> >                  * to this process.
> >> >                  */
> >> > -               vma = find_vma (current->mm, addr);
> >> >                 ret = -EINVAL;
> >> > -               /* Check for overflow.  */
> >> > -               if (addr + len < addr)
> >> > -                       goto out;
> >> > -               if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
> >> > +               down_read(&current->mm->mmap_sem);
> >> > +               vma = find_vma(current->mm, addr);
> >> > +               invalid = !vma || addr < vma->vm_start || addr + len > vma->vm_end;
> >> > +               up_read(&current->mm->mmap_sem);
> >> > +               if (invalid)
> >> >                         goto out;
> >> >         }
> >>
> >> Shouldn't the up_read() be moved to the end of the function?
> >> The vma may still be modified or destroyed between the call to find_vma(),
> >> and the actual cache flush?
> >
> > I don't think so. afaict the vma is only searched to check upon validity
> > for the address being passed. Once the sem is dropped, the call doesn't
> > do absolutely anything else with the returned vma.
> 
> The function indeed doesn't do anything anymore with the vma itself, but
> it does do something with the addr/len pair, which may no longer match
> with the vma if it changes after the up_read(). I.e. the address may no longer
> be valid when the cache is actually flushed.

Apologies for the delay, I completely forgot about this. 

So I wasn't sure if we *really* required to serialize the entire address
space for this operation. However, looking at other archs, sh seems to
do exactly that, so I guess, at least for safety, we should hold the
lock until we exit the function. I guess taking it as a reader enables
us to guarantee it won't be removed underneath us. So here's v2.

Thanks,
Davidlohr


8<-------------------------------------------------------------------------
From: Davidlohr Bueso <davidlohr@hp.com>
Subject: [PATCH v2] m68k: call find_vma with the mmap_sem held in sys_cacheflush()

Performing vma lookups without taking the mm->mmap_sem is asking
for trouble. While doing the search, the vma in question can be
modified or even removed before returning to the caller. Take the
lock (shared) in order to avoid races while iterating through
the vmacache and/or rbtree. In addition, this guarantees that the
address space will remain intact during the CPU flushing.

Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
---
Completely untested patch.

 arch/m68k/kernel/sys_m68k.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 3a480b3..9aa01ad 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
 asmlinkage int
 sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 {
-	struct vm_area_struct *vma;
 	int ret = -EINVAL;
 
 	if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
@@ -389,17 +388,21 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 		if (!capable(CAP_SYS_ADMIN))
 			goto out;
 	} else {
+		struct vm_area_struct *vma;
+
+		/* Check for overflow.  */
+		if (addr + len < addr)
+			goto out;
+
 		/*
 		 * Verify that the specified address region actually belongs
 		 * to this process.
 		 */
-		vma = find_vma (current->mm, addr);
 		ret = -EINVAL;
-		/* Check for overflow.  */
-		if (addr + len < addr)
-			goto out;
-		if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
-			goto out;
+		down_read(&current->mm->mmap_sem);
+		vma = find_vma(current->mm, addr);
+		if (!vma || addr < vma->vm_start || addr + len > vma->vm_end)
+			goto out_unlock;
 	}
 
 	if (CPU_IS_020_OR_030) {
@@ -429,7 +432,7 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 			__asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr));
 		}
 		ret = 0;
-		goto out;
+		goto out_unlock;
 	} else {
 	    /*
 	     * 040 or 060: don't blindly trust 'scope', someone could
@@ -446,6 +449,8 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 		ret = cache_flush_060 (addr, scope, cache, len);
 	    }
 	}
+out_unlock:
+	up_read(&current->mm->mmap_sem);
 out:
 	return ret;
 }
-- 
1.8.1.4



--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

end of thread, other threads:[~2014-08-07 22:44 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-20  2:26 [PATCH 0/6] mm: audit find_vma() callers Davidlohr Bueso
2014-04-20  2:26 ` Davidlohr Bueso
2014-04-20  2:26 ` [PATCH 1/6] blackfin/ptrace: call find_vma with the mmap_sem held Davidlohr Bueso
2014-04-20  2:26   ` Davidlohr Bueso
2014-04-22  3:07   ` Steven Miao
2014-04-22  3:07     ` Steven Miao
2014-04-20  2:26 ` [PATCH 2/6] m68k: call find_vma with the mmap_sem held in sys_cacheflush() Davidlohr Bueso
2014-04-20  2:26   ` Davidlohr Bueso
2014-04-20  8:04   ` Geert Uytterhoeven
2014-04-20  8:04   ` Geert Uytterhoeven
2014-04-20  8:04     ` Geert Uytterhoeven
2014-04-20 22:28     ` Davidlohr Bueso
2014-04-20 22:28     ` Davidlohr Bueso
2014-04-20 22:28       ` Davidlohr Bueso
2014-04-21  7:52       ` Geert Uytterhoeven
2014-04-21  7:52       ` Geert Uytterhoeven
2014-04-21  7:52         ` Geert Uytterhoeven
     [not found]         ` <OF5CEC4294.867C780E-ONCA257CCB.00315352-CA257CCB.003674E6@csc.com>
2014-05-01 14:05           ` Linux-3.15-rcX - PowerPC Serial Console woes Geert Uytterhoeven
2014-08-07 22:44         ` [PATCH 2/6] m68k: call find_vma with the mmap_sem held in sys_cacheflush() Davidlohr Bueso
2014-08-07 22:44           ` Davidlohr Bueso
2014-08-07 22:44         ` Davidlohr Bueso
2014-04-20  2:26 ` Davidlohr Bueso
2014-04-20  2:26 ` [PATCH 3/6] mips: call find_vma with the mmap_sem held Davidlohr Bueso
2014-04-20  2:26   ` Davidlohr Bueso
2014-04-22 13:25   ` Andreas Herrmann
2014-04-22 13:25     ` Andreas Herrmann
2014-04-20  2:26 ` [PATCH 4/6] arc: " Davidlohr Bueso
2014-04-20  2:26   ` Davidlohr Bueso
2014-04-22  6:02   ` Vineet Gupta
2014-04-22  6:02     ` Vineet Gupta
2014-04-20  2:26 ` [PATCH 5/6] drivers,sgi-gru/grufault.c: " Davidlohr Bueso
2014-04-20  2:26   ` Davidlohr Bueso
2014-04-21 13:36   ` Dimitri Sivanich
2014-04-21 13:36     ` Dimitri Sivanich
2014-04-20  2:26 ` [PATCH 6/6] drm/exynos: " Davidlohr Bueso
2014-04-20  2:26   ` Davidlohr Bueso
2014-04-28 18:09 ` [PATCH 7/6] media: videobuf2-dma-sg: " Davidlohr Bueso
2014-04-28 18:09   ` Davidlohr Bueso
2014-04-29  8:35   ` Marek Szyprowski
2014-04-29  8:35     ` Marek Szyprowski

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.