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