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 "snapuserd_daemon.h"
18 
19 #include <android-base/logging.h>
20 #include <android-base/strings.h>
21 #include <gflags/gflags.h>
22 #include <libsnapshot/snapuserd_client.h>
23 
24 #include "snapuserd_server.h"
25 
26 DEFINE_string(socket, android::snapshot::kSnapuserdSocket, "Named socket or socket path.");
27 DEFINE_bool(no_socket, false,
28             "If true, no socket is used. Each additional argument is an INIT message.");
29 
30 namespace android {
31 namespace snapshot {
32 
StartServer(int argc,char ** argv)33 bool Daemon::StartServer(int argc, char** argv) {
34     int arg_start = gflags::ParseCommandLineFlags(&argc, &argv, true);
35 
36     if (!FLAGS_no_socket) {
37         return server_.Start(FLAGS_socket);
38     }
39 
40     for (int i = arg_start; i < argc; i++) {
41         auto parts = android::base::Split(argv[i], ",");
42         if (parts.size() != 3) {
43             LOG(ERROR) << "Malformed message, expected three sub-arguments.";
44             return false;
45         }
46         auto handler = server_.AddHandler(parts[0], parts[1], parts[2]);
47         if (!handler || !server_.StartHandler(handler)) {
48             return false;
49         }
50     }
51 
52     // Skip the accept() call to avoid spurious log spam. The server will still
53     // run until all handlers have completed.
54     server_.SetTerminating();
55     return true;
56 }
57 
MaskAllSignalsExceptIntAndTerm()58 void Daemon::MaskAllSignalsExceptIntAndTerm() {
59     sigset_t signal_mask;
60     sigfillset(&signal_mask);
61     sigdelset(&signal_mask, SIGINT);
62     sigdelset(&signal_mask, SIGTERM);
63     sigdelset(&signal_mask, SIGPIPE);
64     if (sigprocmask(SIG_SETMASK, &signal_mask, NULL) != 0) {
65         PLOG(ERROR) << "Failed to set sigprocmask";
66     }
67 }
68 
MaskAllSignals()69 void Daemon::MaskAllSignals() {
70     sigset_t signal_mask;
71     sigfillset(&signal_mask);
72     if (sigprocmask(SIG_SETMASK, &signal_mask, NULL) != 0) {
73         PLOG(ERROR) << "Couldn't mask all signals";
74     }
75 }
76 
Run()77 void Daemon::Run() {
78     sigfillset(&signal_mask_);
79     sigdelset(&signal_mask_, SIGINT);
80     sigdelset(&signal_mask_, SIGTERM);
81 
82     // Masking signals here ensure that after this point, we won't handle INT/TERM
83     // until after we call into ppoll()
84     signal(SIGINT, Daemon::SignalHandler);
85     signal(SIGTERM, Daemon::SignalHandler);
86     signal(SIGPIPE, Daemon::SignalHandler);
87 
88     LOG(DEBUG) << "Snapuserd-server: ready to accept connections";
89 
90     MaskAllSignalsExceptIntAndTerm();
91 
92     server_.Run();
93 }
94 
Interrupt()95 void Daemon::Interrupt() {
96     server_.Interrupt();
97 }
98 
SignalHandler(int signal)99 void Daemon::SignalHandler(int signal) {
100     LOG(DEBUG) << "Snapuserd received signal: " << signal;
101     switch (signal) {
102         case SIGINT:
103         case SIGTERM: {
104             Daemon::Instance().Interrupt();
105             break;
106         }
107         case SIGPIPE: {
108             LOG(ERROR) << "Received SIGPIPE signal";
109             break;
110         }
111         default:
112             LOG(ERROR) << "Received unknown signal " << signal;
113             break;
114     }
115 }
116 
117 }  // namespace snapshot
118 }  // namespace android
119 
main(int argc,char ** argv)120 int main(int argc, char** argv) {
121     android::base::InitLogging(argv, &android::base::KernelLogger);
122 
123     android::snapshot::Daemon& daemon = android::snapshot::Daemon::Instance();
124 
125     if (!daemon.StartServer(argc, argv)) {
126         LOG(ERROR) << "Snapuserd daemon failed to start.";
127         exit(EXIT_FAILURE);
128     }
129     daemon.Run();
130 
131     return 0;
132 }
133