Skip to content

Commit

Permalink
arm64: Build the kernel with ORC information
Browse files Browse the repository at this point in the history
Add code to scripts/Makefile.lib to define objtool options to generate
ORC data for frame pointer validation.

Define kernel configs:
	- to enable dynamic FRAME_POINTER_VALIDATION
	- to enable the generation of ORC data using objtool

When these configs are enabled, objtool is invoked on relocatable files
during kernel build with the following command:

	objtool --stackval --orc <object-file>

Objtool creates special sections in the object files:

.orc_unwind_ip	PC array.
.orc_unwind	ORC structure table.
.orc_lookup	ORC lookup table.

Change arch/arm64/kernel/vmlinux.lds.S to include ORC_UNWIND_TABLE in
the data section so that the special sections get included there. For
modules, these sections will be added to the kernel during module load.

In the future, the kernel can use these sections to find the ORC for a
given instruction address. The unwinder can then compute the FP at an
instruction address and validate the actual FP with that.

Signed-off-by: Madhavan T. Venkataraman <madvenka@linux.microsoft.com>
  • Loading branch information
madvenka786 committed Jan 29, 2023
1 parent bddd274 commit ca2c004
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 2 deletions.
2 changes: 2 additions & 0 deletions arch/arm64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ config ARM64
select TRACE_IRQFLAGS_SUPPORT
select TRACE_IRQFLAGS_NMI_SUPPORT
select HAVE_SOFTIRQ_ON_OWN_STACK
select HAVE_STACK_VALIDATION if FRAME_POINTER_VALIDATION
select STACK_VALIDATION if HAVE_STACK_VALIDATION
help
ARM 64-bit (AArch64) Linux support.

Expand Down
32 changes: 32 additions & 0 deletions arch/arm64/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,36 @@ config ARM64_RELOC_TEST
depends on m
tristate "Relocation testing module"

config UNWINDER_ORC
bool "ORC unwinder"
depends on FRAME_POINTER_VALIDATION
select HAVE_MOD_ARCH_SPECIFIC
select OBJTOOL
help
This option enables ORC (Oops Rewind Capability) for ARM64. This
allows the unwinder to look up ORC data for an instruction address
and compute the frame pointer at that address. The computed frame
pointer is used to validate the actual frame pointer.

config UNWINDER_FRAME_POINTER
bool "Frame pointer unwinder"
depends on FRAME_POINTER_VALIDATION
select FRAME_POINTER
help
ARM64 already uses the frame pointer for unwinding kernel stack
traces. We need to enable this config to enable STACK_VALIDATION.
STACK_VALIDATION is needed to get objtool to do static analysis
of kernel code.

config FRAME_POINTER_VALIDATION
bool "Dynamic Frame pointer validation"
select UNWINDER_FRAME_POINTER
select UNWINDER_ORC
help
This invokes objtool on every object file causing it to
generate ORC data for the object file. ORC data is in a custom
data format which is a simplified version of the DWARF
Call Frame Information standard. See UNWINDER_ORC for more
details.

source "drivers/hwtracing/coresight/Kconfig"
12 changes: 11 additions & 1 deletion arch/arm64/include/asm/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,32 @@
#define __ASM_MODULE_H

#include <asm-generic/module.h>
#include <asm/orc_types.h>

#ifdef CONFIG_ARM64_MODULE_PLTS
struct mod_plt_sec {
int plt_shndx;
int plt_num_entries;
int plt_max_entries;
};
#endif

#ifdef CONFIG_HAVE_MOD_ARCH_SPECIFIC
struct mod_arch_specific {
#ifdef CONFIG_ARM64_MODULE_PLTS
struct mod_plt_sec core;
struct mod_plt_sec init;

/* for CONFIG_DYNAMIC_FTRACE */
struct plt_entry *ftrace_trampolines;
};
#endif
#ifdef CONFIG_UNWINDER_ORC
unsigned int num_orcs;
int *orc_unwind_ip;
struct orc_entry *orc_unwind;
#endif
};
#endif /* CONFIG_HAVE_MOD_ARCH_SPECIFIC */

u64 module_emit_plt_entry(struct module *mod, Elf64_Shdr *sechdrs,
void *loc, const Elf64_Rela *rela,
Expand Down
3 changes: 3 additions & 0 deletions arch/arm64/kernel/vmlinux.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
#define RUNTIME_DISCARD_EXIT

#include <asm-generic/vmlinux.lds.h>
#include <asm-generic/orc_lookup.h>
#include <asm/cache.h>
#include <asm/kernel-pgtable.h>
#include <asm/kexec.h>
Expand Down Expand Up @@ -294,6 +295,8 @@ SECTIONS
__mmuoff_data_end = .;
}

ORC_UNWIND_TABLE

PECOFF_EDATA_PADDING
__pecoff_data_rawsize = ABSOLUTE(. - __initdata_begin);
_edata = .;
Expand Down
2 changes: 2 additions & 0 deletions include/linux/objtool.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@

#ifdef CONFIG_OBJTOOL

#ifndef CONFIG_ARM64
#include <asm/asm.h>
#endif

#ifndef __ASSEMBLY__

Expand Down
4 changes: 3 additions & 1 deletion scripts/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ HOSTLDLIBS_sign-file = $(shell $(HOSTPKG_CONFIG) --libs libcrypto 2> /dev/null |
ifdef CONFIG_UNWINDER_ORC
ifeq ($(ARCH),x86_64)
ARCH := x86
endif
HOSTCFLAGS_sorttable.o += -I$(srctree)/tools/arch/x86/include
else
HOSTCFLAGS_sorttable.o += -I$(srctree)/tools/arch/$(ARCH)/include
endif
HOSTCFLAGS_sorttable.o += -DUNWINDER_ORC_ENABLED
endif

Expand Down
9 changes: 9 additions & 0 deletions scripts/Makefile.lib
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,13 @@ ifdef CONFIG_OBJTOOL

objtool := $(objtree)/tools/objtool/objtool

ifdef CONFIG_FRAME_POINTER_VALIDATION

objtool-args-$(CONFIG_STACK_VALIDATION) += --stackval
objtool-args-$(CONFIG_UNWINDER_ORC) += --orc

else

objtool-args-$(CONFIG_HAVE_JUMP_LABEL_HACK) += --hacks=jump_label
objtool-args-$(CONFIG_HAVE_NOINSTR_HACK) += --hacks=noinstr
objtool-args-$(CONFIG_X86_KERNEL_IBT) += --ibt
Expand All @@ -265,6 +272,8 @@ objtool-args-$(CONFIG_HAVE_STATIC_CALL_INLINE) += --static-call
objtool-args-$(CONFIG_HAVE_UACCESS_VALIDATION) += --uaccess
objtool-args-$(CONFIG_GCOV_KERNEL) += --no-unreachable

endif

objtool-args = $(objtool-args-y) \
$(if $(delay-objtool), --link) \
$(if $(part-of-module), --module)
Expand Down
2 changes: 2 additions & 0 deletions tools/include/linux/objtool.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@

#ifdef CONFIG_OBJTOOL

#ifndef CONFIG_ARM64
#include <asm/asm.h>
#endif

#ifndef __ASSEMBLY__

Expand Down

0 comments on commit ca2c004

Please sign in to comment.