[PATCH] Using crash with newer xen versions fails
by Dietmar Hahn
Hi Dave,
when trying to debug the xen hypervisor on a vmcore file it doesn't work for me.
xen_version: 4.11.0_08-1
...
This GDB was configured as "x86_64-unknown-linux-gnu"...
crash: invalid kernel virtual address: bf45ffa0001ef8 type:
"fill_pcpu_struct"
WARNING: cannot fill pcpu_struct.
crash: cannot read cpu_info.
I had a look at this and found a change in the struct tss_struct when trying
to read the rsp0. The change in the xen-git-tree was done with commit 98dffb05ce4.
Old:
struct tss_struct {
unsigned short back_link,__blh;
union { u64 rsp0, esp0; };
...
New:
struct __packed __cacheline_aligned tss_struct {
uint32_t :32;
uint64_t rsp0, rsp1, rsp2;
After fixing this in the crash command I got:
...
This GDB was configured as "x86_64-unknown-linux-gnu"...
KERNEL: xen-syms
DUMPFILE: vmcore
CPUS: 4
DOMAINS: 3
UPTIME: --:--:--
MACHINE: Intel(R) Xeon(R) CPU E5520 @ 2.27GHz (2266 Mhz)
MEMORY: 12 GB
Segmentation fault (core dumped)
It seems that the commit 4e1dca21 in xen_hyper.c isn't sufficient
anymore.
Because reading the symbol "dom0" is successful but the address is zero.
My suggestion now is simply to switch the if statement.
First ask for the symbol "hardware_domain" (introduced in xen version 4.5.0)
and if it isn't found use the symbol "dom0".
This works for me with vmcore's with xen-4.4.4.
Dietmar.
---
x86_64.c | 6 +++++-
xen_hyper.c | 8 ++++----
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/x86_64.c b/x86_64.c
index 0f6c584..26eb286 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -7903,7 +7903,11 @@ x86_64_init_hyper(int when)
case POST_GDB:
XEN_HYPER_STRUCT_SIZE_INIT(cpuinfo_x86, "cpuinfo_x86");
XEN_HYPER_STRUCT_SIZE_INIT(tss_struct, "tss_struct");
- XEN_HYPER_ASSIGN_OFFSET(tss_struct_rsp0) = MEMBER_OFFSET("tss_struct", "__blh") + sizeof(short unsigned int);
+ if (MEMBER_EXISTS("tss_struct", "__blh")) {
+ XEN_HYPER_ASSIGN_OFFSET(tss_struct_rsp0) = MEMBER_OFFSET("tss_struct", "__blh") + sizeof(short unsigned int);
+ } else {
+ XEN_HYPER_ASSIGN_OFFSET(tss_struct_rsp0) = MEMBER_OFFSET("tss_struct", "rsp0");
+ }
XEN_HYPER_MEMBER_OFFSET_INIT(tss_struct_ist, "tss_struct", "ist");
if (symbol_exists("cpu_data")) {
xht->cpu_data_address = symbol_value("cpu_data");
diff --git a/xen_hyper.c b/xen_hyper.c
index 20072e9..f2f00e6 100644
--- a/xen_hyper.c
+++ b/xen_hyper.c
@@ -1060,8 +1060,8 @@ xen_hyper_get_domains(void)
long domain_next_in_list;
int i, j;
- if (!try_get_symbol_data("dom0", sizeof(void *), &domain))
- get_symbol_data("hardware_domain", sizeof(void *), &domain);
+ if (!try_get_symbol_data("hardware_domain", sizeof(void *), &domain))
+ get_symbol_data("dom0", sizeof(void *), &domain);
domain_next_in_list = MEMBER_OFFSET("domain", "next_in_list");
i = 0;
@@ -1103,8 +1103,8 @@ xen_hyper_get_domain_next(int mod, ulong *next)
if (xhdt->dom0) {
*next = xhdt->dom0->domain;
} else {
- if (!try_get_symbol_data("dom0", sizeof(void *), next))
- get_symbol_data("hardware_domain", sizeof(void *), next);
+ if (!try_get_symbol_data("hardware_domain", sizeof(void *), next))
+ get_symbol_data("dom0", sizeof(void *), next);
}
return xhdt->domain_struct;
break;
--
2.12.3
5 years, 10 months
[ANNOUNCE] crash version 7.2.5 is available
by Dave Anderson
Download from: http://people.redhat.com/anderson
or
https://github.com/crash-utility/crash/releases
The github master branch serves as a development branch that will contain
all patches that are queued for the next release:
$ git clone git://github.com/crash-utility/crash.git
Changelog:
- Resurrection of the the "dev -p" option for displaying PCI device
data on Linux 2.6.26 and later kernels. The option was deprecated
as of Linux 2.6.26, and without the patch, the option would indicate
"dev: -p option not supported or applicable on this architecture
or kernel" when running against the newer kernel versions. PCI Bus
information will also be displayed with this patch.
(m.mizuma(a)jp.fujitsu.com)
- With Linux 4.19-rc1 commit 7d4340bb92a9df78e6e28152f3dd89d9bd82146b,
titled "powerpc/mm: Increase MAX_PHYSMEM_BITS to 128TB with
SPARSEMEM_VMEMMAP config", the PPC64 MAX_PHYSMEM_BITS value has
been bumped up to 47. The appropriate update has been made in
this patch.
(hbathini(a)linux.ibm.com)
- Fix to allow piping command output to a shell script beginning with
a shebang (#!) character sequence if the script pathname is specified
with a preceding "./" or "/". Without the patch, the piped command
fails with the message "crash: pipe operation failed".
(k-hagio(a)ab.jp.nec.com)
- Fix for the PPC64 "bt" command to recognize when a thread is running
in OPAL firmware. Without the patch, the "bt" command indicates
<task-address>: Invalid Stack Pointer <OPAL-firmware-address>"
(hbathini(a)linux.ibm.com)
- As an addendum to the "dev -p" patch above, add the new structure
member offsets for display by the "help -o" option.
(anderson(a)redhat.com)
- Enhancement to the "kmem -n" option to dump memory block information
if the kernel supports it. In addition, the memory section data
block has a new "STATE" column added to it.
(m.mizuma(a)jp.fujitsu.com)
- Addendum to the previous "kmem -n" patch to fix a FTBFS issue.
Without the patch, certain architectures fail to compile with the
error "memory.c:17315:16: error: ‘PAGE_SHIFT’ undeclared (first
use in this function)"
(m.mizuma(a)jp.fujitsu.com)
- Fix the calculation of the vmalloc memory region size to account for
Linux 4.17 commit a7412546d8cb5ad578805060b4006f2a021b5868, titled
"x86/mm: Adjust vmalloc base and size at boot-time", which increases
the region's size from 32TB to 1280TB when 5-level pagetables are
enabled. Also presume that virtual addresses above the end of the
vmalloc space up to the beginning of vmemmap space are translatable
via 5-level page tables. Without the patch, mapped virtual addresses
may fail translation in whatever command accesses them, with errors
indicating "seek error: kernel virtual address: <mapped-address>
type: <type-string>"
(anderson(a)redhat.com)
- Address several Coverity Scan "RESOURCE_LEAK" issues in the following
top-level source files: cmdline.c, kvmdump.c, lkcd_v8.c, xendump.c,
symbols.c, unwind_x86_32_64.c, va_server.c and va_server_v1.c.
(anderson(a)redhat.com)
- Modify the x86_64 "bt" behavior when a legitimate exception RIP value
cannot be referenced symbolically, such as when the exception occurs
while running in seccomp BPF filter code. Without the patch, the
exception frame register dump is preceded by "[exception RIP: unknown
or invalid address]", and then followed by "bt: WARNING: possibly
bogus exception frame". With the patch applied, the translation of
the exception RIP will show "[exception RIP: no symbolic reference]",
and there will be no warning message.
(anderson(a)redhat.com)
- Account for the /proc/kcore VMCOREINFO PT_NOTE in Linux 4.19 and
later kernels having commit 23c85094fe1895caefdd19ef624ee687ec5f4507,
titled "proc/kcore: add vmcoreinfo note to /proc/kcore". The PT_NOTE
information is stored during session initialization for later display
by "help -[n|D]"; a subsequent commit will make it available for use
by the crash utility's internal pc->read_vmcoreinfo() function.
(anderson(a)redhat.com)
- Second phase of support for the VMCOREINFO PT_NOTE added to the ELF
header of /proc/kcore in Linux 4.19 and later kernels. This patch
introduces support for live session /proc/kcore VMCOREINFO access by
the crash utility's internal pc->read_vmcoreinfo() function. New
usage include the initialization of the x86_64 phys_base value, and
the arm64 phys_offset, page size, and VA bits count.
(anderson(a)redhat.com)
- Fix for Linux 4.20-rc1 and later kernels that contain kernel commit
5c83511bdb9832c86be20fb86b783356e2f58062, titled "x86/paravirt: Use
a single ops structure". Without the patch, the kernel may be
misidentified as an ARCH_XEN kernel, with the most noticable result
being the inability to read vmemmap'd page structures.
(anderson(a)redhat.com)
- Implemented the functionality for a new MEMBER_TYPE_NAME() macro,
which will return a pointer to the type name string of a structure
member. It is being put in place for the support of Linux 4.20
radix tree to xarray replacements, where structure member types may
be changed from radix_tree_root structures to xarray structures.
(anderson(a)redhat.com)
- First phase of support for the XArray facility. The added support is
similar to that of radix trees, but introduces completely separate
functions, structures and #defines. None of the applicable radix
tree users in the crash utility have been switched over, so this
phase does not introduce any functional changes.
(asmadeus(a)codewreck.org, anderson(a)redhat.com)
- Second phase of support for the XArray facility, which handles the
switch-over of PID handling from a radix tree to an XArray in Linux
4.20 and later kernels. Without the patch, the crash session fails
during session initialization with the message "crash: radix trees
do not exist or have changed their format".
(asmadeus(a)codewreck.org, anderson(a)redhat.com)
- Third phase of support for the XArray facility, which consolidates
the radix_tree_pair and xarray_pair structures into a unified
list_pair structure that is used by both facilities, and fixes the
"bpf" command. Without the patch, the command fails on Linux 4.20
or later kernels with the error message "bpf: radix trees do not
exist or have changed their format".
(anderson(a)redhat.com)
- Added support for usage of the XArray facility by the "files -p"
option. Without the patch, the command fails on Linux 4.20 and later
kernels with the error message "files: radix trees do not exist or
have changed their format".
(anderson(a)redhat.com)
- Added support for usage of the XArray facility by the "irq" command.
Without the patch, the command fails on Linux 4.20 and later kernels
with the error message "irq: radix trees do not exist or have changed
their format".
(anderson(a)redhat.com)
- Added support for usage of the XArray facility by the "ipcs" command.
Without the patch, the command may fail on Linux 4.20 and later
kernels with the error message "irq: radix trees do not exist or have
changed their format".
(anderson(a)redhat.com)
- Added a new "tree -t xarray" option to display of the contents of
an XArray in Linux 4.20 and later kernels. The implementation is
similar to that of radix tree displays, but in addition, the "-p"
option will also display the index value of each entry in a radix
tree or XArray.
(anderson(a)redhat.com)
- Fix for the "files -p <inode>" option on a file with a large
number of pages. Without the patch, the command attempts to read
radix tree node slot entries that are RADIX_TREE_EXCEPTIONAL_ENTRY
types instead of page pointers, and as a result may fail with a
dump of the internal buffer allocation stats followed by the message
"files: cannot allocate any more memory!".
(anderson(a)redhat.com)
- Fix for the "ps -s" option on ARM64 if the number of tasks exceeds
2000. Without the patch, the command ultimately fails with a
dump of the internal buffer allocation stats, followed by the
message "ps: cannot allocate any more memory!".
(anderson(a)redhat.com)
- With Linux 4.20-rc1 commit 4ffe713b7587b14695c9bec26a000fc88ef54895,
titled "powerpc/mm: Increase the max addressable memory to 2PB",
the PPC64 MAX_PHYSMEM_BITS value has been bumped up to 51 for
CONFIG_SPARSEMEM_VMEMMAP and CONFIG_SPARSEMEM_EXTREME. The
appropriate update has been made in this patch.
(hbathini(a)linux.ibm.com)
- Implemented a new plugin function for the readline library's tab
completion feature. Without the patch, the use of the default plugin
from the embedded gdb module has been seen to cause segmentation
violations or other fatal malloc/free/corruption assertions. The new
plugin takes gdb out of the picture entirely, and also restricts the
matching options to just symbol names, so as not to clutter the
results with irrelevant filenames.
(anderson(a)redhat.com)
- The RHEL8 kernel will contain a backport of the Linux 4.19 kernel
commit 7d4340bb92a9df78e6e28152f3dd89d9bd82146b, titled "powerpc/mm:
Increase MAX_PHYSMEM_BITS to 128TB with SPARSEMEM_VMEMMAP config".
As a result, the use of the THIS_KERNEL_VERSION() macro by the
crash utility does not suffice for determining the MAX_PHYSMEM_BITS
value for PPC64. The appropriate update has been made in this patch.
(anderson(a)redhat.com)
- Fix for an initialization-time session failure when all three of the
following conditions exist:
(1) invoking the session with "crash -d2" or larger debug number
(2) running against a Linux 3.3 or later kernel
(3) using a post-7.2.4 crash utility that has the new "kmem -n"
support above for the display of memory blocks
Without the patch, the crash session fails with the error message
"crash: invalid structure member offset: device_kobj".
(anderson(a)redhat.com)
- Fix for an initialization-time segmentation violation when invoking
crash-7.2.4 or later with "crash -d2" or larger debug number.
(anderson(a)redhat.com)
- Add a write operation handler to the sample /dev/crash memory driver
that enables writing to kernel memory via the "wr" command.
(serapheim(a)delphix.com)
- Prevent a SIGSEGV if a user attempts to input a command line that
exceeds the maximum length of 1500 bytes. The patch displays an
error message and ignores the command line.
(anderson(a)redhat.com)
- Fix for the "dev -[dD]" options in kernels containing Linux 5.0-rc1
commit 7ff4f8035695984c513598e2d49c8277d5d234ca, titled "block:
remove dead queue members", in which the number of I/Os issued to
a disk driver are no longer stored in the request_queue structure.
Without the patch, the options indicate "dev: -d option not supported
or applicable on this architecture or kernel". With the patch, the
"DRV" column is not shown.
(m.mizuma(a)jp.fujitsu.com)
- A crash-7.1.1 commit added support for Linux version 5.x. To prevent
surprise failures due to unexpected kernel version bumps in the
future, support has been added for version 6, keeping it one step
ahead.
(anderson(a)redhat.com)
- Fix for a gcc-9 compilation error that occurs if an inline asm
statement clobbers the stack pointer. Without the patch, x86 and
x86_64 builds will fail to compile gdb-7.6/gdb/common/linux-ptrace.c,
generating an error that indicates "error: Stack Pointer register
clobbered by '%rsp' in 'asm'".
(anderson(a)redhat.com)
5 years, 10 months
[PATCH] dev: Fix display disk I/O statistics for 4.20
by Masayoshi Mizuma
Fix for the "dev -d|-D" command on Linux 4.20 and later kernels.
In Linux 4.20, in_flight member in struct request_queue is disappeared.
And also struct request_list is removed. So, dev -d|-D doesn't work.
Unfortunately, it seems that there is no alternative information
which shows the number of I/Os issued to disk driver. So this patch
gets DRV column removed if in_flight member in struct request_queue
isn't valid.
Without the patch, the command fails with the error message
"dev: -d option not supported or applicable on this architecture
or kernel".
Signed-off-by: Masayoshi Mizuma <m.mizuma(a)jp.fujitsu.com>
---
defs.h | 2 ++
dev.c | 73 ++++++++++++++++++++++++++++++++++++++++---------------
symbols.c | 4 +++
3 files changed, 59 insertions(+), 20 deletions(-)
diff --git a/defs.h b/defs.h
index a3cb5a4..9ebdde6 100644
--- a/defs.h
+++ b/defs.h
@@ -2064,6 +2064,8 @@ struct offset_table { /* stash of commonly-used offsets */
long xarray_xa_head;
long xa_node_slots;
long xa_node_shift;
+ long hd_struct_dkstats;
+ long disk_stats_in_flight;
};
struct size_table { /* stash of commonly-used sizes */
diff --git a/dev.c b/dev.c
index 7ce2422..24efea2 100644
--- a/dev.c
+++ b/dev.c
@@ -3974,7 +3974,7 @@ struct iter {
* this function reads request_list.count[2], and the first argument
* is the address of request_queue.
*/
- void (*get_diskio)(unsigned long , struct diskio *);
+ void (*get_diskio)(unsigned long , unsigned long, struct diskio *);
/*
* check if device.type == &disk_type
@@ -4187,24 +4187,55 @@ get_mq_diskio(unsigned long q, unsigned long *mq_count)
}
}
+static void
+get_one_diskio_from_dkstats(unsigned long dkstats, unsigned long *count)
+{
+ int cpu;
+ unsigned long dkstats_addr;
+ unsigned long in_flight[2];
+
+ for (cpu = 0; cpu < kt->cpus; cpu++) {
+ if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) {
+ dkstats_addr = dkstats + kt->__per_cpu_offset[cpu];
+ readmem(dkstats_addr + OFFSET(disk_stats_in_flight),
+ KVADDR, in_flight, sizeof(long) * 2,
+ "disk_stats.in_flight", FAULT_ON_ERROR);
+ count[0] += in_flight[0];
+ count[1] += in_flight[1];
+ }
+ }
+}
+
+
/* read request_queue.rq.count[2] */
static void
-get_diskio_1(unsigned long rq, struct diskio *io)
+get_diskio_1(unsigned long rq, unsigned long gendisk, struct diskio *io)
{
int count[2];
- unsigned long mq_count[2] = { 0 };
+ unsigned long io_counts[2] = { 0 };
+ unsigned long dkstats;
if (!use_mq_interface(rq)) {
- readmem(rq + OFFSET(request_queue_rq) +
- OFFSET(request_list_count), KVADDR, count,
- sizeof(int) * 2, "request_list.count", FAULT_ON_ERROR);
+ if (VALID_MEMBER(request_queue_rq)) {
+ readmem(rq + OFFSET(request_queue_rq) +
+ OFFSET(request_list_count), KVADDR, count,
+ sizeof(int) * 2, "request_list.count", FAULT_ON_ERROR);
+
+ io->read = count[0];
+ io->write = count[1];
+ } else {
+ readmem(gendisk + OFFSET(gendisk_part0) +
+ OFFSET(hd_struct_dkstats), KVADDR, &dkstats,
+ sizeof(ulong), "gendisk.part0.dkstats", FAULT_ON_ERROR);
+ get_one_diskio_from_dkstats(dkstats, io_counts);
- io->read = count[0];
- io->write = count[1];
+ io->read = io_counts[0];
+ io->write = io_counts[1];
+ }
} else {
- get_mq_diskio(rq, mq_count);
- io->read = mq_count[0];
- io->write = mq_count[1];
+ get_mq_diskio(rq, io_counts);
+ io->read = io_counts[0];
+ io->write = io_counts[1];
}
}
@@ -4250,9 +4281,6 @@ init_iter(struct iter *i)
i->get_in_flight = get_in_flight_1;
} else if (SIZE(rq_in_flight) == sizeof(int) * 2) {
i->get_in_flight = get_in_flight_2;
- } else {
- option_not_supported('d');
- return;
}
i->get_diskio = get_diskio_1;
@@ -4354,7 +4382,7 @@ display_one_diskio(struct iter *i, unsigned long gendisk, ulong flags)
sizeof(ulong), "gen_disk.queue", FAULT_ON_ERROR);
readmem(gendisk + OFFSET(gendisk_major), KVADDR, &major, sizeof(int),
"gen_disk.major", FAULT_ON_ERROR);
- i->get_diskio(queue_addr, &io);
+ i->get_diskio(queue_addr, gendisk, &io);
if ((flags & DIOF_NONZERO)
&& (io.read + io.write == 0))
@@ -4379,11 +4407,14 @@ display_one_diskio(struct iter *i, unsigned long gendisk, ulong flags)
(char *)(unsigned long)io.write),
space(MINSPACE));
- if (!use_mq_interface(queue_addr)) {
- in_flight = i->get_in_flight(queue_addr);
- fprintf(fp, "%5u\n", in_flight);
+ if (VALID_MEMBER(request_queue_in_flight)) {
+ if (!use_mq_interface(queue_addr)) {
+ in_flight = i->get_in_flight(queue_addr);
+ fprintf(fp, "%5u\n", in_flight);
+ } else
+ fprintf(fp, "%s\n", "N/A(MQ)");
} else
- fprintf(fp, "%s\n", "N/A(MQ)");
+ fprintf(fp, "\n");
}
static void
@@ -4418,7 +4449,7 @@ display_all_diskio(ulong flags)
i.sync_count ? mkstring(buf4, 5, RJUST, "SYNC") :
mkstring(buf4, 5, RJUST, "WRITE"),
space(MINSPACE),
- mkstring(buf5, 5, RJUST, "DRV"));
+ VALID_MEMBER(request_queue_in_flight) ? mkstring(buf5, 5, RJUST, "DRV") : "");
while ((gendisk = i.next_disk(&i)) != 0)
display_one_diskio(&i, gendisk, flags);
@@ -4446,6 +4477,7 @@ void diskio_init(void)
MEMBER_OFFSET_INIT(gendisk_part0, "gendisk", "part0");
MEMBER_OFFSET_INIT(gendisk_queue, "gendisk", "queue");
MEMBER_OFFSET_INIT(hd_struct_dev, "hd_struct", "__dev");
+ MEMBER_OFFSET_INIT(hd_struct_dkstats, "hd_struct", "dkstats");
MEMBER_OFFSET_INIT(klist_k_list, "klist", "k_list");
MEMBER_OFFSET_INIT(klist_node_n_klist, "klist_node", "n_klist");
MEMBER_OFFSET_INIT(klist_node_n_node, "klist_node", "n_node");
@@ -4476,6 +4508,7 @@ void diskio_init(void)
MEMBER_SIZE_INIT(rq_in_flight, "request_queue", "in_flight");
MEMBER_SIZE_INIT(class_private_devices, "class_private",
"class_devices");
+ MEMBER_OFFSET_INIT(disk_stats_in_flight, "disk_stats", "in_flight");
dt->flags |= DISKIO_INIT;
}
diff --git a/symbols.c b/symbols.c
index ef6f934..5f77e27 100644
--- a/symbols.c
+++ b/symbols.c
@@ -10101,6 +10101,10 @@ dump_offset_table(char *spec, ulong makestruct)
OFFSET(gendisk_queue));
fprintf(fp, " hd_struct_dev: %ld\n",
OFFSET(hd_struct_dev));
+ fprintf(fp, " hd_struct_dkstats: %ld\n",
+ OFFSET(hd_struct_dkstats));
+ fprintf(fp, " disk_stats_in_flight: %ld\n",
+ OFFSET(disk_stats_in_flight));
fprintf(fp, " klist_k_list: %ld\n",
OFFSET(klist_k_list));
fprintf(fp, " klist_node_n_klist: %ld\n",
--
2.18.1
5 years, 10 months
[PATCH] Enable writing to kernel memory through "/dev/crash"
by Serapheim Dimitropoulos
From: Serapheim Dimitropoulos <serapheim(a)delphix.com>
Enable writing to kernel memory thorugh the "/dev/crash"
driver.
Signed-off-by: Serapheim Dimitropoulos <serapheim(a)delphix.com>
---
memory_driver/crash.c | 41 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/memory_driver/crash.c b/memory_driver/crash.c
index 2b1ea3d..b57b211 100644
--- a/memory_driver/crash.c
+++ b/memory_driver/crash.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2004, 2011, 2016 Dave Anderson <anderson(a)redhat.com>
* Copyright (C) 2004, 2011, 2016 Red Hat, Inc.
+ * Copyright (C) 2019 Serapheim Dimitropoulos <serapheim(a)delphix.com>
*/
/******************************************************************************
@@ -137,7 +138,7 @@ static inline void unmap_virtual(struct page *page)
#endif
-#define CRASH_VERSION "1.3"
+#define CRASH_VERSION "1.4"
/*
* These are the file operation functions that allow crash utility
@@ -159,6 +160,43 @@ crash_llseek(struct file * file, loff_t offset, int orig)
}
}
+static ssize_t
+crash_write(struct file *file, const char *buf, size_t count, loff_t *poff)
+{
+ void *vaddr;
+ struct page *page;
+ u64 offset;
+ ssize_t written;
+ char *buffer = file->private_data;
+
+ offset = *poff;
+ if (offset >> PAGE_SHIFT != (offset+count-1) >> PAGE_SHIFT)
+ return -EINVAL;
+
+ vaddr = map_virtual(offset, &page);
+ if (!vaddr)
+ return -EFAULT;
+
+ /*
+ * Use bounce buffer to bypass the CONFIG_HARDENED_USERCOPY
+ * kernel text restriction.
+ */
+ if (copy_from_user(buffer, buf, count)) {
+ unmap_virtual(page);
+ return -EFAULT;
+ }
+
+ if (probe_kernel_write(vaddr, buffer, count)) {
+ unmap_virtual(page);
+ return -EFAULT;
+ }
+ unmap_virtual(page);
+
+ written = count;
+ *poff += written;
+ return written;
+}
+
/*
* Determine the page address for an address offset value,
* get a virtual address for it, and copy it out.
@@ -256,6 +294,7 @@ static struct file_operations crash_fops = {
.owner = THIS_MODULE,
.llseek = crash_llseek,
.read = crash_read,
+ .write = crash_write,
.unlocked_ioctl = crash_ioctl,
.open = crash_open,
.release = crash_release,
--
2.19.0
5 years, 10 months