[Crash-utility] [PATCH] Automatically detect kernel aslr offset

Andy Honig ahonig at google.com
Wed Feb 19 00:56:38 UTC 2014


Automatically detext kernel aslr offset

This patch improves support for kernel aslr, to automatically find the
aslr offset based on the location of the _stext symbol in the vmcore
info.

Signed-off-by: Andrew Honig <ahonig at google.com>
---
 netdump.c | 19 ++++++++-----------
 symbols.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 54 insertions(+), 14 deletions(-)

diff --git a/netdump.c b/netdump.c
index 8e7ec15..b327649 100644
--- a/netdump.c
+++ b/netdump.c
@@ -411,18 +411,15 @@ is_netdump(char *file, ulong source_query)
 		get_log_from_vmcoreinfo(file, vmcoreinfo_read_string);
 	}
 
-	// This is the code where I should read the aslr offset.
+	/*
+	 *We may need the _stext_SYMBOL from the vmcore_info to adjust for
+	 * kaslr and we may not have gotten it elsewhere.
+	 */
 	if (source_query == KDUMP_LOCAL) {
-		long aslr_offset = 0;
-		char *aslr_string = vmcoreinfo_read_string("KERNELOFFSET");
-		if (aslr_string) {
-			aslr_offset = strtoul(aslr_string, NULL, 16);
-			free (aslr_string);
-		}
-		if (!(kt->flags & RELOC_SET) && aslr_offset > 0) {
-			kt->flags |= RELOC_SET;
-			kt->relocate=aslr_offset * -1;
-		}
+		char *tmpstring = vmcoreinfo_read_string("SYMBOL(_stext)");
+		kt->vmcoreinfo._stext_SYMBOL =
+			htol(tmpstring, RETURN_ON_ERROR, NULL);
+		free(tmpstring);
 	}
 
 	return nd->header_size;
diff --git a/symbols.c b/symbols.c
index d5f8199..afe5ed0 100755
--- a/symbols.c
+++ b/symbols.c
@@ -553,6 +553,43 @@ strip_symbol_end(const char *name, char *buf)
 }
 
 /*
+ * Derives the kernel aslr offset by comparing the _stext symbol from the
+ * the vmcore_info in the dump file to the _stext symbol in the vmlinux file.
+ */
+static void
+derive_kaslr_offset(bfd *abfd, int dynamic, bfd_byte *start, bfd_byte *end,
+		    unsigned int size, asymbol *store)
+{
+	symbol_info syminfo;
+	asymbol *sym;
+	char *name;
+	unsigned long relocate;
+	char buf[BUFSIZE];
+
+	for (; start < end; start += size) {
+		sym = bfd_minisymbol_to_symbol(abfd, dynamic, start, store);
+		if (sym == NULL)
+			error(FATAL, "bfd_minisymbol_to_symbol() failed\n");
+
+		bfd_get_symbol_info(abfd, sym, &syminfo);
+		name = strip_symbol_end(syminfo.name, buf);
+		if (strcmp("_stext", name) == 0) {
+			relocate = syminfo.value - kt->vmcoreinfo._stext_SYMBOL;
+			/*
+			 *To avoid mistaking an mismatched kernel version with
+			 * a kaslr offset, we make sure that the offset is
+			 * aligned by 0x1000, as it always will be for
+			 * kaslr.
+			 */
+			if ((relocate & 0x1000) == 0) {
+				kt->relocate = relocate;
+				kt->flags |= RELOC_SET;
+			}
+		}
+	}
+}
+
+/*
  *  Store the symbols gathered by symtab_init().  The symbols are stored
  *  in increasing numerical order.
  */
@@ -588,15 +625,21 @@ store_symbols(bfd *abfd, int dynamic, void *minisyms, long symcount,
 	st->symcnt = 0;
 	sp = st->symtable;
 
+	first = 0;
+	from = (bfd_byte *) minisyms;
+	fromend = from + symcount * size;
+
 	if (machine_type("X86") || machine_type("X86_64")) {
+		/* If kernel aslr offset has not been set, try to guess it. */
+		if (kt->relocate == 0)
+			derive_kaslr_offset(abfd, dynamic, from,
+					    fromend, size, store);
+
 		if (!(kt->flags & RELOC_SET))
 			kt->flags |= RELOC_FORCE;
 	} else
 		kt->flags &= ~RELOC_SET;
 
-	first = 0;
-  	from = (bfd_byte *) minisyms;
-  	fromend = from + symcount * size;
   	for (; from < fromend; from += size)
     	{
       		if ((sym = bfd_minisymbol_to_symbol(abfd, dynamic, from, store))
-- 
1.9.0.rc1.175.g0b1dcb5




More information about the Crash-utility mailing list