1*6a59053bSAlex Wilson /* 2*6a59053bSAlex Wilson * This file and its contents are supplied under the terms of the 3*6a59053bSAlex Wilson * Common Development and Distribution License ("CDDL"), version 1.0. 4*6a59053bSAlex Wilson * You may only use this file in accordance with the terms of version 5*6a59053bSAlex Wilson * 1.0 of the CDDL. 6*6a59053bSAlex Wilson * 7*6a59053bSAlex Wilson * A full copy of the text of the CDDL should have accompanied this 8*6a59053bSAlex Wilson * source. A copy of the CDDL is also available via the Internet at 9*6a59053bSAlex Wilson * http://www.illumos.org/license/CDDL. 10*6a59053bSAlex Wilson */ 11*6a59053bSAlex Wilson /* 12*6a59053bSAlex Wilson * Copyright 2015 Alex Wilson, the University of Queensland 13*6a59053bSAlex Wilson * Use is subject to license terms. 14*6a59053bSAlex Wilson */ 15*6a59053bSAlex Wilson 16*6a59053bSAlex Wilson /* 17*6a59053bSAlex Wilson * Support functions for stack smashing protection (-fstack-protector 18*6a59053bSAlex Wilson * and family) 19*6a59053bSAlex Wilson * 20*6a59053bSAlex Wilson * The principle behind SSP is to place a "canary" value on the stack 21*6a59053bSAlex Wilson * just below the arguments to a given function (which are in turn 22*6a59053bSAlex Wilson * below the previous %rbp and return pointer). We write it onto the 23*6a59053bSAlex Wilson * stack at the start of a function, and then at the end just before 24*6a59053bSAlex Wilson * we execute "leave" and "ret", we check that the value is still there. 25*6a59053bSAlex Wilson * 26*6a59053bSAlex Wilson * If the check fails, we jump immediately to a handler (which typically 27*6a59053bSAlex Wilson * just executes panic() straight away). 28*6a59053bSAlex Wilson * 29*6a59053bSAlex Wilson * Since an attacker will not know the value of the "canary", they will 30*6a59053bSAlex Wilson * not be able to repair it correctly when overwriting the stack (and in 31*6a59053bSAlex Wilson * almost all cases they must overwrite the canary to get to the return 32*6a59053bSAlex Wilson * pointer), and the check will fail (and safely panic) instead of 33*6a59053bSAlex Wilson * letting them gain control over %rip in a kernel thread. 34*6a59053bSAlex Wilson * 35*6a59053bSAlex Wilson * To debugging tools the canary just looks like another local variable 36*6a59053bSAlex Wilson * (since it's placed below the normal argument space), and so there 37*6a59053bSAlex Wilson * should be minimal/no impact on things that try to parse the 38*6a59053bSAlex Wilson * function preamble. 39*6a59053bSAlex Wilson * 40*6a59053bSAlex Wilson * Of course, adding these guards to every single function does not come 41*6a59053bSAlex Wilson * without a price in performance, so normally only a subset of functions 42*6a59053bSAlex Wilson * in a given program are guarded. Selecting which subset, and adding the 43*6a59053bSAlex Wilson * guards is all handled automatically by the compiler. 44*6a59053bSAlex Wilson * 45*6a59053bSAlex Wilson * There are 3 (or 4) major relevant compiler options in GCC: 46*6a59053bSAlex Wilson * * -fstack-protector 47*6a59053bSAlex Wilson * * -fstack-protector-strong (only in GCC >= 4.9) 48*6a59053bSAlex Wilson * * -fstack-protector-all 49*6a59053bSAlex Wilson * * -fno-stack-protector 50*6a59053bSAlex Wilson * 51*6a59053bSAlex Wilson * The only differences between -fstack-protector, -strong and -all is in 52*6a59053bSAlex Wilson * which functions are selected for adding guards. 53*6a59053bSAlex Wilson * 54*6a59053bSAlex Wilson * -fstack-protector adds guards to functions that make use of a stack- 55*6a59053bSAlex Wilson * allocated char array (or aggregate containing one) of at least 8 bytes 56*6a59053bSAlex Wilson * in length. 57*6a59053bSAlex Wilson * 58*6a59053bSAlex Wilson * -fstack-protector-strong adds guards everywhere -fstack-protector 59*6a59053bSAlex Wilson * does, and also adds guards to all functions that take or pass an address 60*6a59053bSAlex Wilson * to a stack-allocated array of any type (eg arr, &arr[1] etc), as well as 61*6a59053bSAlex Wilson * functions containing certain kinds of pointer arithmetic. 62*6a59053bSAlex Wilson * 63*6a59053bSAlex Wilson * -fstack-protector-all (as the name suggests) adds guards to every single 64*6a59053bSAlex Wilson * function. 65*6a59053bSAlex Wilson * 66*6a59053bSAlex Wilson * There is also another variant, in the ProPolice patches which are used 67*6a59053bSAlex Wilson * by some members of the BSD family (eg OpenBSD), which also guards any 68*6a59053bSAlex Wilson * functions that store function pointers on the stack, as well as a few 69*6a59053bSAlex Wilson * other heuristics (like re-ordering variables so arrays are as close as 70*6a59053bSAlex Wilson * possible to the canary) 71*6a59053bSAlex Wilson */ 72*6a59053bSAlex Wilson 73*6a59053bSAlex Wilson #include <sys/types.h> 74*6a59053bSAlex Wilson #include <sys/cmn_err.h> 75*6a59053bSAlex Wilson #include <sys/time.h> 76*6a59053bSAlex Wilson #include <sys/note.h> 77*6a59053bSAlex Wilson 78*6a59053bSAlex Wilson /* 79*6a59053bSAlex Wilson * The symbol __stack_chk_guard contains the magic guard value used 80*6a59053bSAlex Wilson * to check stack integrity before returning from selected functions. 81*6a59053bSAlex Wilson * 82*6a59053bSAlex Wilson * Its value is set at startup to a "random" number -- this does not have 83*6a59053bSAlex Wilson * to be cryptographically secure, but it does have to be done before 84*6a59053bSAlex Wilson * calling any C functions that the stack guards may have been generated 85*6a59053bSAlex Wilson * for. 86*6a59053bSAlex Wilson * 87*6a59053bSAlex Wilson * For this reason, the uts/i86pc/os directory is always built *without* 88*6a59053bSAlex Wilson * stack protection enabled so that we can bootstrap. 89*6a59053bSAlex Wilson */ 90*6a59053bSAlex Wilson 91*6a59053bSAlex Wilson uintptr_t __stack_chk_guard = 0; 92*6a59053bSAlex Wilson 93*6a59053bSAlex Wilson /* 94*6a59053bSAlex Wilson * The function __stack_chk_fail is called whenever a guard check fails. 95*6a59053bSAlex Wilson */ 96*6a59053bSAlex Wilson void 97*6a59053bSAlex Wilson __stack_chk_fail(void) 98*6a59053bSAlex Wilson { 99*6a59053bSAlex Wilson /* 100*6a59053bSAlex Wilson * Currently we just panic, but some more debug info could be useful. 101*6a59053bSAlex Wilson * Note that we absolutely cannot trust any part of our stack at this 102*6a59053bSAlex Wilson * point (we already know there's an attack in progress). 103*6a59053bSAlex Wilson */ 104*6a59053bSAlex Wilson panic("Stack smashing detected"); 105*6a59053bSAlex Wilson } 106*6a59053bSAlex Wilson 107*6a59053bSAlex Wilson static void salsa_hash(unsigned int *); 108*6a59053bSAlex Wilson 109*6a59053bSAlex Wilson #ifdef __sparc 110*6a59053bSAlex Wilson extern uint64_t ultra_gettick(void); 111*6a59053bSAlex Wilson #define SSP_GET_TICK ultra_gettick 112*6a59053bSAlex Wilson #else 113*6a59053bSAlex Wilson extern hrtime_t tsc_read(void); 114*6a59053bSAlex Wilson #define SSP_GET_TICK tsc_read 115*6a59053bSAlex Wilson #endif /* __sparc */ 116*6a59053bSAlex Wilson 117*6a59053bSAlex Wilson /* called from os/startup.c */ 118*6a59053bSAlex Wilson void 119*6a59053bSAlex Wilson ssp_init(void) 120*6a59053bSAlex Wilson { 121*6a59053bSAlex Wilson int i; 122*6a59053bSAlex Wilson 123*6a59053bSAlex Wilson if (__stack_chk_guard == 0) { 124*6a59053bSAlex Wilson union { 125*6a59053bSAlex Wilson unsigned int state[16]; 126*6a59053bSAlex Wilson hrtime_t ts[8]; 127*6a59053bSAlex Wilson uintptr_t g; 128*6a59053bSAlex Wilson } s; 129*6a59053bSAlex Wilson 130*6a59053bSAlex Wilson for (i = 0; i < 8; ++i) 131*6a59053bSAlex Wilson s.ts[i] = SSP_GET_TICK(); 132*6a59053bSAlex Wilson 133*6a59053bSAlex Wilson salsa_hash(s.state); 134*6a59053bSAlex Wilson 135*6a59053bSAlex Wilson __stack_chk_guard = s.g; 136*6a59053bSAlex Wilson } 137*6a59053bSAlex Wilson } 138*6a59053bSAlex Wilson 139*6a59053bSAlex Wilson /* 140*6a59053bSAlex Wilson * Stealing the chacha/salsa hash function. It's simple, fast and 141*6a59053bSAlex Wilson * public domain. We don't need/want the full cipher (which would 142*6a59053bSAlex Wilson * belong in crypto) and we can't use the fully fledged PRNG 143*6a59053bSAlex Wilson * framework either, since ssp_init has to be called extremely 144*6a59053bSAlex Wilson * early in startup. 145*6a59053bSAlex Wilson * 146*6a59053bSAlex Wilson * Since we don't have to be cryptographically secure, just using 147*6a59053bSAlex Wilson * this to hash some high res timer values should be good enough. 148*6a59053bSAlex Wilson */ 149*6a59053bSAlex Wilson #define QR(a, b, c, d) do { \ 150*6a59053bSAlex Wilson a += b; d ^= a; d <<= 16; \ 151*6a59053bSAlex Wilson c += d; b ^= c; b <<= 12; \ 152*6a59053bSAlex Wilson a += b; d ^= a; d <<= 8; \ 153*6a59053bSAlex Wilson c += d; b ^= c; b <<= 7; \ 154*6a59053bSAlex Wilson _NOTE(CONSTANTCONDITION) \ 155*6a59053bSAlex Wilson } while (0) 156*6a59053bSAlex Wilson 157*6a59053bSAlex Wilson static inline void 158*6a59053bSAlex Wilson salsa_dr(unsigned int *state) 159*6a59053bSAlex Wilson { 160*6a59053bSAlex Wilson QR(state[0], state[4], state[ 8], state[12]); 161*6a59053bSAlex Wilson QR(state[1], state[5], state[ 9], state[13]); 162*6a59053bSAlex Wilson QR(state[2], state[6], state[10], state[14]); 163*6a59053bSAlex Wilson QR(state[3], state[7], state[11], state[15]); 164*6a59053bSAlex Wilson QR(state[0], state[5], state[10], state[15]); 165*6a59053bSAlex Wilson QR(state[1], state[6], state[11], state[12]); 166*6a59053bSAlex Wilson QR(state[2], state[7], state[ 8], state[13]); 167*6a59053bSAlex Wilson QR(state[3], state[4], state[ 9], state[14]); 168*6a59053bSAlex Wilson } 169*6a59053bSAlex Wilson 170*6a59053bSAlex Wilson static void 171*6a59053bSAlex Wilson salsa_hash(unsigned int *state) 172*6a59053bSAlex Wilson { 173*6a59053bSAlex Wilson /* 10x applications of salsa doubleround */ 174*6a59053bSAlex Wilson salsa_dr(state); 175*6a59053bSAlex Wilson salsa_dr(state); 176*6a59053bSAlex Wilson salsa_dr(state); 177*6a59053bSAlex Wilson salsa_dr(state); 178*6a59053bSAlex Wilson salsa_dr(state); 179*6a59053bSAlex Wilson salsa_dr(state); 180*6a59053bSAlex Wilson salsa_dr(state); 181*6a59053bSAlex Wilson salsa_dr(state); 182*6a59053bSAlex Wilson salsa_dr(state); 183*6a59053bSAlex Wilson salsa_dr(state); 184*6a59053bSAlex Wilson } 185