• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/FuseBridgeLoop.h"
18 
19 #include <sys/epoll.h>
20 #include <sys/socket.h>
21 
22 #include <unordered_map>
23 
24 #include <android-base/logging.h>
25 #include <android-base/unique_fd.h>
26 
27 #include "libappfuse/EpollController.h"
28 
29 namespace android {
30 namespace fuse {
31 namespace {
32 
33 enum class FuseBridgeState { kWaitToReadEither, kWaitToReadProxy, kWaitToWriteProxy, kClosing };
34 
35 struct FuseBridgeEntryEvent {
36     FuseBridgeEntry* entry;
37     int events;
38 };
39 
GetObservedEvents(FuseBridgeState state,int * device_events,int * proxy_events)40 void GetObservedEvents(FuseBridgeState state, int* device_events, int* proxy_events) {
41     switch (state) {
42         case FuseBridgeState::kWaitToReadEither:
43             *device_events = EPOLLIN;
44             *proxy_events = EPOLLIN;
45             return;
46         case FuseBridgeState::kWaitToReadProxy:
47             *device_events = 0;
48             *proxy_events = EPOLLIN;
49             return;
50         case FuseBridgeState::kWaitToWriteProxy:
51             *device_events = 0;
52             *proxy_events = EPOLLOUT;
53             return;
54         case FuseBridgeState::kClosing:
55             *device_events = 0;
56             *proxy_events = 0;
57             return;
58     }
59 }
60 
LogResponseError(const std::string & message,const FuseResponse & response)61 void LogResponseError(const std::string& message, const FuseResponse& response) {
62     LOG(ERROR) << message << ": header.len=" << response.header.len
63                << " header.error=" << response.header.error
64                << " header.unique=" << response.header.unique;
65 }
66 }
67 
68 class FuseBridgeEntry {
69   public:
FuseBridgeEntry(int mount_id,base::unique_fd && dev_fd,base::unique_fd && proxy_fd)70     FuseBridgeEntry(int mount_id, base::unique_fd&& dev_fd, base::unique_fd&& proxy_fd)
71         : mount_id_(mount_id),
72           device_fd_(std::move(dev_fd)),
73           proxy_fd_(std::move(proxy_fd)),
74           state_(FuseBridgeState::kWaitToReadEither),
75           last_state_(FuseBridgeState::kWaitToReadEither),
76           last_device_events_({this, 0}),
77           last_proxy_events_({this, 0}),
78           open_count_(0) {}
79 
80     // Transfer bytes depends on availability of FDs and the internal |state_|.
Transfer(FuseBridgeLoopCallback * callback)81     void Transfer(FuseBridgeLoopCallback* callback) {
82         constexpr int kUnexpectedEventMask = ~(EPOLLIN | EPOLLOUT);
83         const bool unexpected_event = (last_device_events_.events & kUnexpectedEventMask) ||
84                                       (last_proxy_events_.events & kUnexpectedEventMask);
85         const bool device_read_ready = last_device_events_.events & EPOLLIN;
86         const bool proxy_read_ready = last_proxy_events_.events & EPOLLIN;
87         const bool proxy_write_ready = last_proxy_events_.events & EPOLLOUT;
88 
89         last_state_ = state_;
90         last_device_events_.events = 0;
91         last_proxy_events_.events = 0;
92 
93         LOG(VERBOSE) << "Transfer device_read_ready=" << device_read_ready
94                      << " proxy_read_ready=" << proxy_read_ready
95                      << " proxy_write_ready=" << proxy_write_ready;
96 
97         if (unexpected_event) {
98             LOG(ERROR) << "Invalid epoll event is observed";
99             state_ = FuseBridgeState::kClosing;
100             return;
101         }
102 
103         switch (state_) {
104             case FuseBridgeState::kWaitToReadEither:
105                 if (proxy_read_ready) {
106                     state_ = ReadFromProxy();
107                 } else if (device_read_ready) {
108                     state_ = ReadFromDevice(callback);
109                 }
110                 return;
111 
112             case FuseBridgeState::kWaitToReadProxy:
113                 CHECK(proxy_read_ready);
114                 state_ = ReadFromProxy();
115                 return;
116 
117             case FuseBridgeState::kWaitToWriteProxy:
118                 CHECK(proxy_write_ready);
119                 state_ = WriteToProxy();
120                 return;
121 
122             case FuseBridgeState::kClosing:
123                 return;
124         }
125     }
126 
IsClosing() const127     bool IsClosing() const { return state_ == FuseBridgeState::kClosing; }
128 
mount_id() const129     int mount_id() const { return mount_id_; }
130 
131   private:
132     friend class BridgeEpollController;
133 
ReadFromProxy()134     FuseBridgeState ReadFromProxy() {
135         switch (buffer_.response.ReadOrAgain(proxy_fd_)) {
136             case ResultOrAgain::kSuccess:
137                 break;
138             case ResultOrAgain::kFailure:
139                 return FuseBridgeState::kClosing;
140             case ResultOrAgain::kAgain:
141                 return FuseBridgeState::kWaitToReadProxy;
142         }
143 
144         if (!buffer_.response.Write(device_fd_)) {
145             LogResponseError("Failed to write a reply from proxy to device", buffer_.response);
146             return FuseBridgeState::kClosing;
147         }
148 
149         auto it = opcode_map_.find(buffer_.response.header.unique);
150         if (it != opcode_map_.end()) {
151             switch (it->second) {
152                 case FUSE_OPEN:
153                     if (buffer_.response.header.error == fuse::kFuseSuccess) {
154                         open_count_++;
155                     }
156                     break;
157 
158                 case FUSE_RELEASE:
159                     if (open_count_ > 0) {
160                         open_count_--;
161                     } else {
162                         LOG(WARNING) << "Unexpected FUSE_RELEASE before opening a file.";
163                         break;
164                     }
165                     if (open_count_ == 0) {
166                         return FuseBridgeState::kClosing;
167                     }
168                     break;
169             }
170             opcode_map_.erase(it);
171         }
172 
173         return FuseBridgeState::kWaitToReadEither;
174     }
175 
ReadFromDevice(FuseBridgeLoopCallback * callback)176     FuseBridgeState ReadFromDevice(FuseBridgeLoopCallback* callback) {
177         LOG(VERBOSE) << "ReadFromDevice";
178         if (!buffer_.request.Read(device_fd_)) {
179             return FuseBridgeState::kClosing;
180         }
181 
182         const uint32_t opcode = buffer_.request.header.opcode;
183         const uint64_t unique = buffer_.request.header.unique;
184         LOG(VERBOSE) << "Read a fuse packet, opcode=" << opcode << " unique=" << unique;
185         if (unique == 0) {
186             return FuseBridgeState::kWaitToReadEither;
187         }
188         switch (opcode) {
189             case FUSE_FORGET:
190                 // Do not reply to FUSE_FORGET.
191                 return FuseBridgeState::kWaitToReadEither;
192 
193             case FUSE_LOOKUP:
194             case FUSE_GETATTR:
195             case FUSE_OPEN:
196             case FUSE_READ:
197             case FUSE_WRITE:
198             case FUSE_RELEASE:
199             case FUSE_FSYNC:
200                 if (opcode == FUSE_OPEN || opcode == FUSE_RELEASE) {
201                     opcode_map_.emplace(buffer_.request.header.unique, opcode);
202                 }
203                 return WriteToProxy();
204 
205             case FUSE_INIT:
206                 buffer_.HandleInit();
207                 break;
208 
209             default:
210                 buffer_.HandleNotImpl();
211                 break;
212         }
213 
214         if (!buffer_.response.Write(device_fd_)) {
215             LogResponseError("Failed to write a response to device", buffer_.response);
216             return FuseBridgeState::kClosing;
217         }
218 
219         if (opcode == FUSE_INIT) {
220             callback->OnMount(mount_id_);
221         }
222 
223         return FuseBridgeState::kWaitToReadEither;
224     }
225 
WriteToProxy()226     FuseBridgeState WriteToProxy() {
227         switch (buffer_.request.WriteOrAgain(proxy_fd_)) {
228             case ResultOrAgain::kSuccess:
229                 return FuseBridgeState::kWaitToReadEither;
230             case ResultOrAgain::kFailure:
231                 LOG(ERROR) << "Failed to write a request to proxy:"
232                            << " header.len=" << buffer_.request.header.len
233                            << " header.opcode=" << buffer_.request.header.opcode
234                            << " header.unique=" << buffer_.request.header.unique
235                            << " header.nodeid=" << buffer_.request.header.nodeid;
236                 return FuseBridgeState::kClosing;
237             case ResultOrAgain::kAgain:
238                 return FuseBridgeState::kWaitToWriteProxy;
239         }
240     }
241 
242     const int mount_id_;
243     base::unique_fd device_fd_;
244     base::unique_fd proxy_fd_;
245     FuseBuffer buffer_;
246     FuseBridgeState state_;
247     FuseBridgeState last_state_;
248     FuseBridgeEntryEvent last_device_events_;
249     FuseBridgeEntryEvent last_proxy_events_;
250 
251     // Remember map between unique and opcode in fuse_in_header so that we can
252     // refer the opcode later.
253     std::unordered_map<uint64_t, uint32_t> opcode_map_;
254 
255     int open_count_;
256 
257     DISALLOW_COPY_AND_ASSIGN(FuseBridgeEntry);
258 };
259 
260 class BridgeEpollController : private EpollController {
261   public:
BridgeEpollController(base::unique_fd && poll_fd)262     BridgeEpollController(base::unique_fd&& poll_fd) : EpollController(std::move(poll_fd)) {}
263 
AddBridgePoll(FuseBridgeEntry * bridge) const264     bool AddBridgePoll(FuseBridgeEntry* bridge) const {
265         return InvokeControl(EPOLL_CTL_ADD, bridge);
266     }
267 
UpdateOrDeleteBridgePoll(FuseBridgeEntry * bridge) const268     bool UpdateOrDeleteBridgePoll(FuseBridgeEntry* bridge) const {
269         return InvokeControl(
270             bridge->state_ != FuseBridgeState::kClosing ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, bridge);
271     }
272 
Wait(size_t bridge_count,std::unordered_set<FuseBridgeEntry * > * entries_out)273     bool Wait(size_t bridge_count, std::unordered_set<FuseBridgeEntry*>* entries_out) {
274         CHECK(entries_out);
275         const size_t event_count = std::max<size_t>(bridge_count * 2, 1);
276         if (!EpollController::Wait(event_count)) {
277             return false;
278         }
279         entries_out->clear();
280         for (const auto& event : events()) {
281             FuseBridgeEntryEvent* const entry_event =
282                 reinterpret_cast<FuseBridgeEntryEvent*>(event.data.ptr);
283             entry_event->events = event.events;
284             entries_out->insert(entry_event->entry);
285         }
286         return true;
287     }
288 
289   private:
InvokeControl(int op,FuseBridgeEntry * bridge) const290     bool InvokeControl(int op, FuseBridgeEntry* bridge) const {
291         LOG(VERBOSE) << "InvokeControl op=" << op << " bridge=" << bridge->mount_id_
292                      << " state=" << static_cast<int>(bridge->state_)
293                      << " last_state=" << static_cast<int>(bridge->last_state_);
294 
295         int last_device_events;
296         int last_proxy_events;
297         int device_events;
298         int proxy_events;
299         GetObservedEvents(bridge->last_state_, &last_device_events, &last_proxy_events);
300         GetObservedEvents(bridge->state_, &device_events, &proxy_events);
301         bool result = true;
302         if (op != EPOLL_CTL_MOD || last_device_events != device_events) {
303             result &= EpollController::InvokeControl(op, bridge->device_fd_, device_events,
304                                                      &bridge->last_device_events_);
305         }
306         if (op != EPOLL_CTL_MOD || last_proxy_events != proxy_events) {
307             result &= EpollController::InvokeControl(op, bridge->proxy_fd_, proxy_events,
308                                                      &bridge->last_proxy_events_);
309         }
310         return result;
311     }
312 };
313 
FuseBridgeLoop()314 FuseBridgeLoop::FuseBridgeLoop() : opened_(true) {
315     base::unique_fd epoll_fd(epoll_create1(EPOLL_CLOEXEC));
316     if (epoll_fd.get() == -1) {
317         PLOG(ERROR) << "Failed to open FD for epoll";
318         opened_ = false;
319         return;
320     }
321     epoll_controller_.reset(new BridgeEpollController(std::move(epoll_fd)));
322 }
323 
~FuseBridgeLoop()324 FuseBridgeLoop::~FuseBridgeLoop() { CHECK(bridges_.empty()); }
325 
AddBridge(int mount_id,base::unique_fd dev_fd,base::unique_fd proxy_fd)326 bool FuseBridgeLoop::AddBridge(int mount_id, base::unique_fd dev_fd, base::unique_fd proxy_fd) {
327     LOG(VERBOSE) << "Adding bridge " << mount_id;
328 
329     std::unique_ptr<FuseBridgeEntry> bridge(
330         new FuseBridgeEntry(mount_id, std::move(dev_fd), std::move(proxy_fd)));
331     std::lock_guard<std::mutex> lock(mutex_);
332     if (!opened_) {
333         LOG(ERROR) << "Tried to add a mount to a closed bridge";
334         return false;
335     }
336     if (bridges_.count(mount_id)) {
337         LOG(ERROR) << "Tried to add a mount point that has already been added";
338         return false;
339     }
340     if (!epoll_controller_->AddBridgePoll(bridge.get())) {
341         return false;
342     }
343 
344     bridges_.emplace(mount_id, std::move(bridge));
345     return true;
346 }
347 
ProcessEventLocked(const std::unordered_set<FuseBridgeEntry * > & entries,FuseBridgeLoopCallback * callback)348 bool FuseBridgeLoop::ProcessEventLocked(const std::unordered_set<FuseBridgeEntry*>& entries,
349                                         FuseBridgeLoopCallback* callback) {
350     for (auto entry : entries) {
351         entry->Transfer(callback);
352         if (!epoll_controller_->UpdateOrDeleteBridgePoll(entry)) {
353             return false;
354         }
355         if (entry->IsClosing()) {
356             const int mount_id = entry->mount_id();
357             bridges_.erase(mount_id);
358             callback->OnClosed(mount_id);
359             if (bridges_.size() == 0) {
360                 // All bridges are now closed.
361                 return false;
362             }
363         }
364     }
365     return true;
366 }
367 
Start(FuseBridgeLoopCallback * callback)368 void FuseBridgeLoop::Start(FuseBridgeLoopCallback* callback) {
369     LOG(DEBUG) << "Start fuse bridge loop";
370     std::unordered_set<FuseBridgeEntry*> entries;
371     while (true) {
372         const bool wait_result = epoll_controller_->Wait(bridges_.size(), &entries);
373         LOG(VERBOSE) << "Receive epoll events";
374         {
375             std::lock_guard<std::mutex> lock(mutex_);
376             if (!(wait_result && ProcessEventLocked(entries, callback))) {
377                 for (auto it = bridges_.begin(); it != bridges_.end();) {
378                     callback->OnClosed(it->second->mount_id());
379                     it = bridges_.erase(it);
380                 }
381                 opened_ = false;
382                 return;
383             }
384         }
385     }
386 }
387 
388 }  // namespace fuse
389 }  // namespace android
390