xref: /illumos-gate/usr/src/uts/i86pc/os/ssp.c (revision fca4268092e9961ebb9b5e0098dcebc545023586)
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