dec6999
From 973e23bf27b0b2e5021321357fc570cccea3104c Mon Sep 17 00:00:00 2001
dec6999
From: Dave Anderson <anderson@redhat.com>
dec6999
Date: Tue, 26 Nov 2013 12:42:46 -0500
dec6999
Subject: [PATCH] crash-driver
dec6999
dec6999
Bugzilla: N/A
dec6999
Upstream-status: Fedora mustard
dec6999
---
dec6999
 arch/arm/include/asm/crash-driver.h     |   6 ++
dec6999
 arch/arm64/include/asm/crash-driver.h   |   6 ++
dec6999
 arch/ia64/include/asm/crash-driver.h    |  90 ++++++++++++++++++++++
dec6999
 arch/ia64/kernel/ia64_ksyms.c           |   3 +
dec6999
 arch/powerpc/include/asm/crash-driver.h |   6 ++
dec6999
 arch/s390/include/asm/crash-driver.h    |  60 +++++++++++++++
dec6999
 arch/s390/mm/maccess.c                  |   2 +
dec6999
 arch/x86/include/asm/crash-driver.h     |   6 ++
dec6999
 drivers/char/Kconfig                    |   3 +
dec6999
 drivers/char/Makefile                   |   2 +
dec6999
 drivers/char/crash.c                    | 128 ++++++++++++++++++++++++++++++++
dec6999
 include/asm-generic/crash-driver.h      |  72 ++++++++++++++++++
dec6999
 12 files changed, 384 insertions(+)
dec6999
 create mode 100644 arch/arm/include/asm/crash-driver.h
dec6999
 create mode 100644 arch/arm64/include/asm/crash-driver.h
dec6999
 create mode 100644 arch/ia64/include/asm/crash-driver.h
dec6999
 create mode 100644 arch/powerpc/include/asm/crash-driver.h
dec6999
 create mode 100644 arch/s390/include/asm/crash-driver.h
dec6999
 create mode 100644 arch/x86/include/asm/crash-driver.h
dec6999
 create mode 100644 drivers/char/crash.c
dec6999
 create mode 100644 include/asm-generic/crash-driver.h
