2009-02-09 22:17:40 +09:00
/*
* GCC stack protector support .
*
* Stack protector works by putting predefined pattern at the start of
* the stack frame and verifying that it hasn ' t been overwritten when
* returning from the function . The pattern is called stack canary
* and unfortunately gcc requires it to be at a fixed offset from % gs .
* On x86_64 , the offset is 40 bytes and on x86_32 20 bytes . x86_64
* and x86_32 use segment registers differently and thus handles this
* requirement differently .
*
* On x86_64 , % gs is shared by percpu area and stack canary . All
* percpu symbols are zero based and % gs points to the base of percpu
* area . The first occupant of the percpu area is always
* irq_stack_union which contains stack_canary at offset 40. Userland
* % gs is always saved and restored on kernel entry and exit using
* swapgs , so stack protector doesn ' t add any complexity there .
*
* On x86_32 , it ' s slightly more complicated . As in x86_64 , % gs is
* used for userland TLS . Unfortunately , some processors are much
* slower at loading segment registers with different value when
* entering and leaving the kernel , so the kernel uses % fs for percpu
* area and manages % gs lazily so that % gs is switched only when
* necessary , usually during task switch .
*
* As gcc requires the stack canary at % gs : 20 , % gs can ' t be managed
* lazily if stack protector is enabled , so the kernel saves and
* restores userland % gs on kernel entry and exit . This behavior is
* controlled by CONFIG_X86_32_LAZY_GS and accessors are defined in
* system . h to hide the details .
*/
2008-02-14 09:41:09 +01:00
# ifndef _ASM_STACKPROTECTOR_H
# define _ASM_STACKPROTECTOR_H 1
2009-02-09 22:17:39 +09:00
# ifdef CONFIG_CC_STACKPROTECTOR
2008-02-14 09:56:04 +01:00
# include <asm/tsc.h>
2009-01-19 12:21:28 +09:00
# include <asm/processor.h>
2009-02-09 22:17:39 +09:00
# include <asm/percpu.h>
2009-02-09 22:17:40 +09:00
# include <asm/desc.h>
2015-04-26 16:56:05 +02:00
2009-02-09 22:17:39 +09:00
# include <linux/random.h>
2015-04-26 16:56:05 +02:00
# include <linux/sched.h>
2008-02-14 09:56:04 +01:00
2009-02-09 22:17:40 +09:00
/*
* 24 byte read - only segment initializer for stack canary . Linker
* can ' t handle the address bit shifting . Address will be set in
* head_32 for boot CPU and setup_per_cpu_areas ( ) for others .
*/
# define GDT_STACK_CANARY_INIT \
2009-07-19 00:12:20 +09:00
[ GDT_ENTRY_STACK_CANARY ] = GDT_ENTRY_INIT ( 0x4090 , 0 , 0x18 ) ,
2009-02-09 22:17:40 +09:00
2008-02-14 09:42:02 +01:00
/*
* Initialize the stackprotector canary value .
*
* NOTE : this must only be called from functions that never return ,
* and it must always be inlined .
*/
static __always_inline void boot_init_stack_canary ( void )
{
2008-02-14 09:56:04 +01:00
u64 canary ;
u64 tsc ;
2009-02-09 22:17:40 +09:00
# ifdef CONFIG_X86_64
2009-01-19 12:21:28 +09:00
BUILD_BUG_ON ( offsetof ( union irq_stack_union , stack_canary ) ! = 40 ) ;
2009-02-09 22:17:40 +09:00
# endif
2009-01-20 12:29:19 +09:00
/*
2008-02-14 09:56:04 +01:00
* We both use the random pool and the current TSC as a source
* of randomness . The TSC only matters for very early init ,
* there it already has some randomness on most systems . Later
* on during the bootup the random pool has true entropy too .
2008-02-14 09:42:02 +01:00
*/
2008-02-14 09:56:04 +01:00
get_random_bytes ( & canary , sizeof ( canary ) ) ;
2015-06-25 18:44:07 +02:00
tsc = rdtsc ( ) ;
2008-02-14 09:56:04 +01:00
canary + = tsc + ( tsc < < 32UL ) ;
current - > stack_canary = canary ;
2009-02-09 22:17:40 +09:00
# ifdef CONFIG_X86_64
2012-05-11 15:35:27 +08:00
this_cpu_write ( irq_stack_union . stack_canary , canary ) ;
2009-02-09 22:17:40 +09:00
# else
2012-05-11 15:35:27 +08:00
this_cpu_write ( stack_canary . canary , canary ) ;
2009-02-09 22:17:40 +09:00
# endif
}
static inline void setup_stack_canary_segment ( int cpu )
{
# ifdef CONFIG_X86_32
2009-09-03 12:27:15 -07:00
unsigned long canary = ( unsigned long ) & per_cpu ( stack_canary , cpu ) ;
2009-02-09 22:17:40 +09:00
struct desc_struct * gdt_table = get_cpu_gdt_table ( cpu ) ;
struct desc_struct desc ;
desc = gdt_table [ GDT_ENTRY_STACK_CANARY ] ;
2009-07-19 00:11:06 +09:00
set_desc_base ( & desc , canary ) ;
2009-02-09 22:17:40 +09:00
write_gdt_entry ( gdt_table , GDT_ENTRY_STACK_CANARY , & desc , DESCTYPE_S ) ;
# endif
}
static inline void load_stack_canary_segment ( void )
{
# ifdef CONFIG_X86_32
asm ( " mov %0, %%gs " : : " r " ( __KERNEL_STACK_CANARY ) : " memory " ) ;
# endif
}
# else /* CC_STACKPROTECTOR */
# define GDT_STACK_CANARY_INIT
/* dummy boot_init_stack_canary() is defined in linux/stackprotector.h */
static inline void setup_stack_canary_segment ( int cpu )
{ }
static inline void load_stack_canary_segment ( void )
{
# ifdef CONFIG_X86_32
asm volatile ( " mov %0, %%gs " : : " r " ( 0 ) ) ;
# endif
2008-02-14 09:42:02 +01:00
}
2009-02-09 22:17:39 +09:00
# endif /* CC_STACKPROTECTOR */
# endif /* _ASM_STACKPROTECTOR_H */