blob: 03c00640f6725276727432c3b96b66acfc79a45d [file] [log] [blame]
Tom Cherrybac32992015-07-31 12:45:25 -07001/*
2 * Copyright (C) 2015 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 "service.h"
18
19#include <fcntl.h>
Jorge Lucangeli Obes1b3fa3d2016-04-21 15:35:09 -070020#include <sched.h>
21#include <sys/mount.h>
22#include <sys/prctl.h>
Vitalii Tomkiv081705c2016-05-18 17:36:30 -070023#include <sys/resource.h>
Tom Cherrybac32992015-07-31 12:45:25 -070024#include <sys/stat.h>
Vitalii Tomkiv081705c2016-05-18 17:36:30 -070025#include <sys/time.h>
Tom Cherrybac32992015-07-31 12:45:25 -070026#include <sys/types.h>
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -080027#include <sys/wait.h>
Tom Cherrybac32992015-07-31 12:45:25 -070028#include <termios.h>
Dan Albertaf9ba4d2015-08-11 16:37:04 -070029#include <unistd.h>
Tom Cherrybac32992015-07-31 12:45:25 -070030
31#include <selinux/selinux.h>
32
Elliott Hughes4f713192015-12-04 22:00:26 -080033#include <android-base/file.h>
34#include <android-base/stringprintf.h>
Elliott Hughesf86b5a62016-06-24 15:12:21 -070035#include <android-base/strings.h>
Tom Cherrybac32992015-07-31 12:45:25 -070036#include <cutils/android_reboot.h>
37#include <cutils/sockets.h>
Vitalii Tomkiv081705c2016-05-18 17:36:30 -070038#include <system/thread_defs.h>
Tom Cherrybac32992015-07-31 12:45:25 -070039
Collin Mullinerf7e79b92016-06-01 21:03:55 +000040#include <processgroup/processgroup.h>
41
Tom Cherrybac32992015-07-31 12:45:25 -070042#include "action.h"
43#include "init.h"
44#include "init_parser.h"
Tom Cherrybac32992015-07-31 12:45:25 -070045#include "log.h"
46#include "property_service.h"
47#include "util.h"
48
Tom Cherryb7349902015-08-26 11:43:36 -070049using android::base::StringPrintf;
50using android::base::WriteStringToFile;
51
Tom Cherrybac32992015-07-31 12:45:25 -070052#define CRITICAL_CRASH_THRESHOLD 4 // if we crash >4 times ...
53#define CRITICAL_CRASH_WINDOW (4*60) // ... in 4 minutes, goto recovery
54
Jorge Lucangeli Obes1b3fa3d2016-04-21 15:35:09 -070055static void SetUpPidNamespace(const std::string& service_name) {
56 constexpr unsigned int kSafeFlags = MS_NODEV | MS_NOEXEC | MS_NOSUID;
57
58 // It's OK to LOG(FATAL) in this function since it's running in the first
59 // child process.
60 if (mount("", "/proc", "proc", kSafeFlags | MS_REMOUNT, "") == -1) {
61 PLOG(FATAL) << "couldn't remount(/proc)";
62 }
63
64 if (prctl(PR_SET_NAME, service_name.c_str()) == -1) {
65 PLOG(FATAL) << "couldn't set name";
66 }
67
68 pid_t child_pid = fork();
69 if (child_pid == -1) {
70 PLOG(FATAL) << "couldn't fork init inside the PID namespace";
71 }
72
73 if (child_pid > 0) {
74 // So that we exit with the right status.
75 static int init_exitstatus = 0;
76 signal(SIGTERM, [](int) { _exit(init_exitstatus); });
77
78 pid_t waited_pid;
79 int status;
80 while ((waited_pid = wait(&status)) > 0) {
81 // This loop will end when there are no processes left inside the
82 // PID namespace or when the init process inside the PID namespace
83 // gets a signal.
84 if (waited_pid == child_pid) {
85 init_exitstatus = status;
86 }
87 }
88 if (!WIFEXITED(init_exitstatus)) {
89 _exit(EXIT_FAILURE);
90 }
91 _exit(WEXITSTATUS(init_exitstatus));
92 }
93}
94
Tom Cherrybac32992015-07-31 12:45:25 -070095SocketInfo::SocketInfo() : uid(0), gid(0), perm(0) {
96}
97
98SocketInfo::SocketInfo(const std::string& name, const std::string& type, uid_t uid,
99 gid_t gid, int perm, const std::string& socketcon)
100 : name(name), type(type), uid(uid), gid(gid), perm(perm), socketcon(socketcon) {
101}
102
103ServiceEnvironmentInfo::ServiceEnvironmentInfo() {
104}
105
106ServiceEnvironmentInfo::ServiceEnvironmentInfo(const std::string& name,
107 const std::string& value)
108 : name(name), value(value) {
109}
110
111Service::Service(const std::string& name, const std::string& classname,
112 const std::vector<std::string>& args)
113 : name_(name), classname_(classname), flags_(0), pid_(0), time_started_(0),
Jorge Lucangeli Obes1b3fa3d2016-04-21 15:35:09 -0700114 time_crashed_(0), nr_crashed_(0), uid_(0), gid_(0), namespace_flags_(0),
115 seclabel_(""), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0),
116 priority_(0), args_(args) {
Tom Cherrybac32992015-07-31 12:45:25 -0700117 onrestart_.InitSingleTrigger("onrestart");
118}
119
120Service::Service(const std::string& name, const std::string& classname,
Jorge Lucangeli Obes1b3fa3d2016-04-21 15:35:09 -0700121 unsigned flags, uid_t uid, gid_t gid,
122 const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
123 const std::string& seclabel,
124 const std::vector<std::string>& args)
125 : name_(name), classname_(classname), flags_(flags), pid_(0),
126 time_started_(0), time_crashed_(0), nr_crashed_(0), uid_(uid), gid_(gid),
127 supp_gids_(supp_gids), namespace_flags_(namespace_flags),
128 seclabel_(seclabel), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0),
129 priority_(0), args_(args) {
Tom Cherrybac32992015-07-31 12:45:25 -0700130 onrestart_.InitSingleTrigger("onrestart");
131}
132
133void Service::NotifyStateChange(const std::string& new_state) const {
Tom Cherrybac32992015-07-31 12:45:25 -0700134 if ((flags_ & SVC_EXEC) != 0) {
135 // 'exec' commands don't have properties tracking their state.
136 return;
137 }
138
Tom Cherryb7349902015-08-26 11:43:36 -0700139 std::string prop_name = StringPrintf("init.svc.%s", name_.c_str());
Tom Cherrybac32992015-07-31 12:45:25 -0700140 if (prop_name.length() >= PROP_NAME_MAX) {
141 // If the property name would be too long, we can't set it.
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700142 LOG(ERROR) << "Property name \"init.svc." << name_ << "\" too long; not setting to " << new_state;
Tom Cherrybac32992015-07-31 12:45:25 -0700143 return;
144 }
145
146 property_set(prop_name.c_str(), new_state.c_str());
147}
148
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700149void Service::KillProcessGroup(int signal) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700150 LOG(VERBOSE) << "Sending signal " << signal
151 << " to service '" << name_
152 << "' (pid " << pid_ << ") process group...\n",
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700153 kill(pid_, signal);
154 killProcessGroup(uid_, pid_, signal);
155}
156
Tom Cherrybac32992015-07-31 12:45:25 -0700157bool Service::Reap() {
158 if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) {
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700159 KillProcessGroup(SIGKILL);
Tom Cherrybac32992015-07-31 12:45:25 -0700160 }
161
162 // Remove any sockets we may have created.
163 for (const auto& si : sockets_) {
Tom Cherryb7349902015-08-26 11:43:36 -0700164 std::string tmp = StringPrintf(ANDROID_SOCKET_DIR "/%s", si.name.c_str());
Tom Cherrybac32992015-07-31 12:45:25 -0700165 unlink(tmp.c_str());
166 }
167
168 if (flags_ & SVC_EXEC) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700169 LOG(INFO) << "SVC_EXEC pid " << pid_ << " finished...";
Tom Cherrybac32992015-07-31 12:45:25 -0700170 return true;
171 }
172
173 pid_ = 0;
174 flags_ &= (~SVC_RUNNING);
175
176 // Oneshot processes go into the disabled state on exit,
177 // except when manually restarted.
178 if ((flags_ & SVC_ONESHOT) && !(flags_ & SVC_RESTART)) {
179 flags_ |= SVC_DISABLED;
180 }
181
182 // Disabled and reset processes do not get restarted automatically.
183 if (flags_ & (SVC_DISABLED | SVC_RESET)) {
184 NotifyStateChange("stopped");
185 return false;
186 }
187
188 time_t now = gettime();
189 if ((flags_ & SVC_CRITICAL) && !(flags_ & SVC_RESTART)) {
190 if (time_crashed_ + CRITICAL_CRASH_WINDOW >= now) {
191 if (++nr_crashed_ > CRITICAL_CRASH_THRESHOLD) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700192 LOG(ERROR) << "critical process '" << name_ << "' exited "
193 << CRITICAL_CRASH_THRESHOLD << " times in "
194 << (CRITICAL_CRASH_WINDOW / 60) << " minutes; "
195 << "rebooting into recovery mode";
Tom Cherrybac32992015-07-31 12:45:25 -0700196 android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
197 return false;
198 }
199 } else {
200 time_crashed_ = now;
201 nr_crashed_ = 1;
202 }
203 }
204
205 flags_ &= (~SVC_RESTART);
206 flags_ |= SVC_RESTARTING;
207
208 // Execute all onrestart commands for this service.
209 onrestart_.ExecuteAllCommands();
210
211 NotifyStateChange("restarting");
212 return false;
213}
214
215void Service::DumpState() const {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700216 LOG(INFO) << "service " << name_;
217 LOG(INFO) << " class '" << classname_ << "'";
218 LOG(INFO) << " exec "<< android::base::Join(args_, " ");
Tom Cherrybac32992015-07-31 12:45:25 -0700219 for (const auto& si : sockets_) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700220 LOG(INFO) << " socket " << si.name << " " << si.type << " " << std::oct << si.perm;
Tom Cherrybac32992015-07-31 12:45:25 -0700221 }
222}
223
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400224bool Service::ParseClass(const std::vector<std::string>& args, std::string* err) {
Tom Cherryb7349902015-08-26 11:43:36 -0700225 classname_ = args[1];
226 return true;
227}
Tom Cherrybac32992015-07-31 12:45:25 -0700228
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400229bool Service::ParseConsole(const std::vector<std::string>& args, std::string* err) {
Tom Cherryb7349902015-08-26 11:43:36 -0700230 flags_ |= SVC_CONSOLE;
Viorel Suman70daa672016-03-21 10:08:07 +0200231 console_ = args.size() > 1 ? "/dev/" + args[1] : "";
Tom Cherryb7349902015-08-26 11:43:36 -0700232 return true;
233}
Tom Cherrybac32992015-07-31 12:45:25 -0700234
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400235bool Service::ParseCritical(const std::vector<std::string>& args, std::string* err) {
Tom Cherryb7349902015-08-26 11:43:36 -0700236 flags_ |= SVC_CRITICAL;
237 return true;
238}
Tom Cherrybac32992015-07-31 12:45:25 -0700239
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400240bool Service::ParseDisabled(const std::vector<std::string>& args, std::string* err) {
Tom Cherryb7349902015-08-26 11:43:36 -0700241 flags_ |= SVC_DISABLED;
242 flags_ |= SVC_RC_DISABLED;
243 return true;
244}
Tom Cherrybac32992015-07-31 12:45:25 -0700245
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400246bool Service::ParseGroup(const std::vector<std::string>& args, std::string* err) {
Tom Cherryb7349902015-08-26 11:43:36 -0700247 gid_ = decode_uid(args[1].c_str());
248 for (std::size_t n = 2; n < args.size(); n++) {
249 supp_gids_.emplace_back(decode_uid(args[n].c_str()));
Tom Cherrybac32992015-07-31 12:45:25 -0700250 }
251 return true;
252}
253
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400254bool Service::ParsePriority(const std::vector<std::string>& args, std::string* err) {
Vitalii Tomkiv081705c2016-05-18 17:36:30 -0700255 priority_ = std::stoi(args[1]);
256
257 if (priority_ < ANDROID_PRIORITY_HIGHEST || priority_ > ANDROID_PRIORITY_LOWEST) {
258 priority_ = 0;
259 *err = StringPrintf("process priority value must be range %d - %d",
260 ANDROID_PRIORITY_HIGHEST, ANDROID_PRIORITY_LOWEST);
261 return false;
262 }
263
264 return true;
265}
266
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400267bool Service::ParseIoprio(const std::vector<std::string>& args, std::string* err) {
Tom Cherryb7349902015-08-26 11:43:36 -0700268 ioprio_pri_ = std::stoul(args[2], 0, 8);
269
270 if (ioprio_pri_ < 0 || ioprio_pri_ > 7) {
271 *err = "priority value must be range 0 - 7";
272 return false;
273 }
274
275 if (args[1] == "rt") {
276 ioprio_class_ = IoSchedClass_RT;
277 } else if (args[1] == "be") {
278 ioprio_class_ = IoSchedClass_BE;
279 } else if (args[1] == "idle") {
280 ioprio_class_ = IoSchedClass_IDLE;
281 } else {
282 *err = "ioprio option usage: ioprio <rt|be|idle> <0-7>";
283 return false;
284 }
285
286 return true;
287}
288
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400289bool Service::ParseKeycodes(const std::vector<std::string>& args, std::string* err) {
Tom Cherryb7349902015-08-26 11:43:36 -0700290 for (std::size_t i = 1; i < args.size(); i++) {
291 keycodes_.emplace_back(std::stoi(args[i]));
292 }
293 return true;
294}
295
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400296bool Service::ParseOneshot(const std::vector<std::string>& args, std::string* err) {
Tom Cherryb7349902015-08-26 11:43:36 -0700297 flags_ |= SVC_ONESHOT;
298 return true;
299}
300
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400301bool Service::ParseOnrestart(const std::vector<std::string>& args, std::string* err) {
Tom Cherryb7349902015-08-26 11:43:36 -0700302 std::vector<std::string> str_args(args.begin() + 1, args.end());
303 onrestart_.AddCommand(str_args, "", 0, err);
304 return true;
305}
306
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400307bool Service::ParseNamespace(const std::vector<std::string>& args, std::string* err) {
Jorge Lucangeli Obes1b3fa3d2016-04-21 15:35:09 -0700308 for (size_t i = 1; i < args.size(); i++) {
309 if (args[i] == "pid") {
310 namespace_flags_ |= CLONE_NEWPID;
311 // PID namespaces require mount namespaces.
312 namespace_flags_ |= CLONE_NEWNS;
313 } else if (args[i] == "mnt") {
314 namespace_flags_ |= CLONE_NEWNS;
315 } else {
316 *err = "namespace must be 'pid' or 'mnt'";
317 return false;
318 }
319 }
320 return true;
321}
322
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400323bool Service::ParseSeclabel(const std::vector<std::string>& args, std::string* err) {
Tom Cherryb7349902015-08-26 11:43:36 -0700324 seclabel_ = args[1];
325 return true;
326}
327
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400328bool Service::ParseSetenv(const std::vector<std::string>& args, std::string* err) {
Tom Cherryb7349902015-08-26 11:43:36 -0700329 envvars_.emplace_back(args[1], args[2]);
330 return true;
331}
332
333/* name type perm [ uid gid context ] */
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400334bool Service::ParseSocket(const std::vector<std::string>& args, std::string* err) {
Tom Cherryb7349902015-08-26 11:43:36 -0700335 if (args[2] != "dgram" && args[2] != "stream" && args[2] != "seqpacket") {
336 *err = "socket type must be 'dgram', 'stream' or 'seqpacket'";
337 return false;
338 }
339
340 int perm = std::stoul(args[3], 0, 8);
341 uid_t uid = args.size() > 4 ? decode_uid(args[4].c_str()) : 0;
342 gid_t gid = args.size() > 5 ? decode_uid(args[5].c_str()) : 0;
343 std::string socketcon = args.size() > 6 ? args[6] : "";
344
345 sockets_.emplace_back(args[1], args[2], uid, gid, perm, socketcon);
346 return true;
347}
348
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400349bool Service::ParseUser(const std::vector<std::string>& args, std::string* err) {
Tom Cherryb7349902015-08-26 11:43:36 -0700350 uid_ = decode_uid(args[1].c_str());
351 return true;
352}
353
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400354bool Service::ParseWritepid(const std::vector<std::string>& args, std::string* err) {
Tom Cherryb7349902015-08-26 11:43:36 -0700355 writepid_files_.assign(args.begin() + 1, args.end());
356 return true;
357}
358
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400359class Service::OptionParserMap : public KeywordMap<OptionParser> {
Tom Cherryb7349902015-08-26 11:43:36 -0700360public:
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400361 OptionParserMap() {
Tom Cherryb7349902015-08-26 11:43:36 -0700362 }
363private:
364 Map& map() const override;
365};
366
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400367Service::OptionParserMap::Map& Service::OptionParserMap::map() const {
Tom Cherryb7349902015-08-26 11:43:36 -0700368 constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400369 static const Map option_parsers = {
370 {"class", {1, 1, &Service::ParseClass}},
371 {"console", {0, 1, &Service::ParseConsole}},
372 {"critical", {0, 0, &Service::ParseCritical}},
373 {"disabled", {0, 0, &Service::ParseDisabled}},
374 {"group", {1, NR_SVC_SUPP_GIDS + 1, &Service::ParseGroup}},
375 {"ioprio", {2, 2, &Service::ParseIoprio}},
376 {"priority", {1, 1, &Service::ParsePriority}},
377 {"keycodes", {1, kMax, &Service::ParseKeycodes}},
378 {"oneshot", {0, 0, &Service::ParseOneshot}},
379 {"onrestart", {1, kMax, &Service::ParseOnrestart}},
380 {"namespace", {1, 2, &Service::ParseNamespace}},
381 {"seclabel", {1, 1, &Service::ParseSeclabel}},
382 {"setenv", {2, 2, &Service::ParseSetenv}},
383 {"socket", {3, 6, &Service::ParseSocket}},
384 {"user", {1, 1, &Service::ParseUser}},
385 {"writepid", {1, kMax, &Service::ParseWritepid}},
Tom Cherryb7349902015-08-26 11:43:36 -0700386 };
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400387 return option_parsers;
Tom Cherryb7349902015-08-26 11:43:36 -0700388}
389
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400390bool Service::ParseLine(const std::vector<std::string>& args, std::string* err) {
Tom Cherryb7349902015-08-26 11:43:36 -0700391 if (args.empty()) {
392 *err = "option needed, but not provided";
393 return false;
394 }
395
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400396 static const OptionParserMap parser_map;
397 auto parser = parser_map.FindFunction(args[0], args.size() - 1, err);
Tom Cherryb7349902015-08-26 11:43:36 -0700398
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400399 if (!parser) {
Tom Cherryb7349902015-08-26 11:43:36 -0700400 return false;
401 }
402
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400403 return (this->*parser)(args, err);
Tom Cherryb7349902015-08-26 11:43:36 -0700404}
405
Elliott Hughesbdeac392016-04-12 15:38:27 -0700406bool Service::Start() {
Tom Cherrybac32992015-07-31 12:45:25 -0700407 // Starting a service removes it from the disabled or reset state and
408 // immediately takes it out of the restarting state if it was in there.
409 flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));
410 time_started_ = 0;
411
412 // Running processes require no additional work --- if they're in the
413 // process of exiting, we've ensured that they will immediately restart
414 // on exit, unless they are ONESHOT.
415 if (flags_ & SVC_RUNNING) {
416 return false;
417 }
418
419 bool needs_console = (flags_ & SVC_CONSOLE);
Viorel Suman70daa672016-03-21 10:08:07 +0200420 if (needs_console) {
421 if (console_.empty()) {
422 console_ = default_console;
423 }
424
425 bool have_console = (open(console_.c_str(), O_RDWR | O_CLOEXEC) != -1);
426 if (!have_console) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700427 PLOG(ERROR) << "service '" << name_ << "' couldn't open console '" << console_ << "'";
Viorel Suman70daa672016-03-21 10:08:07 +0200428 flags_ |= SVC_DISABLED;
429 return false;
430 }
Tom Cherrybac32992015-07-31 12:45:25 -0700431 }
432
433 struct stat sb;
434 if (stat(args_[0].c_str(), &sb) == -1) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700435 PLOG(ERROR) << "cannot find '" << args_[0] << "', disabling '" << name_ << "'";
Tom Cherrybac32992015-07-31 12:45:25 -0700436 flags_ |= SVC_DISABLED;
437 return false;
438 }
439
Tom Cherrybac32992015-07-31 12:45:25 -0700440 std::string scon;
441 if (!seclabel_.empty()) {
442 scon = seclabel_;
443 } else {
444 char* mycon = nullptr;
445 char* fcon = nullptr;
446
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700447 LOG(INFO) << "computing context for service '" << args_[0] << "'";
Tom Cherrybac32992015-07-31 12:45:25 -0700448 int rc = getcon(&mycon);
449 if (rc < 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700450 LOG(ERROR) << "could not get context while starting '" << name_ << "'";
Tom Cherrybac32992015-07-31 12:45:25 -0700451 return false;
452 }
453
454 rc = getfilecon(args_[0].c_str(), &fcon);
455 if (rc < 0) {
Jorge Lucangeli Obes1b3fa3d2016-04-21 15:35:09 -0700456 LOG(ERROR) << "could not get file context while starting '" << name_ << "'";
Tom Cherrybac32992015-07-31 12:45:25 -0700457 free(mycon);
458 return false;
459 }
460
461 char* ret_scon = nullptr;
462 rc = security_compute_create(mycon, fcon, string_to_security_class("process"),
463 &ret_scon);
464 if (rc == 0) {
465 scon = ret_scon;
466 free(ret_scon);
467 }
468 if (rc == 0 && scon == mycon) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700469 LOG(ERROR) << "Service " << name_ << " does not have a SELinux domain defined.";
Tom Cherrybac32992015-07-31 12:45:25 -0700470 free(mycon);
471 free(fcon);
472 return false;
473 }
474 free(mycon);
475 free(fcon);
476 if (rc < 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700477 LOG(ERROR) << "could not get context while starting '" << name_ << "'";
Tom Cherrybac32992015-07-31 12:45:25 -0700478 return false;
479 }
480 }
481
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700482 LOG(VERBOSE) << "Starting service '" << name_ << "'...";
Tom Cherrybac32992015-07-31 12:45:25 -0700483
Jorge Lucangeli Obes1b3fa3d2016-04-21 15:35:09 -0700484 pid_t pid = -1;
485 if (namespace_flags_) {
486 pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD,
487 nullptr);
488 } else {
489 pid = fork();
490 }
491
Tom Cherrybac32992015-07-31 12:45:25 -0700492 if (pid == 0) {
Tom Cherrybac32992015-07-31 12:45:25 -0700493 umask(077);
Tom Cherrybac32992015-07-31 12:45:25 -0700494
Jorge Lucangeli Obes1b3fa3d2016-04-21 15:35:09 -0700495 if (namespace_flags_ & CLONE_NEWPID) {
496 // This will fork again to run an init process inside the PID
497 // namespace.
498 SetUpPidNamespace(name_);
499 }
500
Tom Cherrybac32992015-07-31 12:45:25 -0700501 for (const auto& ei : envvars_) {
502 add_environment(ei.name.c_str(), ei.value.c_str());
503 }
504
505 for (const auto& si : sockets_) {
506 int socket_type = ((si.type == "stream" ? SOCK_STREAM :
507 (si.type == "dgram" ? SOCK_DGRAM :
508 SOCK_SEQPACKET)));
509 const char* socketcon =
510 !si.socketcon.empty() ? si.socketcon.c_str() : scon.c_str();
511
512 int s = create_socket(si.name.c_str(), socket_type, si.perm,
513 si.uid, si.gid, socketcon);
514 if (s >= 0) {
515 PublishSocket(si.name, s);
516 }
517 }
518
Anestis Bechtsoudisb702b462016-02-05 16:38:48 +0200519 std::string pid_str = StringPrintf("%d", getpid());
Tom Cherrybac32992015-07-31 12:45:25 -0700520 for (const auto& file : writepid_files_) {
Tom Cherryb7349902015-08-26 11:43:36 -0700521 if (!WriteStringToFile(pid_str, file)) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700522 PLOG(ERROR) << "couldn't write " << pid_str << " to " << file;
Tom Cherrybac32992015-07-31 12:45:25 -0700523 }
524 }
525
526 if (ioprio_class_ != IoSchedClass_NONE) {
527 if (android_set_ioprio(getpid(), ioprio_class_, ioprio_pri_)) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700528 PLOG(ERROR) << "Failed to set pid " << getpid()
529 << " ioprio=" << ioprio_class_ << "," << ioprio_pri_;
Tom Cherrybac32992015-07-31 12:45:25 -0700530 }
531 }
532
533 if (needs_console) {
534 setsid();
535 OpenConsole();
536 } else {
537 ZapStdio();
538 }
539
540 setpgid(0, getpid());
541
542 // As requested, set our gid, supplemental gids, and uid.
543 if (gid_) {
544 if (setgid(gid_) != 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700545 PLOG(ERROR) << "setgid failed";
Tom Cherrybac32992015-07-31 12:45:25 -0700546 _exit(127);
547 }
548 }
549 if (!supp_gids_.empty()) {
550 if (setgroups(supp_gids_.size(), &supp_gids_[0]) != 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700551 PLOG(ERROR) << "setgroups failed";
Tom Cherrybac32992015-07-31 12:45:25 -0700552 _exit(127);
553 }
554 }
555 if (uid_) {
556 if (setuid(uid_) != 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700557 PLOG(ERROR) << "setuid failed";
Tom Cherrybac32992015-07-31 12:45:25 -0700558 _exit(127);
559 }
560 }
561 if (!seclabel_.empty()) {
562 if (setexeccon(seclabel_.c_str()) < 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700563 PLOG(ERROR) << "cannot setexeccon('" << seclabel_ << "')";
Tom Cherrybac32992015-07-31 12:45:25 -0700564 _exit(127);
565 }
566 }
Vitalii Tomkiv081705c2016-05-18 17:36:30 -0700567 if (priority_ != 0) {
568 if (setpriority(PRIO_PROCESS, 0, priority_) != 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700569 PLOG(ERROR) << "setpriority failed";
Vitalii Tomkiv081705c2016-05-18 17:36:30 -0700570 _exit(127);
571 }
572 }
Tom Cherrybac32992015-07-31 12:45:25 -0700573
Tom Cherrybac35362016-06-07 11:22:00 -0700574 std::vector<std::string> expanded_args;
Tom Cherrybac32992015-07-31 12:45:25 -0700575 std::vector<char*> strs;
Tom Cherrybac35362016-06-07 11:22:00 -0700576 expanded_args.resize(args_.size());
577 strs.push_back(const_cast<char*>(args_[0].c_str()));
578 for (std::size_t i = 1; i < args_.size(); ++i) {
579 if (!expand_props(args_[i], &expanded_args[i])) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700580 LOG(ERROR) << args_[0] << ": cannot expand '" << args_[i] << "'";
Tom Cherrybac35362016-06-07 11:22:00 -0700581 _exit(127);
582 }
583 strs.push_back(const_cast<char*>(expanded_args[i].c_str()));
Tom Cherrybac32992015-07-31 12:45:25 -0700584 }
Tom Cherrybac32992015-07-31 12:45:25 -0700585 strs.push_back(nullptr);
Tom Cherrybac35362016-06-07 11:22:00 -0700586
587 if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700588 PLOG(ERROR) << "cannot execve('" << strs[0] << "')";
Tom Cherrybac32992015-07-31 12:45:25 -0700589 }
590
591 _exit(127);
592 }
593
594 if (pid < 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700595 PLOG(ERROR) << "failed to fork for '" << name_ << "'";
Tom Cherrybac32992015-07-31 12:45:25 -0700596 pid_ = 0;
597 return false;
598 }
599
600 time_started_ = gettime();
601 pid_ = pid;
602 flags_ |= SVC_RUNNING;
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700603
604 errno = -createProcessGroup(uid_, pid_);
605 if (errno != 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700606 PLOG(ERROR) << "createProcessGroup(" << uid_ << ", " << pid_ << ") failed for service '" << name_ << "'";
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700607 }
Tom Cherrybac32992015-07-31 12:45:25 -0700608
609 if ((flags_ & SVC_EXEC) != 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700610 LOG(INFO) << android::base::StringPrintf("SVC_EXEC pid %d (uid %d gid %d+%zu context %s) started; waiting...",
611 pid_, uid_, gid_, supp_gids_.size(),
612 !seclabel_.empty() ? seclabel_.c_str() : "default");
Tom Cherrybac32992015-07-31 12:45:25 -0700613 }
614
615 NotifyStateChange("running");
616 return true;
617}
618
Tom Cherrybac32992015-07-31 12:45:25 -0700619bool Service::StartIfNotDisabled() {
620 if (!(flags_ & SVC_DISABLED)) {
621 return Start();
622 } else {
623 flags_ |= SVC_DISABLED_START;
624 }
625 return true;
626}
627
628bool Service::Enable() {
629 flags_ &= ~(SVC_DISABLED | SVC_RC_DISABLED);
630 if (flags_ & SVC_DISABLED_START) {
631 return Start();
632 }
633 return true;
634}
635
636void Service::Reset() {
637 StopOrReset(SVC_RESET);
638}
639
640void Service::Stop() {
641 StopOrReset(SVC_DISABLED);
642}
643
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800644void Service::Terminate() {
645 flags_ &= ~(SVC_RESTARTING | SVC_DISABLED_START);
646 flags_ |= SVC_DISABLED;
647 if (pid_) {
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700648 KillProcessGroup(SIGTERM);
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800649 NotifyStateChange("stopping");
650 }
651}
652
Tom Cherrybac32992015-07-31 12:45:25 -0700653void Service::Restart() {
654 if (flags_ & SVC_RUNNING) {
655 /* Stop, wait, then start the service. */
656 StopOrReset(SVC_RESTART);
657 } else if (!(flags_ & SVC_RESTARTING)) {
658 /* Just start the service since it's not running. */
659 Start();
660 } /* else: Service is restarting anyways. */
661}
662
663void Service::RestartIfNeeded(time_t& process_needs_restart) {
664 time_t next_start_time = time_started_ + 5;
665
666 if (next_start_time <= gettime()) {
667 flags_ &= (~SVC_RESTARTING);
668 Start();
669 return;
670 }
671
672 if ((next_start_time < process_needs_restart) ||
673 (process_needs_restart == 0)) {
674 process_needs_restart = next_start_time;
675 }
676}
677
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700678// The how field should be either SVC_DISABLED, SVC_RESET, or SVC_RESTART.
Tom Cherrybac32992015-07-31 12:45:25 -0700679void Service::StopOrReset(int how) {
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700680 // The service is still SVC_RUNNING until its process exits, but if it has
681 // already exited it shoudn't attempt a restart yet.
Tom Cherrybac32992015-07-31 12:45:25 -0700682 flags_ &= ~(SVC_RESTARTING | SVC_DISABLED_START);
683
684 if ((how != SVC_DISABLED) && (how != SVC_RESET) && (how != SVC_RESTART)) {
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700685 // An illegal flag: default to SVC_DISABLED.
Tom Cherrybac32992015-07-31 12:45:25 -0700686 how = SVC_DISABLED;
687 }
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700688
689 // If the service has not yet started, prevent it from auto-starting with its class.
Tom Cherrybac32992015-07-31 12:45:25 -0700690 if (how == SVC_RESET) {
691 flags_ |= (flags_ & SVC_RC_DISABLED) ? SVC_DISABLED : SVC_RESET;
692 } else {
693 flags_ |= how;
694 }
695
696 if (pid_) {
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700697 KillProcessGroup(SIGKILL);
Tom Cherrybac32992015-07-31 12:45:25 -0700698 NotifyStateChange("stopping");
699 } else {
700 NotifyStateChange("stopped");
701 }
702}
703
704void Service::ZapStdio() const {
705 int fd;
706 fd = open("/dev/null", O_RDWR);
707 dup2(fd, 0);
708 dup2(fd, 1);
709 dup2(fd, 2);
710 close(fd);
711}
712
713void Service::OpenConsole() const {
Viorel Suman70daa672016-03-21 10:08:07 +0200714 int fd = open(console_.c_str(), O_RDWR);
715 if (fd == -1) fd = open("/dev/null", O_RDWR);
Tom Cherrybac32992015-07-31 12:45:25 -0700716 ioctl(fd, TIOCSCTTY, 0);
717 dup2(fd, 0);
718 dup2(fd, 1);
719 dup2(fd, 2);
720 close(fd);
721}
722
723void Service::PublishSocket(const std::string& name, int fd) const {
Tom Cherryb7349902015-08-26 11:43:36 -0700724 std::string key = StringPrintf(ANDROID_SOCKET_ENV_PREFIX "%s", name.c_str());
725 std::string val = StringPrintf("%d", fd);
Tom Cherrybac32992015-07-31 12:45:25 -0700726 add_environment(key.c_str(), val.c_str());
727
728 /* make sure we don't close-on-exec */
729 fcntl(fd, F_SETFD, 0);
730}
731
732int ServiceManager::exec_count_ = 0;
733
734ServiceManager::ServiceManager() {
735}
736
737ServiceManager& ServiceManager::GetInstance() {
738 static ServiceManager instance;
739 return instance;
740}
741
Tom Cherryb7349902015-08-26 11:43:36 -0700742void ServiceManager::AddService(std::unique_ptr<Service> service) {
743 Service* old_service = FindServiceByName(service->name());
744 if (old_service) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700745 LOG(ERROR) << "ignored duplicate definition of service '" << service->name() << "'";
Tom Cherryb7349902015-08-26 11:43:36 -0700746 return;
Tom Cherrybac32992015-07-31 12:45:25 -0700747 }
Tom Cherryb7349902015-08-26 11:43:36 -0700748 services_.emplace_back(std::move(service));
Tom Cherrybac32992015-07-31 12:45:25 -0700749}
750
751Service* ServiceManager::MakeExecOneshotService(const std::vector<std::string>& args) {
752 // Parse the arguments: exec [SECLABEL [UID [GID]*] --] COMMAND ARGS...
753 // SECLABEL can be a - to denote default
754 std::size_t command_arg = 1;
755 for (std::size_t i = 1; i < args.size(); ++i) {
756 if (args[i] == "--") {
757 command_arg = i + 1;
758 break;
759 }
760 }
761 if (command_arg > 4 + NR_SVC_SUPP_GIDS) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700762 LOG(ERROR) << "exec called with too many supplementary group ids";
Tom Cherrybac32992015-07-31 12:45:25 -0700763 return nullptr;
764 }
765
766 if (command_arg >= args.size()) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700767 LOG(ERROR) << "exec called without command";
Tom Cherrybac32992015-07-31 12:45:25 -0700768 return nullptr;
769 }
770 std::vector<std::string> str_args(args.begin() + command_arg, args.end());
771
772 exec_count_++;
Tom Cherryb7349902015-08-26 11:43:36 -0700773 std::string name = StringPrintf("exec %d (%s)", exec_count_, str_args[0].c_str());
Tom Cherrybac32992015-07-31 12:45:25 -0700774 unsigned flags = SVC_EXEC | SVC_ONESHOT;
Jorge Lucangeli Obes1b3fa3d2016-04-21 15:35:09 -0700775 unsigned namespace_flags = 0;
Tom Cherrybac32992015-07-31 12:45:25 -0700776
777 std::string seclabel = "";
778 if (command_arg > 2 && args[1] != "-") {
779 seclabel = args[1];
780 }
781 uid_t uid = 0;
782 if (command_arg > 3) {
783 uid = decode_uid(args[2].c_str());
784 }
785 gid_t gid = 0;
786 std::vector<gid_t> supp_gids;
787 if (command_arg > 4) {
788 gid = decode_uid(args[3].c_str());
789 std::size_t nr_supp_gids = command_arg - 1 /* -- */ - 4 /* exec SECLABEL UID GID */;
790 for (size_t i = 0; i < nr_supp_gids; ++i) {
791 supp_gids.push_back(decode_uid(args[4 + i].c_str()));
792 }
793 }
794
795 std::unique_ptr<Service> svc_p(new Service(name, "default", flags, uid, gid,
Jorge Lucangeli Obes1b3fa3d2016-04-21 15:35:09 -0700796 supp_gids, namespace_flags,
797 seclabel, str_args));
Tom Cherrybac32992015-07-31 12:45:25 -0700798 if (!svc_p) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700799 LOG(ERROR) << "Couldn't allocate service for exec of '" << str_args[0] << "'";
Tom Cherrybac32992015-07-31 12:45:25 -0700800 return nullptr;
801 }
802 Service* svc = svc_p.get();
803 services_.push_back(std::move(svc_p));
804
805 return svc;
806}
807
808Service* ServiceManager::FindServiceByName(const std::string& name) const {
809 auto svc = std::find_if(services_.begin(), services_.end(),
810 [&name] (const std::unique_ptr<Service>& s) {
811 return name == s->name();
812 });
813 if (svc != services_.end()) {
814 return svc->get();
815 }
816 return nullptr;
817}
818
819Service* ServiceManager::FindServiceByPid(pid_t pid) const {
820 auto svc = std::find_if(services_.begin(), services_.end(),
821 [&pid] (const std::unique_ptr<Service>& s) {
822 return s->pid() == pid;
823 });
824 if (svc != services_.end()) {
825 return svc->get();
826 }
827 return nullptr;
828}
829
830Service* ServiceManager::FindServiceByKeychord(int keychord_id) const {
831 auto svc = std::find_if(services_.begin(), services_.end(),
832 [&keychord_id] (const std::unique_ptr<Service>& s) {
833 return s->keychord_id() == keychord_id;
834 });
835
836 if (svc != services_.end()) {
837 return svc->get();
838 }
839 return nullptr;
840}
841
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800842void ServiceManager::ForEachService(std::function<void(Service*)> callback) const {
Tom Cherrybac32992015-07-31 12:45:25 -0700843 for (const auto& s : services_) {
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800844 callback(s.get());
Tom Cherrybac32992015-07-31 12:45:25 -0700845 }
846}
847
848void ServiceManager::ForEachServiceInClass(const std::string& classname,
849 void (*func)(Service* svc)) const {
850 for (const auto& s : services_) {
851 if (classname == s->classname()) {
852 func(s.get());
853 }
854 }
855}
856
857void ServiceManager::ForEachServiceWithFlags(unsigned matchflags,
858 void (*func)(Service* svc)) const {
859 for (const auto& s : services_) {
860 if (s->flags() & matchflags) {
861 func(s.get());
862 }
863 }
864}
865
Tom Cherryb7349902015-08-26 11:43:36 -0700866void ServiceManager::RemoveService(const Service& svc) {
Tom Cherrybac32992015-07-31 12:45:25 -0700867 auto svc_it = std::find_if(services_.begin(), services_.end(),
868 [&svc] (const std::unique_ptr<Service>& s) {
869 return svc.name() == s->name();
870 });
871 if (svc_it == services_.end()) {
872 return;
873 }
874
875 services_.erase(svc_it);
876}
877
Tom Cherryb7349902015-08-26 11:43:36 -0700878void ServiceManager::DumpState() const {
879 for (const auto& s : services_) {
880 s->DumpState();
881 }
Tom Cherryb7349902015-08-26 11:43:36 -0700882}
883
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800884bool ServiceManager::ReapOneProcess() {
885 int status;
886 pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG));
887 if (pid == 0) {
888 return false;
889 } else if (pid == -1) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700890 PLOG(ERROR) << "waitpid failed";
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800891 return false;
892 }
893
894 Service* svc = FindServiceByPid(pid);
895
896 std::string name;
897 if (svc) {
898 name = android::base::StringPrintf("Service '%s' (pid %d)",
899 svc->name().c_str(), pid);
900 } else {
901 name = android::base::StringPrintf("Untracked pid %d", pid);
902 }
903
904 if (WIFEXITED(status)) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700905 LOG(VERBOSE) << name << " exited with status " << WEXITSTATUS(status);
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800906 } else if (WIFSIGNALED(status)) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700907 LOG(VERBOSE) << name << " killed by signal " << WTERMSIG(status);
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800908 } else if (WIFSTOPPED(status)) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700909 LOG(VERBOSE) << name << " stopped by signal " << WSTOPSIG(status);
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800910 } else {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700911 LOG(VERBOSE) << name << " state changed";
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800912 }
913
914 if (!svc) {
915 return true;
916 }
917
918 if (svc->Reap()) {
919 waiting_for_exec = false;
920 RemoveService(*svc);
921 }
922
923 return true;
924}
925
926void ServiceManager::ReapAnyOutstandingChildren() {
927 while (ReapOneProcess()) {
928 }
929}
930
Tom Cherryb7349902015-08-26 11:43:36 -0700931bool ServiceParser::ParseSection(const std::vector<std::string>& args,
932 std::string* err) {
933 if (args.size() < 3) {
934 *err = "services must have a name and a program";
935 return false;
936 }
937
938 const std::string& name = args[1];
939 if (!IsValidName(name)) {
940 *err = StringPrintf("invalid service name '%s'", name.c_str());
941 return false;
942 }
943
944 std::vector<std::string> str_args(args.begin() + 2, args.end());
945 service_ = std::make_unique<Service>(name, "default", str_args);
946 return true;
947}
948
949bool ServiceParser::ParseLineSection(const std::vector<std::string>& args,
950 const std::string& filename, int line,
951 std::string* err) const {
Jorge Lucangeli Obes177b27d2016-06-29 14:32:49 -0400952 return service_ ? service_->ParseLine(args, err) : false;
Tom Cherryb7349902015-08-26 11:43:36 -0700953}
954
955void ServiceParser::EndSection() {
956 if (service_) {
957 ServiceManager::GetInstance().AddService(std::move(service_));
958 }
959}
960
961bool ServiceParser::IsValidName(const std::string& name) const {
Tom Cherrybac32992015-07-31 12:45:25 -0700962 if (name.size() > 16) {
963 return false;
964 }
965 for (const auto& c : name) {
966 if (!isalnum(c) && (c != '_') && (c != '-')) {
967 return false;
968 }
969 }
970 return true;
971}