dec6999
dec6999
diff --git a/arch/arm/include/asm/crash-driver.h b/arch/arm/include/asm/crash-driver.h
dec6999
new file mode 100644
dec6999
index 0000000..06e7ae9
dec6999
--- /dev/null
dec6999
+++ b/arch/arm/include/asm/crash-driver.h
dec6999
@@ -0,0 +1,6 @@
dec6999
+#ifndef _ARM_CRASH_H
dec6999
+#define _ARM_CRASH_H
dec6999
+
dec6999
+#include <asm-generic/crash-driver.h>
dec6999
+
dec6999
+#endif /* _ARM_CRASH_H */
dec6999
diff --git a/arch/arm64/include/asm/crash-driver.h b/arch/arm64/include/asm/crash-driver.h
dec6999
new file mode 100644
dec6999
index 0000000..43b26da
dec6999
--- /dev/null
dec6999
+++ b/arch/arm64/include/asm/crash-driver.h
dec6999
@@ -0,0 +1,6 @@
dec6999
+#ifndef _ARM64_CRASH_H
dec6999
+#define _ARM64_CRASH_H
dec6999
+
dec6999
+#include <asm-generic/crash-driver.h>
dec6999
+
dec6999
+#endif /* _ARM64_CRASH_H */
dec6999
diff --git a/arch/ia64/include/asm/crash-driver.h b/arch/ia64/include/asm/crash-driver.h
dec6999
new file mode 100644
dec6999
index 0000000..404bcb9
dec6999
--- /dev/null
dec6999
+++ b/arch/ia64/include/asm/crash-driver.h
dec6999
@@ -0,0 +1,90 @@
dec6999
+#ifndef _ASM_IA64_CRASH_H
dec6999
+#define _ASM_IA64_CRASH_H
dec6999
+
dec6999
+/*
dec6999
+ * linux/include/asm-ia64/crash-driver.h
dec6999
+ *
dec6999
+ * Copyright (c) 2004 Red Hat, Inc. All rights reserved.
dec6999
+ *
dec6999
+ * This program is free software; you can redistribute it and/or modify
dec6999
+ * it under the terms of the GNU General Public License as published by
dec6999
+ * the Free Software Foundation; either version 2, or (at your option)
dec6999
+ * any later version.
dec6999
+ *
dec6999
+ * This program is distributed in the hope that it will be useful,
dec6999
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
dec6999
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
dec6999
+ * GNU General Public License for more details.
dec6999
+ *
dec6999
+ * You should have received a copy of the GNU General Public License
dec6999
+ * along with this program; if not, write to the Free Software
dec6999
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
dec6999
+ *
dec6999
+ */
dec6999
+
dec6999
+#ifdef __KERNEL__
dec6999
+
dec6999
+#include <linux/efi.h>
dec6999
+#include <linux/mm.h>
dec6999
+#include <asm/mmzone.h>
dec6999
+
dec6999
+static inline void *
dec6999
+map_virtual(u64 offset, struct page **pp)
dec6999
+{
dec6999
+	struct page *page;
dec6999
+	unsigned long pfn;
dec6999
+	u32 type;
dec6999
+
dec6999
+	if (REGION_NUMBER(offset) == 5) {
dec6999
+		char byte;
dec6999
+
dec6999
+		if (__get_user(byte, (char *)offset) == 0)
dec6999
+			return (void *)offset;
dec6999
+		else
dec6999
+			return NULL;
dec6999
+	}
dec6999
+
dec6999
+	switch (type = efi_mem_type(offset))
dec6999
+	{
dec6999
+	case EFI_LOADER_CODE:
dec6999
+	case EFI_LOADER_DATA:
dec6999
+	case EFI_BOOT_SERVICES_CODE:
dec6999
+	case EFI_BOOT_SERVICES_DATA:
dec6999
+	case EFI_CONVENTIONAL_MEMORY:
dec6999
+		break;
dec6999
+
dec6999
+	default:
dec6999
+		printk(KERN_INFO
dec6999
+		    "crash memory driver: invalid memory type for %lx: %d\n",
dec6999
+			offset, type);
dec6999
+		return NULL;
dec6999
+	}
dec6999
+
dec6999
+	pfn = offset >> PAGE_SHIFT;
dec6999
+
dec6999
+	if (!pfn_valid(pfn)) {
dec6999
+		printk(KERN_INFO
dec6999
+			"crash memory driver: invalid pfn: %lx )\n", pfn);
dec6999
+		return NULL;
dec6999
+	}
dec6999
+
dec6999
+	page = pfn_to_page(pfn);
dec6999
+
dec6999
+	if (!page->virtual) {
dec6999
+		printk(KERN_INFO
dec6999
+		    "crash memory driver: offset: %lx page: %lx page->virtual: NULL\n",
dec6999
+			offset, (unsigned long)page);
dec6999
+		return NULL;
dec6999
+	}
dec6999
+
dec6999
+	return (page->virtual + (offset & (PAGE_SIZE-1)));
dec6999
+}
dec6999
+
dec6999
+static inline void unmap_virtual(struct page *page)
dec6999
+{
dec6999
+	return;
dec6999
+}
dec6999
+
dec6999
+#endif /* __KERNEL__ */
dec6999
+
dec6999
+#endif /* _ASM_IA64_CRASH_H */
dec6999
diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
dec6999
index d111248..b14b4c6 100644
dec6999
--- a/arch/ia64/kernel/ia64_ksyms.c
dec6999
+++ b/arch/ia64/kernel/ia64_ksyms.c
dec6999
@@ -9,3 +9,6 @@
dec6999
 EXPORT_SYMBOL(min_low_pfn);	/* defined by bootmem.c, but not exported by generic code */
dec6999
 EXPORT_SYMBOL(max_low_pfn);	/* defined by bootmem.c, but not exported by generic code */
dec6999
 #endif
