linux-arch.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 3.18 04/57] vm: add VM_FAULT_SIGSEGV handling support
       [not found] <20150203231211.486950145@linuxfoundation.org>
@ 2015-02-03 23:13 ` Greg Kroah-Hartman
  2015-02-03 23:13   ` Greg Kroah-Hartman
  2015-02-10  8:22   ` Konstantin Khlebnikov
  2015-02-03 23:13 ` [PATCH 3.18 06/57] vm: make stack guard page errors return VM_FAULT_SIGSEGV rather than SIGBUS Greg Kroah-Hartman
  1 sibling, 2 replies; 12+ messages in thread
From: Greg Kroah-Hartman @ 2015-02-03 23:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: Greg Kroah-Hartman, stable, Jan Engelhardt, linux-arch,
	Linus Torvalds

3.18-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Linus Torvalds <torvalds@linux-foundation.org>

commit 33692f27597fcab536d7cbbcc8f52905133e4aa7 upstream.

The core VM already knows about VM_FAULT_SIGBUS, but cannot return a
"you should SIGSEGV" error, because the SIGSEGV case was generally
handled by the caller - usually the architecture fault handler.

That results in lots of duplication - all the architecture fault
handlers end up doing very similar "look up vma, check permissions, do
retries etc" - but it generally works.  However, there are cases where
the VM actually wants to SIGSEGV, and applications _expect_ SIGSEGV.

In particular, when accessing the stack guard page, libsigsegv expects a
SIGSEGV.  And it usually got one, because the stack growth is handled by
that duplicated architecture fault handler.

However, when the generic VM layer started propagating the error return
from the stack expansion in commit fee7e49d4514 ("mm: propagate error
from stack expansion even for guard page"), that now exposed the
existing VM_FAULT_SIGBUS result to user space.  And user space really
expected SIGSEGV, not SIGBUS.

To fix that case, we need to add a VM_FAULT_SIGSEGV, and teach all those
duplicate architecture fault handlers about it.  They all already have
the code to handle SIGSEGV, so it's about just tying that new return
value to the existing code, but it's all a bit annoying.

This is the mindless minimal patch to do this.  A more extensive patch
would be to try to gather up the mostly shared fault handling logic into
one generic helper routine, and long-term we really should do that
cleanup.

Just from this patch, you can generally see that most architectures just
copied (directly or indirectly) the old x86 way of doing things, but in
the meantime that original x86 model has been improved to hold the VM
semaphore for shorter times etc and to handle VM_FAULT_RETRY and other
"newer" things, so it would be a good idea to bring all those
improvements to the generic case and teach other architectures about
them too.

Reported-and-tested-by: Takashi Iwai <tiwai@suse.de>
Tested-by: Jan Engelhardt <jengelh@inai.de>
Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> # "s390 still compiles and boots"
Cc: linux-arch@vger.kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 arch/alpha/mm/fault.c                        |    2 ++
 arch/arc/mm/fault.c                          |    2 ++
 arch/avr32/mm/fault.c                        |    2 ++
 arch/cris/mm/fault.c                         |    2 ++
 arch/frv/mm/fault.c                          |    2 ++
 arch/ia64/mm/fault.c                         |    2 ++
 arch/m32r/mm/fault.c                         |    2 ++
 arch/m68k/mm/fault.c                         |    2 ++
 arch/metag/mm/fault.c                        |    2 ++
 arch/microblaze/mm/fault.c                   |    2 ++
 arch/mips/mm/fault.c                         |    2 ++
 arch/mn10300/mm/fault.c                      |    2 ++
 arch/openrisc/mm/fault.c                     |    2 ++
 arch/parisc/mm/fault.c                       |    2 ++
 arch/powerpc/mm/copro_fault.c                |    2 +-
 arch/powerpc/mm/fault.c                      |    2 ++
 arch/s390/mm/fault.c                         |    6 ++++++
 arch/score/mm/fault.c                        |    2 ++
 arch/sh/mm/fault.c                           |    2 ++
 arch/sparc/mm/fault_32.c                     |    2 ++
 arch/sparc/mm/fault_64.c                     |    2 ++
 arch/tile/mm/fault.c                         |    2 ++
 arch/um/kernel/trap.c                        |    2 ++
 arch/x86/mm/fault.c                          |    2 ++
 arch/xtensa/mm/fault.c                       |    2 ++
 drivers/staging/lustre/lustre/llite/vvp_io.c |    2 +-
 include/linux/mm.h                           |    6 ++++--
 mm/gup.c                                     |    4 ++--
 mm/ksm.c                                     |    2 +-
 29 files changed, 61 insertions(+), 7 deletions(-)

--- a/arch/alpha/mm/fault.c
+++ b/arch/alpha/mm/fault.c
@@ -156,6 +156,8 @@ retry:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/arc/mm/fault.c
+++ b/arch/arc/mm/fault.c
@@ -161,6 +161,8 @@ good_area:
 
 	if (fault & VM_FAULT_OOM)
 		goto out_of_memory;
+	else if (fault & VM_FAULT_SIGSEV)
+		goto bad_area;
 	else if (fault & VM_FAULT_SIGBUS)
 		goto do_sigbus;
 
--- a/arch/avr32/mm/fault.c
+++ b/arch/avr32/mm/fault.c
@@ -142,6 +142,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/cris/mm/fault.c
+++ b/arch/cris/mm/fault.c
@@ -176,6 +176,8 @@ retry:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/frv/mm/fault.c
+++ b/arch/frv/mm/fault.c
@@ -168,6 +168,8 @@ asmlinkage void do_page_fault(int datamm
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -172,6 +172,8 @@ retry:
 		 */
 		if (fault & VM_FAULT_OOM) {
 			goto out_of_memory;
+		} else if (fault & VM_FAULT_SIGSEGV) {
+			goto bad_area;
 		} else if (fault & VM_FAULT_SIGBUS) {
 			signal = SIGBUS;
 			goto bad_area;
--- a/arch/m32r/mm/fault.c
+++ b/arch/m32r/mm/fault.c
@@ -200,6 +200,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/m68k/mm/fault.c
+++ b/arch/m68k/mm/fault.c
@@ -145,6 +145,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto map_err;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto bus_err;
 		BUG();
--- a/arch/metag/mm/fault.c
+++ b/arch/metag/mm/fault.c
@@ -141,6 +141,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/microblaze/mm/fault.c
+++ b/arch/microblaze/mm/fault.c
@@ -224,6 +224,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -158,6 +158,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/mn10300/mm/fault.c
+++ b/arch/mn10300/mm/fault.c
@@ -262,6 +262,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/openrisc/mm/fault.c
+++ b/arch/openrisc/mm/fault.c
@@ -171,6 +171,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -256,6 +256,8 @@ good_area:
 		 */
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto bad_area;
 		BUG();
--- a/arch/powerpc/mm/copro_fault.c
+++ b/arch/powerpc/mm/copro_fault.c
@@ -76,7 +76,7 @@ int copro_handle_mm_fault(struct mm_stru
 		if (*flt & VM_FAULT_OOM) {
 			ret = -ENOMEM;
 			goto out_unlock;
-		} else if (*flt & VM_FAULT_SIGBUS) {
+		} else if (*flt & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) {
 			ret = -EFAULT;
 			goto out_unlock;
 		}
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -444,6 +444,8 @@ good_area:
 	 */
 	fault = handle_mm_fault(mm, vma, address, flags);
 	if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) {
+		if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		rc = mm_fault_error(regs, address, fault);
 		if (rc >= MM_FAULT_RETURN)
 			goto bail;
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -374,6 +374,12 @@ static noinline void do_fault_error(stru
 				do_no_context(regs);
 			else
 				pagefault_out_of_memory();
+		} else if (fault & VM_FAULT_SIGSEGV) {
+			/* Kernel mode? Handle exceptions or die */
+			if (!user_mode(regs))
+				do_no_context(regs);
+			else
+				do_sigsegv(regs, SEGV_MAPERR);
 		} else if (fault & VM_FAULT_SIGBUS) {
 			/* Kernel mode? Handle exceptions or die */
 			if (!user_mode(regs))
--- a/arch/score/mm/fault.c
+++ b/arch/score/mm/fault.c
@@ -114,6 +114,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -353,6 +353,8 @@ mm_fault_error(struct pt_regs *regs, uns
 	} else {
 		if (fault & VM_FAULT_SIGBUS)
 			do_sigbus(regs, error_code, address);
+		else if (fault & VM_FAULT_SIGSEGV)
+			bad_area(regs, error_code, address);
 		else
 			BUG();
 	}
--- a/arch/sparc/mm/fault_32.c
+++ b/arch/sparc/mm/fault_32.c
@@ -249,6 +249,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -446,6 +446,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/tile/mm/fault.c
+++ b/arch/tile/mm/fault.c
@@ -444,6 +444,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -80,6 +80,8 @@ good_area:
 		if (unlikely(fault & VM_FAULT_ERROR)) {
 			if (fault & VM_FAULT_OOM) {
 				goto out_of_memory;
+			} else if (fault & VM_FAULT_SIGSEGV) {
+				goto out;
 			} else if (fault & VM_FAULT_SIGBUS) {
 				err = -EACCES;
 				goto out;
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -905,6 +905,8 @@ mm_fault_error(struct pt_regs *regs, uns
 		if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
 			     VM_FAULT_HWPOISON_LARGE))
 			do_sigbus(regs, error_code, address, fault);
+		else if (fault & VM_FAULT_SIGSEGV)
+			bad_area_nosemaphore(regs, error_code, address);
 		else
 			BUG();
 	}
--- a/arch/xtensa/mm/fault.c
+++ b/arch/xtensa/mm/fault.c
@@ -117,6 +117,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/drivers/staging/lustre/lustre/llite/vvp_io.c
+++ b/drivers/staging/lustre/lustre/llite/vvp_io.c
@@ -632,7 +632,7 @@ static int vvp_io_kernel_fault(struct vv
 		return 0;
 	}
 
-	if (cfio->fault.ft_flags & VM_FAULT_SIGBUS) {
+	if (cfio->fault.ft_flags & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) {
 		CDEBUG(D_PAGE, "got addr %p - SIGBUS\n", vmf->virtual_address);
 		return -EFAULT;
 	}
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1054,6 +1054,7 @@ static inline int page_mapped(struct pag
 #define VM_FAULT_WRITE	0x0008	/* Special case for get_user_pages */
 #define VM_FAULT_HWPOISON 0x0010	/* Hit poisoned small page */
 #define VM_FAULT_HWPOISON_LARGE 0x0020  /* Hit poisoned large page. Index encoded in upper bits */
+#define VM_FAULT_SIGSEGV 0x0040
 
 #define VM_FAULT_NOPAGE	0x0100	/* ->fault installed the pte, not return page */
 #define VM_FAULT_LOCKED	0x0200	/* ->fault locked the returned page */
@@ -1062,8 +1063,9 @@ static inline int page_mapped(struct pag
 
 #define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */
 
-#define VM_FAULT_ERROR	(VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON | \
-			 VM_FAULT_FALLBACK | VM_FAULT_HWPOISON_LARGE)
+#define VM_FAULT_ERROR	(VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \
+			 VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE | \
+			 VM_FAULT_FALLBACK)
 
 /* Encode hstate index for a hwpoisoned large page */
 #define VM_FAULT_SET_HINDEX(x) ((x) << 12)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -296,7 +296,7 @@ static int faultin_page(struct task_stru
 			return -ENOMEM;
 		if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE))
 			return *flags & FOLL_HWPOISON ? -EHWPOISON : -EFAULT;
-		if (ret & VM_FAULT_SIGBUS)
+		if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV))
 			return -EFAULT;
 		BUG();
 	}
@@ -571,7 +571,7 @@ int fixup_user_fault(struct task_struct
 			return -ENOMEM;
 		if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE))
 			return -EHWPOISON;
