183e085b7a331c96237cf8e814f97b3ef4c36a70fjimblandy// Copyright (c) 2010 Google Inc. 2f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// All rights reserved. 3f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// 4f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// Redistribution and use in source and binary forms, with or without 5f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// modification, are permitted provided that the following conditions are 6f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// met: 7f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// 8f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// * Redistributions of source code must retain the above copyright 9f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// notice, this list of conditions and the following disclaimer. 10f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// * Redistributions in binary form must reproduce the above 11f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// copyright notice, this list of conditions and the following disclaimer 12f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// in the documentation and/or other materials provided with the 13f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// distribution. 14f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// * Neither the name of Google Inc. nor the names of its 15f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// contributors may be used to endorse or promote products derived from 16f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// this software without specific prior written permission. 17f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// 18f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 30f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <assert.h> 31f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <dirent.h> 32f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <fcntl.h> 33f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <limits.h> 34f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <poll.h> 35f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <stdio.h> 36f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <string.h> 37f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <sys/socket.h> 38f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <sys/stat.h> 39f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <sys/types.h> 40f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <unistd.h> 41f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 42f66ff1afd2e0f7f16ac2f8d40984cf799f3f099bthestig@chromium.org#include <vector> 43f66ff1afd2e0f7f16ac2f8d40984cf799f3f099bthestig@chromium.org 44f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include "client/linux/crash_generation/crash_generation_server.h" 45f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include "client/linux/crash_generation/client_info.h" 46f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include "client/linux/handler/exception_handler.h" 47f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include "client/linux/minidump_writer/minidump_writer.h" 48f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include "common/linux/eintr_wrapper.h" 49f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include "common/linux/guid_creator.h" 50c9fb1f6e7400b2f7198e62e09d7ac0a2aa68c84cbenchan@chromium.org#include "common/linux/safe_readlink.h" 51f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 52f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekstatic const char kCommandQuit = 'x'; 53f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 54f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczareknamespace google_breakpad { 55f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 56f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::CrashGenerationServer( 57f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek const int listen_fd, 58f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek OnClientDumpRequestCallback dump_callback, 59f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek void* dump_context, 60f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek OnClientExitingCallback exit_callback, 61f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek void* exit_context, 62f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek bool generate_dumps, 634e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com const string* dump_path) : 64f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek server_fd_(listen_fd), 65f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek dump_callback_(dump_callback), 66f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek dump_context_(dump_context), 67f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek exit_callback_(exit_callback), 68f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek exit_context_(exit_context), 69f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek generate_dumps_(generate_dumps), 70f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek started_(false) 71f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 72f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (dump_path) 73f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek dump_dir_ = *dump_path; 74f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek else 75f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek dump_dir_ = "/tmp"; 76f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 77f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 78f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::~CrashGenerationServer() 79f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 80f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (started_) 81f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek Stop(); 82f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 83f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 84f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekbool 85f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::Start() 86f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 87f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (started_ || 0 > server_fd_) 88f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 89f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 90f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek int control_pipe[2]; 91f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (pipe(control_pipe)) 92f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 93f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 94f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (fcntl(control_pipe[0], F_SETFD, FD_CLOEXEC)) 95f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 96f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (fcntl(control_pipe[1], F_SETFD, FD_CLOEXEC)) 97f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 98f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 99f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (fcntl(control_pipe[0], F_SETFL, O_NONBLOCK)) 100f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 101f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 102f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek control_pipe_in_ = control_pipe[0]; 103f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek control_pipe_out_ = control_pipe[1]; 104f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 105f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (pthread_create(&thread_, NULL, 106f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek ThreadMain, reinterpret_cast<void*>(this))) 107f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 108f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 109f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek started_ = true; 110f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 111f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 112f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 113f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekvoid 114f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::Stop() 115f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 116f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek assert(pthread_self() != thread_); 117f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 118f66ff1afd2e0f7f16ac2f8d40984cf799f3f099bthestig@chromium.org if (!started_) 119f66ff1afd2e0f7f16ac2f8d40984cf799f3f099bthestig@chromium.org return; 120f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 121f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek HANDLE_EINTR(write(control_pipe_out_, &kCommandQuit, 1)); 122f66ff1afd2e0f7f16ac2f8d40984cf799f3f099bthestig@chromium.org 123f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek void* dummy; 124f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek pthread_join(thread_, &dummy); 125f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 126f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek started_ = false; 127f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 128f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 129f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek//static 130f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekbool 131f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::CreateReportChannel(int* server_fd, int* client_fd) 132f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 133f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek int fds[2]; 134f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 135f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds)) 136f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 137f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 138f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek static const int on = 1; 139f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // Enable passcred on the server end of the socket 140f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (setsockopt(fds[1], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) 141f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 142f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 143f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (fcntl(fds[1], F_SETFL, O_NONBLOCK)) 144f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 145f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (fcntl(fds[1], F_SETFD, FD_CLOEXEC)) 146f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 147f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 148f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek *client_fd = fds[0]; 149f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek *server_fd = fds[1]; 150f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 151f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 152f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 153f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// The following methods/functions execute on the server thread 154f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 155f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekvoid 156f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::Run() 157f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 158f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek struct pollfd pollfds[2]; 159f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek memset(&pollfds, 0, sizeof(pollfds)); 160f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 161f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek pollfds[0].fd = server_fd_; 162f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek pollfds[0].events = POLLIN; 163f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 164f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek pollfds[1].fd = control_pipe_in_; 165f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek pollfds[1].events = POLLIN; 166f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 167f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek while (true) { 168f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // infinite timeout 169f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek int nevents = poll(pollfds, sizeof(pollfds)/sizeof(pollfds[0]), -1); 170f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (-1 == nevents) { 171f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (EINTR == errno) { 172f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek continue; 173f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } else { 174f66ff1afd2e0f7f16ac2f8d40984cf799f3f099bthestig@chromium.org return; 175f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 176f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 177f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 178f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (pollfds[0].revents && !ClientEvent(pollfds[0].revents)) 179f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return; 180f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 181f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (pollfds[1].revents && !ControlEvent(pollfds[1].revents)) 182f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return; 183f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 184f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 185f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 186f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekbool 187f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::ClientEvent(short revents) 188f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 189f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (POLLHUP & revents) 190f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 191f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek assert(POLLIN & revents); 192f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 193f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // A process has crashed and has signaled us by writing a datagram 194f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // to the death signal socket. The datagram contains the crash context needed 195f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // for writing the minidump as well as a file descriptor and a credentials 196f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // block so that they can't lie about their pid. 197f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 198f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // The length of the control message: 199f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek static const unsigned kControlMsgSize = 200f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct ucred)); 201f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // The length of the regular payload: 202f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek static const unsigned kCrashContextSize = 203f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek sizeof(google_breakpad::ExceptionHandler::CrashContext); 204f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 205f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek struct msghdr msg = {0}; 206f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek struct iovec iov[1]; 207f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek char crash_context[kCrashContextSize]; 208f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek char control[kControlMsgSize]; 209f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek const ssize_t expected_msg_size = sizeof(crash_context); 210f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 211f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek iov[0].iov_base = crash_context; 212f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek iov[0].iov_len = sizeof(crash_context); 213f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek msg.msg_iov = iov; 214f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek msg.msg_iovlen = sizeof(iov)/sizeof(iov[0]); 215f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek msg.msg_control = control; 216f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek msg.msg_controllen = kControlMsgSize; 217f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 218f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek const ssize_t msg_size = HANDLE_EINTR(recvmsg(server_fd_, &msg, 0)); 219f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (msg_size != expected_msg_size) 220f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 221f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 222f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (msg.msg_controllen != kControlMsgSize || 223f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek msg.msg_flags & ~MSG_TRUNC) 224f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 225f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 226f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // Walk the control payload and extract the file descriptor and validated pid. 227f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek pid_t crashing_pid = -1; 228f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek int signal_fd = -1; 229f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek for (struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); hdr; 230f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek hdr = CMSG_NXTHDR(&msg, hdr)) { 231f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (hdr->cmsg_level != SOL_SOCKET) 232f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek continue; 233f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (hdr->cmsg_type == SCM_RIGHTS) { 234f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek const unsigned len = hdr->cmsg_len - 235f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek (((uint8_t*)CMSG_DATA(hdr)) - (uint8_t*)hdr); 236f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek assert(len % sizeof(int) == 0u); 237f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek const unsigned num_fds = len / sizeof(int); 238f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (num_fds > 1 || num_fds == 0) { 239f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // A nasty process could try and send us too many descriptors and 240f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // force a leak. 241f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek for (unsigned i = 0; i < num_fds; ++i) 2421a5016d36e53e2f1f7bebbcd1a7a8e4d667182d4mark@chromium.org close(reinterpret_cast<int*>(CMSG_DATA(hdr))[i]); 243f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 244f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } else { 245f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek signal_fd = reinterpret_cast<int*>(CMSG_DATA(hdr))[0]; 246f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 247f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } else if (hdr->cmsg_type == SCM_CREDENTIALS) { 248f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek const struct ucred *cred = 249f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek reinterpret_cast<struct ucred*>(CMSG_DATA(hdr)); 250f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek crashing_pid = cred->pid; 251f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 252f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 253f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 254f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (crashing_pid == -1 || signal_fd == -1) { 255f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (signal_fd) 2561a5016d36e53e2f1f7bebbcd1a7a8e4d667182d4mark@chromium.org close(signal_fd); 257f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 258f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 259f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 2604e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com string minidump_filename; 261f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (!MakeMinidumpFilename(minidump_filename)) 262f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 263f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 264f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (!google_breakpad::WriteMinidump(minidump_filename.c_str(), 265f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek crashing_pid, crash_context, 266f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek kCrashContextSize)) { 2671a5016d36e53e2f1f7bebbcd1a7a8e4d667182d4mark@chromium.org close(signal_fd); 268f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 269f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 270f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 271f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (dump_callback_) { 272f092d39bfc1090285476784307a10881702179fbted.mielczarek@gmail.com ClientInfo info(crashing_pid, this); 273f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 274f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek dump_callback_(dump_context_, &info, &minidump_filename); 275f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 276f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 277f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // Send the done signal to the process: it can exit now. 2782290db8d52d3d4692d25d4918abc31880f1eb31fted.mielczarek@gmail.com // (Closing this will make the child's sys_read unblock and return 0.) 2791a5016d36e53e2f1f7bebbcd1a7a8e4d667182d4mark@chromium.org close(signal_fd); 280f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 281f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 282f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 283f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 284f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekbool 285f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::ControlEvent(short revents) 286f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 287f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (POLLHUP & revents) 288f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 289f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek assert(POLLIN & revents); 290f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 291f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek char command; 292f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (read(control_pipe_in_, &command, 1)) 293f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 294f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 295f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek switch (command) { 296f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek case kCommandQuit: 297f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 298f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek default: 299f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek assert(0); 300f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 301f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 302f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 303f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 304f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 305f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekbool 3064e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.comCrashGenerationServer::MakeMinidumpFilename(string& outFilename) 307f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 308f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek GUID guid; 309f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek char guidString[kGUIDStringLength+1]; 310f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 311f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (!(CreateGUID(&guid) 312f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek && GUIDToString(&guid, guidString, sizeof(guidString)))) 313f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 314f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 315f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek char path[PATH_MAX]; 316f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek snprintf(path, sizeof(path), "%s/%s.dmp", dump_dir_.c_str(), guidString); 317f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 318f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek outFilename = path; 319f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 320f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 321f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 322f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// static 323f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekvoid* 324f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::ThreadMain(void *arg) 325f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 326f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek reinterpret_cast<CrashGenerationServer*>(arg)->Run(); 327f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return NULL; 328f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 329f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 330f66ff1afd2e0f7f16ac2f8d40984cf799f3f099bthestig@chromium.org} // namespace google_breakpad 331