crash/SOURCES/github_a89ec821_vmcoreinfo_...

194 lines
5.6 KiB
Diff
Raw Normal View History

2019-05-07 13:44:18 +00:00
commit a89ec821cb5dbb106cb58e8740f84c7e382c0140
Author: Dave Anderson <anderson@redhat.com>
Date: Fri Feb 8 11:12:23 2019 -0500
For live system analysis where there is no vmcoreinfo ELF note
attached to /proc/kcore, or for dumpfile analysis where there is no
vmcoreinfo ELF note attached to the dumpfile, this patch sets the
internal pc->read_vmcoreinfo() function to a new plugin function
that reads the data directly from the live kernel or dumpfile.
Because the function is set much later during initialization than
if the ELF note is attached to /proc/kcore or the dumpfile, it may
not be available during very early session initialization.
(anderson@redhat.com)
diff --git a/defs.h b/defs.h
index 05f2d17..5841b1f 100644
--- a/defs.h
+++ b/defs.h
@@ -4872,6 +4872,7 @@ int clean_exit(int);
int untrusted_file(FILE *, char *);
char *readmem_function_name(void);
char *writemem_function_name(void);
+char *no_vmcoreinfo(const char *);
/*
* cmdline.c
diff --git a/kernel.c b/kernel.c
index e512da5..9f5ba89 100644
--- a/kernel.c
+++ b/kernel.c
@@ -93,6 +93,8 @@ static void source_tree_init(void);
static ulong dump_audit_skb_queue(ulong);
static ulong __dump_audit(char *);
static void dump_audit(void);
+static char *vmcoreinfo_read_string(const char *);
+static void check_vmcoreinfo(void);
/*
@@ -127,6 +129,8 @@ kernel_init()
kt->end = highest_bss_symbol();
if ((sp1 = kernel_symbol_search("_end")) && (sp1->value > kt->end))
kt->end = sp1->value;
+
+ check_vmcoreinfo();
/*
* For the traditional (non-pv_ops) Xen architecture, default to writable
@@ -11117,3 +11121,84 @@ dump_audit(void)
if (!qlen)
error(INFO, "kernel audit log is empty\n");
}
+
+/*
+ * Reads a string value from the VMCOREINFO data stored in (live) memory.
+ *
+ * Returns a string (that has to be freed by the caller) that contains the
+ * value for key or NULL if the key has not been found.
+ */
+static char *
+vmcoreinfo_read_string(const char *key)
+{
+ char *buf, *value_string, *p1, *p2;
+ size_t value_length;
+ size_t vmcoreinfo_size;
+ ulong vmcoreinfo_data;
+ char keybuf[BUFSIZE];
+
+ buf = value_string = NULL;
+
+ switch (get_symbol_type("vmcoreinfo_data", NULL, NULL))
+ {
+ case TYPE_CODE_PTR:
+ get_symbol_data("vmcoreinfo_data", sizeof(vmcoreinfo_data), &vmcoreinfo_data);
+ break;
+ case TYPE_CODE_ARRAY:
+ vmcoreinfo_data = symbol_value("vmcoreinfo_data");
+ break;
+ default:
+ return NULL;
+ }
+
+ get_symbol_data("vmcoreinfo_size", sizeof(vmcoreinfo_size), &vmcoreinfo_size);
+
+ sprintf(keybuf, "%s=", key);
+
+ if ((buf = malloc(vmcoreinfo_size+1)) == NULL) {
+ error(INFO, "cannot malloc vmcoreinfo buffer\n");
+ goto err;
+ }
+
+ if (!readmem(vmcoreinfo_data, KVADDR, buf, vmcoreinfo_size,
+ "vmcoreinfo_data", RETURN_ON_ERROR|QUIET)) {
+ error(INFO, "cannot read vmcoreinfo_data\n");
+ goto err;
+ }
+
+ buf[vmcoreinfo_size] = '\n';
+
+ if ((p1 = strstr(buf, keybuf))) {
+ p2 = p1 + strlen(keybuf);
+ p1 = strstr(p2, "\n");
+ value_length = p1-p2;
+ value_string = calloc(value_length+1, sizeof(char));
+ strncpy(value_string, p2, value_length);
+ value_string[value_length] = NULLCHAR;
+ }
+err:
+ if (buf)
+ free(buf);
+
+ return value_string;
+}
+
+static void
+check_vmcoreinfo(void)
+{
+ if (!kernel_symbol_exists("vmcoreinfo_data") ||
+ !kernel_symbol_exists("vmcoreinfo_size"))
+ return;
+
+ if (pc->read_vmcoreinfo == no_vmcoreinfo) {
+ switch (get_symbol_type("vmcoreinfo_data", NULL, NULL))
+ {
+ case TYPE_CODE_PTR:
+ pc->read_vmcoreinfo = vmcoreinfo_read_string;
+ break;
+ case TYPE_CODE_ARRAY:
+ pc->read_vmcoreinfo = vmcoreinfo_read_string;
+ break;
+ }
+ }
+}
diff --git a/main.c b/main.c
index 7248810..cd282cd 100644
--- a/main.c
+++ b/main.c
@@ -1,8 +1,8 @@
/* main.c - core analysis suite
*
* Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
- * Copyright (C) 2002-2018 David Anderson
- * Copyright (C) 2002-2018 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2002-2019 David Anderson
+ * Copyright (C) 2002-2019 Red Hat, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,7 +29,6 @@ static void check_xen_hyper(void);
static void show_untrusted_files(void);
static void get_osrelease(char *);
static void get_log(char *);
-static char *no_vmcoreinfo(const char *);
static struct option long_options[] = {
{"memory_module", required_argument, 0, 0},
@@ -1950,7 +1949,7 @@ get_log(char *dumpfile)
}
-static char *
+char *
no_vmcoreinfo(const char *unused)
{
return NULL;
diff --git a/netdump.c b/netdump.c
index d0179e0..5aeea6f 100644
--- a/netdump.c
+++ b/netdump.c
@@ -1,7 +1,7 @@
/* netdump.c
*
- * Copyright (C) 2002-2018 David Anderson
- * Copyright (C) 2002-2018 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2002-2019 David Anderson
+ * Copyright (C) 2002-2019 Red Hat, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1786,11 +1786,13 @@ vmcoreinfo_read_string(const char *key)
if (STREQ(key, "NUMBER(kimage_voffset)") && nd->arch_data) {
value = calloc(VADDR_PRLEN+1, sizeof(char));
sprintf(value, "%lx", nd->arch_data);
+ pc->read_vmcoreinfo = no_vmcoreinfo;
return value;
}
if (STREQ(key, "relocate") && nd->arch_data) {
value = calloc(VADDR_PRLEN+1, sizeof(char));
sprintf(value, "%lx", nd->arch_data);
+ pc->read_vmcoreinfo = no_vmcoreinfo;
return value;
}
}