[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 14/21] qga: add and populate VMDumpInfo
From: |
Marc-André Lureau |
Subject: |
[Qemu-devel] [PATCH 14/21] qga: add and populate VMDumpInfo |
Date: |
Sat, 11 Mar 2017 17:22:49 +0400 |
Get various addresses and informations that can be useful for qemu to
generate dumps, and provide enough details for KASLR kernels to be
exploitable by tools like crash.
phys-base: the physical address where the kernel is loaded
vmcoreinfo: can be used to read the guest vmcoreinfo ELF note
_text: can be used to compute the kaslr offset (not needed when vmcoreinfo)
Signed-off-by: Marc-André Lureau <address@hidden>
---
qga/main.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 134 insertions(+)
diff --git a/qga/main.c b/qga/main.c
index beff041340..1c39895baa 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -65,6 +65,14 @@ typedef struct GAPersistentState {
int64_t fd_counter;
} GAPersistentState;
+typedef struct VMDumpInfo {
+ bool has_phys_base;
+ uint64_t phys_base;
+ bool has_text;
+ uint64_t text;
+ char *vmcoreinfo;
+} VMDumpInfo;
+
struct GAState {
JSONMessageParser parser;
GMainLoop *main_loop;
@@ -90,6 +98,7 @@ struct GAState {
#endif
gchar *pstate_filepath;
GAPersistentState pstate;
+ VMDumpInfo vmdump;
};
struct GAState *ga_state;
@@ -1357,6 +1366,128 @@ static int run_agent(GAState *s, GAConfig *config)
return EXIT_SUCCESS;
}
+#define __START_KERNEL_map 0xffffffff80000000UL
+
+static void update_vmdump_info(GAState *s)
+{
+#ifndef _WIN32
+ char *vmcoreinfo = NULL;
+ char *iomem = NULL;
+ char *kallsyms = NULL;
+ gsize len;
+ GError *err = NULL;
+#ifdef __x86_64__
+ guint64 kernel_code_start, text_start, phys_base;
+ char *tmp, *line, *eol;
+
+ if (!g_file_get_contents("/proc/iomem", &iomem, &len, &err)) {
+ g_critical("Failed to read /proc/iomem: %s", err->message);
+ g_clear_error(&err);
+ goto end;
+ }
+ if (!iomem[len] == '\0') {
+ g_critical("iomem is not null-terminated");
+ goto end;
+ }
+
+ for (line = iomem; line != NULL; line = eol ? eol + 1 : NULL) {
+ eol = strstr(line, "\n");
+ if (eol) {
+ *eol = '\0';
+ }
+ tmp = strstr(line, " : Kernel code");
+ if (!tmp || *(tmp + 14) != '\0') {
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ if (line == NULL) {
+ g_critical("failed to find kernel_code_start");
+ goto end;
+ } else {
+ tmp = strstr(line, "-");
+ if (!tmp) {
+ g_critical("no -");
+ goto end;
+ }
+ *tmp = '\0';
+ kernel_code_start = g_ascii_strtoull(g_strstrip(line), &tmp, 16);
+ if (*tmp != '\0') {
+ g_critical("failed to parse hex value");
+ goto end;
+ }
+ }
+
+ if (!g_file_get_contents("/proc/kallsyms", &kallsyms, &len, &err)) {
+ g_critical("Failed to read /proc/kallsyms: %s", err->message);
+ g_clear_error(&err);
+ goto end;
+ }
+ if (!kallsyms[len] == '\0') {
+ g_critical("iomem is not null-terminated");
+ goto end;
+ }
+
+ for (line = kallsyms; line != NULL; line = eol ? eol + 1 : NULL) {
+ eol = strstr(line, "\n");
+ if (eol) {
+ *eol = '\0';
+ }
+ tmp = strstr(line, " T _text");
+ if (!tmp || *(tmp + 8) != '\0') {
+ continue;
+ } else {
+ *tmp = '\0';
+ break;
+ }
+ }
+
+ if (line == NULL) {
+ g_critical("failed to find _text");
+ goto end;
+ } else {
+ text_start = g_ascii_strtoull(g_strstrip(line), &tmp, 16);
+ if (*tmp != '\0') {
+ g_critical("failed to parse hex value");
+ goto end;
+ }
+ }
+
+ phys_base = kernel_code_start - (text_start - __START_KERNEL_map);
+ g_debug("_text: %lx, kernel_code_start: %lx",
+ text_start, kernel_code_start);
+ g_debug("-> phys_base: %lx", phys_base);
+ g_debug("vmcoreinfo: %s", vmcoreinfo);
+
+ s->vmdump.has_phys_base = true;
+ s->vmdump.phys_base = phys_base;
+ s->vmdump.has_text = true;
+ s->vmdump.text = text_start;
+#endif /* x86_64 */
+
+ if (!g_file_get_contents("/sys/kernel/vmcoreinfo",
+ &vmcoreinfo, &len, &err)) {
+ g_critical("Failed to read vmcoreinfo: %s", err->message);
+ g_clear_error(&err);
+ goto end;
+ }
+ if (!vmcoreinfo[len] == '\0') {
+ g_critical("vmcoreinfo is not null-terminated");
+ goto end;
+ }
+
+ s->vmdump.vmcoreinfo = vmcoreinfo;
+ vmcoreinfo = NULL;
+
+end:
+ g_free(vmcoreinfo);
+ g_free(kallsyms);
+ g_free(iomem);
+#endif
+}
+
int main(int argc, char **argv)
{
int ret = EXIT_SUCCESS;
@@ -1364,6 +1495,8 @@ int main(int argc, char **argv)
GAConfig *config = g_new0(GAConfig, 1);
int listen_fd;
+ update_vmdump_info(s);
+
config->log_level = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL;
qga_qmp_init_marshal(&ga_commands);
@@ -1460,6 +1593,7 @@ end:
if (s->main_loop) {
g_main_loop_unref(s->main_loop);
}
+ g_free(s->vmdump.vmcoreinfo);
g_free(s);
return ret;
--
2.12.0.191.gc5d8de91d
- [Qemu-devel] [PATCH 04/21] qobject: add quint type, (continued)
- [Qemu-devel] [PATCH 04/21] qobject: add quint type, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 05/21] qapi: update the qobject visitor to use QUInt, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 06/21] json: learn to parse uint64 numbers, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 07/21] object: add uint property setter/getter, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 09/21] qdev: use appropriate type, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 08/21] qdev: use int and uint properties, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 10/21] Use uint property getter/setter where appropriate, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 11/21] qdict: learn to lookup quint, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 12/21] test-qga: drop everything until guest-sync, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 13/21] qga: report error on keyfile dump error, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 14/21] qga: add and populate VMDumpInfo,
Marc-André Lureau <=
- [Qemu-devel] [PATCH 15/21] qga: register event emit function, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 16/21] qga: emit VMDUMP_INFO event, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 17/21] virtio-channel: parse qga stream for VMDUMP_INFO event, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 18/21] dump: use qga VMDUMP_INFO for ELF dump, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 19/21] kdump: write vmcoreinfo in header, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 20/21] scripts/dump-guest-memory.py: fix int128_get64 on recent gcc, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 21/21] scripts/dump-guest-memory.py: add VMCOREINFO, Marc-André Lureau, 2017/03/11
- Re: [Qemu-devel] [PATCH 00/21] WIP: dump: add kaslr support (for after 2.9), no-reply, 2017/03/11
- Re: [Qemu-devel] [PATCH 00/21] WIP: dump: add kaslr support (for after 2.9), Dave Anderson, 2017/03/11