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