[Crash-utility] [patch] crash: Show warning message if specified dumpfile has its kernel data scrubbed out.

Mahesh J Salgaonkar mahesh at linux.vnet.ibm.com
Fri Sep 16 12:25:52 UTC 2011


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 at 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 */




More information about the Crash-utility mailing list