[PATCH 1/2] Add support to kaslr offset for offline vmcore files.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



[PATCH 1/2] Add support to kaslr for offline vmcore files.

This patch adds a --kaslr command line parameter for loading x86_64
crash dumps with kaslr enabled.  This reuses the code from 32-bit
x86 relocations with some small changes.  The ASLR offset is postive
instead of negative.  Also had to move the code to traverse the
kernel section before the symbol storing code to figure out which
symbols were outside any sections and therefore were not relocated.

Also made a very small change in search_for_switch_to it was
searching through gdb command output for a slightly incorrect syntax.

Tested: Tested by loading kdump files from kernels with aslr enabled
and not enabled.  Ran bt, files, and struct file 0xXXXXXX.

Signed-off-by: Andy Honig <ahonig@xxxxxxxxxx>
---
 defs.h    |  2 ++
 main.c    |  8 ++++++--
 symbols.c | 66 +++++++++++++++++++++++++++++++++++++++++++++------------------
 x86_64.c  | 20 +++++++++++++------
 4 files changed, 69 insertions(+), 27 deletions(-)

diff --git a/defs.h b/defs.h
index 4cae5e5..c9a4b73 100644
--- a/defs.h
+++ b/defs.h
@@ -2417,6 +2417,8 @@ struct symbol_table_data {
 	ulong __per_cpu_end;
 	off_t dwarf_debug_frame_file_offset;
 	ulong dwarf_debug_frame_size;
+	ulong first_section_start;
+	ulong last_section_end;
 };
 
 /* flags for st */
diff --git a/main.c b/main.c
index e5829bc..39763da 100644
--- a/main.c
+++ b/main.c
@@ -57,6 +57,7 @@ static struct option long_options[] = {
         {"CRASHPAGER", 0, 0, 0},
         {"no_scroll", 0, 0, 0},
         {"reloc", required_argument, 0, 0},
+	{"kaslr", required_argument, 0, 0},
 	{"active", 0, 0, 0},
 	{"minimal", 0, 0, 0},
 	{"mod", required_argument, 0, 0},
@@ -216,12 +217,15 @@ main(int argc, char **argv)
 		        else if (STREQ(long_options[option_index].name, "mod"))
 				kt->module_tree = optarg;
 
-		        else if (STREQ(long_options[option_index].name, "reloc")) {
+			else if (STREQ(long_options[option_index].name, "reloc") ||
+				 STREQ(long_options[option_index].name, "kaslr")) {
 				if (!calculate(optarg, &kt->relocate, NULL, 0)) {
 					error(INFO, "invalid --reloc argument: %s\n",
 						optarg);
 					program_usage(SHORT_FORM);
-				} 
+				} else if (STREQ(long_options[option_index].name, "kaslr")) {
+					kt->relocate *= -1;
+				}
 				kt->flags |= RELOC_SET;
 			}
 
diff --git a/symbols.c b/symbols.c
index d063a0a..28378ab 100644
--- a/symbols.c
+++ b/symbols.c
@@ -198,22 +198,6 @@ symtab_init(void)
 			no_debugging_data(FATAL);
 	}
 	
-	symcount = bfd_read_minisymbols(st->bfd, FALSE, &minisyms, &size);
-
-	if (symcount <= 0)
-		no_debugging_data(FATAL);
-	
-	sort_x = bfd_make_empty_symbol(st->bfd);
-	sort_y = bfd_make_empty_symbol(st->bfd);
-	if (sort_x == NULL || sort_y == NULL)
-		error(FATAL, "bfd_make_empty_symbol() failed\n");
-	
-	gnu_qsort(st->bfd, minisyms, symcount, size, sort_x, sort_y);
-	
-	store_symbols(st->bfd, FALSE, minisyms, symcount, size);
-	
-	free(minisyms);
-
 	/*
 	 *  Gather references to the kernel sections.
 	 */
@@ -222,6 +206,7 @@ symtab_init(void)
                 error(FATAL, "symbol table section array malloc: %s\n",
                         strerror(errno));
 	BZERO(st->sections, st->bfd->section_count * sizeof(struct sec *));
+	st->first_section_start = st->last_section_end = 0;
 
 	bfd_map_over_sections(st->bfd, section_header_info, KERNEL_SECTIONS);
 	if ((st->flags & (NO_SEC_LOAD|NO_SEC_CONTENTS)) ==
@@ -233,6 +218,22 @@ symtab_init(void)
 		}
 	}
 
+	symcount = bfd_read_minisymbols(st->bfd, FALSE, &minisyms, &size);
+
+	if (symcount <= 0)
+		no_debugging_data(FATAL);
+
+	sort_x = bfd_make_empty_symbol(st->bfd);
+	sort_y = bfd_make_empty_symbol(st->bfd);
+	if (sort_x == NULL || sort_y == NULL)
+		error(FATAL, "bfd_make_empty_symbol() failed\n");
+
+	gnu_qsort(st->bfd, minisyms, symcount, size, sort_x, sort_y);
+
+	store_symbols(st->bfd, FALSE, minisyms, symcount, size);
+
+	free(minisyms);
+
 	symname_hash_init();
 	symval_hash_init();
 }                           
