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
303daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org#include "client/linux/crash_generation/crash_generation_client.h"
313daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org
32de545c09d0363e6964822ec92529a80feaca152dnealsid#include <stdio.h>
33f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <sys/socket.h>
34f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <sys/types.h>
35f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek
36f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <algorithm>
37f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek
38f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include "common/linux/eintr_wrapper.h"
394021866432da1659f6fdd9c4a1fa33aab92a400cthestig@chromium.org#include "common/linux/ignore_ret.h"
400e3b7020b8f679259acfcfdbea4d39e1c13e6f19thestig@chromium.org#include "third_party/lss/linux_syscall_support.h"
41f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek
42f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczareknamespace google_breakpad {
43f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek
443daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.orgnamespace {
453daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org
463daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.orgclass CrashGenerationClientImpl : public CrashGenerationClient {
473daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org public:
483daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org  explicit CrashGenerationClientImpl(int server_fd) : server_fd_(server_fd) {}
493daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org  virtual ~CrashGenerationClientImpl() {}
503daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org
513daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org  virtual bool RequestDump(const void* blob, size_t blob_size) {
523daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    int fds[2];
532290db8d52d3d4692d25d4918abc31880f1eb31fted.mielczarek@gmail.com    if (sys_pipe(fds) < 0)
543daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org      return false;
553daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    static const unsigned kControlMsgSize = CMSG_SPACE(sizeof(int));
563daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org
573daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    struct kernel_iovec iov;
583daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    iov.iov_base = const_cast<void*>(blob);
593daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    iov.iov_len = blob_size;
603daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org
613daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    struct kernel_msghdr msg = { 0 };
623daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    msg.msg_iov = &iov;
633daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    msg.msg_iovlen = 1;
643daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    char cmsg[kControlMsgSize] = "";
653daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    msg.msg_control = cmsg;
663daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    msg.msg_controllen = sizeof(cmsg);
67f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek
683daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    struct cmsghdr* hdr = CMSG_FIRSTHDR(&msg);
693daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    hdr->cmsg_level = SOL_SOCKET;
703daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    hdr->cmsg_type = SCM_RIGHTS;
713daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    hdr->cmsg_len = CMSG_LEN(sizeof(int));
723daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    int* p = reinterpret_cast<int*>(CMSG_DATA(hdr));
733daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    *p = fds[1];
743daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org
753daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    ssize_t ret = HANDLE_EINTR(sys_sendmsg(server_fd_, &msg, 0));
763daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    sys_close(fds[1]);
775d02db696277270a9515010b06589d8cb6e41db7rsesek@chromium.org    if (ret < 0) {
785d02db696277270a9515010b06589d8cb6e41db7rsesek@chromium.org      sys_close(fds[0]);
793daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org      return false;
805d02db696277270a9515010b06589d8cb6e41db7rsesek@chromium.org    }
813daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org
823daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    // Wait for an ACK from the server.
833daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    char b;
843daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    IGNORE_RET(HANDLE_EINTR(sys_read(fds[0], &b, 1)));
853daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    sys_close(fds[0]);
863daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org
873daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org    return true;
883daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org  }
893daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org
903daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org private:
913daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org  int server_fd_;
923daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org
933daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org  DISALLOW_COPY_AND_ASSIGN(CrashGenerationClientImpl);
943daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org};
953daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org
963daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org}  // namespace
973daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org
983daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org// static
993daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.orgCrashGenerationClient* CrashGenerationClient::TryCreate(int server_fd) {
1003daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org  if (server_fd < 0)
101f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek    return NULL;
1023daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org  return new CrashGenerationClientImpl(server_fd);
103f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek}
104f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek
1053daf3e4247a62dccea7187e94ae06f3ec578f619rsesek@chromium.org}  // namespace google_breakpad
106