-		if (ret & VM_FAULT_SIGBUS)
+		if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV))
 			return -EFAULT;
 		BUG();
 	}
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -376,7 +376,7 @@ static int break_ksm(struct vm_area_stru
 		else
 			ret = VM_FAULT_WRITE;
 		put_page(page);
-	} while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_OOM)));
+	} while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | VM_FAULT_OOM)));
 	/*
 	 * We must loop because handle_mm_fault() may back out if there's
 	 * any difficulty e.g. if pte accessed bit gets updated concurrently.

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

* [PATCH 3.18 04/57] vm: add VM_FAULT_SIGSEGV handling support
  2015-02-03 23:13 ` [PATCH 3.18 04/57] vm: add VM_FAULT_SIGSEGV handling support Greg Kroah-Hartman
@ 2015-02-03 23:13   ` Greg Kroah-Hartman
  2015-02-10  8:22   ` Konstantin Khlebnikov
  1 sibling, 0 replies; 12+ messages in thread
From: Greg Kroah-Hartman @ 2015-02-03 23:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: Greg Kroah-Hartman, stable, Jan Engelhardt, linux-arch,
	Linus Torvalds

3.18-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Linus Torvalds <torvalds@linux-foundation.org>

commit 33692f27597fcab536d7cbbcc8f52905133e4aa7 upstream.

The core VM already knows about VM_FAULT_SIGBUS, but cannot return a
"you should SIGSEGV" error, because the SIGSEGV case was generally
handled by the caller - usually the architecture fault handler.

That results in lots of duplication - all the architecture fault
handlers end up doing very similar "look up vma, check permissions, do
retries etc" - but it generally works.  However, there are cases where
the VM actually wants to SIGSEGV, and applications _expect_ SIGSEGV.

In particular, when accessing the stack guard page, libsigsegv expects a
SIGSEGV.  And it usually got one, because the stack growth is handled by
that duplicated architecture fault handler.

However, when the generic VM layer started propagating the error return
from the stack expansion in commit fee7e49d4514 ("mm: propagate error
from stack expansion even for guard page"), that now exposed the
existing VM_FAULT_SIGBUS result to user space.  And user space really
expected SIGSEGV, not SIGBUS.

To fix that case, we need to add a VM_FAULT_SIGSEGV, and teach all those
duplicate architecture fault handlers about it.  They all already have
the code to handle SIGSEGV, so it's about just tying that new return
value to the existing code, but it's all a bit annoying.

This is the mindless minimal patch to do this.  A more extensive patch
would be to try to gather up the mostly shared fault handling logic into
one generic helper routine, and long-term we really should do that
cleanup.

Just from this patch, you can generally see that most architectures just
copied (directly or indirectly) the old x86 way of doing things, but in
the meantime that original x86 model has been improved to hold the VM
semaphore for shorter times etc and to handle VM_FAULT_RETRY and other
"newer" things, so it would be a good idea to bring all those
improvements to the generic case and teach other architectures about
them too.

Reported-and-tested-by: Takashi Iwai <tiwai@suse.de>
Tested-by: Jan Engelhardt <jengelh@inai.de>
Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> # "s390 still compiles and boots"
Cc: linux-arch@vger.kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 arch/alpha/mm/fault.c                        |    2 ++
 arch/arc/mm/fault.c                          |    2 ++
 arch/avr32/mm/fault.c                        |    2 ++
 arch/cris/mm/fault.c                         |    2 ++
 arch/frv/mm/fault.c                          |    2 ++
 arch/ia64/mm/fault.c                         |    2 ++
 arch/m32r/mm/fault.c                         |    2 ++
 arch/m68k/mm/fault.c                         |    2 ++
 arch/metag/mm/fault.c                        |    2 ++
 arch/microblaze/mm/fault.c                   |    2 ++
 arch/mips/mm/fault.c                         |    2 ++
 arch/mn10300/mm/fault.c                      |    2 ++
 arch/openrisc/mm/fault.c                     |    2 ++
 arch/parisc/mm/fault.c                       |    2 ++
 arch/powerpc/mm/copro_fault.c                |    2 +-
 arch/powerpc/mm/fault.c                      |    2 ++
 arch/s390/mm/fault.c                         |    6 ++++++
 arch/score/mm/fault.c                        |    2 ++
 arch/sh/mm/fault.c                           |    2 ++
 arch/sparc/mm/fault_32.c                     |    2 ++
 arch/sparc/mm/fault_64.c                     |    2 ++
 arch/tile/mm/fault.c                         |    2 ++
 arch/um/kernel/trap.c                        |    2 ++
 arch/x86/mm/fault.c                          |    2 ++
 arch/xtensa/mm/fault.c                       |    2 ++
 drivers/staging/lustre/lustre/llite/vvp_io.c |    2 +-
 include/linux/mm.h                           |    6 ++++--
 mm/gup.c                                     |    4 ++--
 mm/ksm.c                                     |    2 +-
 29 files changed, 61 insertions(+), 7 deletions(-)

--- a/arch/alpha/mm/fault.c
+++ b/arch/alpha/mm/fault.c
@@ -156,6 +156,8 @@ retry:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/arc/mm/fault.c
+++ b/arch/arc/mm/fault.c
@@ -161,6 +161,8 @@ good_area:
 
 	if (fault & VM_FAULT_OOM)
 		goto out_of_memory;
+	else if (fault & VM_FAULT_SIGSEV)
+		goto bad_area;
 	else if (fault & VM_FAULT_SIGBUS)
 		goto do_sigbus;
 
--- a/arch/avr32/mm/fault.c
+++ b/arch/avr32/mm/fault.c
@@ -142,6 +142,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/cris/mm/fault.c
+++ b/arch/cris/mm/fault.c
@@ -176,6 +176,8 @@ retry:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/frv/mm/fault.c
+++ b/arch/frv/mm/fault.c
@@ -168,6 +168,8 @@ asmlinkage void do_page_fault(int datamm
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -172,6 +172,8 @@ retry:
 		 */
 		if (fault & VM_FAULT_OOM) {
 			goto out_of_memory;
+		} else if (fault & VM_FAULT_SIGSEGV) {
+			goto bad_area;
 		} else if (fault & VM_FAULT_SIGBUS) {
 			signal = SIGBUS;
 			goto bad_area;
--- a/arch/m32r/mm/fault.c
+++ b/arch/m32r/mm/fault.c
@@ -200,6 +200,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/m68k/mm/fault.c
+++ b/arch/m68k/mm/fault.c
@@ -145,6 +145,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto map_err;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto bus_err;
 		BUG();
--- a/arch/metag/mm/fault.c
+++ b/arch/metag/mm/fault.c
@@ -141,6 +141,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/microblaze/mm/fault.c
+++ b/arch/microblaze/mm/fault.c
@@ -224,6 +224,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -158,6 +158,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/mn10300/mm/fault.c
+++ b/arch/mn10300/mm/fault.c
@@ -262,6 +262,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/openrisc/mm/fault.c
+++ b/arch/openrisc/mm/fault.c
@@ -171,6 +171,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -256,6 +256,8 @@ good_area:
 		 */
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto bad_area;
 		BUG();
--- a/arch/powerpc/mm/copro_fault.c
+++ b/arch/powerpc/mm/copro_fault.c
@@ -76,7 +76,7 @@ int copro_handle_mm_fault(struct mm_stru
 		if (*flt & VM_FAULT_OOM) {
 			ret = -ENOMEM;
 			goto out_unlock;
-		} else if (*flt & VM_FAULT_SIGBUS) {
+		} else if (*flt & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) {
 			ret = -EFAULT;
 			goto out_unlock;
 		}
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -444,6 +444,8 @@ good_area:
 	 */
 	fault = handle_mm_fault(mm, vma, address, flags);
 	if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) {
+		if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		rc = mm_fault_error(regs, address, fault);
 		if (rc >= MM_FAULT_RETURN)
 			goto bail;
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -374,6 +374,12 @@ static noinline void do_fault_error(stru
 				do_no_context(regs);
 			else
 				pagefault_out_of_memory();
+		} else if (fault & VM_FAULT_SIGSEGV) {
+			/* Kernel mode? Handle exceptions or die */
+			if (!user_mode(regs))
+				do_no_context(regs);
+			else
+				do_sigsegv(regs, SEGV_MAPERR);
 		} else if (fault & VM_FAULT_SIGBUS) {
 			/* Kernel mode? Handle exceptions or die */
 			if (!user_mode(regs))
--- a/arch/score/mm/fault.c
+++ b/arch/score/mm/fault.c
@@ -114,6 +114,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -353,6 +353,8 @@ mm_fault_error(struct pt_regs *regs, uns
 	} else {
 		if (fault & VM_FAULT_SIGBUS)
 			do_sigbus(regs, error_code, address);
+		else if (fault & VM_FAULT_SIGSEGV)
+			bad_area(regs, error_code, address);
 		else
 			BUG();
 	}
--- a/arch/sparc/mm/fault_32.c
+++ b/arch/sparc/mm/fault_32.c
@@ -249,6 +249,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -446,6 +446,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/tile/mm/fault.c
+++ b/arch/tile/mm/fault.c
@@ -444,6 +444,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -80,6 +80,8 @@ good_area:
 		if (unlikely(fault & VM_FAULT_ERROR)) {
 			if (fault & VM_FAULT_OOM) {
 				goto out_of_memory;
+			} else if (fault & VM_FAULT_SIGSEGV) {
+				goto out;
 			} else if (fault & VM_FAULT_SIGBUS) {
 				err = -EACCES;
 				goto out;
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -905,6 +905,8 @@ mm_fault_error(struct pt_regs *regs, uns
 		if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
 			     VM_FAULT_HWPOISON_LARGE))
 			do_sigbus(regs, error_code, address, fault);
+		else if (fault & VM_FAULT_SIGSEGV)
+			bad_area_nosemaphore(regs, error_code, address);
 		else
 			BUG();
 	}
--- a/arch/xtensa/mm/fault.c
+++ b/arch/xtensa/mm/fault.c
@@ -117,6 +117,8 @@ good_area:
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
 		else if (fault & VM_FAULT_SIGBUS)
 			goto do_sigbus;
 		BUG();
--- a/drivers/staging/lustre/lustre/llite/vvp_io.c
+++ b/drivers/staging/lustre/lustre/llite/vvp_io.c
@@ -632,7 +632,7 @@ static int vvp_io_kernel_fault(struct vv
 		return 0;
 	}
 
-	if (cfio->fault.ft_flags & VM_FAULT_SIGBUS) {
+	if (cfio->fault.ft_flags & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) {
 		CDEBUG(D_PAGE, "got addr %p - SIGBUS\n", vmf->virtual_address);
 		return -EFAULT;
 	}
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1054,6 +1054,7 @@ static inline int page_mapped(struct pag
 #define VM_FAULT_WRITE	0x0008	/* Special case for get_user_pages */
 #define VM_FAULT_HWPOISON 0x0010	/* Hit poisoned small page */
 #define VM_FAULT_HWPOISON_LARGE 0x0020  /* Hit poisoned large page. Index encoded in upper bits */
+#define VM_FAULT_SIGSEGV 0x0040
 
 #define VM_FAULT_NOPAGE	0x0100	/* ->fault installed the pte, not return page */
 #define VM_FAULT_LOCKED	0x0200	/* ->fault locked the returned page */
@@ -1062,8 +1063,9 @@ static inline int page_mapped(struct pag
 
 #define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */
 
-#define VM_FAULT_ERROR	(VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON | \
-			 VM_FAULT_FALLBACK | VM_FAULT_HWPOISON_LARGE)
+#define VM_FAULT_ERROR	(VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \
+			 VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE | \
+			 VM_FAULT_FALLBACK)
 
 /* Encode hstate index for a hwpoisoned large page */
 #define VM_FAULT_SET_HINDEX(x) ((x) << 12)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -296,7 +296,7 @@ static int faultin_page(struct task_stru
 			return -ENOMEM;
 		if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE))
 			return *flags & FOLL_HWPOISON ? -EHWPOISON : -EFAULT;
-		if (ret & VM_FAULT_SIGBUS)
+		if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV))
 			return -EFAULT;
 		BUG();
 	}
