mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	kallsyms: fix percpu vars on x86-64 with relocation.
x86-64 has a problem: per-cpu variables are actually represented by their absolute offsets within the per-cpu area, but the symbols are not emitted as absolute. Thus kallsyms naively creates them as offsets from _text, meaning their values change if the kernel is relocated (especially noticeable with CONFIG_RANDOMIZE_BASE): $ egrep ' (gdt_|_(stext|_per_cpu_))' /root/kallsyms.nokaslr 0000000000000000 D __per_cpu_start 0000000000004000 D gdt_page 0000000000014280 D __per_cpu_end ffffffff810001c8 T _stext ffffffff81ee53c0 D __per_cpu_offset $ egrep ' (gdt_|_(stext|_per_cpu_))' /root/kallsyms.kaslr1 000000001f200000 D __per_cpu_start 000000001f204000 D gdt_page 000000001f214280 D __per_cpu_end ffffffffa02001c8 T _stext ffffffffa10e53c0 D __per_cpu_offset Making them absolute symbols is the Right Thing, but requires fixes to the relocs tool. So for the moment, we add a --absolute-percpu option which makes them absolute from a kallsyms perspective: $ egrep ' (gdt_|_(stext|_per_cpu_))' /proc/kallsyms # no KASLR 0000000000000000 A __per_cpu_start 000000000000a000 A gdt_page 0000000000013040 A __per_cpu_end ffffffff802001c8 T _stext ffffffff8099b180 D __per_cpu_offset ffffffff809a3000 D __per_cpu_load $ egrep ' (gdt_|_(stext|_per_cpu_))' /proc/kallsyms # With KASLR 0000000000000000 A __per_cpu_start 000000000000a000 A gdt_page 0000000000013040 A __per_cpu_end ffffffff89c001c8 T _stext ffffffff8a39d180 D __per_cpu_offset ffffffff8a3a5000 D __per_cpu_load Based-on-the-original-screenplay-by: Andy Honig <ahonig@google.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Acked-by: Kees Cook <keescook@chromium.org>
This commit is contained in:
		
							parent
							
								
									78eb71594b
								
							
						
					
					
						commit
						c6bda7c988
					
				
					 2 changed files with 25 additions and 0 deletions
				
			
		| 
						 | 
					@ -51,9 +51,14 @@ static struct addr_range text_ranges[] = {
 | 
				
			||||||
#define text_range_text     (&text_ranges[0])
 | 
					#define text_range_text     (&text_ranges[0])
 | 
				
			||||||
#define text_range_inittext (&text_ranges[1])
 | 
					#define text_range_inittext (&text_ranges[1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct addr_range percpu_range = {
 | 
				
			||||||
 | 
						"__per_cpu_start", "__per_cpu_end", -1ULL, 0
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct sym_entry *table;
 | 
					static struct sym_entry *table;
 | 
				
			||||||
static unsigned int table_size, table_cnt;
 | 
					static unsigned int table_size, table_cnt;
 | 
				
			||||||
static int all_symbols = 0;
 | 
					static int all_symbols = 0;
 | 
				
			||||||
 | 
					static int absolute_percpu = 0;
 | 
				
			||||||
static char symbol_prefix_char = '\0';
 | 
					static char symbol_prefix_char = '\0';
 | 
				
			||||||
static unsigned long long kernel_start_addr = 0;
 | 
					static unsigned long long kernel_start_addr = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -166,6 +171,9 @@ static int read_symbol(FILE *in, struct sym_entry *s)
 | 
				
			||||||
	strcpy((char *)s->sym + 1, str);
 | 
						strcpy((char *)s->sym + 1, str);
 | 
				
			||||||
	s->sym[0] = stype;
 | 
						s->sym[0] = stype;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Record if we've found __per_cpu_start/end. */
 | 
				
			||||||
 | 
						check_symbol_range(sym, s->addr, &percpu_range, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -657,6 +665,15 @@ static void sort_symbols(void)
 | 
				
			||||||
	qsort(table, table_cnt, sizeof(struct sym_entry), compare_symbols);
 | 
						qsort(table, table_cnt, sizeof(struct sym_entry), compare_symbols);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void make_percpus_absolute(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < table_cnt; i++)
 | 
				
			||||||
 | 
							if (symbol_in_range(&table[i], &percpu_range, 1))
 | 
				
			||||||
 | 
								table[i].sym[0] = 'A';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char **argv)
 | 
					int main(int argc, char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (argc >= 2) {
 | 
						if (argc >= 2) {
 | 
				
			||||||
| 
						 | 
					@ -664,6 +681,8 @@ int main(int argc, char **argv)
 | 
				
			||||||
		for (i = 1; i < argc; i++) {
 | 
							for (i = 1; i < argc; i++) {
 | 
				
			||||||
			if(strcmp(argv[i], "--all-symbols") == 0)
 | 
								if(strcmp(argv[i], "--all-symbols") == 0)
 | 
				
			||||||
				all_symbols = 1;
 | 
									all_symbols = 1;
 | 
				
			||||||
 | 
								else if (strcmp(argv[i], "--absolute-percpu") == 0)
 | 
				
			||||||
 | 
									absolute_percpu = 1;
 | 
				
			||||||
			else if (strncmp(argv[i], "--symbol-prefix=", 16) == 0) {
 | 
								else if (strncmp(argv[i], "--symbol-prefix=", 16) == 0) {
 | 
				
			||||||
				char *p = &argv[i][16];
 | 
									char *p = &argv[i][16];
 | 
				
			||||||
				/* skip quote */
 | 
									/* skip quote */
 | 
				
			||||||
| 
						 | 
					@ -680,6 +699,8 @@ int main(int argc, char **argv)
 | 
				
			||||||
		usage();
 | 
							usage();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	read_map(stdin);
 | 
						read_map(stdin);
 | 
				
			||||||
 | 
						if (absolute_percpu)
 | 
				
			||||||
 | 
							make_percpus_absolute();
 | 
				
			||||||
	sort_symbols();
 | 
						sort_symbols();
 | 
				
			||||||
	optimize_token_table();
 | 
						optimize_token_table();
 | 
				
			||||||
	write_src();
 | 
						write_src();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,6 +86,10 @@ kallsyms()
 | 
				
			||||||
		kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET"
 | 
							kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET"
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if [ -n "${CONFIG_X86_64}" ]; then
 | 
				
			||||||
 | 
							kallsymopt="${kallsymopt} --absolute-percpu"
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL}               \
 | 
						local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL}               \
 | 
				
			||||||
		      ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
 | 
							      ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue