Path: blob/main/lib/libc/secure/libc_stack_protector.c
39476 views
/* $NetBSD: stack_protector.c,v 1.4 2006/11/22 17:23:25 christos Exp $ */1/* $OpenBSD: stack_protector.c,v 1.10 2006/03/31 05:34:44 deraadt Exp $ */2/*3* Copyright (c) 2002 Hiroaki Etoh, Federico G. Schwindt, and Miodrag Vallat.4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR16* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED17* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE18* DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT,19* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES20* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR21* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)22* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,23* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN24* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE25* POSSIBILITY OF SUCH DAMAGE.26*27*/2829#include <sys/param.h>30#include <sys/sysctl.h>31#include <errno.h>32#include <link.h>33#include <signal.h>34#include <string.h>35#include <syslog.h>36#include <unistd.h>37#include "libc_private.h"3839/*40* We give __guard_setup a defined priority early on so that statically linked41* applications have a defined priority at which __stack_chk_guard will be42* getting initialized. This will not matter to most applications, because43* they're either not usually statically linked or they simply don't do things44* in constructors that would be adversely affected by their positioning with45* respect to this initialization.46*/47static void __guard_setup(void)48__attribute__((__constructor__ (200), __used__));4950extern long __stack_chk_guard[8];51extern int __sysctl(const int *name, u_int namelen, void *oldp,52size_t *oldlenp, void *newp, size_t newlen);5354long __stack_chk_guard[8] = {0, 0, 0, 0, 0, 0, 0, 0};55static void __fail(const char *) __dead2;56void __stack_chk_fail(void) __dead2;57void __chk_fail(void) __dead2;5859/*LINTED used*/60static void61__guard_setup(void)62{63static const int mib[2] = { CTL_KERN, KERN_ARND };64volatile long tmp_stack_chk_guard[nitems(__stack_chk_guard)];65size_t idx, len;66int error;6768if (__stack_chk_guard[0] != 0)69return;70/*71* Avoid using functions which might have stack protection72* enabled, to update the __stack_chk_guard. First fetch the73* data into a temporal array, then do manual volatile copy to74* not allow optimizer to call memcpy() behind us.75*/76error = _elf_aux_info(AT_CANARY,77__DEQUALIFY(void *, tmp_stack_chk_guard),78sizeof(tmp_stack_chk_guard));79if (error == 0 && tmp_stack_chk_guard[0] != 0) {80for (idx = 0; idx < nitems(__stack_chk_guard); idx++) {81__stack_chk_guard[idx] = tmp_stack_chk_guard[idx];82tmp_stack_chk_guard[idx] = 0;83}84return;85}8687len = sizeof(__stack_chk_guard);88if (__sysctl(mib, nitems(mib), __stack_chk_guard, &len, NULL, 0) ==89-1 || len != sizeof(__stack_chk_guard)) {90/* If sysctl was unsuccessful, use the "terminator canary". */91((unsigned char *)(void *)__stack_chk_guard)[0] = 0;92((unsigned char *)(void *)__stack_chk_guard)[1] = 0;93((unsigned char *)(void *)__stack_chk_guard)[2] = '\n';94((unsigned char *)(void *)__stack_chk_guard)[3] = 255;95}96}9798/*ARGSUSED*/99static void100__fail(const char *msg)101{102struct sigaction sa;103sigset_t mask;104105/* Immediately block all signal handlers from running code */106(void)sigfillset(&mask);107(void)sigdelset(&mask, SIGABRT);108(void)sigprocmask(SIG_BLOCK, &mask, NULL);109110/* This may fail on a chroot jail... */111syslog(LOG_CRIT, "%s", msg);112113(void)memset(&sa, 0, sizeof(sa));114(void)sigemptyset(&sa.sa_mask);115sa.sa_flags = 0;116sa.sa_handler = SIG_DFL;117(void)sigaction(SIGABRT, &sa, NULL);118(void)kill(getpid(), SIGABRT);119_exit(127);120}121122void123__stack_chk_fail(void)124{125__fail("stack overflow detected; terminated");126}127128void129__chk_fail(void)130{131__fail("buffer overflow detected; terminated");132}133134#ifndef PIC135__weak_reference(__stack_chk_fail, __stack_chk_fail_local);136#endif137138139