1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28#include <stdio.h> 29#include <stdlib.h> 30#include <signal.h> 31#include <string.h> 32#include <unistd.h> 33#include <fcntl.h> 34#include <ctype.h> 35#include "logd.h" 36 37void *__stack_chk_guard = 0; 38 39/* Initialize the canary with a random value from /dev/urandom. 40 * If that fails, use the "terminator canary". */ 41static void __attribute__ ((constructor)) 42__guard_setup(void) 43{ 44 int fd; 45 46 fd = open("/dev/urandom", O_RDONLY); 47 if (fd != -1) { 48 ssize_t len = read(fd, &__stack_chk_guard, 49 sizeof(__stack_chk_guard)); 50 close(fd); 51 if (len == sizeof(__stack_chk_guard)) 52 return; 53 } 54 55 /* If that failed, switch to 'terminator canary' */ 56 ((unsigned char *)&__stack_chk_guard)[0] = 0; 57 ((unsigned char *)&__stack_chk_guard)[1] = 0; 58 ((unsigned char *)&__stack_chk_guard)[2] = '\n'; 59 ((unsigned char *)&__stack_chk_guard)[3] = 255; 60} 61 62/* This is the crash handler. 63 * Does a best effort at logging and calls _exit to terminate 64 * the process immediately (without atexit handlers, etc.) */ 65void __stack_chk_fail(void) 66{ 67 struct sigaction sa; 68 sigset_t sigmask; 69 static const char message[] = "stack corruption detected: aborted"; 70 char path[PATH_MAX]; 71 int count; 72 73 /* Immediately block all (but SIGABRT) signal handlers from running code */ 74 sigfillset(&sigmask); 75 sigdelset(&sigmask, SIGABRT); 76 sigprocmask(SIG_BLOCK, &sigmask, NULL); 77 78 /* Use /proc/self/exe link to obtain the program name for logging 79 * purposes. If it's not available, we set it to "<unknown>" */ 80 if ((count = readlink("/proc/self/exe", path, sizeof(path) - 1)) == -1) { 81 strlcpy(path, "<unknown>", sizeof(path)); 82 } else { 83 path[count] = '\0'; 84 } 85 86 /* Do a best effort at logging. This ends up calling writev(2) */ 87 __libc_android_log_print(ANDROID_LOG_FATAL, path, message); 88 89 /* Make sure there is no default action for SIGABRT */ 90 bzero(&sa, sizeof(struct sigaction)); 91 sigemptyset(&sa.sa_mask); 92 sa.sa_flags = 0; 93 sa.sa_handler = SIG_DFL; 94 sigaction(SIGABRT, &sa, NULL); 95 96 /* Terminate the process and exit immediately */ 97 kill(getpid(), SIGABRT); 98 99 _exit(127); 100} 101