diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S --- a/sys/amd64/amd64/cpu_switch.S +++ b/sys/amd64/amd64/cpu_switch.S @@ -31,6 +31,8 @@ * SUCH DAMAGE. */ +#include "opt_global.h" + #include #include @@ -145,6 +147,10 @@ * to load up the rest of the next context. */ +#ifdef PERTHREAD_SSP + movq TD_MD_CANARY(%r12),%rax + movq %rax,PCPU(CANARY) +#endif /* Skip loading LDT and user fsbase/gsbase for kthreads */ testl $TDP_KTHREAD,TD_PFLAGS(%r12) jnz do_kthread diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c --- a/sys/amd64/amd64/genassym.c +++ b/sys/amd64/amd64/genassym.c @@ -85,6 +85,7 @@ ASSYM(TD_MD, offsetof(struct thread, td_md)); ASSYM(TD_MD_PCB, offsetof(struct thread, td_md.md_pcb)); ASSYM(TD_MD_STACK_BASE, offsetof(struct thread, td_md.md_stack_base)); +ASSYM(TD_MD_CANARY, offsetof(struct thread, td_md.md_canary)); ASSYM(TDP_CALLCHAIN, TDP_CALLCHAIN); ASSYM(TDP_KTHREAD, TDP_KTHREAD); @@ -257,6 +258,7 @@ ASSYM(PC_MDS_TMP, offsetof(struct pcpu, pc_mds_tmp)); ASSYM(PC_MDS_BUF, offsetof(struct pcpu, pc_mds_buf)); ASSYM(PC_MDS_BUF64, offsetof(struct pcpu, pc_mds_buf64)); +ASSYM(PC_CANARY, offsetof(struct pcpu, pc_canary)); ASSYM(LA_EOI, LAPIC_EOI * LAPIC_MEM_MUL); ASSYM(LA_ISR, LAPIC_ISR0 * LAPIC_MEM_MUL); diff --git a/sys/amd64/amd64/locore.S b/sys/amd64/amd64/locore.S --- a/sys/amd64/amd64/locore.S +++ b/sys/amd64/amd64/locore.S @@ -82,6 +82,10 @@ xorq %rbp, %rbp call hammer_time /* set up cpu for unix operation */ +#ifdef PERTHREAD_SSP + movq boot_canary, %rbx + movq %rbx, PCPU(CANARY) +#endif movq %rax,%rsp /* set up kstack for mi_startup() */ call mi_startup /* autoconfiguration, mountroot etc */ 0: hlt diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -224,6 +224,10 @@ bool efi_boot; +#ifdef PERTHREAD_SSP +uintptr_t boot_canary = 0x6543d292157d3053UL; +#endif + static void cpu_startup(void *dummy) { @@ -1378,6 +1382,9 @@ bzero(thread0.td_kstack, kstack0_sz); cpu_thread_new_kstack(&thread0); physfree += kstack0_sz; +#ifdef PERTHREAD_SSP + thread0.td_md.md_canary = boot_canary; +#endif /* * Initialize enough of thread0 for delayed invalidation to diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -105,6 +105,8 @@ smp_targeted_tlb_shootdown_t smp_targeted_tlb_shootdown = &smp_targeted_tlb_shootdown_native; +extern uintptr_t boot_canary; + /* * Local data and functions. */ @@ -231,6 +233,7 @@ pc->pc_pcid_gen = 1; pc->pc_kpmap_store.pm_pcid = PMAP_PCID_KERN; pc->pc_kpmap_store.pm_gen = 1; + pc->pc_canary = boot_canary; pc->pc_smp_tlb_gen = 1; diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c --- a/sys/amd64/amd64/vm_machdep.c +++ b/sys/amd64/amd64/vm_machdep.c @@ -201,6 +201,9 @@ */ td2->td_frame->tf_rflags &= ~PSL_T; } +#ifdef PERTHREAD_SSP + arc4random_buf(&td2->td_md.md_canary, sizeof(td2->td_md.md_canary)); +#endif } /* diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -91,6 +91,7 @@ options RACCT # Resource accounting framework options RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default options RCTL # Resource limits +options PERTHREAD_SSP # Per-thread SSP canary # Debugging support. Always need this: options KDB # Enable kernel debugger support. diff --git a/sys/amd64/include/pcpu.h b/sys/amd64/include/pcpu.h --- a/sys/amd64/include/pcpu.h +++ b/sys/amd64/include/pcpu.h @@ -101,7 +101,8 @@ u_int pc_small_core; \ u_int pc_pcid_invlpg_workaround; \ struct pmap_pcid pc_kpmap_store; \ - char __pad[2900] /* pad to UMA_PCPU_ALLOC_SIZE */ + uintptr_t pc_canary; \ + char __pad[2892] /* pad to UMA_PCPU_ALLOC_SIZE */ #define PC_DBREG_CMD_NONE 0 #define PC_DBREG_CMD_LOAD 1 diff --git a/sys/amd64/include/proc.h b/sys/amd64/include/proc.h --- a/sys/amd64/include/proc.h +++ b/sys/amd64/include/proc.h @@ -77,6 +77,7 @@ struct pcb md_pcb; void *md_stack_base; void *md_usr_fpu_save; + register_t md_canary; }; struct mdproc { diff --git a/sys/conf/Makefile.amd64 b/sys/conf/Makefile.amd64 --- a/sys/conf/Makefile.amd64 +++ b/sys/conf/Makefile.amd64 @@ -35,6 +35,23 @@ CFLAGS+= -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer .endif +.if ${MK_SSP} != "no" +PERTHREAD_SSP_ENABLED!= grep PERTHREAD_SSP opt_global.h || true ; echo +. if !empty(PERTHREAD_SSP_ENABLED) +. if (${COMPILER_TYPE} == "clang" && ${OSRELDATE} >= 1600019) || \ + ${COMPILER_TYPE} == "gcc" +PCPU_CANARY_OFFSET!= grep PC_CANARY assym.inc | cut -f3 | xargs printf "%d" +AMD64_SSP_CFLAGS+= -mstack-protector-guard=tls +AMD64_SSP_CFLAGS+= -mstack-protector-guard-reg=gs +AMD64_SSP_CFLAGS+= -mstack-protector-guard-offset=${PCPU_CANARY_OFFSET} +. else +. warning "Compiler is too old to support PERTHREAD_SSP" +. endif +CFLAGS+= ${AMD64_SSP_CFLAGS} +ARCH_FLAGS+= ${AMD64_SSP_CFLAGS} +. endif +.endif + %BEFORE_DEPEND %OBJS diff --git a/sys/conf/options.amd64 b/sys/conf/options.amd64 --- a/sys/conf/options.amd64 +++ b/sys/conf/options.amd64 @@ -8,6 +8,7 @@ MAXMEM MPTABLE_FORCE_HTT NKPT opt_pmap.h +PERTHREAD_SSP opt_global.h PV_STATS opt_pmap.h # Options for emulators. These should only be used at config time, so diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -92,7 +92,7 @@ "struct thread KBI td_pflags"); _Static_assert(offsetof(struct thread, td_frame) == 0x4e8, "struct thread KBI td_frame"); -_Static_assert(offsetof(struct thread, td_emuldata) == 0x6f0, +_Static_assert(offsetof(struct thread, td_emuldata) == 0x700, "struct thread KBI td_emuldata"); _Static_assert(offsetof(struct proc, p_flag) == 0xb8, "struct proc KBI p_flag");