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 "snapuserd_daemon.h"
24
25 DEFINE_string(socket, android::snapshot::kSnapuserdSocket, "Named socket or socket path.");
26 DEFINE_bool(no_socket, false,
27 "If true, no socket is used. Each additional argument is an INIT message.");
28 DEFINE_bool(socket_handoff, false,
29 "If true, perform a socket hand-off with an existing snapuserd instance, then exit.");
30 DEFINE_bool(user_snapshot, false, "If true, user-space snapshots are used");
31 DEFINE_bool(io_uring, false, "If true, io_uring feature is enabled");
32
33 namespace android {
34 namespace snapshot {
35
IsUserspaceSnapshotsEnabled()36 bool Daemon::IsUserspaceSnapshotsEnabled() {
37 const std::string UNKNOWN = "unknown";
38 const std::string vendor_release =
39 android::base::GetProperty("ro.vendor.build.version.release_or_codename", UNKNOWN);
40
41 // No user-space snapshots if vendor partition is on Android 12
42 if (vendor_release.find("12") != std::string::npos) {
43 LOG(INFO) << "Userspace snapshots disabled as vendor partition is on Android: "
44 << vendor_release;
45 return false;
46 }
47
48 return android::base::GetBoolProperty("ro.virtual_ab.userspace.snapshots.enabled", false);
49 }
50
IsDmSnapshotTestingEnabled()51 bool Daemon::IsDmSnapshotTestingEnabled() {
52 return android::base::GetBoolProperty("snapuserd.test.dm.snapshots", false);
53 }
54
StartDaemon(int argc,char ** argv)55 bool Daemon::StartDaemon(int argc, char** argv) {
56 int arg_start = gflags::ParseCommandLineFlags(&argc, &argv, true);
57
58 // Daemon launched from first stage init and during selinux transition
59 // will have the command line "-user_snapshot" flag set if the user-space
60 // snapshots are enabled.
61 //
62 // Daemon launched as a init service during "socket-handoff" and when OTA
63 // is applied will check for the property. This is ok as the system
64 // properties are valid at this point. We can't do this during first
65 // stage init and hence use the command line flags to get the information.
66 bool user_snapshots = FLAGS_user_snapshot;
67 if (!user_snapshots) {
68 user_snapshots = (!IsDmSnapshotTestingEnabled() && IsUserspaceSnapshotsEnabled());
69 }
70
71 if (user_snapshots) {
72 LOG(INFO) << "Starting daemon for user-space snapshots.....";
73 return StartServerForUserspaceSnapshots(arg_start, argc, argv);
74 } else {
75 LOG(INFO) << "Starting daemon for dm-snapshots.....";
76 return StartServerForDmSnapshot(arg_start, argc, argv);
77 }
78 }
79
StartServerForUserspaceSnapshots(int arg_start,int argc,char ** argv)80 bool Daemon::StartServerForUserspaceSnapshots(int arg_start, int argc, char** argv) {
81 sigfillset(&signal_mask_);
82 sigdelset(&signal_mask_, SIGINT);
83 sigdelset(&signal_mask_, SIGTERM);
84 sigdelset(&signal_mask_, SIGUSR1);
85
86 // Masking signals here ensure that after this point, we won't handle INT/TERM
87 // until after we call into ppoll()
88 signal(SIGINT, Daemon::SignalHandler);
89 signal(SIGTERM, Daemon::SignalHandler);
90 signal(SIGPIPE, Daemon::SignalHandler);
91 signal(SIGUSR1, Daemon::SignalHandler);
92
93 MaskAllSignalsExceptIntAndTerm();
94
95 user_server_.SetServerRunning();
96 if (FLAGS_io_uring) {
97 user_server_.SetIouringEnabled();
98 }
99
100 if (FLAGS_socket_handoff) {
101 return user_server_.RunForSocketHandoff();
102 }
103 if (!FLAGS_no_socket) {
104 if (!user_server_.Start(FLAGS_socket)) {
105 return false;
106 }
107 return user_server_.Run();
108 }
109
110 for (int i = arg_start; i < argc; i++) {
111 auto parts = android::base::Split(argv[i], ",");
112 if (parts.size() != 4) {
113 LOG(ERROR) << "Malformed message, expected three sub-arguments.";
114 return false;
115 }
116 auto handler = user_server_.AddHandler(parts[0], parts[1], parts[2], parts[3]);
117 if (!handler || !user_server_.StartHandler(handler)) {
118 return false;
119 }
120 }
121
122 // Skip the accept() call to avoid spurious log spam. The server will still
123 // run until all handlers have completed.
124 return user_server_.WaitForSocket();
125 }
126
StartServerForDmSnapshot(int arg_start,int argc,char ** argv)127 bool Daemon::StartServerForDmSnapshot(int arg_start, int argc, char** argv) {
128 sigfillset(&signal_mask_);
129 sigdelset(&signal_mask_, SIGINT);
130 sigdelset(&signal_mask_, SIGTERM);
131 sigdelset(&signal_mask_, SIGUSR1);
132
133 // Masking signals here ensure that after this point, we won't handle INT/TERM
134 // until after we call into ppoll()
135 signal(SIGINT, Daemon::SignalHandler);
136 signal(SIGTERM, Daemon::SignalHandler);
137 signal(SIGPIPE, Daemon::SignalHandler);
138 signal(SIGUSR1, Daemon::SignalHandler);
139
140 MaskAllSignalsExceptIntAndTerm();
141
142 if (FLAGS_socket_handoff) {
143 return server_.RunForSocketHandoff();
144 }
145 if (!FLAGS_no_socket) {
146 if (!server_.Start(FLAGS_socket)) {
147 return false;
148 }
149 return server_.Run();
150 }
151
152 for (int i = arg_start; i < argc; i++) {
153 auto parts = android::base::Split(argv[i], ",");
154 if (parts.size() != 3) {
155 LOG(ERROR) << "Malformed message, expected three sub-arguments.";
156 return false;
157 }
158 auto handler = server_.AddHandler(parts[0], parts[1], parts[2]);
159 if (!handler || !server_.StartHandler(handler)) {
160 return false;
161 }
162 }
163
164 // Skip the accept() call to avoid spurious log spam. The server will still
165 // run until all handlers have completed.
166 return server_.WaitForSocket();
167 }
168
MaskAllSignalsExceptIntAndTerm()169 void Daemon::MaskAllSignalsExceptIntAndTerm() {
170 sigset_t signal_mask;
171 sigfillset(&signal_mask);
172 sigdelset(&signal_mask, SIGINT);
173 sigdelset(&signal_mask, SIGTERM);
174 sigdelset(&signal_mask, SIGPIPE);
175 sigdelset(&signal_mask, SIGUSR1);
176 if (sigprocmask(SIG_SETMASK, &signal_mask, NULL) != 0) {
177 PLOG(ERROR) << "Failed to set sigprocmask";
178 }
179 }
180
MaskAllSignals()181 void Daemon::MaskAllSignals() {
182 sigset_t signal_mask;
183 sigfillset(&signal_mask);
184 if (sigprocmask(SIG_SETMASK, &signal_mask, NULL) != 0) {
185 PLOG(ERROR) << "Couldn't mask all signals";
186 }
187 }
188
Interrupt()189 void Daemon::Interrupt() {
190 // TODO: We cannot access system property during first stage init.
191 // Until we remove the dm-snapshot code, we will have this check
192 // and verify it through a temp variable.
193 if (user_server_.IsServerRunning()) {
194 user_server_.Interrupt();
195 } else {
196 server_.Interrupt();
197 }
198 }
199
ReceivedSocketSignal()200 void Daemon::ReceivedSocketSignal() {
201 if (user_server_.IsServerRunning()) {
202 user_server_.ReceivedSocketSignal();
203 } else {
204 server_.ReceivedSocketSignal();
205 }
206 }
207
SignalHandler(int signal)208 void Daemon::SignalHandler(int signal) {
209 LOG(DEBUG) << "Snapuserd received signal: " << signal;
210 switch (signal) {
211 case SIGINT:
212 case SIGTERM: {
213 Daemon::Instance().Interrupt();
214 break;
215 }
216 case SIGPIPE: {
217 LOG(ERROR) << "Received SIGPIPE signal";
218 break;
219 }
220 case SIGUSR1: {
221 LOG(INFO) << "Received SIGUSR1, attaching to proxy socket";
222 Daemon::Instance().ReceivedSocketSignal();
223 break;
224 }
225 default:
226 LOG(ERROR) << "Received unknown signal " << signal;
227 break;
228 }
229 }
230
231 } // namespace snapshot
232 } // namespace android
233
main(int argc,char ** argv)234 int main(int argc, char** argv) {
235 android::base::InitLogging(argv, &android::base::KernelLogger);
236
237 android::snapshot::Daemon& daemon = android::snapshot::Daemon::Instance();
238
239 if (!daemon.StartDaemon(argc, argv)) {
240 LOG(ERROR) << "Snapuserd daemon failed to start";
241 exit(EXIT_FAILURE);
242 }
243
244 return 0;
245 }
246