diff options
author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2015-08-11 11:28:37 +0000 |
---|---|---|
committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2015-08-11 11:28:37 +0000 |
commit | fd557490faf3af8df569e8931c039b5dde94f0cc (patch) | |
tree | d8d606d4269b6bb57a9e13db56e274afd3614a10 /usr/src | |
parent | 1b4d1aad553d7fdfde8b056e179bd25628ea89f8 (diff) | |
parent | 6a59053b922dcd35760db6b042abda7cb6ef1c80 (diff) | |
download | illumos-joyent-fd557490faf3af8df569e8931c039b5dde94f0cc.tar.gz |
[illumos-gate merge]
commit 6a59053b922dcd35760db6b042abda7cb6ef1c80
5922 Want support for building with -fstack-protector
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/i86pc/Makefile.files | 1 | ||||
-rw-r--r-- | usr/src/uts/i86pc/Makefile.rules | 2 | ||||
-rw-r--r-- | usr/src/uts/i86pc/os/ssp.c | 184 | ||||
-rw-r--r-- | usr/src/uts/i86pc/os/startup.c | 2 | ||||
-rw-r--r-- | usr/src/uts/i86xpv/Makefile.files | 1 | ||||
-rw-r--r-- | usr/src/uts/intel/Makefile.intel | 1 |
6 files changed, 190 insertions, 1 deletions
diff --git a/usr/src/uts/i86pc/Makefile.files b/usr/src/uts/i86pc/Makefile.files index 0a917008ca..9829939b16 100644 --- a/usr/src/uts/i86pc/Makefile.files +++ b/usr/src/uts/i86pc/Makefile.files @@ -110,6 +110,7 @@ CORE_OBJS += \ ppage.o \ pwrnow.o \ speedstep.o \ + ssp.o \ startup.o \ timestamp.o \ todpc_subr.o \ diff --git a/usr/src/uts/i86pc/Makefile.rules b/usr/src/uts/i86pc/Makefile.rules index a0207714f7..dcc5960dbf 100644 --- a/usr/src/uts/i86pc/Makefile.rules +++ b/usr/src/uts/i86pc/Makefile.rules @@ -163,7 +163,7 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/ml/%.s $(COMPILE.s) -o $@ $< $(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/os/%.c - $(COMPILE.c) -o $@ $< + $(COMPILE.c) -_gcc=-fno-stack-protector -o $@ $< $(CTFCONVERT_O) $(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/os/cpupm/%.c diff --git a/usr/src/uts/i86pc/os/ssp.c b/usr/src/uts/i86pc/os/ssp.c new file mode 100644 index 0000000000..093a2d5e56 --- /dev/null +++ b/usr/src/uts/i86pc/os/ssp.c @@ -0,0 +1,184 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ +/* + * Copyright 2015 Alex Wilson, the University of Queensland + * Use is subject to license terms. + */ + +/* + * Support functions for stack smashing protection (-fstack-protector + * and family) + * + * The principle behind SSP is to place a "canary" value on the stack + * just below the arguments to a given function (which are in turn + * below the previous %rbp and return pointer). We write it onto the + * stack at the start of a function, and then at the end just before + * we execute "leave" and "ret", we check that the value is still there. + * + * If the check fails, we jump immediately to a handler (which typically + * just executes panic() straight away). + * + * Since an attacker will not know the value of the "canary", they will + * not be able to repair it correctly when overwriting the stack (and in + * almost all cases they must overwrite the canary to get to the return + * pointer), and the check will fail (and safely panic) instead of + * letting them gain control over %rip in a kernel thread. + * + * To debugging tools the canary just looks like another local variable + * (since it's placed below the normal argument space), and so there + * should be minimal/no impact on things that try to parse the + * function preamble. + * + * Of course, adding these guards to every single function does not come + * without a price in performance, so normally only a subset of functions + * in a given program are guarded. Selecting which subset, and adding the + * guards is all handled automatically by the compiler. + * + * There are 3 (or 4) major relevant compiler options in GCC: + * * -fstack-protector + * * -fstack-protector-strong (only in GCC >= 4.9) + * * -fstack-protector-all + * * -fno-stack-protector + * + * The only differences between -fstack-protector, -strong and -all is in + * which functions are selected for adding guards. + * + * -fstack-protector adds guards to functions that make use of a stack- + * allocated char array (or aggregate containing one) of at least 8 bytes + * in length. + * + * -fstack-protector-strong adds guards everywhere -fstack-protector + * does, and also adds guards to all functions that take or pass an address + * to a stack-allocated array of any type (eg arr, &arr[1] etc), as well as + * functions containing certain kinds of pointer arithmetic. + * + * -fstack-protector-all (as the name suggests) adds guards to every single + * function. + * + * There is also another variant, in the ProPolice patches which are used + * by some members of the BSD family (eg OpenBSD), which also guards any + * functions that store function pointers on the stack, as well as a few + * other heuristics (like re-ordering variables so arrays are as close as + * possible to the canary) + */ + +#include <sys/types.h> +#include <sys/cmn_err.h> +#include <sys/time.h> +#include <sys/note.h> + +/* + * The symbol __stack_chk_guard contains the magic guard value used + * to check stack integrity before returning from selected functions. + * + * Its value is set at startup to a "random" number -- this does not have + * to be cryptographically secure, but it does have to be done before + * calling any C functions that the stack guards may have been generated + * for. + * + * For this reason, the uts/i86pc/os directory is always built *without* + * stack protection enabled so that we can bootstrap. + */ + +uintptr_t __stack_chk_guard = 0; + +/* + * The function __stack_chk_fail is called whenever a guard check fails. + */ +void +__stack_chk_fail(void) +{ + /* + * Currently we just panic, but some more debug info could be useful. + * Note that we absolutely cannot trust any part of our stack at this + * point (we already know there's an attack in progress). + */ + panic("Stack smashing detected"); +} + +static void salsa_hash(unsigned int *); + +#ifdef __sparc +extern uint64_t ultra_gettick(void); +#define SSP_GET_TICK ultra_gettick +#else +extern hrtime_t tsc_read(void); +#define SSP_GET_TICK tsc_read +#endif /* __sparc */ + +/* called from os/startup.c */ +void +ssp_init(void) +{ + int i; + + if (__stack_chk_guard == 0) { + union { + unsigned int state[16]; + hrtime_t ts[8]; + uintptr_t g; + } s; + + for (i = 0; i < 8; ++i) + s.ts[i] = SSP_GET_TICK(); + + salsa_hash(s.state); + + __stack_chk_guard = s.g; + } +} + +/* + * Stealing the chacha/salsa hash function. It's simple, fast and + * public domain. We don't need/want the full cipher (which would + * belong in crypto) and we can't use the fully fledged PRNG + * framework either, since ssp_init has to be called extremely + * early in startup. + * + * Since we don't have to be cryptographically secure, just using + * this to hash some high res timer values should be good enough. + */ +#define QR(a, b, c, d) do { \ + a += b; d ^= a; d <<= 16; \ + c += d; b ^= c; b <<= 12; \ + a += b; d ^= a; d <<= 8; \ + c += d; b ^= c; b <<= 7; \ + _NOTE(CONSTANTCONDITION) \ + } while (0) + +static inline void +salsa_dr(unsigned int *state) +{ + QR(state[0], state[4], state[ 8], state[12]); + QR(state[1], state[5], state[ 9], state[13]); + QR(state[2], state[6], state[10], state[14]); + QR(state[3], state[7], state[11], state[15]); + QR(state[0], state[5], state[10], state[15]); + QR(state[1], state[6], state[11], state[12]); + QR(state[2], state[7], state[ 8], state[13]); + QR(state[3], state[4], state[ 9], state[14]); +} + +static void +salsa_hash(unsigned int *state) +{ + /* 10x applications of salsa doubleround */ + salsa_dr(state); + salsa_dr(state); + salsa_dr(state); + salsa_dr(state); + salsa_dr(state); + salsa_dr(state); + salsa_dr(state); + salsa_dr(state); + salsa_dr(state); + salsa_dr(state); +} diff --git a/usr/src/uts/i86pc/os/startup.c b/usr/src/uts/i86pc/os/startup.c index 82a0a5bc82..700b3456ae 100644 --- a/usr/src/uts/i86pc/os/startup.c +++ b/usr/src/uts/i86pc/os/startup.c @@ -148,6 +148,7 @@ extern void progressbar_init(void); extern void brand_init(void); extern void pcf_init(void); extern void pg_init(void); +extern void ssp_init(void); extern int size_pse_array(pgcnt_t, int); @@ -711,6 +712,7 @@ startup(void) segvn_use_regions = 0; } #endif + ssp_init(); progressbar_init(); startup_init(); #if defined(__xpv) diff --git a/usr/src/uts/i86xpv/Makefile.files b/usr/src/uts/i86xpv/Makefile.files index 3b92ef75c9..bf2ccf8f18 100644 --- a/usr/src/uts/i86xpv/Makefile.files +++ b/usr/src/uts/i86xpv/Makefile.files @@ -94,6 +94,7 @@ CORE_OBJS += \ pmem.o \ ppage.o \ startup.o \ + ssp.o \ xpv_timestamp.o \ todpc_subr.o \ trap.o \ diff --git a/usr/src/uts/intel/Makefile.intel b/usr/src/uts/intel/Makefile.intel index bbcf818b11..75ba9472c2 100644 --- a/usr/src/uts/intel/Makefile.intel +++ b/usr/src/uts/intel/Makefile.intel @@ -130,6 +130,7 @@ CFLAGS += $(SPACEFLAG) CFLAGS += $(CCUNBOUND) CFLAGS += $(CFLAGS_uts) CFLAGS += -xstrconst +CFLAGS += -_gcc=-fstack-protector ASFLAGS_XARCH_32 = $(i386_ASFLAGS) ASFLAGS_XARCH_64 = $(amd64_ASFLAGS) |