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 namespace android { 30 31 // LeakPipe implements a pipe that can transfer vectors of simple objects 32 // between processes. The pipe is created in the sending process and 33 // transferred over a socketpair that was created before forking. This ensures 34 // that only the sending process can have the send side of the pipe open, so if 35 // the sending process dies the pipe will close. 36 class LeakPipe { 37 public: LeakPipe()38 LeakPipe() { 39 int ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv_); 40 if (ret < 0) { 41 MEM_LOG_ALWAYS_FATAL("failed to create socketpair: %s", strerror(errno)); 42 } 43 } 44 ~LeakPipe()45 ~LeakPipe() { Close(); } 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() { Close(); } 81 SetFd(int fd)82 void SetFd(int fd) { fd_ = fd; } 83 Close()84 void Close() { 85 close(fd_); 86 fd_ = -1; 87 } 88 89 protected: 90 int fd_; 91 92 private: 93 DISALLOW_COPY_AND_ASSIGN(LeakPipeBase); 94 }; 95 96 class LeakPipeSender : public LeakPipeBase { 97 public: 98 using LeakPipeBase::LeakPipeBase; 99 100 template <typename T> Send(const T & value)101 bool Send(const T& value) { 102 ssize_t ret = TEMP_FAILURE_RETRY(write(fd_, &value, sizeof(T))); 103 if (ret < 0) { 104 MEM_ALOGE("failed to send value: %s", strerror(errno)); 105 return false; 106 } else if (static_cast<size_t>(ret) != sizeof(T)) { 107 MEM_ALOGE("eof while writing value"); 108 return false; 109 } 110 111 return true; 112 } 113 114 template <class T, class Alloc = std::allocator<T>> SendVector(const std::vector<T,Alloc> & vector)115 bool SendVector(const std::vector<T, Alloc>& vector) { 116 size_t size = vector.size() * sizeof(T); 117 if (!Send(size)) { 118 return false; 119 } 120 121 ssize_t ret = TEMP_FAILURE_RETRY(write(fd_, vector.data(), size)); 122 if (ret < 0) { 123 MEM_ALOGE("failed to send vector: %s", strerror(errno)); 124 return false; 125 } else if (static_cast<size_t>(ret) != size) { 126 MEM_ALOGE("eof while writing vector"); 127 return false; 128 } 129 130 return true; 131 } 132 }; 133 134 class LeakPipeReceiver : public LeakPipeBase { 135 public: 136 using LeakPipeBase::LeakPipeBase; 137 138 template <typename T> Receive(T * value)139 bool Receive(T* value) { 140 ssize_t ret = TEMP_FAILURE_RETRY(read(fd_, reinterpret_cast<void*>(value), sizeof(T))); 141 if (ret < 0) { 142 MEM_ALOGE("failed to receive value: %s", strerror(errno)); 143 return false; 144 } else if (static_cast<size_t>(ret) != sizeof(T)) { 145 MEM_ALOGE("eof while receiving value"); 146 return false; 147 } 148 149 return true; 150 } 151 152 template <class T, class Alloc = std::allocator<T>> ReceiveVector(std::vector<T,Alloc> & vector)153 bool ReceiveVector(std::vector<T, Alloc>& vector) { 154 size_t size = 0; 155 if (!Receive(&size)) { 156 return false; 157 } 158 159 vector.resize(size / sizeof(T)); 160 161 char* ptr = reinterpret_cast<char*>(vector.data()); 162 while (size > 0) { 163 ssize_t ret = TEMP_FAILURE_RETRY(read(fd_, ptr, size)); 164 if (ret < 0) { 165 MEM_ALOGE("failed to send vector: %s", strerror(errno)); 166 return false; 167 } else if (ret == 0) { 168 MEM_ALOGE("eof while reading vector"); 169 return false; 170 } 171 size -= ret; 172 ptr += ret; 173 } 174 175 return true; 176 } 177 }; 178 Receiver()179 LeakPipeReceiver& Receiver() { return receiver_; } 180 Sender()181 LeakPipeSender& Sender() { return sender_; } 182 183 private: 184 LeakPipeReceiver receiver_; 185 LeakPipeSender sender_; 186 bool SendFd(int sock, int fd); 187 int ReceiveFd(int sock); 188 DISALLOW_COPY_AND_ASSIGN(LeakPipe); 189 int sv_[2]; 190 }; 191 192 } // namespace android 193 194 #endif // LIBMEMUNREACHABLE_LEAK_PIPE_H_ 195