blob: d2edddd47ea500c02611b974cb6f757517881199 [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>
Vitalii Tomkiv081705c2016-05-18 17:36:30 -070020#include <sys/resource.h>
Tom Cherrybac32992015-07-31 12:45:25 -070021#include <sys/stat.h>
Vitalii Tomkiv081705c2016-05-18 17:36:30 -070022#include <sys/time.h>
Tom Cherrybac32992015-07-31 12:45:25 -070023#include <sys/types.h>
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -080024#include <sys/wait.h>
Tom Cherrybac32992015-07-31 12:45:25 -070025#include <termios.h>
Dan Albertaf9ba4d2015-08-11 16:37:04 -070026#include <unistd.h>
Tom Cherrybac32992015-07-31 12:45:25 -070027
28#include <selinux/selinux.h>
29
Elliott Hughes4f713192015-12-04 22:00:26 -080030#include <android-base/file.h>
31#include <android-base/stringprintf.h>
Elliott Hughesf86b5a62016-06-24 15:12:21 -070032#include <android-base/strings.h>
Tom Cherrybac32992015-07-31 12:45:25 -070033#include <cutils/android_reboot.h>
34#include <cutils/sockets.h>
Vitalii Tomkiv081705c2016-05-18 17:36:30 -070035#include <system/thread_defs.h>
Tom Cherrybac32992015-07-31 12:45:25 -070036
Collin Mullinerf7e79b92016-06-01 21:03:55 +000037#include <processgroup/processgroup.h>
38
Tom Cherrybac32992015-07-31 12:45:25 -070039#include "action.h"
40#include "init.h"
41#include "init_parser.h"
Tom Cherrybac32992015-07-31 12:45:25 -070042#include "log.h"
43#include "property_service.h"
44#include "util.h"
45
Tom Cherryb7349902015-08-26 11:43:36 -070046using android::base::StringPrintf;
47using android::base::WriteStringToFile;
48
Tom Cherrybac32992015-07-31 12:45:25 -070049#define CRITICAL_CRASH_THRESHOLD 4 // if we crash >4 times ...
50#define CRITICAL_CRASH_WINDOW (4*60) // ... in 4 minutes, goto recovery
51
52SocketInfo::SocketInfo() : uid(0), gid(0), perm(0) {
53}
54
55SocketInfo::SocketInfo(const std::string& name, const std::string& type, uid_t uid,
56 gid_t gid, int perm, const std::string& socketcon)
57 : name(name), type(type), uid(uid), gid(gid), perm(perm), socketcon(socketcon) {
58}
59
60ServiceEnvironmentInfo::ServiceEnvironmentInfo() {
61}
62
63ServiceEnvironmentInfo::ServiceEnvironmentInfo(const std::string& name,
64 const std::string& value)
65 : name(name), value(value) {
66}
67
68Service::Service(const std::string& name, const std::string& classname,
69 const std::vector<std::string>& args)
70 : name_(name), classname_(classname), flags_(0), pid_(0), time_started_(0),
71 time_crashed_(0), nr_crashed_(0), uid_(0), gid_(0), seclabel_(""),
Vitalii Tomkiv081705c2016-05-18 17:36:30 -070072 ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), priority_(0), args_(args) {
Tom Cherrybac32992015-07-31 12:45:25 -070073 onrestart_.InitSingleTrigger("onrestart");
74}
75
76Service::Service(const std::string& name, const std::string& classname,
77 unsigned flags, uid_t uid, gid_t gid, const std::vector<gid_t>& supp_gids,
78 const std::string& seclabel, const std::vector<std::string>& args)
79 : name_(name), classname_(classname), flags_(flags), pid_(0), time_started_(0),
80 time_crashed_(0), nr_crashed_(0), uid_(uid), gid_(gid), supp_gids_(supp_gids),
Vitalii Tomkiv081705c2016-05-18 17:36:30 -070081 seclabel_(seclabel), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), priority_(0),
82 args_(args) {
Tom Cherrybac32992015-07-31 12:45:25 -070083 onrestart_.InitSingleTrigger("onrestart");
84}
85
86void Service::NotifyStateChange(const std::string& new_state) const {
Tom Cherrybac32992015-07-31 12:45:25 -070087 if ((flags_ & SVC_EXEC) != 0) {
88 // 'exec' commands don't have properties tracking their state.
89 return;
90 }
91
Tom Cherryb7349902015-08-26 11:43:36 -070092 std::string prop_name = StringPrintf("init.svc.%s", name_.c_str());
Tom Cherrybac32992015-07-31 12:45:25 -070093 if (prop_name.length() >= PROP_NAME_MAX) {
94 // If the property name would be too long, we can't set it.
Elliott Hughesf86b5a62016-06-24 15:12:21 -070095 LOG(ERROR) << "Property name \"init.svc." << name_ << "\" too long; not setting to " << new_state;
Tom Cherrybac32992015-07-31 12:45:25 -070096 return;
97 }
98
99 property_set(prop_name.c_str(), new_state.c_str());
100}
101
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700102void Service::KillProcessGroup(int signal) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700103 LOG(VERBOSE) << "Sending signal " << signal
104 << " to service '" << name_
105 << "' (pid " << pid_ << ") process group...\n",
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700106 kill(pid_, signal);
107 killProcessGroup(uid_, pid_, signal);
108}
109
Tom Cherrybac32992015-07-31 12:45:25 -0700110bool Service::Reap() {
111 if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) {
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700112 KillProcessGroup(SIGKILL);
Tom Cherrybac32992015-07-31 12:45:25 -0700113 }
114
115 // Remove any sockets we may have created.
116 for (const auto& si : sockets_) {
Tom Cherryb7349902015-08-26 11:43:36 -0700117 std::string tmp = StringPrintf(ANDROID_SOCKET_DIR "/%s", si.name.c_str());
Tom Cherrybac32992015-07-31 12:45:25 -0700118 unlink(tmp.c_str());
119 }
120
121 if (flags_ & SVC_EXEC) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700122 LOG(INFO) << "SVC_EXEC pid " << pid_ << " finished...";
Tom Cherrybac32992015-07-31 12:45:25 -0700123 return true;
124 }
125
126 pid_ = 0;
127 flags_ &= (~SVC_RUNNING);
128
129 // Oneshot processes go into the disabled state on exit,
130 // except when manually restarted.
131 if ((flags_ & SVC_ONESHOT) && !(flags_ & SVC_RESTART)) {
132 flags_ |= SVC_DISABLED;
133 }
134
135 // Disabled and reset processes do not get restarted automatically.
136 if (flags_ & (SVC_DISABLED | SVC_RESET)) {
137 NotifyStateChange("stopped");
138 return false;
139 }
140
141 time_t now = gettime();
142 if ((flags_ & SVC_CRITICAL) && !(flags_ & SVC_RESTART)) {
143 if (time_crashed_ + CRITICAL_CRASH_WINDOW >= now) {
144 if (++nr_crashed_ > CRITICAL_CRASH_THRESHOLD) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700145 LOG(ERROR) << "critical process '" << name_ << "' exited "
146 << CRITICAL_CRASH_THRESHOLD << " times in "
147 << (CRITICAL_CRASH_WINDOW / 60) << " minutes; "
148 << "rebooting into recovery mode";
Tom Cherrybac32992015-07-31 12:45:25 -0700149 android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
150 return false;
151 }
152 } else {
153 time_crashed_ = now;
154 nr_crashed_ = 1;
155 }
156 }
157
158 flags_ &= (~SVC_RESTART);
159 flags_ |= SVC_RESTARTING;
160
161 // Execute all onrestart commands for this service.
162 onrestart_.ExecuteAllCommands();
163
164 NotifyStateChange("restarting");
165 return false;
166}
167
168void Service::DumpState() const {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700169 LOG(INFO) << "service " << name_;
170 LOG(INFO) << " class '" << classname_ << "'";
171 LOG(INFO) << " exec "<< android::base::Join(args_, " ");
Tom Cherrybac32992015-07-31 12:45:25 -0700172 for (const auto& si : sockets_) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700173 LOG(INFO) << " socket " << si.name << " " << si.type << " " << std::oct << si.perm;
Tom Cherrybac32992015-07-31 12:45:25 -0700174 }
175}
176
Tom Cherryb7349902015-08-26 11:43:36 -0700177bool Service::HandleClass(const std::vector<std::string>& args, std::string* err) {
178 classname_ = args[1];
179 return true;
180}
Tom Cherrybac32992015-07-31 12:45:25 -0700181
Tom Cherryb7349902015-08-26 11:43:36 -0700182bool Service::HandleConsole(const std::vector<std::string>& args, std::string* err) {
183 flags_ |= SVC_CONSOLE;
Viorel Suman70daa672016-03-21 10:08:07 +0200184 console_ = args.size() > 1 ? "/dev/" + args[1] : "";
Tom Cherryb7349902015-08-26 11:43:36 -0700185 return true;
186}
Tom Cherrybac32992015-07-31 12:45:25 -0700187
Tom Cherryb7349902015-08-26 11:43:36 -0700188bool Service::HandleCritical(const std::vector<std::string>& args, std::string* err) {
189 flags_ |= SVC_CRITICAL;
190 return true;
191}
Tom Cherrybac32992015-07-31 12:45:25 -0700192
Tom Cherryb7349902015-08-26 11:43:36 -0700193bool Service::HandleDisabled(const std::vector<std::string>& args, std::string* err) {
194 flags_ |= SVC_DISABLED;
195 flags_ |= SVC_RC_DISABLED;
196 return true;
197}
Tom Cherrybac32992015-07-31 12:45:25 -0700198
Tom Cherryb7349902015-08-26 11:43:36 -0700199bool Service::HandleGroup(const std::vector<std::string>& args, std::string* err) {
200 gid_ = decode_uid(args[1].c_str());
201 for (std::size_t n = 2; n < args.size(); n++) {
202 supp_gids_.emplace_back(decode_uid(args[n].c_str()));
Tom Cherrybac32992015-07-31 12:45:25 -0700203 }
204 return true;
205}
206
Vitalii Tomkiv081705c2016-05-18 17:36:30 -0700207bool Service::HandlePriority(const std::vector<std::string>& args, std::string* err) {
208 priority_ = std::stoi(args[1]);
209
210 if (priority_ < ANDROID_PRIORITY_HIGHEST || priority_ > ANDROID_PRIORITY_LOWEST) {
211 priority_ = 0;
212 *err = StringPrintf("process priority value must be range %d - %d",
213 ANDROID_PRIORITY_HIGHEST, ANDROID_PRIORITY_LOWEST);
214 return false;
215 }
216
217 return true;
218}
219
Tom Cherryb7349902015-08-26 11:43:36 -0700220bool Service::HandleIoprio(const std::vector<std::string>& args, std::string* err) {
221 ioprio_pri_ = std::stoul(args[2], 0, 8);
222
223 if (ioprio_pri_ < 0 || ioprio_pri_ > 7) {
224 *err = "priority value must be range 0 - 7";
225 return false;
226 }
227
228 if (args[1] == "rt") {
229 ioprio_class_ = IoSchedClass_RT;
230 } else if (args[1] == "be") {
231 ioprio_class_ = IoSchedClass_BE;
232 } else if (args[1] == "idle") {
233 ioprio_class_ = IoSchedClass_IDLE;
234 } else {
235 *err = "ioprio option usage: ioprio <rt|be|idle> <0-7>";
236 return false;
237 }
238
239 return true;
240}
241
242bool Service::HandleKeycodes(const std::vector<std::string>& args, std::string* err) {
243 for (std::size_t i = 1; i < args.size(); i++) {
244 keycodes_.emplace_back(std::stoi(args[i]));
245 }
246 return true;
247}
248
249bool Service::HandleOneshot(const std::vector<std::string>& args, std::string* err) {
250 flags_ |= SVC_ONESHOT;
251 return true;
252}
253
254bool Service::HandleOnrestart(const std::vector<std::string>& args, std::string* err) {
255 std::vector<std::string> str_args(args.begin() + 1, args.end());
256 onrestart_.AddCommand(str_args, "", 0, err);
257 return true;
258}
259
260bool Service::HandleSeclabel(const std::vector<std::string>& args, std::string* err) {
261 seclabel_ = args[1];
262 return true;
263}
264
265bool Service::HandleSetenv(const std::vector<std::string>& args, std::string* err) {
266 envvars_.emplace_back(args[1], args[2]);
267 return true;
268}
269
270/* name type perm [ uid gid context ] */
271bool Service::HandleSocket(const std::vector<std::string>& args, std::string* err) {
272 if (args[2] != "dgram" && args[2] != "stream" && args[2] != "seqpacket") {
273 *err = "socket type must be 'dgram', 'stream' or 'seqpacket'";
274 return false;
275 }
276
277 int perm = std::stoul(args[3], 0, 8);
278 uid_t uid = args.size() > 4 ? decode_uid(args[4].c_str()) : 0;
279 gid_t gid = args.size() > 5 ? decode_uid(args[5].c_str()) : 0;
280 std::string socketcon = args.size() > 6 ? args[6] : "";
281
282 sockets_.emplace_back(args[1], args[2], uid, gid, perm, socketcon);
283 return true;
284}
285
286bool Service::HandleUser(const std::vector<std::string>& args, std::string* err) {
287 uid_ = decode_uid(args[1].c_str());
288 return true;
289}
290
291bool Service::HandleWritepid(const std::vector<std::string>& args, std::string* err) {
292 writepid_files_.assign(args.begin() + 1, args.end());
293 return true;
294}
295
296class Service::OptionHandlerMap : public KeywordMap<OptionHandler> {
297public:
298 OptionHandlerMap() {
299 }
300private:
301 Map& map() const override;
302};
303
304Service::OptionHandlerMap::Map& Service::OptionHandlerMap::map() const {
305 constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
306 static const Map option_handlers = {
307 {"class", {1, 1, &Service::HandleClass}},
Viorel Suman70daa672016-03-21 10:08:07 +0200308 {"console", {0, 1, &Service::HandleConsole}},
Tom Cherryb7349902015-08-26 11:43:36 -0700309 {"critical", {0, 0, &Service::HandleCritical}},
310 {"disabled", {0, 0, &Service::HandleDisabled}},
311 {"group", {1, NR_SVC_SUPP_GIDS + 1, &Service::HandleGroup}},
312 {"ioprio", {2, 2, &Service::HandleIoprio}},
Vitalii Tomkiv081705c2016-05-18 17:36:30 -0700313 {"priority", {1, 1, &Service::HandlePriority}},
Tom Cherryb7349902015-08-26 11:43:36 -0700314 {"keycodes", {1, kMax, &Service::HandleKeycodes}},
315 {"oneshot", {0, 0, &Service::HandleOneshot}},
316 {"onrestart", {1, kMax, &Service::HandleOnrestart}},
317 {"seclabel", {1, 1, &Service::HandleSeclabel}},
318 {"setenv", {2, 2, &Service::HandleSetenv}},
319 {"socket", {3, 6, &Service::HandleSocket}},
320 {"user", {1, 1, &Service::HandleUser}},
321 {"writepid", {1, kMax, &Service::HandleWritepid}},
322 };
323 return option_handlers;
324}
325
326bool Service::HandleLine(const std::vector<std::string>& args, std::string* err) {
327 if (args.empty()) {
328 *err = "option needed, but not provided";
329 return false;
330 }
331
332 static const OptionHandlerMap handler_map;
333 auto handler = handler_map.FindFunction(args[0], args.size() - 1, err);
334
335 if (!handler) {
336 return false;
337 }
338
339 return (this->*handler)(args, err);
340}
341
Elliott Hughesbdeac392016-04-12 15:38:27 -0700342bool Service::Start() {
Tom Cherrybac32992015-07-31 12:45:25 -0700343 // Starting a service removes it from the disabled or reset state and
344 // immediately takes it out of the restarting state if it was in there.
345 flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));
346 time_started_ = 0;
347
348 // Running processes require no additional work --- if they're in the
349 // process of exiting, we've ensured that they will immediately restart
350 // on exit, unless they are ONESHOT.
351 if (flags_ & SVC_RUNNING) {
352 return false;
353 }
354
355 bool needs_console = (flags_ & SVC_CONSOLE);
Viorel Suman70daa672016-03-21 10:08:07 +0200356 if (needs_console) {
357 if (console_.empty()) {
358 console_ = default_console;
359 }
360
361 bool have_console = (open(console_.c_str(), O_RDWR | O_CLOEXEC) != -1);
362 if (!have_console) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700363 PLOG(ERROR) << "service '" << name_ << "' couldn't open console '" << console_ << "'";
Viorel Suman70daa672016-03-21 10:08:07 +0200364 flags_ |= SVC_DISABLED;
365 return false;
366 }
Tom Cherrybac32992015-07-31 12:45:25 -0700367 }
368
369 struct stat sb;
370 if (stat(args_[0].c_str(), &sb) == -1) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700371 PLOG(ERROR) << "cannot find '" << args_[0] << "', disabling '" << name_ << "'";
Tom Cherrybac32992015-07-31 12:45:25 -0700372 flags_ |= SVC_DISABLED;
373 return false;
374 }
375
Tom Cherrybac32992015-07-31 12:45:25 -0700376 std::string scon;
377 if (!seclabel_.empty()) {
378 scon = seclabel_;
379 } else {
380 char* mycon = nullptr;
381 char* fcon = nullptr;
382
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700383 LOG(INFO) << "computing context for service '" << args_[0] << "'";
Tom Cherrybac32992015-07-31 12:45:25 -0700384 int rc = getcon(&mycon);
385 if (rc < 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700386 LOG(ERROR) << "could not get context while starting '" << name_ << "'";
Tom Cherrybac32992015-07-31 12:45:25 -0700387 return false;
388 }
389
390 rc = getfilecon(args_[0].c_str(), &fcon);
391 if (rc < 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700392 LOG(ERROR) << "could not get context while starting '" << name_ << "'";
Tom Cherrybac32992015-07-31 12:45:25 -0700393 free(mycon);
394 return false;
395 }
396
397 char* ret_scon = nullptr;
398 rc = security_compute_create(mycon, fcon, string_to_security_class("process"),
399 &ret_scon);
400 if (rc == 0) {
401 scon = ret_scon;
402 free(ret_scon);
403 }
404 if (rc == 0 && scon == mycon) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700405 LOG(ERROR) << "Service " << name_ << " does not have a SELinux domain defined.";
Tom Cherrybac32992015-07-31 12:45:25 -0700406 free(mycon);
407 free(fcon);
408 return false;
409 }
410 free(mycon);
411 free(fcon);
412 if (rc < 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700413 LOG(ERROR) << "could not get context while starting '" << name_ << "'";
Tom Cherrybac32992015-07-31 12:45:25 -0700414 return false;
415 }
416 }
417
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700418 LOG(VERBOSE) << "Starting service '" << name_ << "'...";
Tom Cherrybac32992015-07-31 12:45:25 -0700419
420 pid_t pid = fork();
421 if (pid == 0) {
Tom Cherrybac32992015-07-31 12:45:25 -0700422 umask(077);
Tom Cherrybac32992015-07-31 12:45:25 -0700423
424 for (const auto& ei : envvars_) {
425 add_environment(ei.name.c_str(), ei.value.c_str());
426 }
427
428 for (const auto& si : sockets_) {
429 int socket_type = ((si.type == "stream" ? SOCK_STREAM :
430 (si.type == "dgram" ? SOCK_DGRAM :
431 SOCK_SEQPACKET)));
432 const char* socketcon =
433 !si.socketcon.empty() ? si.socketcon.c_str() : scon.c_str();
434
435 int s = create_socket(si.name.c_str(), socket_type, si.perm,
436 si.uid, si.gid, socketcon);
437 if (s >= 0) {
438 PublishSocket(si.name, s);
439 }
440 }
441
Anestis Bechtsoudisb702b462016-02-05 16:38:48 +0200442 std::string pid_str = StringPrintf("%d", getpid());
Tom Cherrybac32992015-07-31 12:45:25 -0700443 for (const auto& file : writepid_files_) {
Tom Cherryb7349902015-08-26 11:43:36 -0700444 if (!WriteStringToFile(pid_str, file)) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700445 PLOG(ERROR) << "couldn't write " << pid_str << " to " << file;
Tom Cherrybac32992015-07-31 12:45:25 -0700446 }
447 }
448
449 if (ioprio_class_ != IoSchedClass_NONE) {
450 if (android_set_ioprio(getpid(), ioprio_class_, ioprio_pri_)) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700451 PLOG(ERROR) << "Failed to set pid " << getpid()
452 << " ioprio=" << ioprio_class_ << "," << ioprio_pri_;
Tom Cherrybac32992015-07-31 12:45:25 -0700453 }
454 }
455
456 if (needs_console) {
457 setsid();
458 OpenConsole();
459 } else {
460 ZapStdio();
461 }
462
463 setpgid(0, getpid());
464
465 // As requested, set our gid, supplemental gids, and uid.
466 if (gid_) {
467 if (setgid(gid_) != 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700468 PLOG(ERROR) << "setgid failed";
Tom Cherrybac32992015-07-31 12:45:25 -0700469 _exit(127);
470 }
471 }
472 if (!supp_gids_.empty()) {
473 if (setgroups(supp_gids_.size(), &supp_gids_[0]) != 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700474 PLOG(ERROR) << "setgroups failed";
Tom Cherrybac32992015-07-31 12:45:25 -0700475 _exit(127);
476 }
477 }
478 if (uid_) {
479 if (setuid(uid_) != 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700480 PLOG(ERROR) << "setuid failed";
Tom Cherrybac32992015-07-31 12:45:25 -0700481 _exit(127);
482 }
483 }
484 if (!seclabel_.empty()) {
485 if (setexeccon(seclabel_.c_str()) < 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700486 PLOG(ERROR) << "cannot setexeccon('" << seclabel_ << "')";
Tom Cherrybac32992015-07-31 12:45:25 -0700487 _exit(127);
488 }
489 }
Vitalii Tomkiv081705c2016-05-18 17:36:30 -0700490 if (priority_ != 0) {
491 if (setpriority(PRIO_PROCESS, 0, priority_) != 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700492 PLOG(ERROR) << "setpriority failed";
Vitalii Tomkiv081705c2016-05-18 17:36:30 -0700493 _exit(127);
494 }
495 }
Tom Cherrybac32992015-07-31 12:45:25 -0700496
Tom Cherrybac35362016-06-07 11:22:00 -0700497 std::vector<std::string> expanded_args;
Tom Cherrybac32992015-07-31 12:45:25 -0700498 std::vector<char*> strs;
Tom Cherrybac35362016-06-07 11:22:00 -0700499 expanded_args.resize(args_.size());
500 strs.push_back(const_cast<char*>(args_[0].c_str()));
501 for (std::size_t i = 1; i < args_.size(); ++i) {
502 if (!expand_props(args_[i], &expanded_args[i])) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700503 LOG(ERROR) << args_[0] << ": cannot expand '" << args_[i] << "'";
Tom Cherrybac35362016-06-07 11:22:00 -0700504 _exit(127);
505 }
506 strs.push_back(const_cast<char*>(expanded_args[i].c_str()));
Tom Cherrybac32992015-07-31 12:45:25 -0700507 }
Tom Cherrybac32992015-07-31 12:45:25 -0700508 strs.push_back(nullptr);
Tom Cherrybac35362016-06-07 11:22:00 -0700509
510 if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700511 PLOG(ERROR) << "cannot execve('" << strs[0] << "')";
Tom Cherrybac32992015-07-31 12:45:25 -0700512 }
513
514 _exit(127);
515 }
516
517 if (pid < 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700518 PLOG(ERROR) << "failed to fork for '" << name_ << "'";
Tom Cherrybac32992015-07-31 12:45:25 -0700519 pid_ = 0;
520 return false;
521 }
522
523 time_started_ = gettime();
524 pid_ = pid;
525 flags_ |= SVC_RUNNING;
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700526
527 errno = -createProcessGroup(uid_, pid_);
528 if (errno != 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700529 PLOG(ERROR) << "createProcessGroup(" << uid_ << ", " << pid_ << ") failed for service '" << name_ << "'";
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700530 }
Tom Cherrybac32992015-07-31 12:45:25 -0700531
532 if ((flags_ & SVC_EXEC) != 0) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700533 LOG(INFO) << android::base::StringPrintf("SVC_EXEC pid %d (uid %d gid %d+%zu context %s) started; waiting...",
534 pid_, uid_, gid_, supp_gids_.size(),
535 !seclabel_.empty() ? seclabel_.c_str() : "default");
Tom Cherrybac32992015-07-31 12:45:25 -0700536 }
537
538 NotifyStateChange("running");
539 return true;
540}
541
Tom Cherrybac32992015-07-31 12:45:25 -0700542bool Service::StartIfNotDisabled() {
543 if (!(flags_ & SVC_DISABLED)) {
544 return Start();
545 } else {
546 flags_ |= SVC_DISABLED_START;
547 }
548 return true;
549}
550
551bool Service::Enable() {
552 flags_ &= ~(SVC_DISABLED | SVC_RC_DISABLED);
553 if (flags_ & SVC_DISABLED_START) {
554 return Start();
555 }
556 return true;
557}
558
559void Service::Reset() {
560 StopOrReset(SVC_RESET);
561}
562
563void Service::Stop() {
564 StopOrReset(SVC_DISABLED);
565}
566
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800567void Service::Terminate() {
568 flags_ &= ~(SVC_RESTARTING | SVC_DISABLED_START);
569 flags_ |= SVC_DISABLED;
570 if (pid_) {
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700571 KillProcessGroup(SIGTERM);
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800572 NotifyStateChange("stopping");
573 }
574}
575
Tom Cherrybac32992015-07-31 12:45:25 -0700576void Service::Restart() {
577 if (flags_ & SVC_RUNNING) {
578 /* Stop, wait, then start the service. */
579 StopOrReset(SVC_RESTART);
580 } else if (!(flags_ & SVC_RESTARTING)) {
581 /* Just start the service since it's not running. */
582 Start();
583 } /* else: Service is restarting anyways. */
584}
585
586void Service::RestartIfNeeded(time_t& process_needs_restart) {
587 time_t next_start_time = time_started_ + 5;
588
589 if (next_start_time <= gettime()) {
590 flags_ &= (~SVC_RESTARTING);
591 Start();
592 return;
593 }
594
595 if ((next_start_time < process_needs_restart) ||
596 (process_needs_restart == 0)) {
597 process_needs_restart = next_start_time;
598 }
599}
600
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700601// The how field should be either SVC_DISABLED, SVC_RESET, or SVC_RESTART.
Tom Cherrybac32992015-07-31 12:45:25 -0700602void Service::StopOrReset(int how) {
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700603 // The service is still SVC_RUNNING until its process exits, but if it has
604 // already exited it shoudn't attempt a restart yet.
Tom Cherrybac32992015-07-31 12:45:25 -0700605 flags_ &= ~(SVC_RESTARTING | SVC_DISABLED_START);
606
607 if ((how != SVC_DISABLED) && (how != SVC_RESET) && (how != SVC_RESTART)) {
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700608 // An illegal flag: default to SVC_DISABLED.
Tom Cherrybac32992015-07-31 12:45:25 -0700609 how = SVC_DISABLED;
610 }
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700611
612 // If the service has not yet started, prevent it from auto-starting with its class.
Tom Cherrybac32992015-07-31 12:45:25 -0700613 if (how == SVC_RESET) {
614 flags_ |= (flags_ & SVC_RC_DISABLED) ? SVC_DISABLED : SVC_RESET;
615 } else {
616 flags_ |= how;
617 }
618
619 if (pid_) {
Elliott Hughesad8e94e2016-06-15 14:49:57 -0700620 KillProcessGroup(SIGKILL);
Tom Cherrybac32992015-07-31 12:45:25 -0700621 NotifyStateChange("stopping");
622 } else {
623 NotifyStateChange("stopped");
624 }
625}
626
627void Service::ZapStdio() const {
628 int fd;
629 fd = open("/dev/null", O_RDWR);
630 dup2(fd, 0);
631 dup2(fd, 1);
632 dup2(fd, 2);
633 close(fd);
634}
635
636void Service::OpenConsole() const {
Viorel Suman70daa672016-03-21 10:08:07 +0200637 int fd = open(console_.c_str(), O_RDWR);
638 if (fd == -1) fd = open("/dev/null", O_RDWR);
Tom Cherrybac32992015-07-31 12:45:25 -0700639 ioctl(fd, TIOCSCTTY, 0);
640 dup2(fd, 0);
641 dup2(fd, 1);
642 dup2(fd, 2);
643 close(fd);
644}
645
646void Service::PublishSocket(const std::string& name, int fd) const {
Tom Cherryb7349902015-08-26 11:43:36 -0700647 std::string key = StringPrintf(ANDROID_SOCKET_ENV_PREFIX "%s", name.c_str());
648 std::string val = StringPrintf("%d", fd);
Tom Cherrybac32992015-07-31 12:45:25 -0700649 add_environment(key.c_str(), val.c_str());
650
651 /* make sure we don't close-on-exec */
652 fcntl(fd, F_SETFD, 0);
653}
654
655int ServiceManager::exec_count_ = 0;
656
657ServiceManager::ServiceManager() {
658}
659
660ServiceManager& ServiceManager::GetInstance() {
661 static ServiceManager instance;
662 return instance;
663}
664
Tom Cherryb7349902015-08-26 11:43:36 -0700665void ServiceManager::AddService(std::unique_ptr<Service> service) {
666 Service* old_service = FindServiceByName(service->name());
667 if (old_service) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700668 LOG(ERROR) << "ignored duplicate definition of service '" << service->name() << "'";
Tom Cherryb7349902015-08-26 11:43:36 -0700669 return;
Tom Cherrybac32992015-07-31 12:45:25 -0700670 }
Tom Cherryb7349902015-08-26 11:43:36 -0700671 services_.emplace_back(std::move(service));
Tom Cherrybac32992015-07-31 12:45:25 -0700672}
673
674Service* ServiceManager::MakeExecOneshotService(const std::vector<std::string>& args) {
675 // Parse the arguments: exec [SECLABEL [UID [GID]*] --] COMMAND ARGS...
676 // SECLABEL can be a - to denote default
677 std::size_t command_arg = 1;
678 for (std::size_t i = 1; i < args.size(); ++i) {
679 if (args[i] == "--") {
680 command_arg = i + 1;
681 break;
682 }
683 }
684 if (command_arg > 4 + NR_SVC_SUPP_GIDS) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700685 LOG(ERROR) << "exec called with too many supplementary group ids";
Tom Cherrybac32992015-07-31 12:45:25 -0700686 return nullptr;
687 }
688
689 if (command_arg >= args.size()) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700690 LOG(ERROR) << "exec called without command";
Tom Cherrybac32992015-07-31 12:45:25 -0700691 return nullptr;
692 }
693 std::vector<std::string> str_args(args.begin() + command_arg, args.end());
694
695 exec_count_++;
Tom Cherryb7349902015-08-26 11:43:36 -0700696 std::string name = StringPrintf("exec %d (%s)", exec_count_, str_args[0].c_str());
Tom Cherrybac32992015-07-31 12:45:25 -0700697 unsigned flags = SVC_EXEC | SVC_ONESHOT;
698
699 std::string seclabel = "";
700 if (command_arg > 2 && args[1] != "-") {
701 seclabel = args[1];
702 }
703 uid_t uid = 0;
704 if (command_arg > 3) {
705 uid = decode_uid(args[2].c_str());
706 }
707 gid_t gid = 0;
708 std::vector<gid_t> supp_gids;
709 if (command_arg > 4) {
710 gid = decode_uid(args[3].c_str());
711 std::size_t nr_supp_gids = command_arg - 1 /* -- */ - 4 /* exec SECLABEL UID GID */;
712 for (size_t i = 0; i < nr_supp_gids; ++i) {
713 supp_gids.push_back(decode_uid(args[4 + i].c_str()));
714 }
715 }
716
717 std::unique_ptr<Service> svc_p(new Service(name, "default", flags, uid, gid,
718 supp_gids, seclabel, str_args));
719 if (!svc_p) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700720 LOG(ERROR) << "Couldn't allocate service for exec of '" << str_args[0] << "'";
Tom Cherrybac32992015-07-31 12:45:25 -0700721 return nullptr;
722 }
723 Service* svc = svc_p.get();
724 services_.push_back(std::move(svc_p));
725
726 return svc;
727}
728
729Service* ServiceManager::FindServiceByName(const std::string& name) const {
730 auto svc = std::find_if(services_.begin(), services_.end(),
731 [&name] (const std::unique_ptr<Service>& s) {
732 return name == s->name();
733 });
734 if (svc != services_.end()) {
735 return svc->get();
736 }
737 return nullptr;
738}
739
740Service* ServiceManager::FindServiceByPid(pid_t pid) const {
741 auto svc = std::find_if(services_.begin(), services_.end(),
742 [&pid] (const std::unique_ptr<Service>& s) {
743 return s->pid() == pid;
744 });
745 if (svc != services_.end()) {
746 return svc->get();
747 }
748 return nullptr;
749}
750
751Service* ServiceManager::FindServiceByKeychord(int keychord_id) const {
752 auto svc = std::find_if(services_.begin(), services_.end(),
753 [&keychord_id] (const std::unique_ptr<Service>& s) {
754 return s->keychord_id() == keychord_id;
755 });
756
757 if (svc != services_.end()) {
758 return svc->get();
759 }
760 return nullptr;
761}
762
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800763void ServiceManager::ForEachService(std::function<void(Service*)> callback) const {
Tom Cherrybac32992015-07-31 12:45:25 -0700764 for (const auto& s : services_) {
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800765 callback(s.get());
Tom Cherrybac32992015-07-31 12:45:25 -0700766 }
767}
768
769void ServiceManager::ForEachServiceInClass(const std::string& classname,
770 void (*func)(Service* svc)) const {
771 for (const auto& s : services_) {
772 if (classname == s->classname()) {
773 func(s.get());
774 }
775 }
776}
777
778void ServiceManager::ForEachServiceWithFlags(unsigned matchflags,
779 void (*func)(Service* svc)) const {
780 for (const auto& s : services_) {
781 if (s->flags() & matchflags) {
782 func(s.get());
783 }
784 }
785}
786
Tom Cherryb7349902015-08-26 11:43:36 -0700787void ServiceManager::RemoveService(const Service& svc) {
Tom Cherrybac32992015-07-31 12:45:25 -0700788 auto svc_it = std::find_if(services_.begin(), services_.end(),
789 [&svc] (const std::unique_ptr<Service>& s) {
790 return svc.name() == s->name();
791 });
792 if (svc_it == services_.end()) {
793 return;
794 }
795
796 services_.erase(svc_it);
797}
798
Tom Cherryb7349902015-08-26 11:43:36 -0700799void ServiceManager::DumpState() const {
800 for (const auto& s : services_) {
801 s->DumpState();
802 }
Tom Cherryb7349902015-08-26 11:43:36 -0700803}
804
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800805bool ServiceManager::ReapOneProcess() {
806 int status;
807 pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG));
808 if (pid == 0) {
809 return false;
810 } else if (pid == -1) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700811 PLOG(ERROR) << "waitpid failed";
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800812 return false;
813 }
814
815 Service* svc = FindServiceByPid(pid);
816
817 std::string name;
818 if (svc) {
819 name = android::base::StringPrintf("Service '%s' (pid %d)",
820 svc->name().c_str(), pid);
821 } else {
822 name = android::base::StringPrintf("Untracked pid %d", pid);
823 }
824
825 if (WIFEXITED(status)) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700826 LOG(VERBOSE) << name << " exited with status " << WEXITSTATUS(status);
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800827 } else if (WIFSIGNALED(status)) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700828 LOG(VERBOSE) << name << " killed by signal " << WTERMSIG(status);
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800829 } else if (WIFSTOPPED(status)) {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700830 LOG(VERBOSE) << name << " stopped by signal " << WSTOPSIG(status);
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800831 } else {
Elliott Hughesf86b5a62016-06-24 15:12:21 -0700832 LOG(VERBOSE) << name << " state changed";
Bertrand SIMONNETb7e03e82015-12-18 11:39:59 -0800833 }
834
835 if (!svc) {
836 return true;
837 }
838
839 if (svc->Reap()) {
840 waiting_for_exec = false;
841 RemoveService(*svc);
842 }
843
844 return true;
845}
846
847void ServiceManager::ReapAnyOutstandingChildren() {
848 while (ReapOneProcess()) {
849 }
850}
851
Tom Cherryb7349902015-08-26 11:43:36 -0700852bool ServiceParser::ParseSection(const std::vector<std::string>& args,
853 std::string* err) {
854 if (args.size() < 3) {
855 *err = "services must have a name and a program";
856 return false;
857 }
858
859 const std::string& name = args[1];
860 if (!IsValidName(name)) {
861 *err = StringPrintf("invalid service name '%s'", name.c_str());
862 return false;
863 }
864
865 std::vector<std::string> str_args(args.begin() + 2, args.end());
866 service_ = std::make_unique<Service>(name, "default", str_args);
867 return true;
868}
869
870bool ServiceParser::ParseLineSection(const std::vector<std::string>& args,
871 const std::string& filename, int line,
872 std::string* err) const {
873 return service_ ? service_->HandleLine(args, err) : false;
874}
875
876void ServiceParser::EndSection() {
877 if (service_) {
878 ServiceManager::GetInstance().AddService(std::move(service_));
879 }
880}
881
882bool ServiceParser::IsValidName(const std::string& name) const {
Tom Cherrybac32992015-07-31 12:45:25 -0700883 if (name.size() > 16) {
884 return false;
885 }
886 for (const auto& c : name) {
887 if (!isalnum(c) && (c != '_') && (c != '-')) {
888 return false;
889 }
890 }
891 return true;
892}