Home | History | Annotate | Download | only in libappfuse
      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