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