[Crash-utility] [PATCH 1/2] Add support to kaslr offset for offline vmcore files.
Andrew Honig
ahonig at google.com
Wed Feb 19 20:25:26 UTC 2014
>
> BTW, I'd prefer to separate out the search_for_switch_to() patch because it
> has nothing to do with kaslr.
Will do.
>
> Which is strange, since "context_switch" has been an inline function
> for pretty much ever, and therefore is not even a kernel symbol. But
> your kernel apparently does have context_switch as a discrete function.
> What kernel version are you testing with? Is it a google-special
> that maybe tinkers with the scheduler code?
Yes I was testing with a Google specific kernel, and yes it tinkers
with the scheduler code.
>
> Dave
>
>
>
> ----- Original Message -----
>> [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 at google.com>
>> ---
>> 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 at redhat.com
>> https://www.redhat.com/mailman/listinfo/crash-utility
>>
>
> --
> Crash-utility mailing list
> Crash-utility at redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility
More information about the Crash-utility
mailing list