diff mbox

[1/2] sparc64: Don't panic on user mode non-resumable errors

Message ID 1483731540-8055-2-git-send-email-Liam.Howlett@Oracle.com
State Superseded
Delegated to: David Miller
Headers show

Commit Message

Liam R. Howlett Jan. 6, 2017, 7:38 p.m. UTC
Send a SIGBUS to the offending process on all userspace non-resumable
traps.  This prevents userspace applications from creating a kernel
panic.  The siginfo will return the code BUS_ADRERR and a valid address
if possible.

Signed-off-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
---
 arch/sparc/kernel/traps_64.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

Comments

David Miller Jan. 6, 2017, 8:04 p.m. UTC | #1
From: "Liam R. Howlett" <Liam.Howlett@Oracle.com>
Date: Fri,  6 Jan 2017 14:38:59 -0500

> Send a SIGBUS to the offending process on all userspace non-resumable
> traps.  This prevents userspace applications from creating a kernel
> panic.  The siginfo will return the code BUS_ADRERR and a valid address
> if possible.
> 
> Signed-off-by: Liam R. Howlett <Liam.Howlett@Oracle.com>

Now that the code will potentially actually continue, you _must_ check
the nature of the error, and potentially retire the physical page if
it is real memory in order to prevent it from being used in some other
way by either userspace of kernel space and thus triggering the
non-resumable error all over again.

The various sun4u async fault handlers have this logic present and do the
right thing, something like:

	if (pfn_valid(afar >> PAGE_SHIFT))
		get_page(pfn_to_page(afar >> PAGE_SHIFT));

This logic prevents the page from being freed up and returned to the
free page pool, even if we kill the process and thus tear down it's
address space.

Thank you.
--
To unsubscribe from this list: send the line "unsubscribe sparclinux" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c
index 496fa92..3a0c153 100644
--- a/arch/sparc/kernel/traps_64.c
+++ b/arch/sparc/kernel/traps_64.c
@@ -2075,6 +2075,27 @@  void sun4v_nonresum_error(struct pt_regs *regs, unsigned long offset)
 
 	put_cpu();
 
+	if (!(regs->tstate & TSTATE_PRIV)) {
+		/* DON'T PANIC.  This error was from userspace. */
+		siginfo_t info;
+		unsigned int insn;
+
+		info.si_signo = SIGBUS;
+		info.si_code = BUS_ADRERR;
+		info.si_errno = 0;
+		info.si_trapno = 0;
+		info.si_addr = 0;
+
+		if (!copy_from_user(&insn, (void __user *)regs->tpc, 4)) {
+			info.si_addr = (void __user *)
+				compute_effective_address(regs, insn,
+						(insn >> 25) & 0x1f);
+		}
+
+		force_sig_info(SIGBUS, &info, current);
+		return;
+	}
+
 #ifdef CONFIG_PCI
 	/* Check for the special PCI poke sequence. */
 	if (pci_poke_in_progress && pci_poke_cpu == cpu) {