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 specic language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "libappfuse/FuseBuffer.h" 18 19 #include <inttypes.h> 20 #include <string.h> 21 #include <unistd.h> 22 23 #include <algorithm> 24 #include <type_traits> 25 26 #include <sys/socket.h> 27 #include <sys/uio.h> 28 29 #include <android-base/file.h> 30 #include <android-base/logging.h> 31 #include <android-base/macros.h> 32 33 namespace android { 34 namespace fuse { 35 namespace { 36 37 constexpr useconds_t kRetrySleepForWriting = 1000; // 1 ms 38 39 template <typename T> 40 bool CheckHeaderLength(const FuseMessage<T>* self, const char* name, size_t max_size) { 41 const auto& header = static_cast<const T*>(self)->header; 42 if (header.len >= sizeof(header) && header.len <= max_size) { 43 return true; 44 } else { 45 LOG(ERROR) << "Invalid header length is found in " << name << ": " << header.len; 46 return false; 47 } 48 } 49 50 template <typename T> 51 ResultOrAgain ReadInternal(FuseMessage<T>* self, int fd, int sockflag) { 52 char* const buf = reinterpret_cast<char*>(self); 53 const ssize_t result = sockflag ? TEMP_FAILURE_RETRY(recv(fd, buf, sizeof(T), sockflag)) 54 : TEMP_FAILURE_RETRY(read(fd, buf, sizeof(T))); 55 56 switch (result) { 57 case 0: 58 // Expected EOF. 59 return ResultOrAgain::kFailure; 60 case -1: 61 if (errno == EAGAIN) { 62 return ResultOrAgain::kAgain; 63 } 64 PLOG(ERROR) << "Failed to read a FUSE message"; 65 return ResultOrAgain::kFailure; 66 } 67 68 const auto& header = static_cast<const T*>(self)->header; 69 if (result < static_cast<ssize_t>(sizeof(header))) { 70 LOG(ERROR) << "Read bytes " << result << " are shorter than header size " << sizeof(header); 71 return ResultOrAgain::kFailure; 72 } 73 74 if (!CheckHeaderLength<T>(self, "Read", sizeof(T))) { 75 return ResultOrAgain::kFailure; 76 } 77 78 if (static_cast<uint32_t>(result) != header.len) { 79 LOG(ERROR) << "Read bytes " << result << " are different from header.len " << header.len; 80 return ResultOrAgain::kFailure; 81 } 82 83 return ResultOrAgain::kSuccess; 84 } 85 86 template <typename T> 87 ResultOrAgain WriteInternal(const FuseMessage<T>* self, int fd, int sockflag, const void* data, 88 size_t max_size) { 89 if (!CheckHeaderLength<T>(self, "Write", max_size)) { 90 return ResultOrAgain::kFailure; 91 } 92 93 const char* const buf = reinterpret_cast<const char*>(self); 94 const auto& header = static_cast<const T*>(self)->header; 95 96 while (true) { 97 int result; 98 if (sockflag) { 99 CHECK(data == nullptr); 100 result = TEMP_FAILURE_RETRY(send(fd, buf, header.len, sockflag)); 101 } else if (data) { 102 const struct iovec vec[] = {{const_cast<char*>(buf), sizeof(header)}, 103 {const_cast<void*>(data), header.len - sizeof(header)}}; 104 result = TEMP_FAILURE_RETRY(writev(fd, vec, arraysize(vec))); 105 } else { 106 result = TEMP_FAILURE_RETRY(write(fd, buf, header.len)); 107 } 108 if (result == -1) { 109 switch (errno) { 110 case ENOBUFS: 111 // When returning ENOBUFS, epoll still reports the FD is writable. Just usleep 112 // and retry again. 113 usleep(kRetrySleepForWriting); 114 continue; 115 case EAGAIN: 116 return ResultOrAgain::kAgain; 117 default: 118 PLOG(ERROR) << "Failed to write a FUSE message: " 119 << "fd=" << fd << " " 120 << "sockflag=" << sockflag << " " 121 << "data=" << data; 122 return ResultOrAgain::kFailure; 123 } 124 } 125 126 if (static_cast<unsigned int>(result) != header.len) { 127 LOG(ERROR) << "Written bytes " << result << " is different from length in header " 128 << header.len; 129 return ResultOrAgain::kFailure; 130 } 131 return ResultOrAgain::kSuccess; 132 } 133 } 134 } 135 136 static_assert(std::is_standard_layout<FuseBuffer>::value, 137 "FuseBuffer must be standard layout union."); 138 139 bool SetupMessageSockets(base::unique_fd (*result)[2]) { 140 base::unique_fd fds[2]; 141 { 142 int raw_fds[2]; 143 if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, raw_fds) == -1) { 144 PLOG(ERROR) << "Failed to create sockets for proxy"; 145 return false; 146 } 147 fds[0].reset(raw_fds[0]); 148 fds[1].reset(raw_fds[1]); 149 } 150 151 constexpr int kMaxMessageSize = sizeof(FuseBuffer); 152 if (setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, &kMaxMessageSize, sizeof(int)) != 0 || 153 setsockopt(fds[1], SOL_SOCKET, SO_SNDBUF, &kMaxMessageSize, sizeof(int)) != 0) { 154 PLOG(ERROR) << "Failed to update buffer size for socket"; 155 return false; 156 } 157 158 (*result)[0] = std::move(fds[0]); 159 (*result)[1] = std::move(fds[1]); 160 return true; 161 } 162 163 template <typename T> 164 bool FuseMessage<T>::Read(int fd) { 165 return ReadInternal(this, fd, 0) == ResultOrAgain::kSuccess; 166 } 167 168 template <typename T> 169 ResultOrAgain FuseMessage<T>::ReadOrAgain(int fd) { 170 return ReadInternal(this, fd, MSG_DONTWAIT); 171 } 172 173 template <typename T> 174 bool FuseMessage<T>::Write(int fd) const { 175 return WriteInternal(this, fd, 0, nullptr, sizeof(T)) == ResultOrAgain::kSuccess; 176 } 177 178 template <typename T> 179 bool FuseMessage<T>::WriteWithBody(int fd, size_t max_size, const void* data) const { 180 CHECK(data != nullptr); 181 return WriteInternal(this, fd, 0, data, max_size) == ResultOrAgain::kSuccess; 182 } 183 184 template <typename T> 185 ResultOrAgain FuseMessage<T>::WriteOrAgain(int fd) const { 186 return WriteInternal(this, fd, MSG_DONTWAIT, nullptr, sizeof(T)); 187 } 188 189 void FuseRequest::Reset( 190 uint32_t data_length, uint32_t opcode, uint64_t unique) { 191 memset(this, 0, sizeof(fuse_in_header) + data_length); 192 header.len = sizeof(fuse_in_header) + data_length; 193 header.opcode = opcode; 194 header.unique = unique; 195 } 196 197 template <size_t N> 198 void FuseResponseBase<N>::ResetHeader(uint32_t data_length, int32_t error, uint64_t unique) { 199 CHECK_LE(error, 0) << "error should be zero or negative."; 200 header.len = sizeof(fuse_out_header) + data_length; 201 header.error = error; 202 header.unique = unique; 203 } 204 205 template <size_t N> 206 void FuseResponseBase<N>::Reset(uint32_t data_length, int32_t error, uint64_t unique) { 207 memset(this, 0, sizeof(fuse_out_header) + data_length); 208 ResetHeader(data_length, error, unique); 209 } 210 211 void FuseBuffer::HandleInit() { 212 const fuse_init_in* const in = &request.init_in; 213 214 // Before writing |out|, we need to copy data from |in|. 215 const uint64_t unique = request.header.unique; 216 const uint32_t minor = in->minor; 217 const uint32_t max_readahead = in->max_readahead; 218 219 // Kernel 2.6.16 is the first stable kernel with struct fuse_init_out 220 // defined (fuse version 7.6). The structure is the same from 7.6 through 221 // 7.22. Beginning with 7.23, the structure increased in size and added 222 // new parameters. 223 if (in->major != FUSE_KERNEL_VERSION || in->minor < 6) { 224 LOG(ERROR) << "Fuse kernel version mismatch: Kernel version " << in->major 225 << "." << in->minor << " Expected at least " << FUSE_KERNEL_VERSION 226 << ".6"; 227 response.Reset(0, -EPERM, unique); 228 return; 229 } 230 231 // We limit ourselves to minor=15 because we don't handle BATCH_FORGET yet. 232 // Thus we need to use FUSE_COMPAT_22_INIT_OUT_SIZE. 233 #if defined(FUSE_COMPAT_22_INIT_OUT_SIZE) 234 // FUSE_KERNEL_VERSION >= 23. 235 const size_t response_size = FUSE_COMPAT_22_INIT_OUT_SIZE; 236 #else 237 const size_t response_size = sizeof(fuse_init_out); 238 #endif 239 240 response.Reset(response_size, kFuseSuccess, unique); 241 fuse_init_out* const out = &response.init_out; 242 out->major = FUSE_KERNEL_VERSION; 243 out->minor = std::min(minor, 15u); 244 out->max_readahead = max_readahead; 245 out->flags = FUSE_ATOMIC_O_TRUNC | FUSE_BIG_WRITES; 246 out->max_background = 32; 247 out->congestion_threshold = 32; 248 out->max_write = kFuseMaxWrite; 249 } 250 251 void FuseBuffer::HandleNotImpl() { 252 LOG(VERBOSE) << "NOTIMPL op=" << request.header.opcode << " uniq=" 253 << request.header.unique << " nid=" << request.header.nodeid; 254 // Add volatile as a workaround for compiler issue which removes the temporary 255 // variable. 256 const volatile uint64_t unique = request.header.unique; 257 response.Reset(0, -ENOSYS, unique); 258 } 259 260 template class FuseMessage<FuseRequest>; 261 template class FuseMessage<FuseResponse>; 262 template class FuseMessage<FuseSimpleResponse>; 263 template struct FuseResponseBase<0u>; 264 template struct FuseResponseBase<kFuseMaxRead>; 265 266 } // namespace fuse 267 } // namespace android 268