xref: /aosp_15_r20/system/core/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp (revision 00c7fec1bb09f3284aad6a6f96d2f63dfc3650ad)
1 /*
2  * Copyright (C) 2020 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 #include <arpa/inet.h>
18 #include <cutils/sockets.h>
19 #include <errno.h>
20 #include <netinet/in.h>
21 #include <stdint.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <sys/socket.h>
25 #include <sys/system_properties.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 
29 #include <android-base/cmsg.h>
30 #include <android-base/logging.h>
31 #include <android-base/properties.h>
32 #include <android-base/scopeguard.h>
33 #include <android-base/strings.h>
34 #include <fs_mgr/file_wait.h>
35 #include <snapuserd/dm_user_block_server.h>
36 #include <snapuserd/snapuserd_client.h>
37 #include "snapuserd_server.h"
38 #include "user-space-merge/snapuserd_core.h"
39 
40 namespace android {
41 namespace snapshot {
42 
43 using namespace std::string_literals;
44 
45 using android::base::borrowed_fd;
46 using android::base::unique_fd;
47 
UserSnapshotServer()48 UserSnapshotServer::UserSnapshotServer() {
49     terminating_ = false;
50     handlers_ = std::make_unique<SnapshotHandlerManager>();
51     block_server_factory_ = std::make_unique<DmUserBlockServerFactory>();
52 }
53 
~UserSnapshotServer()54 UserSnapshotServer::~UserSnapshotServer() {
55     // Close any client sockets that were added via AcceptClient().
56     for (size_t i = 1; i < watched_fds_.size(); i++) {
57         close(watched_fds_[i].fd);
58     }
59 }
60 
GetDaemonStatus()61 std::string UserSnapshotServer::GetDaemonStatus() {
62     std::string msg = "";
63 
64     if (IsTerminating())
65         msg = "passive";
66     else
67         msg = "active";
68 
69     return msg;
70 }
71 
Parsemsg(std::string const & msg,const char delim,std::vector<std::string> & out)72 void UserSnapshotServer::Parsemsg(std::string const& msg, const char delim,
73                                   std::vector<std::string>& out) {
74     std::stringstream ss(msg);
75     std::string s;
76 
77     while (std::getline(ss, s, delim)) {
78         out.push_back(s);
79     }
80 }
81 
ShutdownThreads()82 void UserSnapshotServer::ShutdownThreads() {
83     terminating_ = true;
84     handlers_->JoinAllThreads();
85 }
86 
Sendmsg(android::base::borrowed_fd fd,const std::string & msg)87 bool UserSnapshotServer::Sendmsg(android::base::borrowed_fd fd, const std::string& msg) {
88     ssize_t ret = TEMP_FAILURE_RETRY(send(fd.get(), msg.data(), msg.size(), MSG_NOSIGNAL));
89     if (ret < 0) {
90         PLOG(ERROR) << "Snapuserd:server: send() failed";
91         return false;
92     }
93 
94     if (ret < msg.size()) {
95         LOG(ERROR) << "Partial send; expected " << msg.size() << " bytes, sent " << ret;
96         return false;
97     }
98     return true;
99 }
100 
Recv(android::base::borrowed_fd fd,std::string * data)101 bool UserSnapshotServer::Recv(android::base::borrowed_fd fd, std::string* data) {
102     char msg[kMaxPacketSize];
103     ssize_t rv = TEMP_FAILURE_RETRY(recv(fd.get(), msg, sizeof(msg), 0));
104     if (rv < 0) {
105         PLOG(ERROR) << "recv failed";
106         return false;
107     }
108     *data = std::string(msg, rv);
109     return true;
110 }
111 
Receivemsg(android::base::borrowed_fd fd,const std::string & str)112 bool UserSnapshotServer::Receivemsg(android::base::borrowed_fd fd, const std::string& str) {
113     const char delim = ',';
114 
115     std::vector<std::string> out;
116     Parsemsg(str, delim, out);
117 
118     const auto& cmd = out[0];
119     if (cmd == "init") {
120         // Message format:
121         // init,<misc_name>,<cow_device_path>,<backing_device>,<base_path_merge>
122         //
123         // Reads the metadata and send the number of sectors
124         if (out.size() != 5) {
125             LOG(ERROR) << "Malformed init message, " << out.size() << " parts";
126             return Sendmsg(fd, "fail");
127         }
128 
129         auto handler = AddHandler(out[1], out[2], out[3], out[4], std::nullopt);
130         if (!handler) {
131             return Sendmsg(fd, "fail");
132         }
133 
134         auto num_sectors = handler->snapuserd()->GetNumSectors();
135         if (!num_sectors) {
136             return Sendmsg(fd, "fail");
137         }
138 
139         auto retval = "success," + std::to_string(num_sectors);
140         return Sendmsg(fd, retval);
141     } else if (cmd == "start") {
142         // Message format:
143         // start,<misc_name>
144         //
145         // Start the new thread which binds to dm-user misc device
146         if (out.size() != 2) {
147             LOG(ERROR) << "Malformed start message, " << out.size() << " parts";
148             return Sendmsg(fd, "fail");
149         }
150 
151         if (!handlers_->StartHandler(out[1])) {
152             return Sendmsg(fd, "fail");
153         }
154         return Sendmsg(fd, "success");
155     } else if (cmd == "stop") {
156         // Message format: stop
157         //
158         // Stop all the threads gracefully and then shutdown the
159         // main thread
160         SetTerminating();
161         ShutdownThreads();
162         return true;
163     } else if (cmd == "query") {
164         // Message format: query
165         //
166         // As part of transition, Second stage daemon will be
167         // created before terminating the first stage daemon. Hence,
168         // for a brief period client may have to distiguish between
169         // first stage daemon and second stage daemon.
170         //
171         // Second stage daemon is marked as active and hence will
172         // be ready to receive control message.
173         return Sendmsg(fd, GetDaemonStatus());
174     } else if (cmd == "delete") {
175         // Message format:
176         // delete,<misc_name>
177         if (out.size() != 2) {
178             LOG(ERROR) << "Malformed delete message, " << out.size() << " parts";
179             return Sendmsg(fd, "fail");
180         }
181         if (!handlers_->DeleteHandler(out[1])) {
182             return Sendmsg(fd, "fail");
183         }
184         return Sendmsg(fd, "success");
185     } else if (cmd == "detach") {
186         handlers_->TerminateMergeThreads();
187         terminating_ = true;
188         return true;
189     } else if (cmd == "supports") {
190         if (out.size() != 2) {
191             LOG(ERROR) << "Malformed supports message, " << out.size() << " parts";
192             return Sendmsg(fd, "fail");
193         }
194         if (out[1] == "second_stage_socket_handoff") {
195             return Sendmsg(fd, "success");
196         }
197         return Sendmsg(fd, "fail");
198     } else if (cmd == "initiate_merge") {
199         if (out.size() != 2) {
200             LOG(ERROR) << "Malformed initiate-merge message, " << out.size() << " parts";
201             return Sendmsg(fd, "fail");
202         }
203         if (out[0] == "initiate_merge") {
204             if (!handlers_->InitiateMerge(out[1])) {
205                 return Sendmsg(fd, "fail");
206             }
207             return Sendmsg(fd, "success");
208         }
209         return Sendmsg(fd, "fail");
210     } else if (cmd == "merge_percent") {
211         double percentage = handlers_->GetMergePercentage();
212         return Sendmsg(fd, std::to_string(percentage));
213     } else if (cmd == "getstatus") {
214         // Message format:
215         // getstatus,<misc_name>
216         if (out.size() != 2) {
217             LOG(ERROR) << "Malformed delete message, " << out.size() << " parts";
218             return Sendmsg(fd, "snapshot-merge-failed");
219         }
220         auto status = handlers_->GetMergeStatus(out[1]);
221         if (status.empty()) {
222             return Sendmsg(fd, "snapshot-merge-failed");
223         }
224         return Sendmsg(fd, status);
225     } else if (cmd == "update-verify") {
226         if (!handlers_->GetVerificationStatus()) {
227             return Sendmsg(fd, "fail");
228         }
229         return Sendmsg(fd, "success");
230     } else {
231         LOG(ERROR) << "Received unknown message type from client";
232         Sendmsg(fd, "fail");
233         return false;
234     }
235 }
236 
Start(const std::string & socketname)237 bool UserSnapshotServer::Start(const std::string& socketname) {
238     bool start_listening = true;
239 
240     sockfd_.reset(android_get_control_socket(socketname.c_str()));
241     if (sockfd_ < 0) {
242         sockfd_.reset(socket_local_server(socketname.c_str(), ANDROID_SOCKET_NAMESPACE_RESERVED,
243                                           SOCK_STREAM));
244         if (sockfd_ < 0) {
245             PLOG(ERROR) << "Failed to create server socket " << socketname;
246             return false;
247         }
248         start_listening = false;
249     }
250     return StartWithSocket(start_listening);
251 }
252 
StartWithSocket(bool start_listening)253 bool UserSnapshotServer::StartWithSocket(bool start_listening) {
254     if (start_listening && listen(sockfd_.get(), 4) < 0) {
255         PLOG(ERROR) << "listen socket failed";
256         return false;
257     }
258 
259     AddWatchedFd(sockfd_, POLLIN);
260     is_socket_present_ = true;
261 
262     // If started in first-stage init, the property service won't be online.
263     if (access("/dev/socket/property_service", F_OK) == 0) {
264         if (!android::base::SetProperty("snapuserd.ready", "true")) {
265             LOG(ERROR) << "Failed to set snapuserd.ready property";
266             return false;
267         }
268     }
269 
270     LOG(DEBUG) << "Snapuserd server now accepting connections";
271     return true;
272 }
273 
Run()274 bool UserSnapshotServer::Run() {
275     LOG(INFO) << "Now listening on snapuserd socket";
276 
277     while (!IsTerminating()) {
278         int rv = TEMP_FAILURE_RETRY(poll(watched_fds_.data(), watched_fds_.size(), -1));
279         if (rv < 0) {
280             PLOG(ERROR) << "poll failed";
281             return false;
282         }
283         if (!rv) {
284             continue;
285         }
286 
287         if (watched_fds_[0].revents) {
288             AcceptClient();
289         }
290 
291         auto iter = watched_fds_.begin() + 1;
292         while (iter != watched_fds_.end()) {
293             if (iter->revents && !HandleClient(iter->fd, iter->revents)) {
294                 close(iter->fd);
295                 iter = watched_fds_.erase(iter);
296             } else {
297                 iter++;
298             }
299         }
300     }
301 
302     handlers_->JoinAllThreads();
303     return true;
304 }
305 
AddWatchedFd(android::base::borrowed_fd fd,int events)306 void UserSnapshotServer::AddWatchedFd(android::base::borrowed_fd fd, int events) {
307     struct pollfd p = {};
308     p.fd = fd.get();
309     p.events = events;
310     watched_fds_.emplace_back(std::move(p));
311 }
312 
AcceptClient()313 void UserSnapshotServer::AcceptClient() {
314     int fd = TEMP_FAILURE_RETRY(accept4(sockfd_.get(), nullptr, nullptr, SOCK_CLOEXEC));
315     if (fd < 0) {
316         PLOG(ERROR) << "accept4 failed";
317         return;
318     }
319 
320     AddWatchedFd(fd, POLLIN);
321 }
322 
HandleClient(android::base::borrowed_fd fd,int revents)323 bool UserSnapshotServer::HandleClient(android::base::borrowed_fd fd, int revents) {
324     std::string str;
325     if (!Recv(fd, &str)) {
326         return false;
327     }
328     if (str.empty() && (revents & POLLHUP)) {
329         LOG(DEBUG) << "Snapuserd client disconnected";
330         return false;
331     }
332     if (!Receivemsg(fd, str)) {
333         LOG(ERROR) << "Encountered error handling client message, revents: " << revents;
334         return false;
335     }
336     return true;
337 }
338 
Interrupt()339 void UserSnapshotServer::Interrupt() {
340     // Force close the socket so poll() fails.
341     sockfd_ = {};
342     SetTerminating();
343 }
344 
AddHandler(const std::string & misc_name,const std::string & cow_device_path,const std::string & backing_device,const std::string & base_path_merge,std::optional<uint32_t> num_worker_threads,const bool o_direct,uint32_t cow_op_merge_size)345 std::shared_ptr<HandlerThread> UserSnapshotServer::AddHandler(
346         const std::string& misc_name, const std::string& cow_device_path,
347         const std::string& backing_device, const std::string& base_path_merge,
348         std::optional<uint32_t> num_worker_threads, const bool o_direct,
349         uint32_t cow_op_merge_size) {
350     // We will need multiple worker threads only during
351     // device boot after OTA. For all other purposes,
352     // one thread is sufficient. We don't want to consume
353     // unnecessary memory especially during OTA install phase
354     // when daemon will be up during entire post install phase.
355     //
356     // During boot up, we need multiple threads primarily for
357     // update-verification.
358     if (!num_worker_threads.has_value()) {
359         num_worker_threads = kNumWorkerThreads;
360     }
361     if (is_socket_present_) {
362         num_worker_threads = 1;
363     }
364 
365     if (android::base::EndsWith(misc_name, "-init") || is_socket_present_ ||
366         (access(kBootSnapshotsWithoutSlotSwitch, F_OK) == 0)) {
367         handlers_->DisableVerification();
368     }
369 
370     auto opener = block_server_factory_->CreateOpener(misc_name);
371 
372     return handlers_->AddHandler(misc_name, cow_device_path, backing_device, base_path_merge,
373                                  opener, num_worker_threads.value(), io_uring_enabled_, o_direct,
374                                  cow_op_merge_size);
375 }
376 
WaitForSocket()377 bool UserSnapshotServer::WaitForSocket() {
378     auto scope_guard =
379             android::base::make_scope_guard([this]() -> void { handlers_->JoinAllThreads(); });
380 
381     auto socket_path = ANDROID_SOCKET_DIR "/"s + kSnapuserdSocketProxy;
382 
383     if (!android::fs_mgr::WaitForFile(socket_path, std::chrono::milliseconds::max())) {
384         LOG(ERROR)
385                 << "Failed to wait for proxy socket, second-stage snapuserd will fail to connect";
386         return false;
387     }
388 
389     // This initialization of system property is important. When daemon is
390     // launched post selinux transition (before init second stage),
391     // bionic libc initializes system property as part of __libc_init_common();
392     // however that initialization fails silently given that fact that we don't
393     // have /dev/__properties__ setup which is created at init second stage.
394     //
395     // At this point, we have the handlers setup and is safe to setup property.
396     __system_properties_init();
397 
398     if (!android::base::WaitForProperty("snapuserd.proxy_ready", "true")) {
399         LOG(ERROR)
400                 << "Failed to wait for proxy property, second-stage snapuserd will fail to connect";
401         return false;
402     }
403 
404     unique_fd fd(socket_local_client(kSnapuserdSocketProxy, ANDROID_SOCKET_NAMESPACE_RESERVED,
405                                      SOCK_SEQPACKET));
406     if (fd < 0) {
407         PLOG(ERROR) << "Failed to connect to socket proxy";
408         return false;
409     }
410 
411     char code[1];
412     std::vector<unique_fd> fds;
413     ssize_t rv = android::base::ReceiveFileDescriptorVector(fd, code, sizeof(code), 1, &fds);
414     if (rv < 0) {
415         PLOG(ERROR) << "Failed to receive server socket over proxy";
416         return false;
417     }
418     if (fds.empty()) {
419         LOG(ERROR) << "Expected at least one file descriptor from proxy";
420         return false;
421     }
422 
423     // We don't care if the ACK is received.
424     code[0] = 'a';
425     if (TEMP_FAILURE_RETRY(send(fd, code, sizeof(code), MSG_NOSIGNAL)) < 0) {
426         PLOG(ERROR) << "Failed to send ACK to proxy";
427         return false;
428     }
429 
430     sockfd_ = std::move(fds[0]);
431     if (!StartWithSocket(true)) {
432         return false;
433     }
434 
435     return Run();
436 }
437 
RunForSocketHandoff()438 bool UserSnapshotServer::RunForSocketHandoff() {
439     unique_fd proxy_fd(android_get_control_socket(kSnapuserdSocketProxy));
440     if (proxy_fd < 0) {
441         PLOG(FATAL) << "Proxy could not get android control socket " << kSnapuserdSocketProxy;
442     }
443     borrowed_fd server_fd(android_get_control_socket(kSnapuserdSocket));
444     if (server_fd < 0) {
445         PLOG(FATAL) << "Proxy could not get android control socket " << kSnapuserdSocket;
446     }
447 
448     if (listen(proxy_fd.get(), 4) < 0) {
449         PLOG(FATAL) << "Proxy listen socket failed";
450     }
451 
452     if (!android::base::SetProperty("snapuserd.proxy_ready", "true")) {
453         LOG(FATAL) << "Proxy failed to set ready property";
454     }
455 
456     unique_fd client_fd(
457             TEMP_FAILURE_RETRY(accept4(proxy_fd.get(), nullptr, nullptr, SOCK_CLOEXEC)));
458     if (client_fd < 0) {
459         PLOG(FATAL) << "Proxy accept failed";
460     }
461 
462     char code[1] = {'a'};
463     std::vector<int> fds = {server_fd.get()};
464     ssize_t rv = android::base::SendFileDescriptorVector(client_fd, code, sizeof(code), fds);
465     if (rv < 0) {
466         PLOG(FATAL) << "Proxy could not send file descriptor to snapuserd";
467     }
468     // Wait for an ACK - results don't matter, we just don't want to risk closing
469     // the proxy socket too early.
470     if (recv(client_fd, code, sizeof(code), 0) < 0) {
471         PLOG(FATAL) << "Proxy could not receive terminating code from snapuserd";
472     }
473     return true;
474 }
475 
StartHandler(const std::string & misc_name)476 bool UserSnapshotServer::StartHandler(const std::string& misc_name) {
477     return handlers_->StartHandler(misc_name);
478 }
479 
480 }  // namespace snapshot
481 }  // namespace android
482