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