@@ -590,7 +591,7 @@ store_symbols(bfd *abfd, int dynamic, void *minisyms, long symcount,
 	st->symcnt = 0;
 	sp = st->symtable;
 
-	if (machine_type("X86")) {
+	if (machine_type("X86") || machine_type("X86_64")) {
 		if (!(kt->flags & RELOC_SET))
 			kt->flags |= RELOC_FORCE;
 	} else
@@ -663,7 +664,7 @@ store_sysmap_symbols(void)
                 error(FATAL, "symbol table namespace malloc: %s\n",
                         strerror(errno));
 
-	if (!machine_type("X86"))
+	if (!machine_type("X86") && !machine_type("X86_64"))
 		kt->flags &= ~RELOC_SET;
 
 	first = 0;
@@ -735,7 +736,20 @@ relocate(ulong symval, char *symname, int first_symbol)
 		break;
 	}
 
-	return (symval - kt->relocate);
+	if (machine_type("X86_64")) {
+		/*
+		 * There are some symbols which are outside of any section
+		 * either because they are offsets or because they are absolute
+		 * addresses.  These should not be relocated.
+		 */
+		if (symval >= st->first_section_start &&
+			symval <= st->last_section_end) {
+			return symval - kt->relocate;
+		} else {
+			return symval;
+		}
+	} else
+		return symval - kt->relocate;
 }
 
 /*
@@ -9679,6 +9693,7 @@ section_header_info(bfd *bfd, asection *section, void *reqptr)
 	struct load_module *lm;
 	ulong request;
         asection **sec;
+	ulong section_end_address;
 
 	request = ((ulong)reqptr);
 
@@ -9697,6 +9712,11 @@ section_header_info(bfd *bfd, asection *section, void *reqptr)
                 	kt->etext_init = kt->stext_init +
                         	(ulong)bfd_section_size(bfd, section);
 		}
+
+		if (STREQ(bfd_get_section_name(bfd, section), ".text")) {
+			st->first_section_start = (ulong)
+				bfd_get_section_vma(bfd, section);
+		}
                 if (STREQ(bfd_get_section_name(bfd, section), ".text") ||
                     STREQ(bfd_get_section_name(bfd, section), ".data")) {
                         if (!(bfd_get_section_flags(bfd, section) & SEC_LOAD))
@@ -9713,6 +9733,14 @@ section_header_info(bfd *bfd, asection *section, void *reqptr)
 			st->dwarf_debug_frame_file_offset = (off_t)section->filepos;
 			st->dwarf_debug_frame_size = (ulong)bfd_section_size(bfd, section);
 		}
+
+		if (st->first_section_start != 0) {
+			section_end_address =
+				(ulong) bfd_get_section_vma(bfd, section) +
+				(ulong) bfd_section_size(bfd, section);
+			if (section_end_address > st->last_section_end)
+				st->last_section_end = section_end_address;
+		}
 		break;
 
 	case (ulong)MODULE_SECTIONS:
diff --git a/x86_64.c b/x86_64.c
index 8508e4f..b51e285 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -5414,16 +5414,22 @@ search_for_switch_to(ulong start, ulong end)
 {
 	ulong max_instructions, address;
 	char buf1[BUFSIZE];
-	char buf2[BUFSIZE];
+	char search_string1[BUFSIZE];
+	char search_string2[BUFSIZE];
 	int found;
 
 	max_instructions = end - start;
 	found = FALSE;
 	sprintf(buf1, "x/%ldi 0x%lx", max_instructions, start);
-	if (symbol_exists("__switch_to"))
-		sprintf(buf2, "callq  0x%lx", symbol_value("__switch_to"));
-	else
-		buf2[0] = NULLCHAR;
+	if (symbol_exists("__switch_to")) {
+		sprintf(search_string1,
+			"callq  0x%lx", symbol_value("__switch_to"));
+		sprintf(search_string2,
+			"call   0x%lx", symbol_value("__switch_to"));
+	} else {
+		search_string1[0] = NULLCHAR;
+		search_string2[0] = NULLCHAR;
+	}
 
 	open_tmpfile();
 
@@ -5436,7 +5442,9 @@ search_for_switch_to(ulong start, ulong end)
 			break;
 		if (strstr(buf1, "<__switch_to>"))
 			found = TRUE;
-		if (strlen(buf2) && strstr(buf1, buf2))
+		if (strlen(search_string1) && strstr(buf1, search_string1))
+			found = TRUE;
+		if (strlen(search_string2) && strstr(buf1, search_string2))
 			found = TRUE;
 	}
 	close_tmpfile();
-- 
1.9.0.rc1.175.g0b1dcb5

--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility




[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux