[Patch 3/4][makedumpfile] Capture slimdump if elf-note NT_NOCOREDUMPpresent

From: K.Prasad
Date: Mon Oct 03 2011 - 03:37:54 EST


The kernel decides to add a new elf-note of type NT_NOCOREDUMP for various
hardware error triggered crashes where it makes no sense (or sometimes
dangerous) to capture kernel memory into the dump. This patch teaches
'makedumpfile' tool needs to recognise the new elf-note type and act
accordingly.

Since only a 'slimdump' of a very small size (containing only elf-headers and
elf-notes section) will be captured, the coredump will be of ELF type (and not
kdump-compressed format).

Todo: Make changes to the man pages of makedumpfile to describe these changes.

Signed-off-by: K.Prasad <prasad@xxxxxxxxxxxxxxxxxx>
---
elf_info.c | 36 ++++++++++++++++++++++++++++++++++++
elf_info.h | 8 ++++++++
makedumpfile.c | 13 ++++++++++++-
makedumpfile.h | 1 +
4 files changed, 57 insertions(+), 1 deletions(-)

diff --git a/elf_info.c b/elf_info.c
index 114dd05..de93d9a 100644
--- a/elf_info.c
+++ b/elf_info.c
@@ -287,6 +287,41 @@ offset_note_desc(void *note)
return offset;
}

+/*
+ * The kernel generally adds an elf-note of type NT_NOCOREDUMP if the crash is
+ * due to a hardware error and when it makes no sense to read/store the
+ * crashing kernel's memory. In such a case, only a 'slimdump' is captured.
+ *
+ * This function checks if the elf-header has a note of type NT_NOCOREDUMP.
+ */
+int
+has_nocoredump_note(void)
+{
+ char note[MAX_SIZE_NHDR];
+ off_t offset;
+
+ offset = offset_pt_note_memory;
+ while (offset < offset_pt_note_memory + size_pt_note_memory) {
+ if (lseek(fd_memory, offset, SEEK_SET) < 0) {
+ ERRMSG("Can't seek the dump memory(%s). %s\n",
+ name_memory, strerror(errno));
+ return FALSE;
+ }
+ if (read(fd_memory, note, sizeof(note)) != sizeof(note)) {
+ ERRMSG("Can't read the dump memory(%s). %s\n",
+ name_memory, strerror(errno));
+ return FALSE;
+ }
+ if (note_type(note) == NT_NOCOREDUMP) {
+ DEBUG_MSG("kdump will not be collected. "
+ "NT_NOCOREDUMP elf-note present.\n");
+ return TRUE;
+ }
+ offset += offset_next_note(note);
+ }
+ return FALSE;
+}
+
static int
get_pt_note_info(void)
{
@@ -630,6 +665,7 @@ get_elf_info(int fd, char *filename)
ERRMSG("Can't find PT_NOTE Phdr.\n");
return FALSE;
}
+ has_nocoredump_note();
if (!get_pt_note_info()) {
ERRMSG("Can't get PT_NOTE information.\n");
return FALSE;
diff --git a/elf_info.h b/elf_info.h
index 4dff9c1..10fdc0b 100644
--- a/elf_info.h
+++ b/elf_info.h
@@ -22,6 +22,12 @@
#define ERASEINFO_NOTE_NAME "ERASEINFO"
#define ERASEINFO_NOTE_NAME_BYTES (sizeof(ERASEINFO_NOTE_NAME))

+/*
+ * Temporary definition of new elf-note type for compilation purposes.
+ * Not required when run on a new kernel containing this definition.
+ */
+#define NT_NOCOREDUMP 21
+
#define MAX_SIZE_NHDR MAX(sizeof(Elf64_Nhdr), sizeof(Elf32_Nhdr))


@@ -34,6 +40,8 @@ unsigned long long get_max_paddr(void);
int get_elf64_ehdr(int fd, char *filename, Elf64_Ehdr *ehdr);
int get_elf32_ehdr(int fd, char *filename, Elf32_Ehdr *ehdr);
int get_elf_info(int fd, char *filename);
+int has_nocoredump_note(void);
+
void free_elf_info(void);

int is_elf64_memory(void);
diff --git a/makedumpfile.c b/makedumpfile.c
index 7b7c266..a73b4f7 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -4173,7 +4173,11 @@ write_elf_pages(struct cache_data *cd_header, struct cache_data *cd_page)
if (!get_phdr_memory(i, &load))
return FALSE;

- if (load.p_type != PT_LOAD)
+ /*
+ * Do not capture the kernel's memory if flag_nocoredump is
+ * turned on. This may be dangerous to the system stability.
+ */
+ if ((load.p_type != PT_LOAD) || (info->flag_nocoredump))
continue;

off_memory= load.p_offset;
@@ -5760,6 +5764,13 @@ create_dumpfile(void)
if (!get_elf_info(info->fd_memory, info->name_memory))
return FALSE;
}
+ /*
+ * If NT_NOCOREDUMP elf-note is present, indicate the same through
+ * 'flag_nocoredump' flag. The resultant slimdump will always be in ELF
+ * format, irrespective of the user options.
+ */
+ info->flag_nocoredump = info->flag_elf_dumpfile = has_nocoredump_note();
+
if (is_xen_memory()) {
if (!initial_xen())
return FALSE;
diff --git a/makedumpfile.h b/makedumpfile.h
index f0e5da8..faf1c65 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -778,6 +778,7 @@ struct DumpInfo {
int flag_exclude_xen_dom;/* exclude Domain-U from xen-kdump */
int flag_dmesg; /* dump the dmesg log out of the vmcore file */
int flag_nospace; /* the flag of "No space on device" error */
+ int flag_nocoredump; /* coredump not collected */
unsigned long vaddr_for_vtop; /* virtual address for debugging */
long page_size; /* size of page */
long page_shift;
--
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/