1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "crash_dispatcher" 18 19 #include <vector> 20 21 #include <elf.h> 22 #include <errno.h> 23 #include <unistd.h> 24 25 #include <android-base/file.h> 26 #include <log/logger.h> 27 28 namespace { 29 30 const char kCrashCollector32Path[] = "/system/bin/crash_collector32"; 31 const char kCrashCollector64Path[] = "/system/bin/crash_collector64"; 32 33 } // namespace 34 35 // Reads the coredump from STDIN and checks whether it's 32-bit or 64-bit, 36 // and dispatches it to the appropriate version of crash_collector. 37 int main(int argc, char** argv) { 38 // Do not abort on a write error caused by a broken pipe. 39 signal(SIGPIPE, SIG_IGN); 40 // Read the ELF header until EI_CLASS. 41 char buf_head[EI_CLASS + 1]; 42 if (!android::base::ReadFully(STDIN_FILENO, buf_head, sizeof(buf_head))) { 43 ALOGE("Failed to read. errno = %d", errno); 44 return 1; 45 } 46 // Set up pipe to feed coredump to crash_collector. 47 int pipe_fds[2]; 48 if (pipe(pipe_fds) == -1) { 49 ALOGE("Failed to pipe. errno = %d", errno); 50 return 1; 51 } 52 // Prepare crash_collector arguments. 53 const char* crash_collector_path = buf_head[EI_CLASS] == ELFCLASS64 ? 54 kCrashCollector64Path : kCrashCollector32Path; 55 std::vector<const char*> args(argc + 1); 56 args[0] = crash_collector_path; 57 std::copy(argv + 1, argv + argc, args.begin() + 1); 58 args.back() = nullptr; 59 // Exec crash_collector. 60 const pid_t pid = fork(); 61 if (pid == -1) { 62 ALOGE("Failed to fork. errno = %d", errno); 63 return 1; 64 } 65 if (pid == 0) { 66 if (close(pipe_fds[1]) != 0 && errno != EINTR) { 67 ALOGE("Failed to close the pipe's write end. errno = %d", errno); 68 _exit(1); 69 } 70 if (TEMP_FAILURE_RETRY(dup2(pipe_fds[0], STDIN_FILENO)) != 0) { 71 ALOGE("Failed to dup the pipe's read end. errno = %d", errno); 72 _exit(1); 73 } 74 execve(args[0], const_cast<char**>(&args[0]), environ); 75 ALOGE("Failed to execute crash_collector. errno = %d", errno); 76 _exit(1); 77 } 78 // Send buf_head to crash_collector. 79 if (close(pipe_fds[0]) != 0 && errno != EINTR) { 80 ALOGE("Failed to close the pipe's read end."); 81 return 1; 82 } 83 if (!android::base::WriteFully(pipe_fds[1], buf_head, sizeof(buf_head))) { 84 return 1; 85 } 86 // Send the rest of coredump to crash_collector. 87 const size_t kBufSize = 32768; 88 char buf[kBufSize]; 89 while (true) { 90 int rv = TEMP_FAILURE_RETRY(read(STDIN_FILENO, buf, kBufSize)); 91 if (rv == -1) { 92 ALOGE("Failed to read. errno = %d", errno); 93 return 1; 94 } 95 if (rv == 0) 96 break; 97 if (!android::base::WriteFully(pipe_fds[1], buf, rv)) { 98 return 1; 99 } 100 } 101 return 0; 102 } 103