1cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao/*
2cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * Copyright 2016, The Android Open Source Project
3cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao *
4cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * Licensed under the Apache License, Version 2.0 (the "License");
5cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * you may not use this file except in compliance with the License.
6cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * You may obtain a copy of the License at
7cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao *
8cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao *     http://www.apache.org/licenses/LICENSE-2.0
9cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao *
10cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * Unless required by applicable law or agreed to in writing, software
11cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * distributed under the License is distributed on an "AS IS" BASIS,
12cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * See the License for the specific language governing permissions and
14cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * limitations under the License.
15cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao */
16cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao
17cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include "debuggerd/util.h"
18cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao
19cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <sys/socket.h>
20cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao
21cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <utility>
22cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao
23cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <android-base/unique_fd.h>
24cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <cutils/sockets.h>
25e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao#include <debuggerd/protocol.h>
26cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao
27e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao#include "private/libc_logging.h"
28e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao
29e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gaousing android::base::unique_fd;
30e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao
31e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gaossize_t send_fd(int sockfd, const void* data, size_t len, unique_fd fd) {
32cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  char cmsg_buf[CMSG_SPACE(sizeof(int))];
33cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao
34cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  iovec iov = { .iov_base = const_cast<void*>(data), .iov_len = len };
35cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  msghdr msg = {
36cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao    .msg_iov = &iov, .msg_iovlen = 1, .msg_control = cmsg_buf, .msg_controllen = sizeof(cmsg_buf),
37cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  };
38cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  auto cmsg = CMSG_FIRSTHDR(&msg);
39cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  cmsg->cmsg_level = SOL_SOCKET;
40cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  cmsg->cmsg_type = SCM_RIGHTS;
41cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  cmsg->cmsg_len = CMSG_LEN(sizeof(int));
42cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  *reinterpret_cast<int*>(CMSG_DATA(cmsg)) = fd.get();
43cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao
44cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  return TEMP_FAILURE_RETRY(sendmsg(sockfd, &msg, 0));
45cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao}
46cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao
47e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gaossize_t recv_fd(int sockfd, void* _Nonnull data, size_t len, unique_fd* _Nullable out_fd) {
48cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  char cmsg_buf[CMSG_SPACE(sizeof(int))];
49cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao
50cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  iovec iov = { .iov_base = const_cast<void*>(data), .iov_len = len };
51cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  msghdr msg = {
52cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao    .msg_iov = &iov,
53cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao    .msg_iovlen = 1,
54cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao    .msg_control = cmsg_buf,
55cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao    .msg_controllen = sizeof(cmsg_buf),
56cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao    .msg_flags = 0,
57cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  };
58cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  auto cmsg = CMSG_FIRSTHDR(&msg);
59cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  cmsg->cmsg_level = SOL_SOCKET;
60cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  cmsg->cmsg_type = SCM_RIGHTS;
61cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  cmsg->cmsg_len = CMSG_LEN(sizeof(int));
62cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao
63cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  ssize_t result = TEMP_FAILURE_RETRY(recvmsg(sockfd, &msg, 0));
64cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  if (result == -1) {
65cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao    return -1;
66cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  }
67cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao
68e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gao  unique_fd fd;
69cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  bool received_fd = msg.msg_controllen == sizeof(cmsg_buf);
70cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  if (received_fd) {
71cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao    fd.reset(*reinterpret_cast<int*>(CMSG_DATA(cmsg)));
72cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  }
73cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao
74cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  if ((msg.msg_flags & MSG_TRUNC) != 0) {
75cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao    errno = EFBIG;
76cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao    return -1;
77cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  } else if ((msg.msg_flags & MSG_CTRUNC) != 0) {
78cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao    errno = ERANGE;
79cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao    return -1;
80cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  }
81cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao
82cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  if (out_fd) {
83cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao    *out_fd = std::move(fd);
84cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  } else if (received_fd) {
85cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao    errno = ERANGE;
86cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao    return -1;
87cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  }
88cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao
89cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  return result;
90cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao}
91cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao
92e1aa0ca58a2a356039047ffcc8a98d85d1bce8edJosh Gaobool Pipe(unique_fd* read, unique_fd* write) {
93cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  int pipefds[2];
94cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  if (pipe(pipefds) != 0) {
95cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao    return false;
96cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  }
97cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  read->reset(pipefds[0]);
98cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  write->reset(pipefds[1]);
99cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao  return true;
100cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao}
101