• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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