dec6999
+
dec6999
+#include <linux/efi.h>
dec6999
+EXPORT_SYMBOL_GPL(efi_mem_type);
dec6999
diff --git a/arch/powerpc/include/asm/crash-driver.h b/arch/powerpc/include/asm/crash-driver.h
dec6999
new file mode 100644
dec6999
index 0000000..50092d9
dec6999
--- /dev/null
dec6999
+++ b/arch/powerpc/include/asm/crash-driver.h
dec6999
@@ -0,0 +1,6 @@
dec6999
+#ifndef _PPC64_CRASH_H
dec6999
+#define _PPC64_CRASH_H
dec6999
+
dec6999
+#include <asm-generic/crash-driver.h>
dec6999
+
dec6999
+#endif /* _PPC64_CRASH_H */
dec6999
diff --git a/arch/s390/include/asm/crash-driver.h b/arch/s390/include/asm/crash-driver.h
dec6999
new file mode 100644
dec6999
index 0000000..552be5e
dec6999
--- /dev/null
dec6999
+++ b/arch/s390/include/asm/crash-driver.h
dec6999
@@ -0,0 +1,60 @@
dec6999
+#ifndef _S390_CRASH_H
dec6999
+#define _S390_CRASH_H
dec6999
+
dec6999
+#ifdef __KERNEL__
dec6999
+
dec6999
+#include <linux/mm.h>
dec6999
+#include <linux/highmem.h>
dec6999
+
dec6999
+/*
dec6999
+ * For swapped prefix pages get bounce buffer using xlate_dev_mem_ptr()
dec6999
+ */
dec6999
+static inline void *map_virtual(u64 offset, struct page **pp)
dec6999
+{
dec6999
+	struct page *page;
dec6999
+	unsigned long pfn;
dec6999
+	void *vaddr;
dec6999
+
dec6999
+	vaddr = xlate_dev_mem_ptr(offset);
dec6999
+	pfn = ((unsigned long) vaddr) >> PAGE_SHIFT;
dec6999
+	if ((unsigned long) vaddr != offset)
dec6999
+		page = pfn_to_page(pfn);
dec6999
+	else
dec6999
+		page = NULL;
dec6999
+
dec6999
+	if (!page_is_ram(pfn)) {
dec6999
+		printk(KERN_INFO
dec6999
+		    "crash memory driver: !page_is_ram(pfn: %lx)\n", pfn);
dec6999
+		return NULL;
dec6999
+	}
dec6999
+
dec6999
+	if (!pfn_valid(pfn)) {
dec6999
+		printk(KERN_INFO
dec6999
+		    "crash memory driver: invalid pfn: %lx )\n", pfn);
dec6999
+		return NULL;
dec6999
+	}
dec6999
+
dec6999
+	*pp = page;
dec6999
+	return vaddr;
dec6999
+}
dec6999
+
dec6999
+/*
dec6999
+ * Free bounce buffer if necessary
dec6999
+ */
dec6999
+static inline void unmap_virtual(struct page *page)
dec6999
+{
dec6999
+	void *vaddr;
dec6999
+
dec6999
+	if (page) {
dec6999
+		/*
dec6999
+		 * Because for bounce buffers vaddr will never be 0
dec6999
+		 * unxlate_dev_mem_ptr() will always free the bounce buffer.
dec6999
+		 */
dec6999
+		vaddr = (void *)(page_to_pfn(page) << PAGE_SHIFT);
dec6999
+		unxlate_dev_mem_ptr(0, vaddr);
dec6999
+	}
dec6999
+}
dec6999
+
dec6999
+#endif /* __KERNEL__ */
dec6999
+
dec6999
+#endif /* _S390_CRASH_H */
dec6999
diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c
dec6999
index 792f9c6..3197995 100644
dec6999
--- a/arch/s390/mm/maccess.c
dec6999
+++ b/arch/s390/mm/maccess.c
dec6999
@@ -201,6 +201,7 @@ void *xlate_dev_mem_ptr(phys_addr_t addr)
dec6999
 	put_online_cpus();
dec6999
 	return bounce;
dec6999
 }
dec6999
+EXPORT_SYMBOL_GPL(xlate_dev_mem_ptr);
dec6999
 
