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)
This commit is contained in:
Dave Anderson 2019-02-08 11:12:23 -05:00
parent ac5a7889d3
commit a89ec821cb
4 changed files with 93 additions and 6 deletions

1
defs.h
View File

@ -4908,6 +4908,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

View File

@ -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);
/*
@ -128,6 +130,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
@ -11162,3 +11166,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;
}
}
}

7
main.c
View File

@ -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;

View File

@ -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
@ -1787,11 +1787,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;
}
}