@@ -571,7 +571,7 @@ int fixup_user_fault(struct task_struct
 			return -ENOMEM;
 		if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE))
 			return -EHWPOISON;
-		if (ret & VM_FAULT_SIGBUS)
+		if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV))
 			return -EFAULT;
 		BUG();
 	}
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -376,7 +376,7 @@ static int break_ksm(struct vm_area_stru
 		else
 			ret = VM_FAULT_WRITE;
 		put_page(page);
-	} while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_OOM)));
+	} while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | VM_FAULT_OOM)));
 	/*
 	 * We must loop because handle_mm_fault() may back out if there's
 	 * any difficulty e.g. if pte accessed bit gets updated concurrently.



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

* [PATCH 3.18 06/57] vm: make stack guard page errors return VM_FAULT_SIGSEGV rather than SIGBUS
       [not found] <20150203231211.486950145@linuxfoundation.org>
  2015-02-03 23:13 ` [PATCH 3.18 04/57] vm: add VM_FAULT_SIGSEGV handling support Greg Kroah-Hartman
@ 2015-02-03 23:13 ` Greg Kroah-Hartman
  1 sibling, 0 replies; 12+ messages in thread
From: Greg Kroah-Hartman @ 2015-02-03 23:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: Greg Kroah-Hartman, stable, Jan Engelhardt, linux-arch,
	Linus Torvalds

3.18-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Linus Torvalds <torvalds@linux-foundation.org>

commit 9c145c56d0c8a0b62e48c8d71e055ad0fb2012ba upstream.

The stack guard page error case has long incorrectly caused a SIGBUS
rather than a SIGSEGV, but nobody actually noticed until commit
fee7e49d4514 ("mm: propagate error from stack expansion even for guard
page") because that error case was never actually triggered in any
normal situations.

Now that we actually report the error, people noticed the wrong signal
that resulted.  So far, only the test suite of libsigsegv seems to have
actually cared, but there are real applications that use libsigsegv, so
let's not wait for any of those to break.

Reported-and-tested-by: Takashi Iwai <tiwai@suse.de>
Tested-by: Jan Engelhardt <jengelh@inai.de>
Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> # "s390 still compiles and boots"
Cc: linux-arch@vger.kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 mm/memory.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2645,7 +2645,7 @@ static int do_anonymous_page(struct mm_s
 
 	/* Check if we need to add a guard page to the stack */
 	if (check_stack_guard_page(vma, address) < 0)