dec6999
 /*
dec6999
  * Free converted buffer for /dev/mem access (if necessary)
dec6999
@@ -210,3 +211,4 @@ void unxlate_dev_mem_ptr(phys_addr_t addr, void *buf)
dec6999
 	if ((void *) addr != buf)
dec6999
 		free_page((unsigned long) buf);
dec6999
 }
dec6999
+EXPORT_SYMBOL_GPL(unxlate_dev_mem_ptr);
dec6999
diff --git a/arch/x86/include/asm/crash-driver.h b/arch/x86/include/asm/crash-driver.h
dec6999
new file mode 100644
dec6999
index 0000000..fd4736e
dec6999
--- /dev/null
dec6999
+++ b/arch/x86/include/asm/crash-driver.h
dec6999
@@ -0,0 +1,6 @@
dec6999
+#ifndef _X86_CRASH_H
dec6999
+#define _X86_CRASH_H
dec6999
+
dec6999
+#include <asm-generic/crash-driver.h>
dec6999
+
dec6999
+#endif /* _X86_CRASH_H */
dec6999
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
dec6999
index dcc0973..99b99d5 100644
dec6999
--- a/drivers/char/Kconfig
dec6999
+++ b/drivers/char/Kconfig
dec6999
@@ -4,6 +4,9 @@
dec6999
 
dec6999
 menu "Character devices"
dec6999
 
dec6999
+config CRASH
dec6999
+	tristate "Crash Utility memory driver"
dec6999
+
dec6999
 source "drivers/tty/Kconfig"
dec6999
 
dec6999
 config DEVMEM
dec6999
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
dec6999
index 6e6c244..29cc9c8 100644
dec6999
--- a/drivers/char/Makefile
dec6999
+++ b/drivers/char/Makefile
5a506e7
@@ -58,3 +58,5 @@ js-rtc-y = rtc.o
dec6999
 obj-$(CONFIG_XILLYBUS)		+= xillybus/
dec6999
 obj-$(CONFIG_POWERNV_OP_PANEL)	+= powernv-op-panel.o
5a506e7
 obj-$(CONFIG_ADI)		+= adi.o
