If a QEMU COMPRESSED dump from a KASLR-enabled kernel is missing the
vmcoreinfo data, try to calculate phys_base and kaslr_offset by using
the technique developed by Takao Indoh.
---
 defs.h         |  5 ++++-
 diskdump.c     | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 kaslr_helper.c |  9 ++++++++-
 symbols.c      |  4 ++++
 x86_64.c       |  3 ++-
 5 files changed, 79 insertions(+), 3 deletions(-)

diff --git a/defs.h b/defs.h
index ec2d61c..fe87a05 100644
--- a/defs.h
+++ b/defs.h
@@ -284,7 +284,7 @@ struct number_option {
 #define KVMDUMP_DUMPFILE()  (pc->flags & KVMDUMP)
 #define SADUMP_DUMPFILE()  (pc->flags & SADUMP)
 #define QEMU_MEM_DUMP_NO_VMCOREINFO() \
-           ((pc->flags2 & (QEMU_MEM_DUMP_ELF)) && !(pc->flags2 & VMCOREINFO))
+           ((pc->flags2 & (QEMU_MEM_DUMP_ELF|QEMU_MEM_DUMP_COMPRESSED)) && 
!(pc->flags2 & VMCOREINFO))
 
 #define NETDUMP_LOCAL    (0x1)  /* netdump_data flags */
 #define NETDUMP_REMOTE   (0x2)  
@@ -6274,6 +6274,7 @@ int diskdump_memory_dump(FILE *);
 FILE *set_diskdump_fp(FILE *);
 void get_diskdump_regs(struct bt_info *, ulong *, ulong *);
 int diskdump_phys_base(unsigned long *);
+int diskdump_set_phys_base(unsigned long);
 ulong *diskdump_flags;
 int is_partial_diskdump(void);
 int dumpfile_is_split(void);
@@ -6285,6 +6286,8 @@ void diskdump_display_regs(int, FILE *);
 void process_elf32_notes(void *, ulong);
 void process_elf64_notes(void *, ulong);
 void dump_registers_for_compressed_kdump(void);
+int diskdump_kaslr_check(void);
+QEMUCPUState *diskdump_get_qemucpustate(int);
 
 /*
  * makedumpfile.c
diff --git a/diskdump.c b/diskdump.c
index b08a46c..40ad59d 100644
--- a/diskdump.c
+++ b/diskdump.c
@@ -56,6 +56,7 @@ struct diskdump_data {
        void    **nt_prstatus_percpu;
        uint    num_prstatus_notes;
        void    **nt_qemu_percpu;
+       void    **nt_qemucs_percpu;
        uint    num_qemu_notes;
 
        /* page cache */
@@ -153,8 +154,13 @@ resize_note_pointers:
                            dd->num_qemu_notes * sizeof(void *))) == NULL)
                                error(FATAL, 
                                    "compressed kdump: cannot realloc QEMU note 
pointers\n");
+                       if  ((dd->nt_qemucs_percpu = 
realloc(dd->nt_qemucs_percpu,
+                           dd->num_qemu_notes * sizeof(void *))) == NULL)
+                               error(FATAL,
+                                   "compressed kdump: cannot realloc QEMU note 
pointers\n");
                } else
                        free(dd->nt_qemu_percpu);
+                       free(dd->nt_qemucs_percpu);
        }
 }
 
@@ -283,6 +289,10 @@ process_elf32_notes(void *note_buf, unsigned long 
size_note)
                }
                len = sizeof(Elf32_Nhdr);
                if (STRNEQ((char *)nt + len, "QEMU")) {
+                       ulong *ptr =
+                           (ulong *)((char *)nt + sizeof(Elf32_Nhdr) + 
nt->n_namesz);
+                       dd->nt_qemucs_percpu[qemu_num] =
+                           (ulong *)roundup((ulong) ptr, 4);
                        dd->nt_qemu_percpu[qemu_num] = nt;
                        qemu_num++;
                }
@@ -332,6 +342,10 @@ process_elf64_notes(void *note_buf, unsigned long 
size_note)
                }
                len = sizeof(Elf64_Nhdr);
                if (STRNEQ((char *)nt + len, "QEMU")) {
+                       ulong *ptr =
+                           (ulong *)((char *)nt + sizeof(Elf64_Nhdr) + 
nt->n_namesz);
+                       dd->nt_qemucs_percpu[qemu_num] =
+                           (ulong *)roundup((ulong) ptr, 4);
                        dd->nt_qemu_percpu[qemu_num] = nt;
                        qemu_num++;
                }
@@ -759,6 +773,10 @@ restart:
                        error(FATAL, "qemu mem dump compressed: cannot malloc 
pointer"
                                " to QEMU notes\n");
 