-		return VM_FAULT_SIGBUS;
+		return VM_FAULT_SIGSEGV;
 
 	/* Use the zero-page for reads */
 	if (!(flags & FAULT_FLAG_WRITE)) {

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

* Re: [PATCH 3.18 04/57] vm: add VM_FAULT_SIGSEGV handling support
  2015-02-03 23:13 ` [PATCH 3.18 04/57] vm: add VM_FAULT_SIGSEGV handling support Greg Kroah-Hartman
  2015-02-03 23:13   ` Greg Kroah-Hartman
@ 2015-02-10  8:22   ` Konstantin Khlebnikov
  2015-02-11  3:43     ` Greg Kroah-Hartman
  2015-02-16  9:50     ` Luis Henriques
  1 sibling, 2 replies; 12+ messages in thread
From: Konstantin Khlebnikov @ 2015-02-10  8:22 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Linux Kernel Mailing List, Stable, Jan Engelhardt, linux-arch,
	Linus Torvalds, linux-mm@kvack.org

I've found regression:

[  257.139907] ================================================
[  257.139909] [ BUG: lock held when returning to user space! ]
[  257.139912] 3.18.6-debug+ #161 Tainted: G     U
[  257.139914] ------------------------------------------------
[  257.139916] python/22843 is leaving the kernel with locks still held!
[  257.139918] 1 lock held by python/22843:
[  257.139920]  #0:  (&mm->mmap_sem){++++++}, at: [<ffffffff8104e4c2>]
__do_page_fault+0x162/0x570

upstream commit 7fb08eca45270d0ae86e1ad9d39c40b7a55d0190 must be backported too.

On Wed, Feb 4, 2015 at 2:13 AM, Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
> 3.18-stable review patch.  If anyone has any objections, please let me know.
>
> ------------------
>
> From: Linus Torvalds <torvalds@linux-foundation.org>
>
> commit 33692f27597fcab536d7cbbcc8f52905133e4aa7 upstream.
>
> The core VM already knows about VM_FAULT_SIGBUS, but cannot return a
> "you should SIGSEGV" error, because the SIGSEGV case was generally
> handled by the caller - usually the architecture fault handler.
>
> That results in lots of duplication - all the architecture fault
> handlers end up doing very similar "look up vma, check permissions, do
> retries etc" - but it generally works.  However, there are cases where
> the VM actually wants to SIGSEGV, and applications _expect_ SIGSEGV.
>
> In particular, when accessing the stack guard page, libsigsegv expects a
> SIGSEGV.  And it usually got one, because the stack growth is handled by
> that duplicated architecture fault handler.
>
> However, when the generic VM layer started propagating the error return
> from the stack expansion in commit fee7e49d4514 ("mm: propagate error
> from stack expansion even for guard page"), that now exposed the
> existing VM_FAULT_SIGBUS result to user space.  And user space really
> expected SIGSEGV, not SIGBUS.
>
> To fix that case, we need to add a VM_FAULT_SIGSEGV, and teach all those
> duplicate architecture fault handlers about it.  They all already have
> the code to handle SIGSEGV, so it's about just tying that new return
> value to the existing code, but it's all a bit annoying.
>
> This is the mindless minimal patch to do this.  A more extensive patch
> would be to try to gather up the mostly shared fault handling logic into
> one generic helper routine, and long-term we really should do that
> cleanup.
>
> Just from this patch, you can generally see that most architectures just
> copied (directly or indirectly) the old x86 way of doing things, but in
> the meantime that original x86 model has been improved to hold the VM
> semaphore for shorter times etc and to handle VM_FAULT_RETRY and other
> "newer" things, so it would be a good idea to bring all those
> improvements to the generic case and teach other architectures about
> them too.
>
> Reported-and-tested-by: Takashi Iwai <tiwai@suse.de>
> Tested-by: Jan Engelhardt <jengelh@inai.de>
> Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> # "s390 still compiles and boots"
> Cc: linux-arch@vger.kernel.org
> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>
> ---
>  arch/alpha/mm/fault.c                        |    2 ++
>  arch/arc/mm/fault.c                          |    2 ++
>  arch/avr32/mm/fault.c                        |    2 ++
>  arch/cris/mm/fault.c                         |    2 ++
>  arch/frv/mm/fault.c                          |    2 ++
>  arch/ia64/mm/fault.c                         |    2 ++
>  arch/m32r/mm/fault.c                         |    2 ++
>  arch/m68k/mm/fault.c                         |    2 ++
>  arch/metag/mm/fault.c                        |    2 ++
>  arch/microblaze/mm/fault.c                   |    2 ++
>  arch/mips/mm/fault.c                         |    2 ++
>  arch/mn10300/mm/fault.c                      |    2 ++
>  arch/openrisc/mm/fault.c                     |    2 ++
>  arch/parisc/mm/fault.c                       |    2 ++
>  arch/powerpc/mm/copro_fault.c                |    2 +-
>  arch/powerpc/mm/fault.c                      |    2 ++
>  arch/s390/mm/fault.c                         |    6 ++++++
>  arch/score/mm/fault.c                        |    2 ++
>  arch/sh/mm/fault.c                           |    2 ++
>  arch/sparc/mm/fault_32.c                     |    2 ++
>  arch/sparc/mm/fault_64.c                     |    2 ++
>  arch/tile/mm/fault.c                         |    2 ++
>  arch/um/kernel/trap.c                        |    2 ++
>  arch/x86/mm/fault.c                          |    2 ++
>  arch/xtensa/mm/fault.c                       |    2 ++
>  drivers/staging/lustre/lustre/llite/vvp_io.c |    2 +-
>  include/linux/mm.h                           |    6 ++++--
>  mm/gup.c                                     |    4 ++--
>  mm/ksm.c                                     |    2 +-
>  29 files changed, 61 insertions(+), 7 deletions(-)
>
> --- a/arch/alpha/mm/fault.c
> +++ b/arch/alpha/mm/fault.c
> @@ -156,6 +156,8 @@ retry:
>         if (unlikely(fault & VM_FAULT_ERROR)) {
>                 if (fault & VM_FAULT_OOM)
>                         goto out_of_memory;
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       goto bad_area;
>                 else if (fault & VM_FAULT_SIGBUS)
>                         goto do_sigbus;
>                 BUG();
> --- a/arch/arc/mm/fault.c
> +++ b/arch/arc/mm/fault.c
> @@ -161,6 +161,8 @@ good_area:
>
>         if (fault & VM_FAULT_OOM)
>                 goto out_of_memory;
> +       else if (fault & VM_FAULT_SIGSEV)
> +               goto bad_area;
>         else if (fault & VM_FAULT_SIGBUS)
>                 goto do_sigbus;
>
> --- a/arch/avr32/mm/fault.c
> +++ b/arch/avr32/mm/fault.c
> @@ -142,6 +142,8 @@ good_area:
>         if (unlikely(fault & VM_FAULT_ERROR)) {
>                 if (fault & VM_FAULT_OOM)
>                         goto out_of_memory;
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       goto bad_area;
>                 else if (fault & VM_FAULT_SIGBUS)
>                         goto do_sigbus;
>                 BUG();
> --- a/arch/cris/mm/fault.c
> +++ b/arch/cris/mm/fault.c
> @@ -176,6 +176,8 @@ retry:
>         if (unlikely(fault & VM_FAULT_ERROR)) {
>                 if (fault & VM_FAULT_OOM)
>                         goto out_of_memory;
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       goto bad_area;
>                 else if (fault & VM_FAULT_SIGBUS)
>                         goto do_sigbus;
>                 BUG();
> --- a/arch/frv/mm/fault.c
> +++ b/arch/frv/mm/fault.c
> @@ -168,6 +168,8 @@ asmlinkage void do_page_fault(int datamm
>         if (unlikely(fault & VM_FAULT_ERROR)) {
>                 if (fault & VM_FAULT_OOM)
>                         goto out_of_memory;
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       goto bad_area;
>                 else if (fault & VM_FAULT_SIGBUS)
>                         goto do_sigbus;
>                 BUG();
> --- a/arch/ia64/mm/fault.c
> +++ b/arch/ia64/mm/fault.c
> @@ -172,6 +172,8 @@ retry:
>                  */
>                 if (fault & VM_FAULT_OOM) {
>                         goto out_of_memory;
> +               } else if (fault & VM_FAULT_SIGSEGV) {
> +                       goto bad_area;
>                 } else if (fault & VM_FAULT_SIGBUS) {
>                         signal = SIGBUS;
>                         goto bad_area;
> --- a/arch/m32r/mm/fault.c
> +++ b/arch/m32r/mm/fault.c
> @@ -200,6 +200,8 @@ good_area:
>         if (unlikely(fault & VM_FAULT_ERROR)) {
>                 if (fault & VM_FAULT_OOM)
>                         goto out_of_memory;
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       goto bad_area;
>                 else if (fault & VM_FAULT_SIGBUS)
>                         goto do_sigbus;
>                 BUG();
> --- a/arch/m68k/mm/fault.c
> +++ b/arch/m68k/mm/fault.c
> @@ -145,6 +145,8 @@ good_area:
>         if (unlikely(fault & VM_FAULT_ERROR)) {
>                 if (fault & VM_FAULT_OOM)
>                         goto out_of_memory;
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       goto map_err;
>                 else if (fault & VM_FAULT_SIGBUS)
>                         goto bus_err;
>                 BUG();
> --- a/arch/metag/mm/fault.c
> +++ b/arch/metag/mm/fault.c
> @@ -141,6 +141,8 @@ good_area:
>         if (unlikely(fault & VM_FAULT_ERROR)) {
>                 if (fault & VM_FAULT_OOM)
>                         goto out_of_memory;
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       goto bad_area;
>                 else if (fault & VM_FAULT_SIGBUS)
>                         goto do_sigbus;
>                 BUG();
> --- a/arch/microblaze/mm/fault.c
> +++ b/arch/microblaze/mm/fault.c
> @@ -224,6 +224,8 @@ good_area:
>         if (unlikely(fault & VM_FAULT_ERROR)) {
>                 if (fault & VM_FAULT_OOM)
>                         goto out_of_memory;
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       goto bad_area;
>                 else if (fault & VM_FAULT_SIGBUS)
>                         goto do_sigbus;
>                 BUG();
> --- a/arch/mips/mm/fault.c
> +++ b/arch/mips/mm/fault.c
> @@ -158,6 +158,8 @@ good_area:
>         if (unlikely(fault & VM_FAULT_ERROR)) {
>                 if (fault & VM_FAULT_OOM)
>                         goto out_of_memory;
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       goto bad_area;
>                 else if (fault & VM_FAULT_SIGBUS)
>                         goto do_sigbus;
>                 BUG();
> --- a/arch/mn10300/mm/fault.c
> +++ b/arch/mn10300/mm/fault.c
> @@ -262,6 +262,8 @@ good_area:
>         if (unlikely(fault & VM_FAULT_ERROR)) {
>                 if (fault & VM_FAULT_OOM)
>                         goto out_of_memory;
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       goto bad_area;
>                 else if (fault & VM_FAULT_SIGBUS)
>                         goto do_sigbus;
>                 BUG();
> --- a/arch/openrisc/mm/fault.c
> +++ b/arch/openrisc/mm/fault.c
> @@ -171,6 +171,8 @@ good_area:
>         if (unlikely(fault & VM_FAULT_ERROR)) {
>                 if (fault & VM_FAULT_OOM)
>                         goto out_of_memory;
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       goto bad_area;
>                 else if (fault & VM_FAULT_SIGBUS)
>                         goto do_sigbus;
>                 BUG();
> --- a/arch/parisc/mm/fault.c
> +++ b/arch/parisc/mm/fault.c
> @@ -256,6 +256,8 @@ good_area:
>                  */
>                 if (fault & VM_FAULT_OOM)
>                         goto out_of_memory;
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       goto bad_area;
>                 else if (fault & VM_FAULT_SIGBUS)
>                         goto bad_area;
>                 BUG();
> --- a/arch/powerpc/mm/copro_fault.c
> +++ b/arch/powerpc/mm/copro_fault.c
> @@ -76,7 +76,7 @@ int copro_handle_mm_fault(struct mm_stru
>                 if (*flt & VM_FAULT_OOM) {
>                         ret = -ENOMEM;
>                         goto out_unlock;
> -               } else if (*flt & VM_FAULT_SIGBUS) {
> +               } else if (*flt & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) {
>                         ret = -EFAULT;
>                         goto out_unlock;
>                 }
> --- a/arch/powerpc/mm/fault.c
> +++ b/arch/powerpc/mm/fault.c
> @@ -444,6 +444,8 @@ good_area:
>          */
>         fault = handle_mm_fault(mm, vma, address, flags);
>         if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) {
> +               if (fault & VM_FAULT_SIGSEGV)
> +                       goto bad_area;
>                 rc = mm_fault_error(regs, address, fault);
>                 if (rc >= MM_FAULT_RETURN)
>                         goto bail;
> --- a/arch/s390/mm/fault.c
> +++ b/arch/s390/mm/fault.c
> @@ -374,6 +374,12 @@ static noinline void do_fault_error(stru
>                                 do_no_context(regs);
>                         else
>                                 pagefault_out_of_memory();
> +               } else if (fault & VM_FAULT_SIGSEGV) {
> +                       /* Kernel mode? Handle exceptions or die */
> +                       if (!user_mode(regs))
> +                               do_no_context(regs);
> +                       else
> +                               do_sigsegv(regs, SEGV_MAPERR);
>                 } else if (fault & VM_FAULT_SIGBUS) {
>                         /* Kernel mode? Handle exceptions or die */
>                         if (!user_mode(regs))
> --- a/arch/score/mm/fault.c
> +++ b/arch/score/mm/fault.c
> @@ -114,6 +114,8 @@ good_area:
>         if (unlikely(fault & VM_FAULT_ERROR)) {
>                 if (fault & VM_FAULT_OOM)
>                         goto out_of_memory;
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       goto bad_area;
>                 else if (fault & VM_FAULT_SIGBUS)
>                         goto do_sigbus;
>                 BUG();
> --- a/arch/sh/mm/fault.c
> +++ b/arch/sh/mm/fault.c
> @@ -353,6 +353,8 @@ mm_fault_error(struct pt_regs *regs, uns
>         } else {
>                 if (fault & VM_FAULT_SIGBUS)
>                         do_sigbus(regs, error_code, address);
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       bad_area(regs, error_code, address);
>                 else
>                         BUG();
>         }
> --- a/arch/sparc/mm/fault_32.c
> +++ b/arch/sparc/mm/fault_32.c
> @@ -249,6 +249,8 @@ good_area:
>         if (unlikely(fault & VM_FAULT_ERROR)) {
>                 if (fault & VM_FAULT_OOM)
>                         goto out_of_memory;
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       goto bad_area;
>                 else if (fault & VM_FAULT_SIGBUS)
>                         goto do_sigbus;
>                 BUG();
> --- a/arch/sparc/mm/fault_64.c
> +++ b/arch/sparc/mm/fault_64.c
> @@ -446,6 +446,8 @@ good_area:
>         if (unlikely(fault & VM_FAULT_ERROR)) {
>                 if (fault & VM_FAULT_OOM)
>                         goto out_of_memory;
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       goto bad_area;
>                 else if (fault & VM_FAULT_SIGBUS)
>                         goto do_sigbus;
>                 BUG();
> --- a/arch/tile/mm/fault.c
> +++ b/arch/tile/mm/fault.c
> @@ -444,6 +444,8 @@ good_area:
>         if (unlikely(fault & VM_FAULT_ERROR)) {
>                 if (fault & VM_FAULT_OOM)
>                         goto out_of_memory;
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       goto bad_area;
>                 else if (fault & VM_FAULT_SIGBUS)
>                         goto do_sigbus;
>                 BUG();
> --- a/arch/um/kernel/trap.c
> +++ b/arch/um/kernel/trap.c
> @@ -80,6 +80,8 @@ good_area:
>                 if (unlikely(fault & VM_FAULT_ERROR)) {
>                         if (fault & VM_FAULT_OOM) {
>                                 goto out_of_memory;
> +                       } else if (fault & VM_FAULT_SIGSEGV) {
> +                               goto out;
>                         } else if (fault & VM_FAULT_SIGBUS) {
>                                 err = -EACCES;
>                                 goto out;
> --- a/arch/x86/mm/fault.c
> +++ b/arch/x86/mm/fault.c
> @@ -905,6 +905,8 @@ mm_fault_error(struct pt_regs *regs, uns
>                 if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
>                              VM_FAULT_HWPOISON_LARGE))
>                         do_sigbus(regs, error_code, address, fault);
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       bad_area_nosemaphore(regs, error_code, address);
>                 else
>                         BUG();
>         }
> --- a/arch/xtensa/mm/fault.c
> +++ b/arch/xtensa/mm/fault.c
> @@ -117,6 +117,8 @@ good_area:
>         if (unlikely(fault & VM_FAULT_ERROR)) {
>                 if (fault & VM_FAULT_OOM)
>                         goto out_of_memory;
> +               else if (fault & VM_FAULT_SIGSEGV)
> +                       goto bad_area;
>                 else if (fault & VM_FAULT_SIGBUS)
>                         goto do_sigbus;
>                 BUG();
> --- a/drivers/staging/lustre/lustre/llite/vvp_io.c
> +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c
> @@ -632,7 +632,7 @@ static int vvp_io_kernel_fault(struct vv
>                 return 0;
>         }
>
> -       if (cfio->fault.ft_flags & VM_FAULT_SIGBUS) {
> +       if (cfio->fault.ft_flags & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) {
>                 CDEBUG(D_PAGE, "got addr %p - SIGBUS\n", vmf->virtual_address);
>                 return -EFAULT;
>         }
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -1054,6 +1054,7 @@ static inline int page_mapped(struct pag
>  #define VM_FAULT_WRITE 0x0008  /* Special case for get_user_pages */
>  #define VM_FAULT_HWPOISON 0x0010       /* Hit poisoned small page */
>  #define VM_FAULT_HWPOISON_LARGE 0x0020  /* Hit poisoned large page. Index encoded in upper bits */
> +#define VM_FAULT_SIGSEGV 0x0040
>
>  #define VM_FAULT_NOPAGE        0x0100  /* ->fault installed the pte, not return page */
>  #define VM_FAULT_LOCKED        0x0200  /* ->fault locked the returned page */
> @@ -1062,8 +1063,9 @@ static inline int page_mapped(struct pag
>
>  #define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */
>
> -#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON | \
> -                        VM_FAULT_FALLBACK | VM_FAULT_HWPOISON_LARGE)
> +#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \
> +                        VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE | \
> +                        VM_FAULT_FALLBACK)
>
>  /* Encode hstate index for a hwpoisoned large page */
>  #define VM_FAULT_SET_HINDEX(x) ((x) << 12)
> --- a/mm/gup.c
> +++ b/mm/gup.c
> @@ -296,7 +296,7 @@ static int faultin_page(struct task_stru
>                         return -ENOMEM;
>                 if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE))
>                         return *flags & FOLL_HWPOISON ? -EHWPOISON : -EFAULT;
> -               if (ret & VM_FAULT_SIGBUS)
> +               if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV))
>                         return -EFAULT;
>                 BUG();
>         }
> @@ -571,7 +571,7 @@ int fixup_user_fault(struct task_struct
>                         return -ENOMEM;
>                 if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE))
>                         return -EHWPOISON;
> -               if (ret & VM_FAULT_SIGBUS)
> +               if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV))
>                         return -EFAULT;
>                 BUG();
>         }
> --- a/mm/ksm.c
> +++ b/mm/ksm.c
> @@ -376,7 +376,7 @@ static int break_ksm(struct vm_area_stru
>                 else
>                         ret = VM_FAULT_WRITE;
>                 put_page(page);
> -       } while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_OOM)));
> +       } while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | VM_FAULT_OOM)));
>         /*
>          * We must loop because handle_mm_fault() may back out if there's
>          * any difficulty e.g. if pte accessed bit gets updated concurrently.
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [PATCH 3.18 04/57] vm: add VM_FAULT_SIGSEGV handling support
  2015-02-10  8:22   ` Konstantin Khlebnikov
@ 2015-02-11  3:43     ` Greg Kroah-Hartman
  2015-02-11  3:43       ` Greg Kroah-Hartman
                         ` (2 more replies)
  2015-02-16  9:50     ` Luis Henriques
  1 sibling, 3 replies; 12+ messages in thread
From: Greg Kroah-Hartman @ 2015-02-11  3:43 UTC (permalink / raw)
  To: Konstantin Khlebnikov
  Cc: Linux Kernel Mailing List, Stable, Jan Engelhardt, linux-arch,
	Linus Torvalds, linux-mm@kvack.org

On Tue, Feb 10, 2015 at 12:22:41PM +0400, Konstantin Khlebnikov wrote:
> I've found regression:
> 
> [  257.139907] ================================================
> [  257.139909] [ BUG: lock held when returning to user space! ]
> [  257.139912] 3.18.6-debug+ #161 Tainted: G     U
> [  257.139914] ------------------------------------------------
> [  257.139916] python/22843 is leaving the kernel with locks still held!
> [  257.139918] 1 lock held by python/22843:
> [  257.139920]  #0:  (&mm->mmap_sem){++++++}, at: [<ffffffff8104e4c2>]
> __do_page_fault+0x162/0x570
> 
> upstream commit 7fb08eca45270d0ae86e1ad9d39c40b7a55d0190 must be backported too.

Ah, nice, I missed that one.  How did you test this?

thanks,

greg k-h

--
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] 12+ messages in thread