dec6999
+
dec6999
+obj-$(CONFIG_CRASH)            += crash.o
dec6999
diff --git a/drivers/char/crash.c b/drivers/char/crash.c
dec6999
new file mode 100644
dec6999
index 0000000..085378a
dec6999
--- /dev/null
dec6999
+++ b/drivers/char/crash.c
dec6999
@@ -0,0 +1,128 @@
dec6999
+/*
dec6999
+ *  linux/drivers/char/crash.c
dec6999
+ *
dec6999
+ *  Copyright (C) 2004  Dave Anderson <anderson@redhat.com>
dec6999
+ *  Copyright (C) 2004  Red Hat, Inc.
dec6999
+ */
dec6999
+
dec6999
+/******************************************************************************
dec6999
+ *
dec6999
+ *   This program is free software; you can redistribute it and/or modify
dec6999
+ *   it under the terms of the GNU General Public License as published by
dec6999
+ *   the Free Software Foundation; either version 2, or (at your option)
dec6999
+ *   any later version.
dec6999
+ *
dec6999
+ *   This program is distributed in the hope that it will be useful,
dec6999
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
dec6999
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
dec6999
+ *   GNU General Public License for more details.
dec6999
+ *
dec6999
+ *   You should have received a copy of the GNU General Public License
dec6999
+ *   along with this program; if not, write to the Free Software
dec6999
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
dec6999
+ *
dec6999
+ *****************************************************************************/
dec6999
+
dec6999
+#include <linux/module.h>
dec6999
+#include <linux/types.h>
dec6999
+#include <linux/miscdevice.h>
dec6999
+#include <linux/init.h>
dec6999
+#include <asm/io.h>
dec6999
+#include <asm/uaccess.h>
dec6999
+#include <asm/types.h>
dec6999
+#include <asm/crash-driver.h>
dec6999
+
dec6999
+#define CRASH_VERSION   "1.0"
dec6999
+
dec6999
+/*
dec6999
+ *  These are the file operation functions that allow crash utility
dec6999
+ *  access to physical memory.
dec6999
+ */
dec6999
+
dec6999
+static loff_t
dec6999
+crash_llseek(struct file * file, loff_t offset, int orig)
dec6999
+{
dec6999
+	switch (orig) {
dec6999
+	case 0:
dec6999
+		file->f_pos = offset;
dec6999
+		return file->f_pos;
dec6999
+	case 1:
dec6999
+		file->f_pos += offset;
dec6999
+		return file->f_pos;
dec6999
+	default:
dec6999
+		return -EINVAL;
dec6999
+	}
dec6999
+}
dec6999
+
dec6999
+/*
dec6999
+ *  Determine the page address for an address offset value,
dec6999
+ *  get a virtual address for it, and copy it out.
dec6999
+ *  Accesses must fit within a page.
dec6999
+ */
dec6999
+static ssize_t
dec6999
+crash_read(struct file *file, char *buf, size_t count, loff_t *poff)
dec6999
+{
dec6999
+	void *vaddr;
dec6999
+	struct page *page;
dec6999
+	u64 offset;
dec6999
+	ssize_t read;
dec6999
+
dec6999
+	offset = *poff;
dec6999
+	if (offset >> PAGE_SHIFT != (offset+count-1) >> PAGE_SHIFT)
dec6999
+		return -EINVAL;
dec6999
+
dec6999
+	vaddr = map_virtual(offset, &page);
dec6999
+	if (!vaddr)
dec6999
+		return -EFAULT;
dec6999
+
dec6999
+	if (copy_to_user(buf, vaddr, count)) {
dec6999
+		unmap_virtual(page);
dec6999
+		return -EFAULT;
dec6999
+	}
dec6999
+	unmap_virtual(page);
dec6999
+
dec6999
+	read = count;
dec6999
+	*poff += read;
dec6999
+	return read;
dec6999
+}
dec6999
+
dec6999
+static struct file_operations crash_fops = {
dec6999
+	.owner = THIS_MODULE,
dec6999
+	.llseek = crash_llseek,
dec6999
+	.read = crash_read,
dec6999
+};
dec6999
+
dec6999
+static struct miscdevice crash_dev = {
dec6999
+	MISC_DYNAMIC_MINOR,
dec6999
+	"crash",
dec6999
+	&crash_fops
dec6999
+};
dec6999
+
dec6999
+static int __init
dec6999
+crash_init(void)
dec6999
+{
dec6999
+	int ret;
dec6999
+
dec6999
+	ret = misc_register(&crash_dev);
dec6999
+	if (ret) {
dec6999
+		printk(KERN_ERR
dec6999
+		    "crash memory driver: cannot misc_register (MISC_DYNAMIC_MINOR)\n");
dec6999
+		goto out;
dec6999
+	}
dec6999
+
dec6999
+	ret = 0;
dec6999
+	printk(KERN_INFO "crash memory driver: version %s\n", CRASH_VERSION);
dec6999
+out:
dec6999
+	return ret;
dec6999
+}
dec6999
+
dec6999
+static void __exit
dec6999
+crash_cleanup_module(void)
dec6999
+{
dec6999
+	misc_deregister(&crash_dev);
dec6999
+}
dec6999
+
dec6999
+module_init(crash_init);
dec6999
+module_exit(crash_cleanup_module);
dec6999
+
dec6999
+MODULE_LICENSE("GPL");
dec6999
diff --git a/include/asm-generic/crash-driver.h b/include/asm-generic/crash-driver.h
dec6999
new file mode 100644
dec6999
index 0000000..25ab986
dec6999
--- /dev/null
dec6999
+++ b/include/asm-generic/crash-driver.h
dec6999
@@ -0,0 +1,72 @@
dec6999
+#ifndef __CRASH_H__
dec6999
+#define __CRASH_H__
dec6999
+
dec6999
+/*
dec6999
+ * include/linux/crash-driver.h
dec6999
+ *
dec6999
+ * Copyright (c) 2013 Red Hat, Inc. All rights reserved.
dec6999
+ *
dec6999
+ * This program is free software; you can redistribute it and/or modify
dec6999
+ * it under the terms of the GNU General Public License as published by
dec6999
+ * the Free Software Foundation; either version 2, or (at your option)
dec6999
+ * any later version.
dec6999
+ *
dec6999
+ * This program is distributed in the hope that it will be useful,
dec6999
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
dec6999
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
dec6999
+ * GNU General Public License for more details.
dec6999
+ *
dec6999
+ * You should have received a copy of the GNU General Public License
dec6999
+ * along with this program; if not, write to the Free Software
dec6999
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
dec6999
+ *
dec6999
+ */
dec6999
+
dec6999
+#ifdef __KERNEL__
dec6999
+
dec6999
+#include <linux/mm.h>
dec6999
+#include <linux/highmem.h>
dec6999
+
dec6999
+static inline void *
dec6999
+map_virtual(u64 offset, struct page **pp)
dec6999
+{
dec6999
+	struct page *page;
dec6999
+	unsigned long pfn;
dec6999
+	void *vaddr;
dec6999
+
dec6999
+	pfn = (unsigned long)(offset >> PAGE_SHIFT);
dec6999
+
dec6999
+	if (!page_is_ram(pfn)) {
dec6999
+		printk(KERN_INFO
dec6999
+		    "crash memory driver: !page_is_ram(pfn: %lx)\n", pfn);
dec6999
+		return NULL;
dec6999
+	}
dec6999
+
dec6999
+	if (!pfn_valid(pfn)) {
dec6999
+		printk(KERN_INFO
dec6999
+		    "crash memory driver: invalid pfn: %lx )\n", pfn);
dec6999
+		return NULL;
dec6999
+	}
dec6999
+
dec6999
+	page = pfn_to_page(pfn);
dec6999
+
dec6999
+	vaddr = kmap(page);
dec6999
+	if (!vaddr) {
dec6999
+		printk(KERN_INFO
dec6999
+		    "crash memory driver: pfn: %lx kmap(page: %lx) failed\n",
dec6999
+			pfn, (unsigned long)page);
dec6999
+		return NULL;
dec6999
+	}
dec6999
+
dec6999
+	*pp = page;
dec6999
+	return (vaddr + (offset & (PAGE_SIZE-1)));
dec6999
+}
dec6999
+
dec6999
+static inline void unmap_virtual(struct page *page)
dec6999
+{
dec6999
+	kunmap(page);
dec6999
+}
dec6999
+
dec6999
+#endif /* __KERNEL__ */
dec6999
+
dec6999
+#endif /* __CRASH_H__ */
dec6999
-- 
dec6999
2.7.4
dec6999
dec6999
From 23d8bd48303acda2d3a95a3e1a662784a4fa9fcd Mon Sep 17 00:00:00 2001
dec6999
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
dec6999
Date: Tue, 20 Sep 2016 19:39:46 +0200
dec6999
Subject: [PATCH] Update of crash driver to handle CONFIG_HARDENED_USERCOPY and
dec6999
 to restrict the supported architectures.
