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 <android-base/logging.h>
18 #include <android-base/properties.h>
19 #include <android-base/strings.h>
20 #include <gflags/gflags.h>
21 #include <snapuserd/snapuserd_client.h>
22
23 #include <storage_literals/storage_literals.h>
24 #include "user-space-merge/snapuserd_core.h"
25
26 #include "snapuserd_daemon.h"
27
28 using namespace android::storage_literals;
29
30 DEFINE_string(socket, android::snapshot::kSnapuserdSocket, "Named socket or socket path.");
31 DEFINE_bool(no_socket, false,
32 "If true, no socket is used. Each additional argument is an INIT message.");
33 DEFINE_bool(socket_handoff, false,
34 "If true, perform a socket hand-off with an existing snapuserd instance, then exit.");
35 DEFINE_bool(user_snapshot, false, "If true, user-space snapshots are used");
36 DEFINE_bool(io_uring, false, "If true, io_uring feature is enabled");
37 DEFINE_bool(o_direct, false, "If true, enable direct reads on source device");
38 DEFINE_bool(skip_verification, false, "If true, skip verification of partitions");
39 DEFINE_int32(cow_op_merge_size, 0, "number of operations to be processed at once");
40 DEFINE_int32(worker_count, android::snapshot::kNumWorkerThreads,
41 "number of worker threads used to serve I/O requests to dm-user");
42 DEFINE_int32(verify_block_size, 1_MiB, "block sized used during verification of snapshots");
43 DEFINE_int32(num_verify_threads, 3, "number of threads used during verification phase");
44
45 namespace android {
46 namespace snapshot {
47
IsUserspaceSnapshotsEnabled()48 bool Daemon::IsUserspaceSnapshotsEnabled() {
49 const std::string UNKNOWN = "unknown";
50 const std::string vendor_release =
51 android::base::GetProperty("ro.vendor.build.version.release_or_codename", UNKNOWN);
52
53 // If the vendor is on Android S, install process will forcefully take the
54 // userspace snapshots path.
55 //
56 // We will not reach here post OTA reboot as the binary will be from vendor
57 // ramdisk which is on Android S.
58 if (vendor_release.find("12") != std::string::npos) {
59 LOG(INFO) << "Userspace snapshots enabled as vendor partition is on Android: "
60 << vendor_release;
61 return true;
62 }
63
64 return android::base::GetBoolProperty("ro.virtual_ab.userspace.snapshots.enabled", false);
65 }
66
StartDaemon(int argc,char ** argv)67 bool Daemon::StartDaemon(int argc, char** argv) {
68 int arg_start = gflags::ParseCommandLineFlags(&argc, &argv, true);
69
70 // Daemon launched from first stage init and during selinux transition
71 // will have the command line "-user_snapshot" flag set if the user-space
72 // snapshots are enabled.
73 //
74 // Daemon launched as a init service during "socket-handoff" and when OTA
75 // is applied will check for the property. This is ok as the system
76 // properties are valid at this point. We can't do this during first
77 // stage init and hence use the command line flags to get the information.
78 bool user_snapshots = FLAGS_user_snapshot;
79 if (!user_snapshots) {
80 user_snapshots = IsUserspaceSnapshotsEnabled();
81 }
82 if (user_snapshots) {
83 LOG(INFO) << "Starting daemon for user-space snapshots.....";
84 return StartServerForUserspaceSnapshots(arg_start, argc, argv);
85 } else {
86 LOG(ERROR) << "Userspace snapshots not enabled. No support for legacy snapshots";
87 }
88 return false;
89 }
90
StartServerForUserspaceSnapshots(int arg_start,int argc,char ** argv)91 bool Daemon::StartServerForUserspaceSnapshots(int arg_start, int argc, char** argv) {
92 sigfillset(&signal_mask_);
93 sigdelset(&signal_mask_, SIGINT);
94 sigdelset(&signal_mask_, SIGTERM);
95 sigdelset(&signal_mask_, SIGUSR1);
96
97 // Masking signals here ensure that after this point, we won't handle INT/TERM
98 // until after we call into ppoll()
99 signal(SIGINT, Daemon::SignalHandler);
100 signal(SIGTERM, Daemon::SignalHandler);
101 signal(SIGPIPE, Daemon::SignalHandler);
102 signal(SIGUSR1, Daemon::SignalHandler);
103
104 MaskAllSignalsExceptIntAndTerm();
105
106 user_server_.SetServerRunning();
107
108 if (FLAGS_socket_handoff) {
109 return user_server_.RunForSocketHandoff();
110 }
111 if (!FLAGS_no_socket) {
112 if (!user_server_.Start(FLAGS_socket)) {
113 return false;
114 }
115 return user_server_.Run();
116 }
117 for (int i = arg_start; i < argc; i++) {
118 auto parts = android::base::Split(argv[i], ",");
119 if (parts.size() != 4) {
120 LOG(ERROR) << "Malformed message, expected at least four sub-arguments.";
121 return false;
122 }
123 HandlerOptions options = {
124 .num_worker_threads = FLAGS_worker_count,
125 .use_iouring = FLAGS_io_uring,
126 .o_direct = FLAGS_o_direct,
127 .skip_verification = FLAGS_skip_verification,
128 .cow_op_merge_size = static_cast<uint32_t>(FLAGS_cow_op_merge_size),
129 .verify_block_size = static_cast<uint32_t>(FLAGS_verify_block_size),
130 .num_verification_threads = static_cast<uint32_t>(FLAGS_num_verify_threads),
131 };
132 auto handler = user_server_.AddHandler(parts[0], parts[1], parts[2], parts[3], options);
133 if (!handler || !user_server_.StartHandler(parts[0])) {
134 return false;
135 }
136 }
137
138 // We reach this point only during selinux transition during device boot.
139 // At this point, all threads are spin up and are ready to serve the I/O
140 // requests for dm-user. Lets inform init.
141 auto client = std::make_unique<SnapuserdClient>();
142 client->NotifyTransitionDaemonIsReady();
143
144 // Skip the accept() call to avoid spurious log spam. The server will still
145 // run until all handlers have completed.
146 return user_server_.WaitForSocket();
147 }
148
MaskAllSignalsExceptIntAndTerm()149 void Daemon::MaskAllSignalsExceptIntAndTerm() {
150 sigset_t signal_mask;
151 sigfillset(&signal_mask);
152 sigdelset(&signal_mask, SIGINT);
153 sigdelset(&signal_mask, SIGTERM);
154 sigdelset(&signal_mask, SIGPIPE);
155 sigdelset(&signal_mask, SIGUSR1);
156 if (sigprocmask(SIG_SETMASK, &signal_mask, NULL) != 0) {
157 PLOG(ERROR) << "Failed to set sigprocmask";
158 }
159 }
160
MaskAllSignals()161 void Daemon::MaskAllSignals() {
162 sigset_t signal_mask;
163 sigfillset(&signal_mask);
164 if (sigprocmask(SIG_SETMASK, &signal_mask, NULL) != 0) {
165 PLOG(ERROR) << "Couldn't mask all signals";
166 }
167 }
168
Interrupt()169 void Daemon::Interrupt() {
170 // TODO: We cannot access system property during first stage init.
171 // Until we remove the dm-snapshot code, we will have this check
172 // and verify it through a temp variable.
173 if (user_server_.IsServerRunning()) {
174 user_server_.Interrupt();
175 }
176 }
177
ReceivedSocketSignal()178 void Daemon::ReceivedSocketSignal() {
179 if (user_server_.IsServerRunning()) {
180 user_server_.ReceivedSocketSignal();
181 }
182 }
183
SignalHandler(int signal)184 void Daemon::SignalHandler(int signal) {
185 LOG(DEBUG) << "Snapuserd received signal: " << signal;
186 switch (signal) {
187 case SIGINT:
188 case SIGTERM: {
189 Daemon::Instance().Interrupt();
190 break;
191 }
192 case SIGPIPE: {
193 LOG(ERROR) << "Received SIGPIPE signal";
194 break;
195 }
196 case SIGUSR1: {
197 LOG(INFO) << "Received SIGUSR1, attaching to proxy socket";
198 Daemon::Instance().ReceivedSocketSignal();
199 break;
200 }
201 default:
202 LOG(ERROR) << "Received unknown signal " << signal;
203 break;
204 }
205 }
206
207 } // namespace snapshot
208 } // namespace android
209
main(int argc,char ** argv)210 int main(int argc, char** argv) {
211 android::base::InitLogging(argv, &android::base::KernelLogger);
212
213 android::snapshot::Daemon& daemon = android::snapshot::Daemon::Instance();
214
215 if (!daemon.StartDaemon(argc, argv)) {
216 LOG(ERROR) << "Snapuserd daemon failed to start";
217 exit(EXIT_FAILURE);
218 }
219
220 return 0;
221 }
222