* Re: [PATCH 3.18 04/57] vm: add VM_FAULT_SIGSEGV handling support
  2015-02-11  3:43     ` Greg Kroah-Hartman
@ 2015-02-11  3:43       ` Greg Kroah-Hartman
  2015-02-11  3:49       ` Linus Torvalds
  2015-02-11  5:34       ` Konstantin Khlebnikov
  2 siblings, 0 replies; 12+ messages in thread
From: Greg Kroah-Hartman @ 2015-02-11  3:43 UTC (permalink / raw)
  To: Konstantin Khlebnikov
  Cc: Linux Kernel Mailing List, Stable, Jan Engelhardt, linux-arch,
	Linus Torvalds, linux-mm@kvack.org

On Tue, Feb 10, 2015 at 12:22:41PM +0400, Konstantin Khlebnikov wrote:
> I've found regression:
> 
> [  257.139907] ================================================
> [  257.139909] [ BUG: lock held when returning to user space! ]
> [  257.139912] 3.18.6-debug+ #161 Tainted: G     U
> [  257.139914] ------------------------------------------------
> [  257.139916] python/22843 is leaving the kernel with locks still held!
> [  257.139918] 1 lock held by python/22843:
> [  257.139920]  #0:  (&mm->mmap_sem){++++++}, at: [<ffffffff8104e4c2>]
> __do_page_fault+0x162/0x570
> 
> upstream commit 7fb08eca45270d0ae86e1ad9d39c40b7a55d0190 must be backported too.