dec6999
dec6999
---
dec6999
 drivers/char/Kconfig |  1 +
dec6999
 drivers/char/crash.c | 33 ++++++++++++++++++++++++++++++---
dec6999
 2 files changed, 31 insertions(+), 3 deletions(-)
dec6999
dec6999
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
dec6999
index 99b99d5..be6a3ae 100644
dec6999
--- a/drivers/char/Kconfig
dec6999
+++ b/drivers/char/Kconfig
dec6999
@@ -6,6 +6,7 @@ menu "Character devices"
dec6999
 
dec6999
 config CRASH
dec6999
 	tristate "Crash Utility memory driver"
dec6999
+	depends on X86_32 || X86_64 || ARM || ARM64 || PPC64 || S390
dec6999
 
dec6999
 source "drivers/tty/Kconfig"
dec6999
 
dec6999
diff --git a/drivers/char/crash.c b/drivers/char/crash.c
dec6999
index 085378a..0258bf8 100644
dec6999
--- a/drivers/char/crash.c
dec6999
+++ b/drivers/char/crash.c
dec6999
@@ -32,7 +32,7 @@
dec6999
 #include <asm/types.h>
dec6999
 #include <asm/crash-driver.h>
dec6999
 
dec6999
-#define CRASH_VERSION   "1.0"
dec6999
+#define CRASH_VERSION   "1.2"
dec6999
 
