6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson/*
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * This file and its contents are supplied under the terms of the
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * Common Development and Distribution License ("CDDL"), version 1.0.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * You may only use this file in accordance with the terms of version
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * 1.0 of the CDDL.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson *
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * A full copy of the text of the CDDL should have accompanied this
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * source. A copy of the CDDL is also available via the Internet at
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * http://www.illumos.org/license/CDDL.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson */
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson/*
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * Copyright 2015 Alex Wilson, the University of Queensland
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * Use is subject to license terms.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson */
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson/*
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * Support functions for stack smashing protection (-fstack-protector
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * and family)
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson *
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * The principle behind SSP is to place a "canary" value on the stack
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * just below the arguments to a given function (which are in turn
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * below the previous %rbp and return pointer). We write it onto the
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * stack at the start of a function, and then at the end just before
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * we execute "leave" and "ret", we check that the value is still there.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson *
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * If the check fails, we jump immediately to a handler (which typically
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * just executes panic() straight away).
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson *
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * Since an attacker will not know the value of the "canary", they will
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * not be able to repair it correctly when overwriting the stack (and in
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * almost all cases they must overwrite the canary to get to the return
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * pointer), and the check will fail (and safely panic) instead of
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * letting them gain control over %rip in a kernel thread.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson *
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * To debugging tools the canary just looks like another local variable
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * (since it's placed below the normal argument space), and so there
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * should be minimal/no impact on things that try to parse the
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * function preamble.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson *
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * Of course, adding these guards to every single function does not come
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * without a price in performance, so normally only a subset of functions
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * in a given program are guarded. Selecting which subset, and adding the
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * guards is all handled automatically by the compiler.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson *
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * There are 3 (or 4) major relevant compiler options in GCC:
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * * -fstack-protector
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * * -fstack-protector-strong (only in GCC >= 4.9)
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * * -fstack-protector-all
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * * -fno-stack-protector
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson *
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * The only differences between -fstack-protector, -strong and -all is in
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * which functions are selected for adding guards.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson *
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * -fstack-protector adds guards to functions that make use of a stack-
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * allocated char array (or aggregate containing one) of at least 8 bytes
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * in length.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson *
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * -fstack-protector-strong adds guards everywhere -fstack-protector
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * does, and also adds guards to all functions that take or pass an address
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * to a stack-allocated array of any type (eg arr, &arr[1] etc), as well as
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * functions containing certain kinds of pointer arithmetic.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson *
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * -fstack-protector-all (as the name suggests) adds guards to every single
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * function.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson *
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * There is also another variant, in the ProPolice patches which are used
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * by some members of the BSD family (eg OpenBSD), which also guards any
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * functions that store function pointers on the stack, as well as a few
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * other heuristics (like re-ordering variables so arrays are as close as
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * possible to the canary)
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson */
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson#include <sys/types.h>
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson#include <sys/cmn_err.h>
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson#include <sys/time.h>
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson#include <sys/note.h>
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson/*
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * The symbol __stack_chk_guard contains the magic guard value used
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * to check stack integrity before returning from selected functions.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson *
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * Its value is set at startup to a "random" number -- this does not have
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * to be cryptographically secure, but it does have to be done before
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * calling any C functions that the stack guards may have been generated
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * for.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson *
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * For this reason, the uts/i86pc/os directory is always built *without*
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * stack protection enabled so that we can bootstrap.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson */
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilsonuintptr_t __stack_chk_guard = 0;
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson/*
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * The function __stack_chk_fail is called whenever a guard check fails.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson */
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilsonvoid
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson__stack_chk_fail(void)
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson{
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson /*
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * Currently we just panic, but some more debug info could be useful.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * Note that we absolutely cannot trust any part of our stack at this
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * point (we already know there's an attack in progress).
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson */
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson panic("Stack smashing detected");
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson}
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilsonstatic void salsa_hash(unsigned int *);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson#ifdef __sparc
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilsonextern uint64_t ultra_gettick(void);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson#define SSP_GET_TICK ultra_gettick
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson#else
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilsonextern hrtime_t tsc_read(void);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson#define SSP_GET_TICK tsc_read
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson#endif /* __sparc */
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson/* called from os/startup.c */
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilsonvoid
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilsonssp_init(void)
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson{
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson int i;
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson if (__stack_chk_guard == 0) {
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson union {
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson unsigned int state[16];
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson hrtime_t ts[8];
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson uintptr_t g;
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson } s;
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson for (i = 0; i < 8; ++i)
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson s.ts[i] = SSP_GET_TICK();
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson salsa_hash(s.state);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson __stack_chk_guard = s.g;
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson }
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson}
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson/*
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * Stealing the chacha/salsa hash function. It's simple, fast and
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * public domain. We don't need/want the full cipher (which would
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * belong in crypto) and we can't use the fully fledged PRNG
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * framework either, since ssp_init has to be called extremely
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * early in startup.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson *
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * Since we don't have to be cryptographically secure, just using
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson * this to hash some high res timer values should be good enough.
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson */
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson#define QR(a, b, c, d) do { \
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson a += b; d ^= a; d <<= 16; \
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson c += d; b ^= c; b <<= 12; \
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson a += b; d ^= a; d <<= 8; \
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson c += d; b ^= c; b <<= 7; \
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson _NOTE(CONSTANTCONDITION) \
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson } while (0)
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilsonstatic inline void
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilsonsalsa_dr(unsigned int *state)
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson{
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson QR(state[0], state[4], state[ 8], state[12]);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson QR(state[1], state[5], state[ 9], state[13]);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson QR(state[2], state[6], state[10], state[14]);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson QR(state[3], state[7], state[11], state[15]);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson QR(state[0], state[5], state[10], state[15]);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson QR(state[1], state[6], state[11], state[12]);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson QR(state[2], state[7], state[ 8], state[13]);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson QR(state[3], state[4], state[ 9], state[14]);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson}
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilsonstatic void
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilsonsalsa_hash(unsigned int *state)
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson{
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson /* 10x applications of salsa doubleround */
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson salsa_dr(state);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson salsa_dr(state);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson salsa_dr(state);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson salsa_dr(state);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson salsa_dr(state);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson salsa_dr(state);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson salsa_dr(state);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson salsa_dr(state);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson salsa_dr(state);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson salsa_dr(state);
6a59053b922dcd35760db6b042abda7cb6ef1c80Alex Wilson}