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 #ifndef LIBMEMUNREACHABLE_LEAK_PIPE_H_ 18 #define LIBMEMUNREACHABLE_LEAK_PIPE_H_ 19 20 #include <sys/socket.h> 21 22 #include <vector> 23 24 #include "android-base/macros.h" 25 26 #include "ScopedPipe.h" 27 #include "log.h" 28 29 // LeakPipe implements a pipe that can transfer vectors of simple objects 30 // between processes. The pipe is created in the sending process and 31 // transferred over a socketpair that was created before forking. This ensures 32 // that only the sending process can have the send side of the pipe open, so if 33 // the sending process dies the pipe will close. 34 class LeakPipe { 35 public: LeakPipe()36 LeakPipe() { 37 int ret = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sv_); 38 if (ret < 0) { 39 LOG_ALWAYS_FATAL("failed to create socketpair: %s", strerror(errno)); 40 } 41 } 42 ~LeakPipe()43 ~LeakPipe() { 44 Close(); 45 } 46 Close()47 void Close() { 48 close(sv_[0]); 49 close(sv_[1]); 50 sv_[0] = -1; 51 sv_[1] = -1; 52 } 53 OpenReceiver()54 bool OpenReceiver() { 55 int fd = ReceiveFd(sv_[0]); 56 if (fd < 0) { 57 return false; 58 } 59 60 receiver_.SetFd(fd); 61 return true; 62 } 63 OpenSender()64 bool OpenSender() { 65 ScopedPipe pipe; 66 67 if (!SendFd(sv_[1], pipe.Receiver())) { 68 return false; 69 } 70 pipe.ReleaseReceiver(); 71 72 sender_.SetFd(pipe.ReleaseSender()); 73 return true; 74 } 75 76 class LeakPipeBase { 77 public: LeakPipeBase()78 LeakPipeBase() : fd_(-1) {} 79 ~LeakPipeBase()80 ~LeakPipeBase() { 81 Close(); 82 } 83 SetFd(int fd)84 void SetFd(int fd) { 85 fd_ = fd; 86 } 87 Close()88 void Close() { 89 close(fd_); 90 fd_ = -1; 91 } 92 93 protected: 94 int fd_; 95 96 private: 97 DISALLOW_COPY_AND_ASSIGN(LeakPipeBase); 98 }; 99 100 class LeakPipeSender : public LeakPipeBase { 101 public: 102 using LeakPipeBase::LeakPipeBase; 103 104 template<typename T> Send(const T & value)105 bool Send(const T& value) { 106 ssize_t ret = TEMP_FAILURE_RETRY(write(fd_, &value, sizeof(T))); 107 if (ret < 0) { 108 ALOGE("failed to send value: %s", strerror(errno)); 109 return false; 110 } else if (static_cast<size_t>(ret) != sizeof(T)) { 111 ALOGE("eof while writing value"); 112 return false; 113 } 114 115 return true; 116 } 117 118 template<class T, class Alloc = std::allocator<T>> SendVector(const std::vector<T,Alloc> & vector)119 bool SendVector(const std::vector<T, Alloc>& vector) { 120 size_t size = vector.size() * sizeof(T); 121 if (!Send(size)) { 122 return false; 123 } 124 125 ssize_t ret = TEMP_FAILURE_RETRY(write(fd_, vector.data(), size)); 126 if (ret < 0) { 127 ALOGE("failed to send vector: %s", strerror(errno)); 128 return false; 129 } else if (static_cast<size_t>(ret) != size) { 130 ALOGE("eof while writing vector"); 131 return false; 132 } 133 134 return true; 135 } 136 }; 137 138 class LeakPipeReceiver : public LeakPipeBase { 139 public: 140 using LeakPipeBase::LeakPipeBase; 141 142 template<typename T> Receive(T * value)143 bool Receive(T* value) { 144 ssize_t ret = TEMP_FAILURE_RETRY(read(fd_, reinterpret_cast<void*>(value), sizeof(T))); 145 if (ret < 0) { 146 ALOGE("failed to receive value: %s", strerror(errno)); 147 return false; 148 } else if (static_cast<size_t>(ret) != sizeof(T)) { 149 ALOGE("eof while receiving value"); 150 return false; 151 } 152 153 return true; 154 } 155 156 template<class T, class Alloc = std::allocator<T>> ReceiveVector(std::vector<T,Alloc> & vector)157 bool ReceiveVector(std::vector<T, Alloc>& vector) { 158 size_t size = 0; 159 if (!Receive(&size)) { 160 return false; 161 } 162 163 vector.resize(size / sizeof(T)); 164 165 char* ptr = reinterpret_cast<char*>(vector.data()); 166 while (size > 0) { 167 ssize_t ret = TEMP_FAILURE_RETRY(read(fd_, ptr, size)); 168 if (ret < 0) { 169 ALOGE("failed to send vector: %s", strerror(errno)); 170 return false; 171 } else if (ret == 0) { 172 ALOGE("eof while reading vector"); 173 return false; 174 } 175 size -= ret; 176 ptr += ret; 177 } 178 179 return true; 180 } 181 182 }; 183 Receiver()184 LeakPipeReceiver& Receiver() { 185 return receiver_; 186 } 187 Sender()188 LeakPipeSender& Sender() { 189 return sender_; 190 } 191 192 private: 193 LeakPipeReceiver receiver_; 194 LeakPipeSender sender_; 195 bool SendFd(int sock, int fd); 196 int ReceiveFd(int sock); 197 DISALLOW_COPY_AND_ASSIGN(LeakPipe); 198 int sv_[2]; 199 }; 200 201 #endif // LIBMEMUNREACHABLE_LEAK_PIPE_H_ 202