Home | History | Annotate | Download | only in libmemunreachable
      1 /*
      2  * Copyright (C) 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 <errno.h>
     18 #include <string.h>
     19 
     20 #include "LeakPipe.h"
     21 
     22 #include "log.h"
     23 
     24 namespace android {
     25 
     26 bool LeakPipe::SendFd(int sock, int fd) {
     27   struct msghdr hdr {};
     28   struct iovec iov {};
     29   unsigned int data = 0xfdfdfdfd;
     30   alignas(struct cmsghdr) char cmsgbuf[CMSG_SPACE(sizeof(int))];
     31 
     32   hdr.msg_iov = &iov;
     33   hdr.msg_iovlen = 1;
     34   iov.iov_base = &data;
     35   iov.iov_len = sizeof(data);
     36 
     37   hdr.msg_control = cmsgbuf;
     38   hdr.msg_controllen = CMSG_LEN(sizeof(int));
     39 
     40   struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr);
     41   cmsg->cmsg_len = CMSG_LEN(sizeof(int));
     42   cmsg->cmsg_level = SOL_SOCKET;
     43   cmsg->cmsg_type = SCM_RIGHTS;
     44 
     45   *(int*)CMSG_DATA(cmsg) = fd;
     46 
     47   int ret = sendmsg(sock, &hdr, 0);
     48   if (ret < 0) {
     49     MEM_ALOGE("failed to send fd: %s", strerror(errno));
     50     return false;
     51   }
     52   if (ret == 0) {
     53     MEM_ALOGE("eof when sending fd");
     54     return false;
     55   }
     56 
     57   return true;
     58 }
     59 
     60 int LeakPipe::ReceiveFd(int sock) {
     61   struct msghdr hdr {};
     62   struct iovec iov {};
     63   unsigned int data;
     64   alignas(struct cmsghdr) char cmsgbuf[CMSG_SPACE(sizeof(int))];
     65 
     66   hdr.msg_iov = &iov;
     67   hdr.msg_iovlen = 1;
     68   iov.iov_base = &data;
     69   iov.iov_len = sizeof(data);
     70 
     71   hdr.msg_control = cmsgbuf;
     72   hdr.msg_controllen = CMSG_LEN(sizeof(int));
     73 
     74   int ret = recvmsg(sock, &hdr, 0);
     75   if (ret < 0) {
     76     MEM_ALOGE("failed to receive fd: %s", strerror(errno));
     77     return -1;
     78   }
     79   if (ret == 0) {
     80     MEM_ALOGE("eof when receiving fd");
     81     return -1;
     82   }
     83 
     84   struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr);
     85   if (cmsg == NULL || cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
     86     MEM_ALOGE("missing fd while receiving fd");
     87     return -1;
     88   }
     89 
     90   return *(int*)CMSG_DATA(cmsg);
     91 }
     92 
     93 }  // namespace android
     94