• 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 "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