x86/crash: Define arch_crash_save_vmcoreinfo() if CONFIG_CRASH_CORE=y
authorOmar Sandoval <osandov@fb.com>
Fri, 20 Dec 2019 16:22:49 +0000 (08:22 -0800)
committerBorislav Petkov <bp@suse.de>
Mon, 23 Dec 2019 11:58:41 +0000 (12:58 +0100)
On x86 kernels configured with CONFIG_PROC_KCORE=y and
CONFIG_KEXEC_CORE=n, the vmcoreinfo note in /proc/kcore is incomplete.

Specifically, it is missing arch-specific information like the KASLR
offset and whether 5-level page tables are enabled. This breaks
applications like drgn [1] and crash [2], which need this information
for live debugging via /proc/kcore.

This happens because:

1. CONFIG_PROC_KCORE selects CONFIG_CRASH_CORE.
2. kernel/crash_core.c (compiled if CONFIG_CRASH_CORE=y) calls
   arch_crash_save_vmcoreinfo() to get the arch-specific parts of
   vmcoreinfo. If it is not defined, then it uses a no-op fallback.
3. x86 defines arch_crash_save_vmcoreinfo() in
   arch/x86/kernel/machine_kexec_*.c, which is only compiled if
   CONFIG_KEXEC_CORE=y.

Therefore, an x86 kernel with CONFIG_CRASH_CORE=y and
CONFIG_KEXEC_CORE=n uses the no-op fallback and gets incomplete
vmcoreinfo data. This isn't relevant to kdump, which requires
CONFIG_KEXEC_CORE. It only affects applications which read vmcoreinfo at
runtime, like the ones mentioned above.

Fix it by moving arch_crash_save_vmcoreinfo() into two new
arch/x86/kernel/crash_core_*.c files, which are gated behind
CONFIG_CRASH_CORE.

1: https://github.com/osandov/drgn/blob/73dd7def1217e24cc83d8ca95c995decbd9ba24c/libdrgn/program.c#L385
2: https://github.com/crash-utility/crash/commit/60a42d709280cdf38ab06327a5b4fa9d9208ef86

Signed-off-by: Omar Sandoval <osandov@fb.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Kairui Song <kasong@redhat.com>
Cc: Lianbo Jiang <lijiang@redhat.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
Cc: "Peter Zijlstra (Intel)" <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: x86-ml <x86@kernel.org>
Link: https://lkml.kernel.org/r/0589961254102cca23e3618b96541b89f2b249e2.1576858905.git.osandov@fb.com
arch/x86/kernel/Makefile
arch/x86/kernel/crash_core_32.c [new file with mode: 0644]
arch/x86/kernel/crash_core_64.c [new file with mode: 0644]
arch/x86/kernel/machine_kexec_32.c
arch/x86/kernel/machine_kexec_64.c

index 6175e37..9b294c1 100644 (file)
@@ -94,6 +94,7 @@ obj-$(CONFIG_FUNCTION_TRACER) += ftrace_$(BITS).o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
 obj-$(CONFIG_FTRACE_SYSCALLS)  += ftrace.o
 obj-$(CONFIG_X86_TSC)          += trace_clock.o
+obj-$(CONFIG_CRASH_CORE)       += crash_core_$(BITS).o
 obj-$(CONFIG_KEXEC_CORE)       += machine_kexec_$(BITS).o
 obj-$(CONFIG_KEXEC_CORE)       += relocate_kernel_$(BITS).o crash.o
 obj-$(CONFIG_KEXEC_FILE)       += kexec-bzimage64.o
diff --git a/arch/x86/kernel/crash_core_32.c b/arch/x86/kernel/crash_core_32.c
new file mode 100644 (file)
index 0000000..c0159a7
--- /dev/null
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/crash_core.h>
+
+#include <asm/pgtable.h>
+#include <asm/setup.h>
+
+void arch_crash_save_vmcoreinfo(void)
+{
+#ifdef CONFIG_NUMA
+       VMCOREINFO_SYMBOL(node_data);
+       VMCOREINFO_LENGTH(node_data, MAX_NUMNODES);
+#endif
+#ifdef CONFIG_X86_PAE
+       VMCOREINFO_CONFIG(X86_PAE);
+#endif
+}
diff --git a/arch/x86/kernel/crash_core_64.c b/arch/x86/kernel/crash_core_64.c
new file mode 100644 (file)
index 0000000..845a57e
--- /dev/null
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/crash_core.h>
+
+#include <asm/pgtable.h>
+#include <asm/setup.h>
+
+void arch_crash_save_vmcoreinfo(void)
+{
+       u64 sme_mask = sme_me_mask;
+
+       VMCOREINFO_NUMBER(phys_base);
+       VMCOREINFO_SYMBOL(init_top_pgt);
+       vmcoreinfo_append_str("NUMBER(pgtable_l5_enabled)=%d\n",
+                             pgtable_l5_enabled());
+
+#ifdef CONFIG_NUMA
+       VMCOREINFO_SYMBOL(node_data);
+       VMCOREINFO_LENGTH(node_data, MAX_NUMNODES);
+#endif
+       vmcoreinfo_append_str("KERNELOFFSET=%lx\n", kaslr_offset());
+       VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE);
+       VMCOREINFO_NUMBER(sme_mask);
+}
index 7b45e8d..02bddfc 100644 (file)
@@ -250,15 +250,3 @@ void machine_kexec(struct kimage *image)
 
        __ftrace_enabled_restore(save_ftrace_enabled);
 }
-
-void arch_crash_save_vmcoreinfo(void)
-{
-#ifdef CONFIG_NUMA
-       VMCOREINFO_SYMBOL(node_data);
-       VMCOREINFO_LENGTH(node_data, MAX_NUMNODES);
-#endif
-#ifdef CONFIG_X86_PAE
-       VMCOREINFO_CONFIG(X86_PAE);
-#endif
-}
-
index 16e125a..ad5cdd6 100644 (file)
@@ -398,25 +398,6 @@ void machine_kexec(struct kimage *image)
        __ftrace_enabled_restore(save_ftrace_enabled);
 }
 
-void arch_crash_save_vmcoreinfo(void)
-{
-       u64 sme_mask = sme_me_mask;
-
-       VMCOREINFO_NUMBER(phys_base);
-       VMCOREINFO_SYMBOL(init_top_pgt);
-       vmcoreinfo_append_str("NUMBER(pgtable_l5_enabled)=%d\n",
-                       pgtable_l5_enabled());
-
-#ifdef CONFIG_NUMA
-       VMCOREINFO_SYMBOL(node_data);
-       VMCOREINFO_LENGTH(node_data, MAX_NUMNODES);
-#endif
-       vmcoreinfo_append_str("KERNELOFFSET=%lx\n",
-                             kaslr_offset());
-       VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE);
-       VMCOREINFO_NUMBER(sme_mask);
-}
-
 /* arch-dependent functionality related to kexec file-based syscall */
 
 #ifdef CONFIG_KEXEC_FILE