+               if ((dd->nt_qemucs_percpu = malloc(NR_CPUS * sizeof(void *))) 
== NULL)
+                       error(FATAL, "qemu mem dump compressed: cannot malloc 
pointer"
+                               " to QEMUCS notes\n");
+
                if (FLAT_FORMAT()) {
                        if (!read_flattened_format(dd->dfd, offset, 
dd->notes_buf, size)) {
                                error(INFO, "compressed kdump: cannot read 
notes data"
@@ -854,6 +872,8 @@ err:
                free(dd->nt_prstatus_percpu);
        if (dd->nt_qemu_percpu)
                free(dd->nt_qemu_percpu);
+       if (dd->nt_qemucs_percpu)
+               free(dd->nt_qemucs_percpu);
 
        dd->flags &= ~(DISKDUMP_LOCAL|KDUMP_CMPRS_LOCAL);
        pc->flags2 &= ~ELF_NOTES;
@@ -967,6 +987,17 @@ diskdump_phys_base(unsigned long *phys_base)
        return FALSE;
 }
 
+int
+diskdump_set_phys_base(unsigned long phys_base)
+{
+       if (diskdump_kaslr_check()) {
+               dd->sub_header_kdump->phys_base = phys_base;
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
 /*
  *  Check whether paddr is already cached.
  */
@@ -2435,4 +2466,34 @@ dump_registers_for_compressed_kdump(void)
        }
 }
 
+int diskdump_kaslr_check()
+{
+       if (!QEMU_MEM_DUMP_NO_VMCOREINFO())
+               return FALSE;
 
+       if (dd->num_qemu_notes)
+               return TRUE;
+
+       return FALSE;
+}
+
+#ifdef X86_64
+QEMUCPUState * diskdump_get_qemucpustate(int cpu)
+{
+        if (cpu >= dd->num_qemu_notes) {
+                if (CRASHDEBUG(1))
+                        error(INFO,
+                            "Invalid index for QEMU Note: %d (>= %d)\n",
+                            cpu, dd->num_qemu_notes);
+                return NULL;
+        }
+
+        if (dd->machine_type != EM_X86_64) {
+                if (CRASHDEBUG(1))
+                        error(INFO, "Only x86_64 64bit is supported.\n");
+                return NULL;
+        }
+
+        return (QEMUCPUState *)dd->nt_qemucs_percpu[cpu];
+}
+#endif
diff --git a/kaslr_helper.c b/kaslr_helper.c
index d02ef72..8646b8f 100644
--- a/kaslr_helper.c
+++ b/kaslr_helper.c
@@ -241,7 +241,14 @@ qemu_get_cr3_idtr(ulong *cr3, ulong *idtr)
 {
        QEMUCPUState *cpustat;
 
-       cpustat = kdump_get_qemucpustate(0);
+       if (DISKDUMP_DUMPFILE()) {
+               cpustat = diskdump_get_qemucpustate(0);
+       } else if (KDUMP_DUMPFILE()) {
+               cpustat = kdump_get_qemucpustate(0);
+       } else {
+               return FALSE;
+       }
+
        if (!cpustat) {
                return FALSE;
        }
diff --git a/symbols.c b/symbols.c
index 348d9ae..ddbce7d 100644
--- a/symbols.c
+++ b/symbols.c
@@ -613,6 +613,8 @@ kaslr_init(void)
        if (QEMU_MEM_DUMP_NO_VMCOREINFO()) {
                if (KDUMP_DUMPFILE() && kdump_kaslr_check()) {
                        kt->flags2 |= KASLR_CHECK;
+               } else if (DISKDUMP_DUMPFILE() && diskdump_kaslr_check()) {
+                       kt->flags2 |= KASLR_CHECK;
                }
        } else if (KDUMP_DUMPFILE() || DISKDUMP_DUMPFILE()) {
                if ((string = pc->read_vmcoreinfo("SYMBOL(_stext)"))) {
@@ -660,6 +662,8 @@ derive_kaslr_offset(bfd *abfd, int dynamic, bfd_byte 
*start, bfd_byte *end,
                                sadump_set_phys_base(phys_base);
                        else if (KDUMP_DUMPFILE())
                                kdump_set_phys_base(phys_base);
+                       else if (DISKDUMP_DUMPFILE())
+                               diskdump_set_phys_base(phys_base);
                }
 
                return;
diff --git a/x86_64.c b/x86_64.c
index f6f6c0e..c36bf66 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -6633,7 +6633,8 @@ x86_64_calc_phys_base(void)
         */
 
        if (QEMU_MEM_DUMP_NO_VMCOREINFO()) {
-               if (KDUMP_DUMPFILE() && kdump_phys_base(&phys_base))
+               if ((KDUMP_DUMPFILE() && kdump_phys_base(&phys_base)) ||
+                   (DISKDUMP_DUMPFILE() && diskdump_phys_base(&phys_base)))
                        machdep->machspec->phys_base = phys_base;
 
                if (!x86_64_virt_phys_base())
-- 
2.14.3

--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to