Ah, nice, I missed that one.  How did you test this?

thanks,

greg k-h

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

* Re: [PATCH 3.18 04/57] vm: add VM_FAULT_SIGSEGV handling support
  2015-02-11  3:43     ` Greg Kroah-Hartman
  2015-02-11  3:43       ` Greg Kroah-Hartman
@ 2015-02-11  3:49       ` Linus Torvalds
  2015-02-11  4:16         ` Greg Kroah-Hartman
  2015-02-11  5:34       ` Konstantin Khlebnikov
  2 siblings, 1 reply; 12+ messages in thread
From: Linus Torvalds @ 2015-02-11  3:49 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Konstantin Khlebnikov, Linux Kernel Mailing List, Stable,
	Jan Engelhardt, linux-arch@vger.kernel.org, linux-mm@kvack.org

On Tue, Feb 10, 2015 at 7:43 PM, Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
>
> Ah, nice, I missed that one.

Ugh, to be fair, I missed it too.

The alternative to backporting 7fb08eca4527 is to make the backport of
commit 33692f27597f use "bad_area()" instead of
"bad_area_nosemaphore()".

                    Linus

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

* Re: [PATCH 3.18 04/57] vm: add VM_FAULT_SIGSEGV handling support
  2015-02-11  3:49       ` Linus Torvalds
@ 2015-02-11  4:16         ` Greg Kroah-Hartman
  2015-02-11  4:16           ` Greg Kroah-Hartman
  0 siblings, 1 reply; 12+ messages in thread
From: Greg Kroah-Hartman @ 2015-02-11  4:16 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Konstantin Khlebnikov, Linux Kernel Mailing List, Stable,
	Jan Engelhardt, linux-arch@vger.kernel.org, linux-mm@kvack.org

On Tue, Feb 10, 2015 at 07:49:27PM -0800, Linus Torvalds wrote:
> On Tue, Feb 10, 2015 at 7:43 PM, Greg Kroah-Hartman
> <gregkh@linuxfoundation.org> wrote:
> >
> > Ah, nice, I missed that one.
> 
> Ugh, to be fair, I missed it too.
> 
> The alternative to backporting 7fb08eca4527 is to make the backport of
> commit 33692f27597f use "bad_area()" instead of
> "bad_area_nosemaphore()".

33692f27597f already showed up in 3.18.6, so I can't go back and change
that version :(

I'll just queue this one up, thanks.

greg k-h

--
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] 12+ messages in thread

* Re: [PATCH 3.18 04/57] vm: add VM_FAULT_SIGSEGV handling support
  2015-02-11  4:16         ` Greg Kroah-Hartman
@ 2015-02-11  4:16           ` Greg Kroah-Hartman
  0 siblings, 0 replies; 12+ messages in thread
From: Greg Kroah-Hartman @ 2015-02-11  4:16 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Konstantin Khlebnikov, Linux Kernel Mailing List, Stable,
	Jan Engelhardt, linux-arch@vger.kernel.org, linux-mm@kvack.org

On Tue, Feb 10, 2015 at 07:49:27PM -0800, Linus Torvalds wrote:
> On Tue, Feb 10, 2015 at 7:43 PM, Greg Kroah-Hartman
> <gregkh@linuxfoundation.org> wrote:
> >
> > Ah, nice, I missed that one.
> 
> Ugh, to be fair, I missed it too.
> 
> The alternative to backporting 7fb08eca4527 is to make the backport of
> commit 33692f27597f use "bad_area()" instead of
> "bad_area_nosemaphore()".

