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