Home | History | Annotate | Download | only in debuggerd
      1 /*
      2  * Copyright 2016, 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 #include "util.h"
     18 
     19 #include <sys/socket.h>
     20 
     21 #include <utility>
     22 
     23 #include <android-base/unique_fd.h>
     24 #include <cutils/sockets.h>
     25 #include "protocol.h"
     26 
     27 using android::base::unique_fd;
     28 
     29 ssize_t send_fd(int sockfd, const void* data, size_t len, unique_fd fd) {
     30   char cmsg_buf[CMSG_SPACE(sizeof(int))];
     31 
     32   iovec iov = { .iov_base = const_cast<void*>(data), .iov_len = len };
     33   msghdr msg = {
     34     .msg_iov = &iov, .msg_iovlen = 1, .msg_control = cmsg_buf, .msg_controllen = sizeof(cmsg_buf),
     35   };
     36   auto cmsg = CMSG_FIRSTHDR(&msg);
     37   cmsg->cmsg_level = SOL_SOCKET;
     38   cmsg->cmsg_type = SCM_RIGHTS;
     39   cmsg->cmsg_len = CMSG_LEN(sizeof(int));
     40   *reinterpret_cast<int*>(CMSG_DATA(cmsg)) = fd.get();
     41 
     42   return TEMP_FAILURE_RETRY(sendmsg(sockfd, &msg, 0));
     43 }
     44 
     45 ssize_t recv_fd(int sockfd, void* _Nonnull data, size_t len, unique_fd* _Nullable out_fd) {
     46   char cmsg_buf[CMSG_SPACE(sizeof(int))];
     47 
     48   iovec iov = { .iov_base = const_cast<void*>(data), .iov_len = len };
     49   msghdr msg = {
     50     .msg_iov = &iov,
     51     .msg_iovlen = 1,
     52     .msg_control = cmsg_buf,
     53     .msg_controllen = sizeof(cmsg_buf),
     54     .msg_flags = 0,
     55   };
     56   auto cmsg = CMSG_FIRSTHDR(&msg);
     57   cmsg->cmsg_level = SOL_SOCKET;
     58   cmsg->cmsg_type = SCM_RIGHTS;
     59   cmsg->cmsg_len = CMSG_LEN(sizeof(int));
     60 
     61   ssize_t result = TEMP_FAILURE_RETRY(recvmsg(sockfd, &msg, 0));
     62   if (result == -1) {
     63     return -1;
     64   }
     65 
     66   unique_fd fd;
     67   bool received_fd = msg.msg_controllen == sizeof(cmsg_buf);
     68   if (received_fd) {
     69     fd.reset(*reinterpret_cast<int*>(CMSG_DATA(cmsg)));
     70   }
     71 
     72   if ((msg.msg_flags & MSG_TRUNC) != 0) {
     73     errno = EFBIG;
     74     return -1;
     75   } else if ((msg.msg_flags & MSG_CTRUNC) != 0) {
     76     errno = ERANGE;
     77     return -1;
     78   }
     79 
     80   if (out_fd) {
     81     *out_fd = std::move(fd);
     82   } else if (received_fd) {
     83     errno = ERANGE;
     84     return -1;
     85   }
     86 
     87   return result;
     88 }
     89 
     90 bool Pipe(unique_fd* read, unique_fd* write) {
     91   int pipefds[2];
     92   if (pipe(pipefds) != 0) {
     93     return false;
     94   }
     95   read->reset(pipefds[0]);
     96   write->reset(pipefds[1]);
     97   return true;
     98 }
     99