dec6999
 /*
dec6999
  *  These are the file operation functions that allow crash utility
dec6999
@@ -66,6 +66,7 @@ crash_read(struct file *file, char *buf, size_t count, loff_t *poff)
dec6999
 	struct page *page;
dec6999
 	u64 offset;
dec6999
 	ssize_t read;
dec6999
+	char *buffer = file->private_data;
dec6999
 
dec6999
 	offset = *poff;
dec6999
 	if (offset >> PAGE_SHIFT != (offset+count-1) >> PAGE_SHIFT)
dec6999
@@ -74,8 +75,12 @@ crash_read(struct file *file, char *buf, size_t count, loff_t *poff)
dec6999
 	vaddr = map_virtual(offset, &page);
dec6999
 	if (!vaddr)
dec6999
 		return -EFAULT;
dec6999
-
dec6999
-	if (copy_to_user(buf, vaddr, count)) {
dec6999
+	/*
dec6999
+	 * Use bounce buffer to bypass the CONFIG_HARDENED_USERCOPY
dec6999
+	 * kernel text restriction.
dec6999
+	*/
dec6999
+	memcpy(buffer, (char *)vaddr, count);
dec6999
+	if (copy_to_user(buf, buffer, count)) {
dec6999
 		unmap_virtual(page);
dec6999
 		return -EFAULT;
dec6999
 	}
dec6999
@@ -86,10 +91,32 @@ crash_read(struct file *file, char *buf, size_t count, loff_t *poff)
dec6999
 	return read;
dec6999
 }
dec6999
 
dec6999
+static int
dec6999
+crash_open(struct inode * inode, struct file * filp)
dec6999
+{
dec6999
+	if (!capable(CAP_SYS_RAWIO))
dec6999
+		return -EPERM;
dec6999
+
dec6999
+	filp->private_data = (void *)__get_free_page(GFP_KERNEL);
dec6999
+	if (!filp->private_data)
dec6999
+		return -ENOMEM;
dec6999
+
dec6999
+	return 0;
dec6999
+}
dec6999
+
dec6999
+static int
dec6999
+crash_release(struct inode *inode, struct file *filp)
dec6999
+{
dec6999
+	free_pages((unsigned long)filp->private_data, 0);
dec6999
+	return 0;
dec6999
+}
dec6999
+
dec6999
 static struct file_operations crash_fops = {
dec6999
 	.owner = THIS_MODULE,
dec6999
 	.llseek = crash_llseek,
dec6999
 	.read = crash_read,
dec6999
+	.open = crash_open,
dec6999
+	.release = crash_release,
dec6999
 };
dec6999
 
dec6999
 static struct miscdevice crash_dev = {
dec6999
-- 
dec6999
2.7.4
dec6999
dec6999
From: Dave Anderson <anderson@redhat.com>
dec6999
Date: Fri, 18 Nov 2016 11:52:35 -0500
dec6999
Cc: onestero@redhat.com
dec6999
Subject: [PATCH v2] Restore live system crash analysis for ARM64
dec6999
dec6999
This v2 version simplifies the copy out of the kimage_voffset value
dec6999
to user-space per Oleg's suggestion.
dec6999
dec6999
Upstream status: N/A
dec6999
dec6999
Test: v2 version tested successfully with a modified crash utility
dec6999
dec6999
The following Linux 4.6 commit breaks support for live system
dec6999
crash analysis on ARM64:
dec6999
dec6999
   commit a7f8de168ace487fa7b88cb154e413cf40e87fc6
dec6999
   Author: Ard Biesheuvel <ard.biesheuvel@linaro.org>
dec6999
   arm64: allow kernel Image to be loaded anywhere in physical memory
dec6999
dec6999
The patchset drastically modified the kernel's virtual memory layout,
dec6999
where notably the static kernel text and data image was moved from the
dec6999
unity mapped region into the vmalloc region.  Prior to Linux 4.6,
dec6999
the kernel's __virt_to_phys() function was this:
dec6999
dec6999
 #define __virt_to_phys(x)  (((phys_addr_t)(x) - PAGE_OFFSET + PHYS_OFFSET))
dec6999
dec6999
When running on a live system, the crash utility could determine PAGE_OFFSET
dec6999
by looking at the virtual addresses compiled into the vmlinux file, and
dec6999
PHYS_OFFSET can be determined by looking at /proc/iomem.
dec6999
dec6999
As of Linux 4.6, it is done differently:
dec6999
dec6999
 #define __virt_to_phys(x) ({                                            \
dec6999
        phys_addr_t __x = (phys_addr_t)(x);                             \
dec6999
        __x & BIT(VA_BITS - 1) ? (__x & ~PAGE_OFFSET) + PHYS_OFFSET :   \
dec6999
                                 (__x - kimage_voffset); })
