Skip to content

Commit

Permalink
Added a new "--kaslr <offset>" command line option for X86 or
Browse files Browse the repository at this point in the history
X86_64 kernels that are configured with CONFIG_RANDOMIZE_BASE.
The offset value must be equal to the difference between the
symbol values compiled into the vmlinux file and their relocated
value.
(ahonig@google.com, anderson@redhat.com)
  • Loading branch information
Dave Anderson committed Feb 21, 2014
1 parent c0b7a74 commit 648d0f6
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 24 deletions.
9 changes: 8 additions & 1 deletion crash.8
Expand Up @@ -399,7 +399,8 @@ or
.TP
.B --less
Use
.I /usr/bin/less as the command output scroller, overriding
.I /usr/bin/less
as the command output scroller, overriding
any settings in either
.I ./.crashrc
or
Expand Down Expand Up @@ -447,6 +448,12 @@ command, search for their object files in
.I directory
instead of in the standard location.
.TP
.BI --kaslr \ offset
If an x86 or x86_64 kernel was configured with
.B CONFIG_RANDOMIZE_BASE,
the offset value is equal to the difference between the symbol values
compiled into the vmlinux file and their relocated value.
.TP
.BI --reloc \ size
When analyzing live x86 kernels that were configured with a
.B CONFIG_PHYSICAL_START
Expand Down
2 changes: 2 additions & 0 deletions defs.h
Expand Up @@ -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 */
Expand Down
5 changes: 5 additions & 0 deletions help.c
Expand Up @@ -297,6 +297,11 @@ char *program_usage_info[] = {
" be necessary to enter a relocation size equal to the difference between",
" the two values.",
"",
" --kaslr offset",
" If an x86 or x86_64 kernel was configured with CONFIG_RANDOMIZE_BASE,",
" the offset value is equal to the difference between the symbol values ",
" compiled into the vmlinux file and their relocated value.",
"",
" --minimal",
" Bring up a session that is restricted to the log, dis, rd, sym,",
" eval, set and exit commands. This option may provide a way to",
Expand Down
18 changes: 14 additions & 4 deletions main.c
@@ -1,8 +1,8 @@
/* main.c - core analysis suite
*
* Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
* Copyright (C) 2002-2013 David Anderson
* Copyright (C) 2002-2013 Red Hat, Inc. All rights reserved.
* Copyright (C) 2002-2014 David Anderson
* Copyright (C) 2002-2014 Red Hat, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -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},
Expand Down Expand Up @@ -216,12 +217,21 @@ 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, "kaslr")) {
if (!calculate(optarg, &kt->relocate, NULL, 0)) {
error(INFO, "invalid --kaslr argument: %s\n",
optarg);
program_usage(SHORT_FORM);
}
kt->relocate *= -1;
kt->flags |= RELOC_SET;

} else if (STREQ(long_options[option_index].name, "reloc")) {
if (!calculate(optarg, &kt->relocate, NULL, 0)) {
error(INFO, "invalid --reloc argument: %s\n",
optarg);
program_usage(SHORT_FORM);
}
}
kt->flags |= RELOC_SET;
}

Expand Down
69 changes: 50 additions & 19 deletions symbols.c
Expand Up @@ -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.
*/
Expand All @@ -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)) ==
Expand All @@ -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();
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

/*
Expand Down Expand Up @@ -2722,6 +2736,9 @@ dump_symbol_table(void)
fprintf(fp, " __per_cpu_end: (unused)\n");
}

fprintf(fp, " first_section_start: %lx\n", st->first_section_start);
fprintf(fp, " last_section_end: %lx\n", st->last_section_end);

fprintf(fp, " symval_hash[%d]: %lx\n", SYMVAL_HASH,
(ulong)&st->symval_hash[0]);

Expand Down Expand Up @@ -9679,6 +9696,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);

Expand All @@ -9697,6 +9715,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))
Expand All @@ -9713,6 +9736,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:
Expand Down

0 comments on commit 648d0f6

Please sign in to comment.