1169719Skan/* $NetBSD: stack_protector.c,v 1.4 2006/11/22 17:23:25 christos Exp $ */ 2169719Skan/* $OpenBSD: stack_protector.c,v 1.10 2006/03/31 05:34:44 deraadt Exp $ */ 3169719Skan/* 4169719Skan * Copyright (c) 2002 Hiroaki Etoh, Federico G. Schwindt, and Miodrag Vallat. 5169719Skan * All rights reserved. 6169719Skan * 7169719Skan * Redistribution and use in source and binary forms, with or without 8169719Skan * modification, are permitted provided that the following conditions 9169719Skan * are met: 10169719Skan * 1. Redistributions of source code must retain the above copyright 11169719Skan * notice, this list of conditions and the following disclaimer. 12169719Skan * 2. Redistributions in binary form must reproduce the above copyright 13169719Skan * notice, this list of conditions and the following disclaimer in the 14169719Skan * documentation and/or other materials provided with the distribution. 15169719Skan * 16169719Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 17169719Skan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18169719Skan * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19169719Skan * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, 20169719Skan * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21169719Skan * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22169719Skan * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23169719Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24169719Skan * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25169719Skan * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26169719Skan * POSSIBILITY OF SUCH DAMAGE. 27169719Skan * 28169719Skan */ 29169719Skan 30169719Skan#include <sys/cdefs.h> 31169719Skan__FBSDID("$FreeBSD$"); 32169719Skan 33169719Skan#include <sys/param.h> 34169719Skan#include <sys/sysctl.h> 35169719Skan#include <sys/types.h> 36211416Skib#include <errno.h> 37211416Skib#include <link.h> 38169719Skan#include <signal.h> 39169719Skan#include <string.h> 40169719Skan#include <syslog.h> 41169719Skan#include <unistd.h> 42211416Skib#include "libc_private.h" 43169719Skan 44288105Sjlhextern int __sysctl(const int *name, u_int namelen, void *oldp, 45288105Sjlh size_t *oldlenp, void *newp, size_t newlen); 46169719Skan 47169719Skanlong __stack_chk_guard[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 48169719Skanstatic void __guard_setup(void) __attribute__((__constructor__, __used__)); 49169719Skanstatic void __fail(const char *); 50169719Skanvoid __stack_chk_fail(void); 51169719Skanvoid __chk_fail(void); 52169719Skan 53169719Skan/*LINTED used*/ 54169719Skanstatic void 55169719Skan__guard_setup(void) 56169719Skan{ 57288105Sjlh static const int mib[2] = { CTL_KERN, KERN_ARND }; 58169719Skan size_t len; 59211416Skib int error; 60169719Skan 61169719Skan if (__stack_chk_guard[0] != 0) 62169719Skan return; 63211416Skib error = _elf_aux_info(AT_CANARY, __stack_chk_guard, 64211416Skib sizeof(__stack_chk_guard)); 65211416Skib if (error == 0 && __stack_chk_guard[0] != 0) 66211416Skib return; 67169719Skan 68169719Skan len = sizeof(__stack_chk_guard); 69288105Sjlh if (__sysctl(mib, nitems(mib), __stack_chk_guard, &len, NULL, 0) == 70288105Sjlh -1 || len != sizeof(__stack_chk_guard)) { 71169719Skan /* If sysctl was unsuccessful, use the "terminator canary". */ 72169719Skan ((unsigned char *)(void *)__stack_chk_guard)[0] = 0; 73169719Skan ((unsigned char *)(void *)__stack_chk_guard)[1] = 0; 74169719Skan ((unsigned char *)(void *)__stack_chk_guard)[2] = '\n'; 75169719Skan ((unsigned char *)(void *)__stack_chk_guard)[3] = 255; 76169719Skan } 77169719Skan} 78169719Skan 79169719Skan/*ARGSUSED*/ 80169719Skanstatic void 81169719Skan__fail(const char *msg) 82169719Skan{ 83169719Skan struct sigaction sa; 84169719Skan sigset_t mask; 85169719Skan 86169719Skan /* Immediately block all signal handlers from running code */ 87169719Skan (void)sigfillset(&mask); 88169719Skan (void)sigdelset(&mask, SIGABRT); 89169719Skan (void)sigprocmask(SIG_BLOCK, &mask, NULL); 90169719Skan 91169719Skan /* This may fail on a chroot jail... */ 92213785Srpaulo syslog(LOG_CRIT, "%s", msg); 93169719Skan 94169719Skan (void)memset(&sa, 0, sizeof(sa)); 95169719Skan (void)sigemptyset(&sa.sa_mask); 96169719Skan sa.sa_flags = 0; 97169719Skan sa.sa_handler = SIG_DFL; 98169719Skan (void)sigaction(SIGABRT, &sa, NULL); 99169719Skan (void)kill(getpid(), SIGABRT); 100169719Skan _exit(127); 101169719Skan} 102169719Skan 103169719Skanvoid 104169719Skan__stack_chk_fail(void) 105169719Skan{ 106169719Skan __fail("stack overflow detected; terminated"); 107169719Skan} 108169719Skan 109169719Skanvoid 110169719Skan__chk_fail(void) 111169719Skan{ 112169719Skan __fail("buffer overflow detected; terminated"); 113169719Skan} 114169719Skan 115211748Skib#ifndef PIC 116197277Skan__weak_reference(__stack_chk_fail, __stack_chk_fail_local); 117197277Skan#endif 118