33692f27597f already showed up in 3.18.6, so I can't go back and change
that version :(

I'll just queue this one up, thanks.

greg k-h

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

* Re: [PATCH 3.18 04/57] vm: add VM_FAULT_SIGSEGV handling support
  2015-02-11  3:43     ` Greg Kroah-Hartman
  2015-02-11  3:43       ` Greg Kroah-Hartman
  2015-02-11  3:49       ` Linus Torvalds
@ 2015-02-11  5:34       ` Konstantin Khlebnikov
  2015-02-11  5:34         ` Konstantin Khlebnikov
  2 siblings, 1 reply; 12+ messages in thread
From: Konstantin Khlebnikov @ 2015-02-11  5:34 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Linux Kernel Mailing List, Stable, Jan Engelhardt, linux-arch,
	Linus Torvalds, linux-mm@kvack.org

On Wed, Feb 11, 2015 at 6:43 AM, Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
> On Tue, Feb 10, 2015 at 12:22:41PM +0400, Konstantin Khlebnikov wrote:
>> I've found regression:
>>
>> [  257.139907] ================================================
>> [  257.139909] [ BUG: lock held when returning to user space! ]
>> [  257.139912] 3.18.6-debug+ #161 Tainted: G     U
>> [  257.139914] ------------------------------------------------
>> [  257.139916] python/22843 is leaving the kernel with locks still held!
>> [  257.139918] 1 lock held by python/22843:
>> [  257.139920]  #0:  (&mm->mmap_sem){++++++}, at: [<ffffffff8104e4c2>]
>> __do_page_fault+0x162/0x570
>>
>> upstream commit 7fb08eca45270d0ae86e1ad9d39c40b7a55d0190 must be backported too.
>
> Ah, nice, I missed that one.  How did you test this?

I've catched hang on mmap_sem in some python self-test inside exherbo chroot.
With that patch test has finished successfully.

It seems the only way to tigger this is stack-overflow: for now VM_FAULT_SIGSEGV
is returned only if kernel cannot add guard page when stack expands.

>
> thanks,
>
> greg k-h

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

* Re: [PATCH 3.18 04/57] vm: add VM_FAULT_SIGSEGV handling support
  2015-02-11  5:34       ` Konstantin Khlebnikov
@ 2015-02-11  5:34         ` Konstantin Khlebnikov
  0 siblings, 0 replies; 12+ messages in thread
From: Konstantin Khlebnikov @ 2015-02-11  5:34 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Linux Kernel Mailing List, Stable, Jan Engelhardt, linux-arch,
	Linus Torvalds, linux-mm@kvack.org

On Wed, Feb 11, 2015 at 6:43 AM, Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
> On Tue, Feb 10, 2015 at 12:22:41PM +0400, Konstantin Khlebnikov wrote:
>> I've found regression:
>>
>> [  257.139907] ================================================
>> [  257.139909] [ BUG: lock held when returning to user space! ]
>> [  257.139912] 3.18.6-debug+ #161 Tainted: G     U
>> [  257.139914] ------------------------------------------------
>> [  257.139916] python/22843 is leaving the kernel with locks still held!
>> [  257.139918] 1 lock held by python/22843:
>> [  257.139920]  #0:  (&mm->mmap_sem){++++++}, at: [<ffffffff8104e4c2>]
>> __do_page_fault+0x162/0x570
>>
>> upstream commit 7fb08eca45270d0ae86e1ad9d39c40b7a55d0190 must be backported too.
>
> Ah, nice, I missed that one.  How did you test this?

I've catched hang on mmap_sem in some python self-test inside exherbo chroot.
With that patch test has finished successfully.

It seems the only way to tigger this is stack-overflow: for now VM_FAULT_SIGSEGV
is returned only if kernel cannot add guard page when stack expands.

>
> thanks,
>
> greg k-h

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

* Re: [PATCH 3.18 04/57] vm: add VM_FAULT_SIGSEGV handling support
  2015-02-10  8:22   ` Konstantin Khlebnikov
  2015-02-11  3:43     ` Greg Kroah-Hartman
@ 2015-02-16  9:50     ` Luis Henriques
  1 sibling, 0 replies; 12+ messages in thread
From: Luis Henriques @ 2015-02-16  9:50 UTC (permalink / raw)
  To: Konstantin Khlebnikov
  Cc: Greg Kroah-Hartman, Linux Kernel Mailing List, Stable,
	Jan Engelhardt, linux-arch, Linus Torvalds, linux-mm@kvack.org

On Tue, Feb 10, 2015 at 12:22:41PM +0400, Konstantin Khlebnikov wrote:
> I've found regression:
> 
> [  257.139907] ================================================
> [  257.139909] [ BUG: lock held when returning to user space! ]
> [  257.139912] 3.18.6-debug+ #161 Tainted: G     U
> [  257.139914] ------------------------------------------------
> [  257.139916] python/22843 is leaving the kernel with locks still held!
> [  257.139918] 1 lock held by python/22843:
> [  257.139920]  #0:  (&mm->mmap_sem){++++++}, at: [<ffffffff8104e4c2>]
> __do_page_fault+0x162/0x570
> 
> upstream commit 7fb08eca45270d0ae86e1ad9d39c40b7a55d0190 must be backported too.
>

I guess the same regression can be found in the 3.16 kernel as it also
includes a backport of 33692f27597f ("vm: add VM_FAULT_SIGSEGV
handling support").  I'll queue 7fb08eca4527 ("x86: mm: move mmap_sem
unlock from mm_fault_error() to caller") as well.

Cheers,
--
Luís

> On Wed, Feb 4, 2015 at 2:13 AM, Greg Kroah-Hartman
> <gregkh@linuxfoundation.org> wrote:
> > 3.18-stable review patch.  If anyone has any objections, please let me know.
> >
> > ------------------
> >
> > From: Linus Torvalds <torvalds@linux-foundation.org>
> >
> > commit 33692f27597fcab536d7cbbcc8f52905133e4aa7 upstream.
> >
> > The core VM already knows about VM_FAULT_SIGBUS, but cannot return a
> > "you should SIGSEGV" error, because the SIGSEGV case was generally
> > handled by the caller - usually the architecture fault handler.
> >
> > That results in lots of duplication - all the architecture fault
> > handlers end up doing very similar "look up vma, check permissions, do
> > retries etc" - but it generally works.  However, there are cases where
> > the VM actually wants to SIGSEGV, and applications _expect_ SIGSEGV.
> >
> > In particular, when accessing the stack guard page, libsigsegv expects a
> > SIGSEGV.  And it usually got one, because the stack growth is handled by
> > that duplicated architecture fault handler.
> >
> > However, when the generic VM layer started propagating the error return
> > from the stack expansion in commit fee7e49d4514 ("mm: propagate error
> > from stack expansion even for guard page"), that now exposed the
> > existing VM_FAULT_SIGBUS result to user space.  And user space really
> > expected SIGSEGV, not SIGBUS.
> >
> > To fix that case, we need to add a VM_FAULT_SIGSEGV, and teach all those
> > duplicate architecture fault handlers about it.  They all already have
> > the code to handle SIGSEGV, so it's about just tying that new return
> > value to the existing code, but it's all a bit annoying.
> >
> > This is the mindless minimal patch to do this.  A more extensive patch
> > would be to try to gather up the mostly shared fault handling logic into
> > one generic helper routine, and long-term we really should do that
> > cleanup.
> >
> > Just from this patch, you can generally see that most architectures just
> > copied (directly or indirectly) the old x86 way of doing things, but in
> > the meantime that original x86 model has been improved to hold the VM
> > semaphore for shorter times etc and to handle VM_FAULT_RETRY and other
> > "newer" things, so it would be a good idea to bring all those
> > improvements to the generic case and teach other architectures about
> > them too.
> >
> > Reported-and-tested-by: Takashi Iwai <tiwai@suse.de>
> > Tested-by: Jan Engelhardt <jengelh@inai.de>
> > Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> # "s390 still compiles and boots"
> > Cc: linux-arch@vger.kernel.org
> > Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
> > Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> >
> > ---
> >  arch/alpha/mm/fault.c                        |    2 ++
> >  arch/arc/mm/fault.c                          |    2 ++
> >  arch/avr32/mm/fault.c                        |    2 ++
> >  arch/cris/mm/fault.c                         |    2 ++
> >  arch/frv/mm/fault.c                          |    2 ++
> >  arch/ia64/mm/fault.c                         |    2 ++
> >  arch/m32r/mm/fault.c                         |    2 ++
> >  arch/m68k/mm/fault.c                         |    2 ++
> >  arch/metag/mm/fault.c                        |    2 ++
> >  arch/microblaze/mm/fault.c                   |    2 ++
> >  arch/mips/mm/fault.c                         |    2 ++
> >  arch/mn10300/mm/fault.c                      |    2 ++
> >  arch/openrisc/mm/fault.c                     |    2 ++
> >  arch/parisc/mm/fault.c                       |    2 ++
> >  arch/powerpc/mm/copro_fault.c                |    2 +-
> >  arch/powerpc/mm/fault.c                      |    2 ++
> >  arch/s390/mm/fault.c                         |    6 ++++++
> >  arch/score/mm/fault.c                        |    2 ++
> >  arch/sh/mm/fault.c                           |    2 ++
> >  arch/sparc/mm/fault_32.c                     |    2 ++
> >  arch/sparc/mm/fault_64.c                     |    2 ++
> >  arch/tile/mm/fault.c                         |    2 ++
> >  arch/um/kernel/trap.c                        |    2 ++
> >  arch/x86/mm/fault.c                          |    2 ++
> >  arch/xtensa/mm/fault.c                       |    2 ++
> >  drivers/staging/lustre/lustre/llite/vvp_io.c |    2 +-
> >  include/linux/mm.h                           |    6 ++++--
> >  mm/gup.c                                     |    4 ++--
> >  mm/ksm.c                                     |    2 +-
> >  29 files changed, 61 insertions(+), 7 deletions(-)
> >
> > --- a/arch/alpha/mm/fault.c
> > +++ b/arch/alpha/mm/fault.c
> > @@ -156,6 +156,8 @@ retry:
> >         if (unlikely(fault & VM_FAULT_ERROR)) {
> >                 if (fault & VM_FAULT_OOM)
> >                         goto out_of_memory;
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       goto bad_area;
> >                 else if (fault & VM_FAULT_SIGBUS)
> >                         goto do_sigbus;
> >                 BUG();
> > --- a/arch/arc/mm/fault.c
> > +++ b/arch/arc/mm/fault.c
> > @@ -161,6 +161,8 @@ good_area:
> >
> >         if (fault & VM_FAULT_OOM)
> >                 goto out_of_memory;
> > +       else if (fault & VM_FAULT_SIGSEV)
> > +               goto bad_area;
> >         else if (fault & VM_FAULT_SIGBUS)
> >                 goto do_sigbus;
> >
> > --- a/arch/avr32/mm/fault.c
> > +++ b/arch/avr32/mm/fault.c
> > @@ -142,6 +142,8 @@ good_area:
> >         if (unlikely(fault & VM_FAULT_ERROR)) {
> >                 if (fault & VM_FAULT_OOM)
> >                         goto out_of_memory;
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       goto bad_area;
> >                 else if (fault & VM_FAULT_SIGBUS)
> >                         goto do_sigbus;
> >                 BUG();
> > --- a/arch/cris/mm/fault.c
> > +++ b/arch/cris/mm/fault.c
> > @@ -176,6 +176,8 @@ retry:
> >         if (unlikely(fault & VM_FAULT_ERROR)) {
> >                 if (fault & VM_FAULT_OOM)
> >                         goto out_of_memory;
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       goto bad_area;
> >                 else if (fault & VM_FAULT_SIGBUS)
> >                         goto do_sigbus;
> >                 BUG();
> > --- a/arch/frv/mm/fault.c
> > +++ b/arch/frv/mm/fault.c
> > @@ -168,6 +168,8 @@ asmlinkage void do_page_fault(int datamm
> >         if (unlikely(fault & VM_FAULT_ERROR)) {
> >                 if (fault & VM_FAULT_OOM)
> >                         goto out_of_memory;
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       goto bad_area;
> >                 else if (fault & VM_FAULT_SIGBUS)
> >                         goto do_sigbus;
> >                 BUG();
> > --- a/arch/ia64/mm/fault.c
> > +++ b/arch/ia64/mm/fault.c
> > @@ -172,6 +172,8 @@ retry:
> >                  */
> >                 if (fault & VM_FAULT_OOM) {
> >                         goto out_of_memory;
> > +               } else if (fault & VM_FAULT_SIGSEGV) {
> > +                       goto bad_area;
> >                 } else if (fault & VM_FAULT_SIGBUS) {
> >                         signal = SIGBUS;
> >                         goto bad_area;
> > --- a/arch/m32r/mm/fault.c
> > +++ b/arch/m32r/mm/fault.c
> > @@ -200,6 +200,8 @@ good_area:
> >         if (unlikely(fault & VM_FAULT_ERROR)) {
> >                 if (fault & VM_FAULT_OOM)
> >                         goto out_of_memory;
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       goto bad_area;
> >                 else if (fault & VM_FAULT_SIGBUS)
> >                         goto do_sigbus;
> >                 BUG();
> > --- a/arch/m68k/mm/fault.c
> > +++ b/arch/m68k/mm/fault.c
> > @@ -145,6 +145,8 @@ good_area:
> >         if (unlikely(fault & VM_FAULT_ERROR)) {
> >                 if (fault & VM_FAULT_OOM)
> >                         goto out_of_memory;
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       goto map_err;
> >                 else if (fault & VM_FAULT_SIGBUS)
> >                         goto bus_err;
> >                 BUG();
> > --- a/arch/metag/mm/fault.c
> > +++ b/arch/metag/mm/fault.c
> > @@ -141,6 +141,8 @@ good_area:
> >         if (unlikely(fault & VM_FAULT_ERROR)) {
> >                 if (fault & VM_FAULT_OOM)
> >                         goto out_of_memory;
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       goto bad_area;
> >                 else if (fault & VM_FAULT_SIGBUS)
> >                         goto do_sigbus;
> >                 BUG();
> > --- a/arch/microblaze/mm/fault.c
> > +++ b/arch/microblaze/mm/fault.c
> > @@ -224,6 +224,8 @@ good_area:
> >         if (unlikely(fault & VM_FAULT_ERROR)) {
> >                 if (fault & VM_FAULT_OOM)
> >                         goto out_of_memory;
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       goto bad_area;
> >                 else if (fault & VM_FAULT_SIGBUS)
> >                         goto do_sigbus;
> >                 BUG();
> > --- a/arch/mips/mm/fault.c
> > +++ b/arch/mips/mm/fault.c
> > @@ -158,6 +158,8 @@ good_area:
> >         if (unlikely(fault & VM_FAULT_ERROR)) {
> >                 if (fault & VM_FAULT_OOM)
> >                         goto out_of_memory;
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       goto bad_area;
> >                 else if (fault & VM_FAULT_SIGBUS)
> >                         goto do_sigbus;
> >                 BUG();
> > --- a/arch/mn10300/mm/fault.c
> > +++ b/arch/mn10300/mm/fault.c
> > @@ -262,6 +262,8 @@ good_area:
> >         if (unlikely(fault & VM_FAULT_ERROR)) {
> >                 if (fault & VM_FAULT_OOM)
> >                         goto out_of_memory;
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       goto bad_area;
> >                 else if (fault & VM_FAULT_SIGBUS)
> >                         goto do_sigbus;
> >                 BUG();
> > --- a/arch/openrisc/mm/fault.c
> > +++ b/arch/openrisc/mm/fault.c
> > @@ -171,6 +171,8 @@ good_area:
> >         if (unlikely(fault & VM_FAULT_ERROR)) {
> >                 if (fault & VM_FAULT_OOM)
> >                         goto out_of_memory;
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       goto bad_area;
> >                 else if (fault & VM_FAULT_SIGBUS)
> >                         goto do_sigbus;
> >                 BUG();
> > --- a/arch/parisc/mm/fault.c
> > +++ b/arch/parisc/mm/fault.c
> > @@ -256,6 +256,8 @@ good_area:
> >                  */
> >                 if (fault & VM_FAULT_OOM)
> >                         goto out_of_memory;
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       goto bad_area;
> >                 else if (fault & VM_FAULT_SIGBUS)
> >                         goto bad_area;
> >                 BUG();
> > --- a/arch/powerpc/mm/copro_fault.c
> > +++ b/arch/powerpc/mm/copro_fault.c
> > @@ -76,7 +76,7 @@ int copro_handle_mm_fault(struct mm_stru
> >                 if (*flt & VM_FAULT_OOM) {
> >                         ret = -ENOMEM;
> >                         goto out_unlock;
> > -               } else if (*flt & VM_FAULT_SIGBUS) {
> > +               } else if (*flt & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) {
> >                         ret = -EFAULT;
> >                         goto out_unlock;
> >                 }
> > --- a/arch/powerpc/mm/fault.c
> > +++ b/arch/powerpc/mm/fault.c
> > @@ -444,6 +444,8 @@ good_area:
> >          */
> >         fault = handle_mm_fault(mm, vma, address, flags);
> >         if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) {
> > +               if (fault & VM_FAULT_SIGSEGV)
> > +                       goto bad_area;
> >                 rc = mm_fault_error(regs, address, fault);
> >                 if (rc >= MM_FAULT_RETURN)
> >                         goto bail;
> > --- a/arch/s390/mm/fault.c
> > +++ b/arch/s390/mm/fault.c
> > @@ -374,6 +374,12 @@ static noinline void do_fault_error(stru
> >                                 do_no_context(regs);
> >                         else
> >                                 pagefault_out_of_memory();
> > +               } else if (fault & VM_FAULT_SIGSEGV) {
> > +                       /* Kernel mode? Handle exceptions or die */
> > +                       if (!user_mode(regs))
> > +                               do_no_context(regs);
> > +                       else
> > +                               do_sigsegv(regs, SEGV_MAPERR);
> >                 } else if (fault & VM_FAULT_SIGBUS) {
> >                         /* Kernel mode? Handle exceptions or die */
> >                         if (!user_mode(regs))
> > --- a/arch/score/mm/fault.c
> > +++ b/arch/score/mm/fault.c
> > @@ -114,6 +114,8 @@ good_area:
> >         if (unlikely(fault & VM_FAULT_ERROR)) {
> >                 if (fault & VM_FAULT_OOM)
> >                         goto out_of_memory;
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       goto bad_area;
> >                 else if (fault & VM_FAULT_SIGBUS)
> >                         goto do_sigbus;
> >                 BUG();
> > --- a/arch/sh/mm/fault.c
> > +++ b/arch/sh/mm/fault.c
> > @@ -353,6 +353,8 @@ mm_fault_error(struct pt_regs *regs, uns
> >         } else {
> >                 if (fault & VM_FAULT_SIGBUS)
> >                         do_sigbus(regs, error_code, address);
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       bad_area(regs, error_code, address);
> >                 else
> >                         BUG();
> >         }
> > --- a/arch/sparc/mm/fault_32.c
> > +++ b/arch/sparc/mm/fault_32.c
> > @@ -249,6 +249,8 @@ good_area:
> >         if (unlikely(fault & VM_FAULT_ERROR)) {
> >                 if (fault & VM_FAULT_OOM)
> >                         goto out_of_memory;
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       goto bad_area;
> >                 else if (fault & VM_FAULT_SIGBUS)
> >                         goto do_sigbus;
> >                 BUG();
> > --- a/arch/sparc/mm/fault_64.c
> > +++ b/arch/sparc/mm/fault_64.c
> > @@ -446,6 +446,8 @@ good_area:
> >         if (unlikely(fault & VM_FAULT_ERROR)) {
> >                 if (fault & VM_FAULT_OOM)
> >                         goto out_of_memory;
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       goto bad_area;
> >                 else if (fault & VM_FAULT_SIGBUS)
> >                         goto do_sigbus;
> >                 BUG();
> > --- a/arch/tile/mm/fault.c
> > +++ b/arch/tile/mm/fault.c
> > @@ -444,6 +444,8 @@ good_area:
> >         if (unlikely(fault & VM_FAULT_ERROR)) {
> >                 if (fault & VM_FAULT_OOM)
> >                         goto out_of_memory;
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       goto bad_area;
> >                 else if (fault & VM_FAULT_SIGBUS)
> >                         goto do_sigbus;
> >                 BUG();
> > --- a/arch/um/kernel/trap.c
> > +++ b/arch/um/kernel/trap.c
> > @@ -80,6 +80,8 @@ good_area:
> >                 if (unlikely(fault & VM_FAULT_ERROR)) {
> >                         if (fault & VM_FAULT_OOM) {
> >                                 goto out_of_memory;
> > +                       } else if (fault & VM_FAULT_SIGSEGV) {
> > +                               goto out;
> >                         } else if (fault & VM_FAULT_SIGBUS) {
> >                                 err = -EACCES;
> >                                 goto out;
> > --- a/arch/x86/mm/fault.c
> > +++ b/arch/x86/mm/fault.c
> > @@ -905,6 +905,8 @@ mm_fault_error(struct pt_regs *regs, uns
> >                 if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
> >                              VM_FAULT_HWPOISON_LARGE))
> >                         do_sigbus(regs, error_code, address, fault);
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       bad_area_nosemaphore(regs, error_code, address);
> >                 else
> >                         BUG();
> >         }
> > --- a/arch/xtensa/mm/fault.c
> > +++ b/arch/xtensa/mm/fault.c
> > @@ -117,6 +117,8 @@ good_area:
> >         if (unlikely(fault & VM_FAULT_ERROR)) {
> >                 if (fault & VM_FAULT_OOM)
> >                         goto out_of_memory;
> > +               else if (fault & VM_FAULT_SIGSEGV)
> > +                       goto bad_area;
> >                 else if (fault & VM_FAULT_SIGBUS)
> >                         goto do_sigbus;
> >                 BUG();
> > --- a/drivers/staging/lustre/lustre/llite/vvp_io.c
> > +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c
> > @@ -632,7 +632,7 @@ static int vvp_io_kernel_fault(struct vv
> >                 return 0;
> >         }
> >
> > -       if (cfio->fault.ft_flags & VM_FAULT_SIGBUS) {
> > +       if (cfio->fault.ft_flags & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) {
> >                 CDEBUG(D_PAGE, "got addr %p - SIGBUS\n", vmf->virtual_address);
> >                 return -EFAULT;
> >         }
> > --- a/include/linux/mm.h
> > +++ b/include/linux/mm.h
> > @@ -1054,6 +1054,7 @@ static inline int page_mapped(struct pag
> >  #define VM_FAULT_WRITE 0x0008  /* Special case for get_user_pages */
> >  #define VM_FAULT_HWPOISON 0x0010       /* Hit poisoned small page */
> >  #define VM_FAULT_HWPOISON_LARGE 0x0020  /* Hit poisoned large page. Index encoded in upper bits */
> > +#define VM_FAULT_SIGSEGV 0x0040
> >
> >  #define VM_FAULT_NOPAGE        0x0100  /* ->fault installed the pte, not return page */
> >  #define VM_FAULT_LOCKED        0x0200  /* ->fault locked the returned page */
> > @@ -1062,8 +1063,9 @@ static inline int page_mapped(struct pag
> >
> >  #define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */
> >
> > -#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON | \
> > -                        VM_FAULT_FALLBACK | VM_FAULT_HWPOISON_LARGE)
> > +#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \
> > +                        VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE | \
> > +                        VM_FAULT_FALLBACK)
> >
> >  /* Encode hstate index for a hwpoisoned large page */
> >  #define VM_FAULT_SET_HINDEX(x) ((x) << 12)
> > --- a/mm/gup.c
> > +++ b/mm/gup.c
> > @@ -296,7 +296,7 @@ static int faultin_page(struct task_stru
> >                         return -ENOMEM;
> >                 if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE))
> >                         return *flags & FOLL_HWPOISON ? -EHWPOISON : -EFAULT;
> > -               if (ret & VM_FAULT_SIGBUS)
> > +               if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV))
> >                         return -EFAULT;
> >                 BUG();
> >         }
> > @@ -571,7 +571,7 @@ int fixup_user_fault(struct task_struct
> >                         return -ENOMEM;
> >                 if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE))
> >                         return -EHWPOISON;
> > -               if (ret & VM_FAULT_SIGBUS)
> > +               if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV))
> >                         return -EFAULT;
> >                 BUG();
> >         }
> > --- a/mm/ksm.c
> > +++ b/mm/ksm.c
> > @@ -376,7 +376,7 @@ static int break_ksm(struct vm_area_stru
> >                 else
> >                         ret = VM_FAULT_WRITE;
> >                 put_page(page);
> > -       } while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_OOM)));
> > +       } while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | VM_FAULT_OOM)));
> >         /*
> >          * We must loop because handle_mm_fault() may back out if there's
> >          * any difficulty e.g. if pte accessed bit gets updated concurrently.
> >
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at  http://www.tux.org/lkml/
> --
> To unsubscribe from this list: send the line "unsubscribe stable" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

end of thread, other threads:[~2015-02-16  9:49 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20150203231211.486950145@linuxfoundation.org>
2015-02-03 23:13 ` [PATCH 3.18 04/57] vm: add VM_FAULT_SIGSEGV handling support Greg Kroah-Hartman
2015-02-03 23:13   ` Greg Kroah-Hartman
2015-02-10  8:22   ` Konstantin Khlebnikov
2015-02-11  3:43     ` Greg Kroah-Hartman
2015-02-11  3:43       ` Greg Kroah-Hartman
2015-02-11  3:49       ` Linus Torvalds
2015-02-11  4:16         ` Greg Kroah-Hartman
2015-02-11  4:16           ` Greg Kroah-Hartman
2015-02-11  5:34       ` Konstantin Khlebnikov
2015-02-11  5:34         ` Konstantin Khlebnikov
2015-02-16  9:50     ` Luis Henriques
2015-02-03 23:13 ` [PATCH 3.18 06/57] vm: make stack guard page errors return VM_FAULT_SIGSEGV rather than SIGBUS Greg Kroah-Hartman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).