platform_bionic/libc/bionic/abort.cpp

58 lines
2.3 KiB
C++
Raw Normal View History

/*
* Copyright (c) 1985 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <signal.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <unistd.h>
#include "private/bionic_inline_raise.h"
Abort harder. Some PoS internal system can't cope with more than 4 stack frames, so the fact that our abort(3) implementation takes 4 frames by itself makes it useless. Re-reading POSIX, it only says "behaves as if", so the previous implementation chain wasn't mandatory and we can just go straight to calling tgkill... Before: #00 pc 0000000000069be4 /system/lib64/libc.so (tgkill+8) #01 pc 0000000000066d50 /system/lib64/libc.so (pthread_kill+64) #02 pc 0000000000028110 /system/lib64/libc.so (raise+24) #03 pc 000000000001d4ec /system/lib64/libc.so (abort+52) After: #00 pc 0000000000069bc8 /system/lib64/libc.so (tgkill+8) #01 pc 000000000001d4c8 /system/lib64/libc.so (abort+80) #02 pc 0000000000001494 /system/xbin/crasher64 (_ZL9do_actionPKc+872) #03 pc 00000000000010e0 /system/xbin/crasher64 (main+88) This is less useful on 32-bit ARM because there there's an extra trampoline from an assembler abort(3) implementation, so you'll still only get one meaningful stack frame. But every other architecture will now get two! But wait! It turns out that the assembler hack isn't needed any more. Here we are unwinding just fine all the way through the 32-bit ARM crasher: Before (with direct call to tgkill but still using the assembler): #00 pc 00049e7c /system/lib/libc.so (tgkill+12) #01 pc 00019c6f /system/lib/libc.so (__libc_android_abort+50) #02 pc 000181f8 /system/lib/libc.so (abort+4) #03 pc 00001025 /system/xbin/crasher (_ZL9do_actionPKc+656) #04 pc 00017721 /system/lib/libc.so (__libc_init+48) #05 pc 00000b38 /system/xbin/crasher (_start+96) After: #00 pc 00049e6c /system/lib/libc.so (tgkill+12) #01 pc 00019c5f /system/lib/libc.so (abort+50) #02 pc 00001025 /system/xbin/crasher (_ZL9do_actionPKc+656) #03 pc 00017721 /system/lib/libc.so (__libc_init+48) #04 pc 00000b38 /system/xbin/crasher (_start+96) (As you can see, the fact that we see __libc_init rather than main was true with the assembler stub too, so that's not a regression even if it does seem odd...) Bug: N/A Test: ran crasher64 Change-Id: I9dd5b214c495604c8b502c7ec0de3631080d8c29
2016-11-30 01:59:26 +01:00
void abort() {
// Don't block SIGABRT to give any signal handler a chance; we ignore
// any errors -- X311J doesn't allow abort to return anyway.
sigset64_t mask;
sigfillset64(&mask);
sigdelset64(&mask, SIGABRT);
sigprocmask64(SIG_SETMASK, &mask, nullptr);
inline_raise(SIGABRT);
// If SIGABRT is ignored or it's caught and the handler returns,
// remove the SIGABRT signal handler and raise SIGABRT again.
struct sigaction64 sa = { .sa_handler = SIG_DFL, .sa_flags = SA_RESTART };
sigaction64(SIGABRT, &sa, nullptr);
Abort harder. Some PoS internal system can't cope with more than 4 stack frames, so the fact that our abort(3) implementation takes 4 frames by itself makes it useless. Re-reading POSIX, it only says "behaves as if", so the previous implementation chain wasn't mandatory and we can just go straight to calling tgkill... Before: #00 pc 0000000000069be4 /system/lib64/libc.so (tgkill+8) #01 pc 0000000000066d50 /system/lib64/libc.so (pthread_kill+64) #02 pc 0000000000028110 /system/lib64/libc.so (raise+24) #03 pc 000000000001d4ec /system/lib64/libc.so (abort+52) After: #00 pc 0000000000069bc8 /system/lib64/libc.so (tgkill+8) #01 pc 000000000001d4c8 /system/lib64/libc.so (abort+80) #02 pc 0000000000001494 /system/xbin/crasher64 (_ZL9do_actionPKc+872) #03 pc 00000000000010e0 /system/xbin/crasher64 (main+88) This is less useful on 32-bit ARM because there there's an extra trampoline from an assembler abort(3) implementation, so you'll still only get one meaningful stack frame. But every other architecture will now get two! But wait! It turns out that the assembler hack isn't needed any more. Here we are unwinding just fine all the way through the 32-bit ARM crasher: Before (with direct call to tgkill but still using the assembler): #00 pc 00049e7c /system/lib/libc.so (tgkill+12) #01 pc 00019c6f /system/lib/libc.so (__libc_android_abort+50) #02 pc 000181f8 /system/lib/libc.so (abort+4) #03 pc 00001025 /system/xbin/crasher (_ZL9do_actionPKc+656) #04 pc 00017721 /system/lib/libc.so (__libc_init+48) #05 pc 00000b38 /system/xbin/crasher (_start+96) After: #00 pc 00049e6c /system/lib/libc.so (tgkill+12) #01 pc 00019c5f /system/lib/libc.so (abort+50) #02 pc 00001025 /system/xbin/crasher (_ZL9do_actionPKc+656) #03 pc 00017721 /system/lib/libc.so (__libc_init+48) #04 pc 00000b38 /system/xbin/crasher (_start+96) (As you can see, the fact that we see __libc_init rather than main was true with the assembler stub too, so that's not a regression even if it does seem odd...) Bug: N/A Test: ran crasher64 Change-Id: I9dd5b214c495604c8b502c7ec0de3631080d8c29
2016-11-30 01:59:26 +01:00
sigprocmask64(SIG_SETMASK, &mask, nullptr);
inline_raise(SIGABRT);
Abort harder. Some PoS internal system can't cope with more than 4 stack frames, so the fact that our abort(3) implementation takes 4 frames by itself makes it useless. Re-reading POSIX, it only says "behaves as if", so the previous implementation chain wasn't mandatory and we can just go straight to calling tgkill... Before: #00 pc 0000000000069be4 /system/lib64/libc.so (tgkill+8) #01 pc 0000000000066d50 /system/lib64/libc.so (pthread_kill+64) #02 pc 0000000000028110 /system/lib64/libc.so (raise+24) #03 pc 000000000001d4ec /system/lib64/libc.so (abort+52) After: #00 pc 0000000000069bc8 /system/lib64/libc.so (tgkill+8) #01 pc 000000000001d4c8 /system/lib64/libc.so (abort+80) #02 pc 0000000000001494 /system/xbin/crasher64 (_ZL9do_actionPKc+872) #03 pc 00000000000010e0 /system/xbin/crasher64 (main+88) This is less useful on 32-bit ARM because there there's an extra trampoline from an assembler abort(3) implementation, so you'll still only get one meaningful stack frame. But every other architecture will now get two! But wait! It turns out that the assembler hack isn't needed any more. Here we are unwinding just fine all the way through the 32-bit ARM crasher: Before (with direct call to tgkill but still using the assembler): #00 pc 00049e7c /system/lib/libc.so (tgkill+12) #01 pc 00019c6f /system/lib/libc.so (__libc_android_abort+50) #02 pc 000181f8 /system/lib/libc.so (abort+4) #03 pc 00001025 /system/xbin/crasher (_ZL9do_actionPKc+656) #04 pc 00017721 /system/lib/libc.so (__libc_init+48) #05 pc 00000b38 /system/xbin/crasher (_start+96) After: #00 pc 00049e6c /system/lib/libc.so (tgkill+12) #01 pc 00019c5f /system/lib/libc.so (abort+50) #02 pc 00001025 /system/xbin/crasher (_ZL9do_actionPKc+656) #03 pc 00017721 /system/lib/libc.so (__libc_init+48) #04 pc 00000b38 /system/xbin/crasher (_start+96) (As you can see, the fact that we see __libc_init rather than main was true with the assembler stub too, so that's not a regression even if it does seem odd...) Bug: N/A Test: ran crasher64 Change-Id: I9dd5b214c495604c8b502c7ec0de3631080d8c29
2016-11-30 01:59:26 +01:00
// If we get this far, just exit.
_exit(127);
}