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/types.h>
26 #include <unistd.h>
27
28 #include <android-base/cmsg.h>
29 #include <android-base/logging.h>
30 #include <android-base/properties.h>
31 #include <android-base/scopeguard.h>
32 #include <fs_mgr/file_wait.h>
33 #include <snapuserd/snapuserd_client.h>
34 #include "snapuserd_server.h"
35
36 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
37 #include <sys/_system_properties.h>
38
39 namespace android {
40 namespace snapshot {
41
42 using namespace std::string_literals;
43
44 using android::base::borrowed_fd;
45 using android::base::unique_fd;
46
Resolveop(std::string & input)47 DaemonOps UserSnapshotServer::Resolveop(std::string& input) {
48 if (input == "init") return DaemonOps::INIT;
49 if (input == "start") return DaemonOps::START;
50 if (input == "stop") return DaemonOps::STOP;
51 if (input == "query") return DaemonOps::QUERY;
52 if (input == "delete") return DaemonOps::DELETE;
53 if (input == "detach") return DaemonOps::DETACH;
54 if (input == "supports") return DaemonOps::SUPPORTS;
55 if (input == "initiate_merge") return DaemonOps::INITIATE;
56 if (input == "merge_percent") return DaemonOps::PERCENTAGE;
57 if (input == "getstatus") return DaemonOps::GETSTATUS;
58 if (input == "update-verify") return DaemonOps::UPDATE_VERIFY;
59
60 return DaemonOps::INVALID;
61 }
62
UserSnapshotServer()63 UserSnapshotServer::UserSnapshotServer() {
64 monitor_merge_event_fd_.reset(eventfd(0, EFD_CLOEXEC));
65 if (monitor_merge_event_fd_ == -1) {
66 PLOG(FATAL) << "monitor_merge_event_fd_: failed to create eventfd";
67 }
68 terminating_ = false;
69 }
70
~UserSnapshotServer()71 UserSnapshotServer::~UserSnapshotServer() {
72 // Close any client sockets that were added via AcceptClient().
73 for (size_t i = 1; i < watched_fds_.size(); i++) {
74 close(watched_fds_[i].fd);
75 }
76 }
77
GetDaemonStatus()78 std::string UserSnapshotServer::GetDaemonStatus() {
79 std::string msg = "";
80
81 if (IsTerminating())
82 msg = "passive";
83 else
84 msg = "active";
85
86 return msg;
87 }
88
Parsemsg(std::string const & msg,const char delim,std::vector<std::string> & out)89 void UserSnapshotServer::Parsemsg(std::string const& msg, const char delim,
90 std::vector<std::string>& out) {
91 std::stringstream ss(msg);
92 std::string s;
93
94 while (std::getline(ss, s, delim)) {
95 out.push_back(s);
96 }
97 }
98
ShutdownThreads()99 void UserSnapshotServer::ShutdownThreads() {
100 terminating_ = true;
101 JoinAllThreads();
102 }
103
UserSnapshotDmUserHandler(std::shared_ptr<SnapshotHandler> snapuserd)104 UserSnapshotDmUserHandler::UserSnapshotDmUserHandler(std::shared_ptr<SnapshotHandler> snapuserd)
105 : snapuserd_(snapuserd), misc_name_(snapuserd_->GetMiscName()) {}
106
Sendmsg(android::base::borrowed_fd fd,const std::string & msg)107 bool UserSnapshotServer::Sendmsg(android::base::borrowed_fd fd, const std::string& msg) {
108 ssize_t ret = TEMP_FAILURE_RETRY(send(fd.get(), msg.data(), msg.size(), MSG_NOSIGNAL));
109 if (ret < 0) {
110 PLOG(ERROR) << "Snapuserd:server: send() failed";
111 return false;
112 }
113
114 if (ret < msg.size()) {
115 LOG(ERROR) << "Partial send; expected " << msg.size() << " bytes, sent " << ret;
116 return false;
117 }
118 return true;
119 }
120
Recv(android::base::borrowed_fd fd,std::string * data)121 bool UserSnapshotServer::Recv(android::base::borrowed_fd fd, std::string* data) {
122 char msg[kMaxPacketSize];
123 ssize_t rv = TEMP_FAILURE_RETRY(recv(fd.get(), msg, sizeof(msg), 0));
124 if (rv < 0) {
125 PLOG(ERROR) << "recv failed";
126 return false;
127 }
128 *data = std::string(msg, rv);
129 return true;
130 }
131
Receivemsg(android::base::borrowed_fd fd,const std::string & str)132 bool UserSnapshotServer::Receivemsg(android::base::borrowed_fd fd, const std::string& str) {
133 const char delim = ',';
134
135 std::vector<std::string> out;
136 Parsemsg(str, delim, out);
137 DaemonOps op = Resolveop(out[0]);
138
139 switch (op) {
140 case DaemonOps::INIT: {
141 // Message format:
142 // init,<misc_name>,<cow_device_path>,<backing_device>,<base_path_merge>
143 //
144 // Reads the metadata and send the number of sectors
145 if (out.size() != 5) {
146 LOG(ERROR) << "Malformed init message, " << out.size() << " parts";
147 return Sendmsg(fd, "fail");
148 }
149
150 auto handler = AddHandler(out[1], out[2], out[3], out[4]);
151 if (!handler) {
152 return Sendmsg(fd, "fail");
153 }
154
155 auto retval = "success," + std::to_string(handler->snapuserd()->GetNumSectors());
156 return Sendmsg(fd, retval);
157 }
158 case DaemonOps::START: {
159 // Message format:
160 // start,<misc_name>
161 //
162 // Start the new thread which binds to dm-user misc device
163 if (out.size() != 2) {
164 LOG(ERROR) << "Malformed start message, " << out.size() << " parts";
165 return Sendmsg(fd, "fail");
166 }
167
168 std::lock_guard<std::mutex> lock(lock_);
169 auto iter = FindHandler(&lock, out[1]);
170 if (iter == dm_users_.end()) {
171 LOG(ERROR) << "Could not find handler: " << out[1];
172 return Sendmsg(fd, "fail");
173 }
174 if (!(*iter)->snapuserd() || (*iter)->snapuserd()->IsAttached()) {
175 LOG(ERROR) << "Tried to re-attach control device: " << out[1];
176 return Sendmsg(fd, "fail");
177 }
178 if (!StartHandler(*iter)) {
179 return Sendmsg(fd, "fail");
180 }
181 return Sendmsg(fd, "success");
182 }
183 case DaemonOps::STOP: {
184 // Message format: stop
185 //
186 // Stop all the threads gracefully and then shutdown the
187 // main thread
188 SetTerminating();
189 ShutdownThreads();
190 return true;
191 }
192 case DaemonOps::QUERY: {
193 // Message format: query
194 //
195 // As part of transition, Second stage daemon will be
196 // created before terminating the first stage daemon. Hence,
197 // for a brief period client may have to distiguish between
198 // first stage daemon and second stage daemon.
199 //
200 // Second stage daemon is marked as active and hence will
201 // be ready to receive control message.
202 return Sendmsg(fd, GetDaemonStatus());
203 }
204 case DaemonOps::DELETE: {
205 // Message format:
206 // delete,<misc_name>
207 if (out.size() != 2) {
208 LOG(ERROR) << "Malformed delete message, " << out.size() << " parts";
209 return Sendmsg(fd, "fail");
210 }
211 {
212 std::lock_guard<std::mutex> lock(lock_);
213 auto iter = FindHandler(&lock, out[1]);
214 if (iter == dm_users_.end()) {
215 // After merge is completed, we swap dm-user table with
216 // the underlying dm-linear base device. Hence, worker
217 // threads would have terminted and was removed from
218 // the list.
219 LOG(DEBUG) << "Could not find handler: " << out[1];
220 return Sendmsg(fd, "success");
221 }
222
223 if (!(*iter)->ThreadTerminated()) {
224 (*iter)->snapuserd()->NotifyIOTerminated();
225 }
226 }
227 if (!RemoveAndJoinHandler(out[1])) {
228 return Sendmsg(fd, "fail");
229 }
230 return Sendmsg(fd, "success");
231 }
232 case DaemonOps::DETACH: {
233 std::lock_guard<std::mutex> lock(lock_);
234 TerminateMergeThreads(&lock);
235 terminating_ = true;
236 return true;
237 }
238 case DaemonOps::SUPPORTS: {
239 if (out.size() != 2) {
240 LOG(ERROR) << "Malformed supports message, " << out.size() << " parts";
241 return Sendmsg(fd, "fail");
242 }
243 if (out[1] == "second_stage_socket_handoff") {
244 return Sendmsg(fd, "success");
245 }
246 return Sendmsg(fd, "fail");
247 }
248 case DaemonOps::INITIATE: {
249 if (out.size() != 2) {
250 LOG(ERROR) << "Malformed initiate-merge message, " << out.size() << " parts";
251 return Sendmsg(fd, "fail");
252 }
253 if (out[0] == "initiate_merge") {
254 std::lock_guard<std::mutex> lock(lock_);
255 auto iter = FindHandler(&lock, out[1]);
256 if (iter == dm_users_.end()) {
257 LOG(ERROR) << "Could not find handler: " << out[1];
258 return Sendmsg(fd, "fail");
259 }
260
261 if (!StartMerge(&lock, *iter)) {
262 return Sendmsg(fd, "fail");
263 }
264
265 return Sendmsg(fd, "success");
266 }
267 return Sendmsg(fd, "fail");
268 }
269 case DaemonOps::PERCENTAGE: {
270 std::lock_guard<std::mutex> lock(lock_);
271 double percentage = GetMergePercentage(&lock);
272
273 return Sendmsg(fd, std::to_string(percentage));
274 }
275 case DaemonOps::GETSTATUS: {
276 // Message format:
277 // getstatus,<misc_name>
278 if (out.size() != 2) {
279 LOG(ERROR) << "Malformed delete message, " << out.size() << " parts";
280 return Sendmsg(fd, "snapshot-merge-failed");
281 }
282 {
283 std::lock_guard<std::mutex> lock(lock_);
284 auto iter = FindHandler(&lock, out[1]);
285 if (iter == dm_users_.end()) {
286 LOG(ERROR) << "Could not find handler: " << out[1];
287 return Sendmsg(fd, "snapshot-merge-failed");
288 }
289
290 std::string merge_status = GetMergeStatus(*iter);
291 return Sendmsg(fd, merge_status);
292 }
293 }
294 case DaemonOps::UPDATE_VERIFY: {
295 std::lock_guard<std::mutex> lock(lock_);
296 if (!UpdateVerification(&lock)) {
297 return Sendmsg(fd, "fail");
298 }
299
300 return Sendmsg(fd, "success");
301 }
302 default: {
303 LOG(ERROR) << "Received unknown message type from client";
304 Sendmsg(fd, "fail");
305 return false;
306 }
307 }
308 }
309
RunThread(std::shared_ptr<UserSnapshotDmUserHandler> handler)310 void UserSnapshotServer::RunThread(std::shared_ptr<UserSnapshotDmUserHandler> handler) {
311 LOG(INFO) << "Entering thread for handler: " << handler->misc_name();
312
313 if (!handler->snapuserd()->Start()) {
314 LOG(ERROR) << " Failed to launch all worker threads";
315 }
316
317 handler->snapuserd()->CloseFds();
318 bool merge_completed = handler->snapuserd()->CheckMergeCompletionStatus();
319 handler->snapuserd()->UnmapBufferRegion();
320
321 auto misc_name = handler->misc_name();
322 LOG(INFO) << "Handler thread about to exit: " << misc_name;
323
324 {
325 std::lock_guard<std::mutex> lock(lock_);
326 if (merge_completed) {
327 num_partitions_merge_complete_ += 1;
328 active_merge_threads_ -= 1;
329 WakeupMonitorMergeThread();
330 }
331 handler->SetThreadTerminated();
332 auto iter = FindHandler(&lock, handler->misc_name());
333 if (iter == dm_users_.end()) {
334 // RemoveAndJoinHandler() already removed us from the list, and is
335 // now waiting on a join(), so just return. Additionally, release
336 // all the resources held by snapuserd object which are shared
337 // by worker threads. This should be done when the last reference
338 // of "handler" is released; but we will explicitly release here
339 // to make sure snapuserd object is freed as it is the biggest
340 // consumer of memory in the daemon.
341 handler->FreeResources();
342 LOG(INFO) << "Exiting handler thread to allow for join: " << misc_name;
343 return;
344 }
345
346 LOG(INFO) << "Exiting handler thread and freeing resources: " << misc_name;
347
348 if (handler->snapuserd()->IsAttached()) {
349 handler->thread().detach();
350 }
351
352 // Important: free resources within the lock. This ensures that if
353 // WaitForDelete() is called, the handler is either in the list, or
354 // it's not and its resources are guaranteed to be freed.
355 handler->FreeResources();
356 dm_users_.erase(iter);
357 }
358 }
359
Start(const std::string & socketname)360 bool UserSnapshotServer::Start(const std::string& socketname) {
361 bool start_listening = true;
362
363 sockfd_.reset(android_get_control_socket(socketname.c_str()));
364 if (sockfd_ < 0) {
365 sockfd_.reset(socket_local_server(socketname.c_str(), ANDROID_SOCKET_NAMESPACE_RESERVED,
366 SOCK_STREAM));
367 if (sockfd_ < 0) {
368 PLOG(ERROR) << "Failed to create server socket " << socketname;
369 return false;
370 }
371 start_listening = false;
372 }
373 return StartWithSocket(start_listening);
374 }
375
StartWithSocket(bool start_listening)376 bool UserSnapshotServer::StartWithSocket(bool start_listening) {
377 if (start_listening && listen(sockfd_.get(), 4) < 0) {
378 PLOG(ERROR) << "listen socket failed";
379 return false;
380 }
381
382 AddWatchedFd(sockfd_, POLLIN);
383 is_socket_present_ = true;
384
385 // If started in first-stage init, the property service won't be online.
386 if (access("/dev/socket/property_service", F_OK) == 0) {
387 if (!android::base::SetProperty("snapuserd.ready", "true")) {
388 LOG(ERROR) << "Failed to set snapuserd.ready property";
389 return false;
390 }
391 }
392
393 LOG(DEBUG) << "Snapuserd server now accepting connections";
394 return true;
395 }
396
Run()397 bool UserSnapshotServer::Run() {
398 LOG(INFO) << "Now listening on snapuserd socket";
399
400 while (!IsTerminating()) {
401 int rv = TEMP_FAILURE_RETRY(poll(watched_fds_.data(), watched_fds_.size(), -1));
402 if (rv < 0) {
403 PLOG(ERROR) << "poll failed";
404 return false;
405 }
406 if (!rv) {
407 continue;
408 }
409
410 if (watched_fds_[0].revents) {
411 AcceptClient();
412 }
413
414 auto iter = watched_fds_.begin() + 1;
415 while (iter != watched_fds_.end()) {
416 if (iter->revents && !HandleClient(iter->fd, iter->revents)) {
417 close(iter->fd);
418 iter = watched_fds_.erase(iter);
419 } else {
420 iter++;
421 }
422 }
423 }
424
425 JoinAllThreads();
426 return true;
427 }
428
JoinAllThreads()429 void UserSnapshotServer::JoinAllThreads() {
430 // Acquire the thread list within the lock.
431 std::vector<std::shared_ptr<UserSnapshotDmUserHandler>> dm_users;
432 {
433 std::lock_guard<std::mutex> guard(lock_);
434 dm_users = std::move(dm_users_);
435 }
436
437 for (auto& client : dm_users) {
438 auto& th = client->thread();
439
440 if (th.joinable()) th.join();
441 }
442
443 stop_monitor_merge_thread_ = true;
444 WakeupMonitorMergeThread();
445 }
446
AddWatchedFd(android::base::borrowed_fd fd,int events)447 void UserSnapshotServer::AddWatchedFd(android::base::borrowed_fd fd, int events) {
448 struct pollfd p = {};
449 p.fd = fd.get();
450 p.events = events;
451 watched_fds_.emplace_back(std::move(p));
452 }
453
AcceptClient()454 void UserSnapshotServer::AcceptClient() {
455 int fd = TEMP_FAILURE_RETRY(accept4(sockfd_.get(), nullptr, nullptr, SOCK_CLOEXEC));
456 if (fd < 0) {
457 PLOG(ERROR) << "accept4 failed";
458 return;
459 }
460
461 AddWatchedFd(fd, POLLIN);
462 }
463
HandleClient(android::base::borrowed_fd fd,int revents)464 bool UserSnapshotServer::HandleClient(android::base::borrowed_fd fd, int revents) {
465 if (revents & POLLHUP) {
466 LOG(DEBUG) << "Snapuserd client disconnected";
467 return false;
468 }
469
470 std::string str;
471 if (!Recv(fd, &str)) {
472 return false;
473 }
474 if (!Receivemsg(fd, str)) {
475 LOG(ERROR) << "Encountered error handling client message, revents: " << revents;
476 return false;
477 }
478 return true;
479 }
480
Interrupt()481 void UserSnapshotServer::Interrupt() {
482 // Force close the socket so poll() fails.
483 sockfd_ = {};
484 SetTerminating();
485 }
486
AddHandler(const std::string & misc_name,const std::string & cow_device_path,const std::string & backing_device,const std::string & base_path_merge)487 std::shared_ptr<UserSnapshotDmUserHandler> UserSnapshotServer::AddHandler(
488 const std::string& misc_name, const std::string& cow_device_path,
489 const std::string& backing_device, const std::string& base_path_merge) {
490 auto snapuserd = std::make_shared<SnapshotHandler>(misc_name, cow_device_path, backing_device,
491 base_path_merge);
492 if (!snapuserd->InitCowDevice()) {
493 LOG(ERROR) << "Failed to initialize Snapuserd";
494 return nullptr;
495 }
496
497 snapuserd->SetSocketPresent(is_socket_present_);
498 snapuserd->SetIouringEnabled(io_uring_enabled_);
499
500 if (!snapuserd->InitializeWorkers()) {
501 LOG(ERROR) << "Failed to initialize workers";
502 return nullptr;
503 }
504
505 auto handler = std::make_shared<UserSnapshotDmUserHandler>(snapuserd);
506 {
507 std::lock_guard<std::mutex> lock(lock_);
508 if (FindHandler(&lock, misc_name) != dm_users_.end()) {
509 LOG(ERROR) << "Handler already exists: " << misc_name;
510 return nullptr;
511 }
512 dm_users_.push_back(handler);
513 }
514 return handler;
515 }
516
StartHandler(const std::shared_ptr<UserSnapshotDmUserHandler> & handler)517 bool UserSnapshotServer::StartHandler(const std::shared_ptr<UserSnapshotDmUserHandler>& handler) {
518 if (handler->snapuserd()->IsAttached()) {
519 LOG(ERROR) << "Handler already attached";
520 return false;
521 }
522
523 handler->snapuserd()->AttachControlDevice();
524
525 handler->thread() = std::thread(std::bind(&UserSnapshotServer::RunThread, this, handler));
526 return true;
527 }
528
StartMerge(std::lock_guard<std::mutex> * proof_of_lock,const std::shared_ptr<UserSnapshotDmUserHandler> & handler)529 bool UserSnapshotServer::StartMerge(std::lock_guard<std::mutex>* proof_of_lock,
530 const std::shared_ptr<UserSnapshotDmUserHandler>& handler) {
531 CHECK(proof_of_lock);
532
533 if (!handler->snapuserd()->IsAttached()) {
534 LOG(ERROR) << "Handler not attached to dm-user - Merge thread cannot be started";
535 return false;
536 }
537
538 handler->snapuserd()->MonitorMerge();
539
540 if (!is_merge_monitor_started_.has_value()) {
541 std::thread(&UserSnapshotServer::MonitorMerge, this).detach();
542 is_merge_monitor_started_ = true;
543 }
544
545 merge_handlers_.push(handler);
546 WakeupMonitorMergeThread();
547 return true;
548 }
549
FindHandler(std::lock_guard<std::mutex> * proof_of_lock,const std::string & misc_name)550 auto UserSnapshotServer::FindHandler(std::lock_guard<std::mutex>* proof_of_lock,
551 const std::string& misc_name) -> HandlerList::iterator {
552 CHECK(proof_of_lock);
553
554 for (auto iter = dm_users_.begin(); iter != dm_users_.end(); iter++) {
555 if ((*iter)->misc_name() == misc_name) {
556 return iter;
557 }
558 }
559 return dm_users_.end();
560 }
561
TerminateMergeThreads(std::lock_guard<std::mutex> * proof_of_lock)562 void UserSnapshotServer::TerminateMergeThreads(std::lock_guard<std::mutex>* proof_of_lock) {
563 CHECK(proof_of_lock);
564
565 for (auto iter = dm_users_.begin(); iter != dm_users_.end(); iter++) {
566 if (!(*iter)->ThreadTerminated()) {
567 (*iter)->snapuserd()->NotifyIOTerminated();
568 }
569 }
570 }
571
GetMergeStatus(const std::shared_ptr<UserSnapshotDmUserHandler> & handler)572 std::string UserSnapshotServer::GetMergeStatus(
573 const std::shared_ptr<UserSnapshotDmUserHandler>& handler) {
574 return handler->snapuserd()->GetMergeStatus();
575 }
576
GetMergePercentage(std::lock_guard<std::mutex> * proof_of_lock)577 double UserSnapshotServer::GetMergePercentage(std::lock_guard<std::mutex>* proof_of_lock) {
578 CHECK(proof_of_lock);
579 double percentage = 0.0;
580 int n = 0;
581
582 for (auto iter = dm_users_.begin(); iter != dm_users_.end(); iter++) {
583 auto& th = (*iter)->thread();
584 if (th.joinable()) {
585 // Merge percentage by individual partitions wherein merge is still
586 // in-progress
587 percentage += (*iter)->snapuserd()->GetMergePercentage();
588 n += 1;
589 }
590 }
591
592 // Calculate final merge including those partitions where merge was already
593 // completed - num_partitions_merge_complete_ will track them when each
594 // thread exists in RunThread.
595 int total_partitions = n + num_partitions_merge_complete_;
596
597 if (total_partitions) {
598 percentage = ((num_partitions_merge_complete_ * 100.0) + percentage) / total_partitions;
599 }
600
601 LOG(DEBUG) << "Merge %: " << percentage
602 << " num_partitions_merge_complete_: " << num_partitions_merge_complete_
603 << " total_partitions: " << total_partitions << " n: " << n;
604 return percentage;
605 }
606
RemoveAndJoinHandler(const std::string & misc_name)607 bool UserSnapshotServer::RemoveAndJoinHandler(const std::string& misc_name) {
608 std::shared_ptr<UserSnapshotDmUserHandler> handler;
609 {
610 std::lock_guard<std::mutex> lock(lock_);
611
612 auto iter = FindHandler(&lock, misc_name);
613 if (iter == dm_users_.end()) {
614 // Client already deleted.
615 return true;
616 }
617 handler = std::move(*iter);
618 dm_users_.erase(iter);
619 }
620
621 auto& th = handler->thread();
622 if (th.joinable()) {
623 th.join();
624 }
625 return true;
626 }
627
WakeupMonitorMergeThread()628 void UserSnapshotServer::WakeupMonitorMergeThread() {
629 uint64_t notify = 1;
630 ssize_t rc = TEMP_FAILURE_RETRY(write(monitor_merge_event_fd_.get(), ¬ify, sizeof(notify)));
631 if (rc < 0) {
632 PLOG(FATAL) << "failed to notify monitor merge thread";
633 }
634 }
635
MonitorMerge()636 void UserSnapshotServer::MonitorMerge() {
637 while (!stop_monitor_merge_thread_) {
638 uint64_t testVal;
639 ssize_t ret =
640 TEMP_FAILURE_RETRY(read(monitor_merge_event_fd_.get(), &testVal, sizeof(testVal)));
641 if (ret == -1) {
642 PLOG(FATAL) << "Failed to read from eventfd";
643 } else if (ret == 0) {
644 LOG(FATAL) << "Hit EOF on eventfd";
645 }
646
647 LOG(INFO) << "MonitorMerge: active-merge-threads: " << active_merge_threads_;
648 {
649 std::lock_guard<std::mutex> lock(lock_);
650 while (active_merge_threads_ < kMaxMergeThreads && merge_handlers_.size() > 0) {
651 auto handler = merge_handlers_.front();
652 merge_handlers_.pop();
653 LOG(INFO) << "Starting merge for partition: "
654 << handler->snapuserd()->GetMiscName();
655 handler->snapuserd()->InitiateMerge();
656 active_merge_threads_ += 1;
657 }
658 }
659 }
660
661 LOG(INFO) << "Exiting MonitorMerge: size: " << merge_handlers_.size();
662 }
663
WaitForSocket()664 bool UserSnapshotServer::WaitForSocket() {
665 auto scope_guard = android::base::make_scope_guard([this]() -> void { JoinAllThreads(); });
666
667 auto socket_path = ANDROID_SOCKET_DIR "/"s + kSnapuserdSocketProxy;
668
669 if (!android::fs_mgr::WaitForFile(socket_path, std::chrono::milliseconds::max())) {
670 LOG(ERROR)
671 << "Failed to wait for proxy socket, second-stage snapuserd will fail to connect";
672 return false;
673 }
674
675 // This initialization of system property is important. When daemon is
676 // launched post selinux transition (before init second stage),
677 // bionic libc initializes system property as part of __libc_init_common();
678 // however that initialization fails silently given that fact that we don't
679 // have /dev/__properties__ setup which is created at init second stage.
680 //
681 // At this point, we have the handlers setup and is safe to setup property.
682 __system_properties_init();
683
684 if (!android::base::WaitForProperty("snapuserd.proxy_ready", "true")) {
685 LOG(ERROR)
686 << "Failed to wait for proxy property, second-stage snapuserd will fail to connect";
687 return false;
688 }
689
690 unique_fd fd(socket_local_client(kSnapuserdSocketProxy, ANDROID_SOCKET_NAMESPACE_RESERVED,
691 SOCK_SEQPACKET));
692 if (fd < 0) {
693 PLOG(ERROR) << "Failed to connect to socket proxy";
694 return false;
695 }
696
697 char code[1];
698 std::vector<unique_fd> fds;
699 ssize_t rv = android::base::ReceiveFileDescriptorVector(fd, code, sizeof(code), 1, &fds);
700 if (rv < 0) {
701 PLOG(ERROR) << "Failed to receive server socket over proxy";
702 return false;
703 }
704 if (fds.empty()) {
705 LOG(ERROR) << "Expected at least one file descriptor from proxy";
706 return false;
707 }
708
709 // We don't care if the ACK is received.
710 code[0] = 'a';
711 if (TEMP_FAILURE_RETRY(send(fd, code, sizeof(code), MSG_NOSIGNAL) < 0)) {
712 PLOG(ERROR) << "Failed to send ACK to proxy";
713 return false;
714 }
715
716 sockfd_ = std::move(fds[0]);
717 if (!StartWithSocket(true)) {
718 return false;
719 }
720
721 return Run();
722 }
723
RunForSocketHandoff()724 bool UserSnapshotServer::RunForSocketHandoff() {
725 unique_fd proxy_fd(android_get_control_socket(kSnapuserdSocketProxy));
726 if (proxy_fd < 0) {
727 PLOG(FATAL) << "Proxy could not get android control socket " << kSnapuserdSocketProxy;
728 }
729 borrowed_fd server_fd(android_get_control_socket(kSnapuserdSocket));
730 if (server_fd < 0) {
731 PLOG(FATAL) << "Proxy could not get android control socket " << kSnapuserdSocket;
732 }
733
734 if (listen(proxy_fd.get(), 4) < 0) {
735 PLOG(FATAL) << "Proxy listen socket failed";
736 }
737
738 if (!android::base::SetProperty("snapuserd.proxy_ready", "true")) {
739 LOG(FATAL) << "Proxy failed to set ready property";
740 }
741
742 unique_fd client_fd(
743 TEMP_FAILURE_RETRY(accept4(proxy_fd.get(), nullptr, nullptr, SOCK_CLOEXEC)));
744 if (client_fd < 0) {
745 PLOG(FATAL) << "Proxy accept failed";
746 }
747
748 char code[1] = {'a'};
749 std::vector<int> fds = {server_fd.get()};
750 ssize_t rv = android::base::SendFileDescriptorVector(client_fd, code, sizeof(code), fds);
751 if (rv < 0) {
752 PLOG(FATAL) << "Proxy could not send file descriptor to snapuserd";
753 }
754 // Wait for an ACK - results don't matter, we just don't want to risk closing
755 // the proxy socket too early.
756 if (recv(client_fd, code, sizeof(code), 0) < 0) {
757 PLOG(FATAL) << "Proxy could not receive terminating code from snapuserd";
758 }
759 return true;
760 }
761
UpdateVerification(std::lock_guard<std::mutex> * proof_of_lock)762 bool UserSnapshotServer::UpdateVerification(std::lock_guard<std::mutex>* proof_of_lock) {
763 CHECK(proof_of_lock);
764
765 bool status = true;
766 for (auto iter = dm_users_.begin(); iter != dm_users_.end(); iter++) {
767 auto& th = (*iter)->thread();
768 if (th.joinable() && status) {
769 status = (*iter)->snapuserd()->CheckPartitionVerification() && status;
770 } else {
771 // return immediately if there is a failure
772 return false;
773 }
774 }
775
776 return status;
777 }
778
779 } // namespace snapshot
780 } // namespace android
781