Browse Source

proc/kcore: add vmcoreinfo note to /proc/kcore

The vmcoreinfo information is useful for runtime debugging tools, not just
for crash dumps.  A lot of this information can be determined by other
means, but this is much more convenient, and it only adds a page at most
to the file.

Link: http://lkml.kernel.org/r/fddbcd08eed76344863303878b12de1c1e2a04b6.1531953780.git.osandov@fb.com
Signed-off-by: Omar Sandoval <osandov@fb.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Bhupesh Sharma <bhsharma@redhat.com>
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: James Morse <james.morse@arm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Omar Sandoval 7 years ago
parent
commit
23c85094fe
4 changed files with 21 additions and 4 deletions
  1. 1 0
      fs/proc/Kconfig
  2. 16 2
      fs/proc/kcore.c
  3. 2 0
      include/linux/crash_core.h
  4. 2 2
      kernel/crash_core.c

+ 1 - 0
fs/proc/Kconfig

@@ -31,6 +31,7 @@ config PROC_FS
 config PROC_KCORE
 config PROC_KCORE
 	bool "/proc/kcore support" if !ARM
 	bool "/proc/kcore support" if !ARM
 	depends on PROC_FS && MMU
 	depends on PROC_FS && MMU
+	select CRASH_CORE
 	help
 	help
 	  Provides a virtual ELF core file of the live kernel.  This can
 	  Provides a virtual ELF core file of the live kernel.  This can
 	  be read with gdb and other ELF tools.  No modifications can be
 	  be read with gdb and other ELF tools.  No modifications can be

+ 16 - 2
fs/proc/kcore.c

@@ -10,6 +10,7 @@
  *	Safe accesses to vmalloc/direct-mapped discontiguous areas, Kanoj Sarcar <kanoj@sgi.com>
  *	Safe accesses to vmalloc/direct-mapped discontiguous areas, Kanoj Sarcar <kanoj@sgi.com>
  */
  */
 
 
+#include <linux/crash_core.h>
 #include <linux/mm.h>
 #include <linux/mm.h>
 #include <linux/proc_fs.h>
 #include <linux/proc_fs.h>
 #include <linux/kcore.h>
 #include <linux/kcore.h>
@@ -81,10 +82,13 @@ static size_t get_kcore_size(int *nphdr, size_t *phdrs_len, size_t *notes_len,
 	}
 	}
 
 
 	*phdrs_len = *nphdr * sizeof(struct elf_phdr);
 	*phdrs_len = *nphdr * sizeof(struct elf_phdr);
-	*notes_len = (3 * (sizeof(struct elf_note) + ALIGN(sizeof(CORE_STR), 4)) +
+	*notes_len = (4 * sizeof(struct elf_note) +
+		      3 * ALIGN(sizeof(CORE_STR), 4) +
+		      VMCOREINFO_NOTE_NAME_BYTES +
 		      ALIGN(sizeof(struct elf_prstatus), 4) +
 		      ALIGN(sizeof(struct elf_prstatus), 4) +
 		      ALIGN(sizeof(struct elf_prpsinfo), 4) +
 		      ALIGN(sizeof(struct elf_prpsinfo), 4) +
-		      ALIGN(arch_task_struct_size, 4));
+		      ALIGN(arch_task_struct_size, 4) +
+		      ALIGN(vmcoreinfo_size, 4));
 	*data_offset = PAGE_ALIGN(sizeof(struct elfhdr) + *phdrs_len +
 	*data_offset = PAGE_ALIGN(sizeof(struct elfhdr) + *phdrs_len +
 				  *notes_len);
 				  *notes_len);
 	return *data_offset + size;
 	return *data_offset + size;
@@ -406,6 +410,16 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
 				  sizeof(prpsinfo));
 				  sizeof(prpsinfo));
 		append_kcore_note(notes, &i, CORE_STR, NT_TASKSTRUCT, current,
 		append_kcore_note(notes, &i, CORE_STR, NT_TASKSTRUCT, current,
 				  arch_task_struct_size);
 				  arch_task_struct_size);
+		/*
+		 * vmcoreinfo_size is mostly constant after init time, but it
+		 * can be changed by crash_save_vmcoreinfo(). Racing here with a
+		 * panic on another CPU before the machine goes down is insanely
+		 * unlikely, but it's better to not leave potential buffer
+		 * overflows lying around, regardless.
+		 */
+		append_kcore_note(notes, &i, VMCOREINFO_NOTE_NAME, 0,
+				  vmcoreinfo_data,
+				  min(vmcoreinfo_size, notes_len - i));
 
 
 		tsz = min_t(size_t, buflen, notes_offset + notes_len - *fpos);
 		tsz = min_t(size_t, buflen, notes_offset + notes_len - *fpos);
 		if (copy_to_user(buffer, notes + *fpos - notes_offset, tsz)) {
 		if (copy_to_user(buffer, notes + *fpos - notes_offset, tsz)) {

+ 2 - 0
include/linux/crash_core.h

@@ -60,6 +60,8 @@ phys_addr_t paddr_vmcoreinfo_note(void);
 #define VMCOREINFO_CONFIG(name) \
 #define VMCOREINFO_CONFIG(name) \
 	vmcoreinfo_append_str("CONFIG_%s=y\n", #name)
 	vmcoreinfo_append_str("CONFIG_%s=y\n", #name)
 
 
+extern unsigned char *vmcoreinfo_data;
+extern size_t vmcoreinfo_size;
 extern u32 *vmcoreinfo_note;
 extern u32 *vmcoreinfo_note;
 
 
 Elf_Word *append_elf_note(Elf_Word *buf, char *name, unsigned int type,
 Elf_Word *append_elf_note(Elf_Word *buf, char *name, unsigned int type,

+ 2 - 2
kernel/crash_core.c

@@ -14,8 +14,8 @@
 #include <asm/sections.h>
 #include <asm/sections.h>
 
 
 /* vmcoreinfo stuff */
 /* vmcoreinfo stuff */
-static unsigned char *vmcoreinfo_data;
-static size_t vmcoreinfo_size;
+unsigned char *vmcoreinfo_data;
+size_t vmcoreinfo_size;
 u32 *vmcoreinfo_note;
 u32 *vmcoreinfo_note;
 
 
 /* trusted vmcoreinfo, e.g. we can make a copy in the crash memory */
 /* trusted vmcoreinfo, e.g. we can make a copy in the crash memory */