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