The new version of makedumpfile 1.4.0 allows user to filter out kernel data
(e.g. security keys, confidential/secret information etc.) from the vmcore.
The data to be filtered out is poisoned with character 'X' (0x58 in Hex).
The filtered ELF kdump now carries a new ELF note section "ERASEINFO" that
contains eraseinfo data. The filtered compressed kdump now contains new
members (offset_eraseinfo, size_eraseinfo) int the sub header with new header
version 5.
With the above change in place, there may be instances where the filtered
dumpfile may not be readable OR may not be helpful in analyzing the problem
using crash tool. Most of the time crash tool will be able to read/analyze
the dump unless someone scrubs out the data on which crash utility is
dependent on. Hence, This patch adds support into crash utility to detect the
above changes and show early warning message to the user about the fact that
he is dealing with filtered dumpfile.
This patch adds support for "help -n" output to display the filter data
strings that are appended to the dumpfile or stored in an ELF note.
Signed-off-by: Mahesh Salgaonkar <mahesh(a)linux.vnet.ibm.com>
---
defs.h | 1 +
diskdump.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diskdump.h | 2 ++
main.c | 5 +++++
netdump.c | 22 ++++++++++++++++------
5 files changed, 84 insertions(+), 6 deletions(-)
Index: crash-5.1.7/defs.h
===================================================================
--- crash-5.1.7.orig/defs.h
+++ crash-5.1.7/defs.h
@@ -431,6 +431,7 @@ struct program_context {
#define FLAT (0x1ULL)
#define ELF_NOTES (0x2ULL)
#define GET_OSRELEASE (0x4ULL)
+#define ERASEINFO_DATA (0x8ULL)
#define FLAT_FORMAT() (pc->flags2 & FLAT)
#define ELF_NOTES_VALID() (pc->flags2 & ELF_NOTES)
char *cleanup;
Index: crash-5.1.7/main.c
===================================================================
--- crash-5.1.7.orig/main.c
+++ crash-5.1.7/main.c
@@ -603,6 +603,11 @@ main(int argc, char **argv)
void
main_loop(void)
{
+ if (pc->flags2 & ERASEINFO_DATA)
+ error(WARNING, "\nFile %s may not be readable/analyzable. Some"
+ " of the kernel data from the dump has been scrubbed"
+ " out\n", pc->dumpfile);
+
if (!(pc->flags & GDB_INIT)) {
gdb_session_init();
show_untrusted_files();
Index: crash-5.1.7/netdump.c
===================================================================
--- crash-5.1.7.orig/netdump.c
+++ crash-5.1.7/netdump.c
@@ -1636,13 +1636,13 @@ dump_Elf32_Nhdr(Elf32_Off offset, int st
char buf[BUFSIZE];
char *ptr;
ulong *uptr;
- int xen_core, vmcoreinfo;
+ int xen_core, vmcoreinfo, eraseinfo;
uint64_t remaining, notesize;
note = (Elf32_Nhdr *)((char *)nd->elf32 + offset);
BZERO(buf, BUFSIZE);
- xen_core = vmcoreinfo = FALSE;
+ xen_core = vmcoreinfo = eraseinfo = FALSE;
ptr = (char *)note + sizeof(Elf32_Nhdr);
if (ptr > (nd->elf_header + nd->header_size)) {
@@ -1730,6 +1730,7 @@ dump_Elf32_Nhdr(Elf32_Off offset, int st
default:
xen_core = STRNEQ(buf, "XEN CORE") || STRNEQ(buf, "Xen");
vmcoreinfo = STRNEQ(buf, "VMCOREINFO");
+ eraseinfo = STRNEQ(buf, "ERASEINFO");
if (xen_core) {
netdump_print("(unknown Xen n_type)\n");
if (store)
@@ -1739,6 +1740,10 @@ dump_Elf32_Nhdr(Elf32_Off offset, int st
netdump_print("(unused)\n");
nd->vmcoreinfo = (char *)(ptr + note->n_namesz + 1);
nd->size_vmcoreinfo = note->n_descsz;
+ } else if (eraseinfo) {
+ netdump_print("(unused)\n");
+ if (note->n_descsz)
+ pc->flags2 |= ERASEINFO_DATA;
} else
netdump_print("(?)\n");
break;
@@ -1813,7 +1818,7 @@ dump_Elf32_Nhdr(Elf32_Off offset, int st
if (xen_core)
uptr = (ulong *)roundup((ulong)uptr, 4);
- if (vmcoreinfo) {
+ if (vmcoreinfo || eraseinfo) {
netdump_print(" ");
ptr += note->n_namesz + 1;
for (i = 0; i < note->n_descsz; i++, ptr++) {
@@ -1856,14 +1861,14 @@ dump_Elf64_Nhdr(Elf64_Off offset, int st
ulonglong *uptr;
int *iptr;
ulong *up;
- int xen_core, vmcoreinfo;
+ int xen_core, vmcoreinfo, eraseinfo;
uint64_t remaining, notesize;
note = (Elf64_Nhdr *)((char *)nd->elf64 + offset);
BZERO(buf, BUFSIZE);
ptr = (char *)note + sizeof(Elf64_Nhdr);
- xen_core = vmcoreinfo = FALSE;
+ xen_core = vmcoreinfo = eraseinfo = FALSE;
if (ptr > (nd->elf_header + nd->header_size)) {
error(WARNING,
@@ -1981,6 +1986,7 @@ dump_Elf64_Nhdr(Elf64_Off offset, int st
default:
xen_core = STRNEQ(buf, "XEN CORE") || STRNEQ(buf, "Xen");
vmcoreinfo = STRNEQ(buf, "VMCOREINFO");
+ eraseinfo = STRNEQ(buf, "ERASEINFO");
if (xen_core) {
netdump_print("(unknown Xen n_type)\n");
if (store)
@@ -1997,6 +2003,10 @@ dump_Elf64_Nhdr(Elf64_Off offset, int st
if (READ_PAGESIZE_FROM_VMCOREINFO() && store)
nd->page_size = (uint)
vmcoreinfo_read_integer("PAGESIZE", 0);
+ } else if (eraseinfo) {
+ netdump_print("(unused)\n");
+ if (note->n_descsz)
+ pc->flags2 |= ERASEINFO_DATA;
} else
netdump_print("(?)\n");
break;
@@ -2090,7 +2100,7 @@ dump_Elf64_Nhdr(Elf64_Off offset, int st
lf = 0;
netdump_print("%08lx ", *iptr++);
}
- } else if (vmcoreinfo) {
+ } else if (vmcoreinfo || eraseinfo) {
netdump_print(" ");
ptr += note->n_namesz + 1;
for (i = 0; i < note->n_descsz; i++, ptr++) {
Index: crash-5.1.7/diskdump.c
===================================================================
--- crash-5.1.7.orig/diskdump.c
+++ crash-5.1.7/diskdump.c
@@ -516,6 +516,12 @@ restart:
machdep->process_elf_notes(dd->notes_buf, size);
}
+ /* Check if dump file contains erasesinfo data */
+ if (KDUMP_CMPRS_VALID() && (dd->header->header_version >= 5)
&&
+ (sub_header_kdump->offset_eraseinfo) &&
+ (sub_header_kdump->size_eraseinfo))
+ pc->flags2 |= ERASEINFO_DATA;
+
/* For split dumpfile */
if (KDUMP_CMPRS_VALID()) {
is_split = ((dd->header->header_version >= 2) &&
@@ -1016,6 +1022,50 @@ err:
}
static void
+dump_eraseinfo(FILE *fp)
+{
+ char *buf = NULL;
+ unsigned long i = 0;
+ unsigned long size_eraseinfo = dd->sub_header_kdump->size_eraseinfo;
+ off_t offset = dd->sub_header_kdump->offset_eraseinfo;
+ const off_t failed = (off_t)-1;
+
+ if ((buf = malloc(size_eraseinfo)) == NULL) {
+ error(FATAL, "compressed kdump: cannot malloc eraseinfo"
+ " buffer\n");
+ }
+
+ if (FLAT_FORMAT()) {
+ if (!read_flattened_format(dd->dfd, offset, buf, size_eraseinfo)) {
+ error(INFO, "compressed kdump: cannot read eraseinfo data\n");
+ goto err;
+ }
+ } else {
+ if (lseek(dd->dfd, offset, SEEK_SET) == failed) {
+ error(INFO, "compressed kdump: cannot lseek dump eraseinfo\n");
+ goto err;
+ }
+ if (read(dd->dfd, buf, size_eraseinfo) < size_eraseinfo) {
+ error(INFO, "compressed kdump: cannot read eraseinfo data\n");
+ goto err;
+ }
+ }
+
+ fprintf(fp, " ");
+ for (i = 0; i < size_eraseinfo; i++) {
+ fprintf(fp, "%c", buf[i]);
+ if (buf[i] == '\n')
+ fprintf(fp, " ");
+ }
+ if (buf[i - 1] != '\n')
+ fprintf(fp, "\n");
+err:
+ if (buf)
+ free(buf);
+ return;
+}
+
+static void
dump_nt_prstatus_offset(FILE *fp)
{
struct kdump_sub_header *sub_header_kdump = dd->sub_header_kdump;
@@ -1260,6 +1310,16 @@ __diskdump_memory_dump(FILE *fp)
}
dump_nt_prstatus_offset(fp);
}
+ if (dh->header_version >= 5) {
+ fprintf(fp, " offset_eraseinfo: %lx\n",
+ (ulong)dd->sub_header_kdump->offset_eraseinfo);
+ fprintf(fp, " size_eraseinfo: %lu\n",
+ dd->sub_header_kdump->size_eraseinfo);
+ if (dd->sub_header_kdump->offset_eraseinfo &&
+ dd->sub_header_kdump->size_eraseinfo) {
+ dump_eraseinfo(fp);
+ }
+ }
fprintf(fp, "\n");
} else
fprintf(fp, "(n/a)\n\n");
Index: crash-5.1.7/diskdump.h
===================================================================
--- crash-5.1.7.orig/diskdump.h
+++ crash-5.1.7/diskdump.h
@@ -67,6 +67,8 @@ struct kdump_sub_header {
unsigned long size_vmcoreinfo; /* header_version 3 and later */
off_t offset_note; /* header_version 4 and later */
unsigned long size_note; /* header_version 4 and later */
+ off_t offset_eraseinfo; /* header_version 5 and later */
+ unsigned long size_eraseinfo; /* header_version 5 and later */
};
/* page flags */