dec6999
dec6999
The PAGE_OFFSET/PHYS_OFFSET section of the conditional expression is for
dec6999
traditional unity-mapped virtual addresses, but kernel text and static
dec6999
data requires the new "kimage_voffset" variable.  Unfortunately, the
dec6999
contents of the new "kimage_voffset" variable is not available or
dec6999
calculatable from a user-space perspective, even with root privileges.
dec6999
dec6999
At least the ARM64 developers made its contents available to modules
dec6999
with an EXPORT_SYMBOL(kimage_voffset) declaration.  Accordingly, with
dec6999
a modification to the /dev/crash driver to return its contents, the
dec6999
crash utility can run on a live system.
dec6999
dec6999
The patch allows for architecture-specific DEV_CRASH_ARCH_DATA ioctls
dec6999
to be created, where this is the first instance of one.
dec6999
dec6999
dec6999
---
dec6999
 arch/arm64/include/asm/crash-driver.h | 16 ++++++++++++++++
dec6999
 drivers/char/crash.c                  | 13 ++++++++++++-
dec6999
 2 files changed, 28 insertions(+), 1 deletion(-)
dec6999
dec6999
diff --git a/arch/arm64/include/asm/crash-driver.h b/arch/arm64/include/asm/crash-driver.h
dec6999
index 43b26da..fe68e7c 100644
dec6999
--- a/arch/arm64/include/asm/crash-driver.h
dec6999
+++ b/arch/arm64/include/asm/crash-driver.h
dec6999
@@ -3,4 +3,20 @@
dec6999
 
dec6999
 #include <asm-generic/crash-driver.h>
dec6999
 
dec6999
+#define DEV_CRASH_ARCH_DATA _IOR('c', 1, long)
dec6999
+
dec6999
+static long
dec6999
+crash_arch_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dec6999
+{
dec6999
+	extern u64 kimage_voffset;
dec6999
+
dec6999
+	switch (cmd)
dec6999
+	{
dec6999
+	case DEV_CRASH_ARCH_DATA:
dec6999
+		return put_user(kimage_voffset, (unsigned long __user *)arg);
dec6999
+	default:
dec6999
+		return -EINVAL;
dec6999
+	}
dec6999
+}
dec6999
+
dec6999
 #endif /* _ARM64_CRASH_H */
dec6999
diff --git a/drivers/char/crash.c b/drivers/char/crash.c
dec6999
index 0258bf8..dfb767c 100644
dec6999
--- a/drivers/char/crash.c
dec6999
+++ b/drivers/char/crash.c
dec6999
@@ -32,7 +32,7 @@
dec6999
 #include <asm/types.h>
dec6999
 #include <asm/crash-driver.h>
dec6999
 
dec6999
-#define CRASH_VERSION   "1.2"
dec6999
+#define CRASH_VERSION   "1.3"
dec6999
 
dec6999
 /*
dec6999
  *  These are the file operation functions that allow crash utility
dec6999
@@ -111,10 +111,21 @@ crash_release(struct inode *inode, struct file *filp)
dec6999
 	return 0;
dec6999
 }
dec6999
 
dec6999
+static long
dec6999
+crash_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dec6999
+{
dec6999
+#ifdef DEV_CRASH_ARCH_DATA
dec6999
+	return crash_arch_ioctl(file, cmd, arg);
dec6999
+#else
dec6999
+	return -EINVAL;
dec6999
+#endif
dec6999
+}
dec6999
+
dec6999
 static struct file_operations crash_fops = {
dec6999
 	.owner = THIS_MODULE,
dec6999
 	.llseek = crash_llseek,
dec6999
 	.read = crash_read,
dec6999
+	.unlocked_ioctl = crash_ioctl,
dec6999
 	.open = crash_open,
dec6999
 	.release = crash_release,
dec6999
 };
dec6999
-- 
dec6999
1.8.3.1
dec6999