summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2015-08-11 11:28:37 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2015-08-11 11:28:37 +0000
commitfd557490faf3af8df569e8931c039b5dde94f0cc (patch)
treed8d606d4269b6bb57a9e13db56e274afd3614a10 /usr/src
parent1b4d1aad553d7fdfde8b056e179bd25628ea89f8 (diff)
parent6a59053b922dcd35760db6b042abda7cb6ef1c80 (diff)
downloadillumos-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.files1
-rw-r--r--usr/src/uts/i86pc/Makefile.rules2
-rw-r--r--usr/src/uts/i86pc/os/ssp.c184
-rw-r--r--usr/src/uts/i86pc/os/startup.c2
-rw-r--r--usr/src/uts/i86xpv/Makefile.files1
-rw-r--r--usr/src/uts/intel/Makefile.intel1
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)