service.cpp revision f7e79b99c1e9e3128dd9921871f7740bebb755e6
1bac3299720623f4226bca103b26260052732ad30Tom Cherry/* 2bac3299720623f4226bca103b26260052732ad30Tom Cherry * Copyright (C) 2015 The Android Open Source Project 3bac3299720623f4226bca103b26260052732ad30Tom Cherry * 4bac3299720623f4226bca103b26260052732ad30Tom Cherry * Licensed under the Apache License, Version 2.0 (the "License"); 5bac3299720623f4226bca103b26260052732ad30Tom Cherry * you may not use this file except in compliance with the License. 6bac3299720623f4226bca103b26260052732ad30Tom Cherry * You may obtain a copy of the License at 7bac3299720623f4226bca103b26260052732ad30Tom Cherry * 8bac3299720623f4226bca103b26260052732ad30Tom Cherry * http://www.apache.org/licenses/LICENSE-2.0 9bac3299720623f4226bca103b26260052732ad30Tom Cherry * 10bac3299720623f4226bca103b26260052732ad30Tom Cherry * Unless required by applicable law or agreed to in writing, software 11bac3299720623f4226bca103b26260052732ad30Tom Cherry * distributed under the License is distributed on an "AS IS" BASIS, 12bac3299720623f4226bca103b26260052732ad30Tom Cherry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bac3299720623f4226bca103b26260052732ad30Tom Cherry * See the License for the specific language governing permissions and 14bac3299720623f4226bca103b26260052732ad30Tom Cherry * limitations under the License. 15bac3299720623f4226bca103b26260052732ad30Tom Cherry */ 16bac3299720623f4226bca103b26260052732ad30Tom Cherry 17bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "service.h" 18bac3299720623f4226bca103b26260052732ad30Tom Cherry 19bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <fcntl.h> 20bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <sys/stat.h> 21bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <sys/types.h> 22b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET#include <sys/wait.h> 23bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <termios.h> 24af9ba4dc6ca98e136e887b0baa59b72fb8302dd3Dan Albert#include <unistd.h> 25bac3299720623f4226bca103b26260052732ad30Tom Cherry 26bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <selinux/selinux.h> 27bac3299720623f4226bca103b26260052732ad30Tom Cherry 284f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/file.h> 294f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/stringprintf.h> 30bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <cutils/android_reboot.h> 31bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <cutils/sockets.h> 32bac3299720623f4226bca103b26260052732ad30Tom Cherry 33f7e79b99c1e9e3128dd9921871f7740bebb755e6Collin Mulliner#include <processgroup/processgroup.h> 34f7e79b99c1e9e3128dd9921871f7740bebb755e6Collin Mulliner 35bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "action.h" 36bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "init.h" 37bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "init_parser.h" 38bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "log.h" 39bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "property_service.h" 40bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "util.h" 41bac3299720623f4226bca103b26260052732ad30Tom Cherry 42b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryusing android::base::StringPrintf; 43b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryusing android::base::WriteStringToFile; 44b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 45bac3299720623f4226bca103b26260052732ad30Tom Cherry#define CRITICAL_CRASH_THRESHOLD 4 // if we crash >4 times ... 46bac3299720623f4226bca103b26260052732ad30Tom Cherry#define CRITICAL_CRASH_WINDOW (4*60) // ... in 4 minutes, goto recovery 47bac3299720623f4226bca103b26260052732ad30Tom Cherry 48bac3299720623f4226bca103b26260052732ad30Tom CherrySocketInfo::SocketInfo() : uid(0), gid(0), perm(0) { 49bac3299720623f4226bca103b26260052732ad30Tom Cherry} 50bac3299720623f4226bca103b26260052732ad30Tom Cherry 51bac3299720623f4226bca103b26260052732ad30Tom CherrySocketInfo::SocketInfo(const std::string& name, const std::string& type, uid_t uid, 52bac3299720623f4226bca103b26260052732ad30Tom Cherry gid_t gid, int perm, const std::string& socketcon) 53bac3299720623f4226bca103b26260052732ad30Tom Cherry : name(name), type(type), uid(uid), gid(gid), perm(perm), socketcon(socketcon) { 54bac3299720623f4226bca103b26260052732ad30Tom Cherry} 55bac3299720623f4226bca103b26260052732ad30Tom Cherry 56bac3299720623f4226bca103b26260052732ad30Tom CherryServiceEnvironmentInfo::ServiceEnvironmentInfo() { 57bac3299720623f4226bca103b26260052732ad30Tom Cherry} 58bac3299720623f4226bca103b26260052732ad30Tom Cherry 59bac3299720623f4226bca103b26260052732ad30Tom CherryServiceEnvironmentInfo::ServiceEnvironmentInfo(const std::string& name, 60bac3299720623f4226bca103b26260052732ad30Tom Cherry const std::string& value) 61bac3299720623f4226bca103b26260052732ad30Tom Cherry : name(name), value(value) { 62bac3299720623f4226bca103b26260052732ad30Tom Cherry} 63bac3299720623f4226bca103b26260052732ad30Tom Cherry 64bac3299720623f4226bca103b26260052732ad30Tom CherryService::Service(const std::string& name, const std::string& classname, 65bac3299720623f4226bca103b26260052732ad30Tom Cherry const std::vector<std::string>& args) 66bac3299720623f4226bca103b26260052732ad30Tom Cherry : name_(name), classname_(classname), flags_(0), pid_(0), time_started_(0), 67bac3299720623f4226bca103b26260052732ad30Tom Cherry time_crashed_(0), nr_crashed_(0), uid_(0), gid_(0), seclabel_(""), 68bac3299720623f4226bca103b26260052732ad30Tom Cherry ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), args_(args) { 69bac3299720623f4226bca103b26260052732ad30Tom Cherry onrestart_.InitSingleTrigger("onrestart"); 70bac3299720623f4226bca103b26260052732ad30Tom Cherry} 71bac3299720623f4226bca103b26260052732ad30Tom Cherry 72bac3299720623f4226bca103b26260052732ad30Tom CherryService::Service(const std::string& name, const std::string& classname, 73bac3299720623f4226bca103b26260052732ad30Tom Cherry unsigned flags, uid_t uid, gid_t gid, const std::vector<gid_t>& supp_gids, 74bac3299720623f4226bca103b26260052732ad30Tom Cherry const std::string& seclabel, const std::vector<std::string>& args) 75bac3299720623f4226bca103b26260052732ad30Tom Cherry : name_(name), classname_(classname), flags_(flags), pid_(0), time_started_(0), 76bac3299720623f4226bca103b26260052732ad30Tom Cherry time_crashed_(0), nr_crashed_(0), uid_(uid), gid_(gid), supp_gids_(supp_gids), 77bac3299720623f4226bca103b26260052732ad30Tom Cherry seclabel_(seclabel), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), args_(args) { 78bac3299720623f4226bca103b26260052732ad30Tom Cherry onrestart_.InitSingleTrigger("onrestart"); 79bac3299720623f4226bca103b26260052732ad30Tom Cherry} 80bac3299720623f4226bca103b26260052732ad30Tom Cherry 81bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::NotifyStateChange(const std::string& new_state) const { 82bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((flags_ & SVC_EXEC) != 0) { 83bac3299720623f4226bca103b26260052732ad30Tom Cherry // 'exec' commands don't have properties tracking their state. 84bac3299720623f4226bca103b26260052732ad30Tom Cherry return; 85bac3299720623f4226bca103b26260052732ad30Tom Cherry } 86bac3299720623f4226bca103b26260052732ad30Tom Cherry 87b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string prop_name = StringPrintf("init.svc.%s", name_.c_str()); 88bac3299720623f4226bca103b26260052732ad30Tom Cherry if (prop_name.length() >= PROP_NAME_MAX) { 89bac3299720623f4226bca103b26260052732ad30Tom Cherry // If the property name would be too long, we can't set it. 90bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("Property name \"init.svc.%s\" too long; not setting to %s\n", 91bac3299720623f4226bca103b26260052732ad30Tom Cherry name_.c_str(), new_state.c_str()); 92bac3299720623f4226bca103b26260052732ad30Tom Cherry return; 93bac3299720623f4226bca103b26260052732ad30Tom Cherry } 94bac3299720623f4226bca103b26260052732ad30Tom Cherry 95bac3299720623f4226bca103b26260052732ad30Tom Cherry property_set(prop_name.c_str(), new_state.c_str()); 96bac3299720623f4226bca103b26260052732ad30Tom Cherry} 97bac3299720623f4226bca103b26260052732ad30Tom Cherry 98bac3299720623f4226bca103b26260052732ad30Tom Cherrybool Service::Reap() { 99bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) { 100bac3299720623f4226bca103b26260052732ad30Tom Cherry NOTICE("Service '%s' (pid %d) killing any children in process group\n", 101bac3299720623f4226bca103b26260052732ad30Tom Cherry name_.c_str(), pid_); 102f7e79b99c1e9e3128dd9921871f7740bebb755e6Collin Mulliner killProcessGroup(uid_, pid_, SIGKILL); 103bac3299720623f4226bca103b26260052732ad30Tom Cherry } 104bac3299720623f4226bca103b26260052732ad30Tom Cherry 105bac3299720623f4226bca103b26260052732ad30Tom Cherry // Remove any sockets we may have created. 106bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& si : sockets_) { 107b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string tmp = StringPrintf(ANDROID_SOCKET_DIR "/%s", si.name.c_str()); 108bac3299720623f4226bca103b26260052732ad30Tom Cherry unlink(tmp.c_str()); 109bac3299720623f4226bca103b26260052732ad30Tom Cherry } 110bac3299720623f4226bca103b26260052732ad30Tom Cherry 111bac3299720623f4226bca103b26260052732ad30Tom Cherry if (flags_ & SVC_EXEC) { 112bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO("SVC_EXEC pid %d finished...\n", pid_); 113bac3299720623f4226bca103b26260052732ad30Tom Cherry return true; 114bac3299720623f4226bca103b26260052732ad30Tom Cherry } 115bac3299720623f4226bca103b26260052732ad30Tom Cherry 116bac3299720623f4226bca103b26260052732ad30Tom Cherry pid_ = 0; 117bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ &= (~SVC_RUNNING); 118bac3299720623f4226bca103b26260052732ad30Tom Cherry 119bac3299720623f4226bca103b26260052732ad30Tom Cherry // Oneshot processes go into the disabled state on exit, 120bac3299720623f4226bca103b26260052732ad30Tom Cherry // except when manually restarted. 121bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((flags_ & SVC_ONESHOT) && !(flags_ & SVC_RESTART)) { 122bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_DISABLED; 123bac3299720623f4226bca103b26260052732ad30Tom Cherry } 124bac3299720623f4226bca103b26260052732ad30Tom Cherry 125bac3299720623f4226bca103b26260052732ad30Tom Cherry // Disabled and reset processes do not get restarted automatically. 126bac3299720623f4226bca103b26260052732ad30Tom Cherry if (flags_ & (SVC_DISABLED | SVC_RESET)) { 127bac3299720623f4226bca103b26260052732ad30Tom Cherry NotifyStateChange("stopped"); 128bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 129bac3299720623f4226bca103b26260052732ad30Tom Cherry } 130bac3299720623f4226bca103b26260052732ad30Tom Cherry 131bac3299720623f4226bca103b26260052732ad30Tom Cherry time_t now = gettime(); 132bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((flags_ & SVC_CRITICAL) && !(flags_ & SVC_RESTART)) { 133bac3299720623f4226bca103b26260052732ad30Tom Cherry if (time_crashed_ + CRITICAL_CRASH_WINDOW >= now) { 134bac3299720623f4226bca103b26260052732ad30Tom Cherry if (++nr_crashed_ > CRITICAL_CRASH_THRESHOLD) { 135bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("critical process '%s' exited %d times in %d minutes; " 136bac3299720623f4226bca103b26260052732ad30Tom Cherry "rebooting into recovery mode\n", name_.c_str(), 137bac3299720623f4226bca103b26260052732ad30Tom Cherry CRITICAL_CRASH_THRESHOLD, CRITICAL_CRASH_WINDOW / 60); 138bac3299720623f4226bca103b26260052732ad30Tom Cherry android_reboot(ANDROID_RB_RESTART2, 0, "recovery"); 139bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 140bac3299720623f4226bca103b26260052732ad30Tom Cherry } 141bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 142bac3299720623f4226bca103b26260052732ad30Tom Cherry time_crashed_ = now; 143bac3299720623f4226bca103b26260052732ad30Tom Cherry nr_crashed_ = 1; 144bac3299720623f4226bca103b26260052732ad30Tom Cherry } 145bac3299720623f4226bca103b26260052732ad30Tom Cherry } 146bac3299720623f4226bca103b26260052732ad30Tom Cherry 147bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ &= (~SVC_RESTART); 148bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_RESTARTING; 149bac3299720623f4226bca103b26260052732ad30Tom Cherry 150bac3299720623f4226bca103b26260052732ad30Tom Cherry // Execute all onrestart commands for this service. 151bac3299720623f4226bca103b26260052732ad30Tom Cherry onrestart_.ExecuteAllCommands(); 152bac3299720623f4226bca103b26260052732ad30Tom Cherry 153bac3299720623f4226bca103b26260052732ad30Tom Cherry NotifyStateChange("restarting"); 154bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 155bac3299720623f4226bca103b26260052732ad30Tom Cherry} 156bac3299720623f4226bca103b26260052732ad30Tom Cherry 157bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::DumpState() const { 158bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO("service %s\n", name_.c_str()); 159bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO(" class '%s'\n", classname_.c_str()); 160bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO(" exec"); 161bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& s : args_) { 162bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO(" '%s'", s.c_str()); 163bac3299720623f4226bca103b26260052732ad30Tom Cherry } 164bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO("\n"); 165bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& si : sockets_) { 166bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO(" socket %s %s 0%o\n", si.name.c_str(), si.type.c_str(), si.perm); 167bac3299720623f4226bca103b26260052732ad30Tom Cherry } 168bac3299720623f4226bca103b26260052732ad30Tom Cherry} 169bac3299720623f4226bca103b26260052732ad30Tom Cherry 170b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleClass(const std::vector<std::string>& args, std::string* err) { 171b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry classname_ = args[1]; 172b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 173b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 174bac3299720623f4226bca103b26260052732ad30Tom Cherry 175b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleConsole(const std::vector<std::string>& args, std::string* err) { 176b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry flags_ |= SVC_CONSOLE; 17770daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman console_ = args.size() > 1 ? "/dev/" + args[1] : ""; 178b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 179b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 180bac3299720623f4226bca103b26260052732ad30Tom Cherry 181b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleCritical(const std::vector<std::string>& args, std::string* err) { 182b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry flags_ |= SVC_CRITICAL; 183b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 184b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 185bac3299720623f4226bca103b26260052732ad30Tom Cherry 186b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleDisabled(const std::vector<std::string>& args, std::string* err) { 187b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry flags_ |= SVC_DISABLED; 188b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry flags_ |= SVC_RC_DISABLED; 189b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 190b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 191bac3299720623f4226bca103b26260052732ad30Tom Cherry 192b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleGroup(const std::vector<std::string>& args, std::string* err) { 193b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry gid_ = decode_uid(args[1].c_str()); 194b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry for (std::size_t n = 2; n < args.size(); n++) { 195b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry supp_gids_.emplace_back(decode_uid(args[n].c_str())); 196b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 197b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 198b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 199bac3299720623f4226bca103b26260052732ad30Tom Cherry 200b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleIoprio(const std::vector<std::string>& args, std::string* err) { 201b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ioprio_pri_ = std::stoul(args[2], 0, 8); 202b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 203b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (ioprio_pri_ < 0 || ioprio_pri_ > 7) { 204b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry *err = "priority value must be range 0 - 7"; 205b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return false; 206b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 207b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 208b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (args[1] == "rt") { 209b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ioprio_class_ = IoSchedClass_RT; 210b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } else if (args[1] == "be") { 211b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ioprio_class_ = IoSchedClass_BE; 212b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } else if (args[1] == "idle") { 213b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ioprio_class_ = IoSchedClass_IDLE; 214b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } else { 215b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry *err = "ioprio option usage: ioprio <rt|be|idle> <0-7>"; 216b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return false; 217bac3299720623f4226bca103b26260052732ad30Tom Cherry } 218bac3299720623f4226bca103b26260052732ad30Tom Cherry 219b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 220b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 221bac3299720623f4226bca103b26260052732ad30Tom Cherry 222b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleKeycodes(const std::vector<std::string>& args, std::string* err) { 223b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry for (std::size_t i = 1; i < args.size(); i++) { 224b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry keycodes_.emplace_back(std::stoi(args[i])); 225bac3299720623f4226bca103b26260052732ad30Tom Cherry } 226b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 227b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 228b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 229b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleOneshot(const std::vector<std::string>& args, std::string* err) { 230b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry flags_ |= SVC_ONESHOT; 231b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 232b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 233b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 234b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleOnrestart(const std::vector<std::string>& args, std::string* err) { 235b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::vector<std::string> str_args(args.begin() + 1, args.end()); 236b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry onrestart_.AddCommand(str_args, "", 0, err); 237b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 238b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 239bac3299720623f4226bca103b26260052732ad30Tom Cherry 240b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleSeclabel(const std::vector<std::string>& args, std::string* err) { 241b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry seclabel_ = args[1]; 242b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 243b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 244b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 245b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleSetenv(const std::vector<std::string>& args, std::string* err) { 246b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry envvars_.emplace_back(args[1], args[2]); 247b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 248b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 249b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 250b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry/* name type perm [ uid gid context ] */ 251b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleSocket(const std::vector<std::string>& args, std::string* err) { 252b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (args[2] != "dgram" && args[2] != "stream" && args[2] != "seqpacket") { 253b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry *err = "socket type must be 'dgram', 'stream' or 'seqpacket'"; 254bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 255bac3299720623f4226bca103b26260052732ad30Tom Cherry } 256b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 257b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry int perm = std::stoul(args[3], 0, 8); 258b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry uid_t uid = args.size() > 4 ? decode_uid(args[4].c_str()) : 0; 259b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry gid_t gid = args.size() > 5 ? decode_uid(args[5].c_str()) : 0; 260b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string socketcon = args.size() > 6 ? args[6] : ""; 261b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 262b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry sockets_.emplace_back(args[1], args[2], uid, gid, perm, socketcon); 263bac3299720623f4226bca103b26260052732ad30Tom Cherry return true; 264bac3299720623f4226bca103b26260052732ad30Tom Cherry} 265bac3299720623f4226bca103b26260052732ad30Tom Cherry 266b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleUser(const std::vector<std::string>& args, std::string* err) { 267b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry uid_ = decode_uid(args[1].c_str()); 268b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 269b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 270b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 271b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleWritepid(const std::vector<std::string>& args, std::string* err) { 272b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry writepid_files_.assign(args.begin() + 1, args.end()); 273b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 274b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 275b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 276b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryclass Service::OptionHandlerMap : public KeywordMap<OptionHandler> { 277b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrypublic: 278b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry OptionHandlerMap() { 279b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 280b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryprivate: 281b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry Map& map() const override; 282b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}; 283b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 284b7349902a945903f9e36a569051f5131beb0bc24Tom CherryService::OptionHandlerMap::Map& Service::OptionHandlerMap::map() const { 285b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max(); 286b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry static const Map option_handlers = { 287b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"class", {1, 1, &Service::HandleClass}}, 28870daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman {"console", {0, 1, &Service::HandleConsole}}, 289b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"critical", {0, 0, &Service::HandleCritical}}, 290b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"disabled", {0, 0, &Service::HandleDisabled}}, 291b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"group", {1, NR_SVC_SUPP_GIDS + 1, &Service::HandleGroup}}, 292b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"ioprio", {2, 2, &Service::HandleIoprio}}, 293b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"keycodes", {1, kMax, &Service::HandleKeycodes}}, 294b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"oneshot", {0, 0, &Service::HandleOneshot}}, 295b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"onrestart", {1, kMax, &Service::HandleOnrestart}}, 296b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"seclabel", {1, 1, &Service::HandleSeclabel}}, 297b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"setenv", {2, 2, &Service::HandleSetenv}}, 298b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"socket", {3, 6, &Service::HandleSocket}}, 299b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"user", {1, 1, &Service::HandleUser}}, 300b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"writepid", {1, kMax, &Service::HandleWritepid}}, 301b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry }; 302b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return option_handlers; 303b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 304b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 305b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleLine(const std::vector<std::string>& args, std::string* err) { 306b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (args.empty()) { 307b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry *err = "option needed, but not provided"; 308b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return false; 309b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 310b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 311b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry static const OptionHandlerMap handler_map; 312b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry auto handler = handler_map.FindFunction(args[0], args.size() - 1, err); 313b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 314b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (!handler) { 315b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return false; 316b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 317b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 318b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return (this->*handler)(args, err); 319b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 320b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 321bdeac39a42c1b9c7195ada1c30fe12f94314490fElliott Hughesbool Service::Start() { 322bac3299720623f4226bca103b26260052732ad30Tom Cherry // Starting a service removes it from the disabled or reset state and 323bac3299720623f4226bca103b26260052732ad30Tom Cherry // immediately takes it out of the restarting state if it was in there. 324bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START)); 325bac3299720623f4226bca103b26260052732ad30Tom Cherry time_started_ = 0; 326bac3299720623f4226bca103b26260052732ad30Tom Cherry 327bac3299720623f4226bca103b26260052732ad30Tom Cherry // Running processes require no additional work --- if they're in the 328bac3299720623f4226bca103b26260052732ad30Tom Cherry // process of exiting, we've ensured that they will immediately restart 329bac3299720623f4226bca103b26260052732ad30Tom Cherry // on exit, unless they are ONESHOT. 330bac3299720623f4226bca103b26260052732ad30Tom Cherry if (flags_ & SVC_RUNNING) { 331bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 332bac3299720623f4226bca103b26260052732ad30Tom Cherry } 333bac3299720623f4226bca103b26260052732ad30Tom Cherry 334bac3299720623f4226bca103b26260052732ad30Tom Cherry bool needs_console = (flags_ & SVC_CONSOLE); 33570daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman if (needs_console) { 33670daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman if (console_.empty()) { 33770daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman console_ = default_console; 33870daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman } 33970daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman 34070daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman bool have_console = (open(console_.c_str(), O_RDWR | O_CLOEXEC) != -1); 34170daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman if (!have_console) { 34270daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman ERROR("service '%s' couldn't open console '%s': %s\n", 34370daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman name_.c_str(), console_.c_str(), strerror(errno)); 34470daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman flags_ |= SVC_DISABLED; 34570daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman return false; 34670daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman } 347bac3299720623f4226bca103b26260052732ad30Tom Cherry } 348bac3299720623f4226bca103b26260052732ad30Tom Cherry 349bac3299720623f4226bca103b26260052732ad30Tom Cherry struct stat sb; 350bac3299720623f4226bca103b26260052732ad30Tom Cherry if (stat(args_[0].c_str(), &sb) == -1) { 351bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("cannot find '%s' (%s), disabling '%s'\n", 352bac3299720623f4226bca103b26260052732ad30Tom Cherry args_[0].c_str(), strerror(errno), name_.c_str()); 353bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_DISABLED; 354bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 355bac3299720623f4226bca103b26260052732ad30Tom Cherry } 356bac3299720623f4226bca103b26260052732ad30Tom Cherry 357bac3299720623f4226bca103b26260052732ad30Tom Cherry std::string scon; 358bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!seclabel_.empty()) { 359bac3299720623f4226bca103b26260052732ad30Tom Cherry scon = seclabel_; 360bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 361bac3299720623f4226bca103b26260052732ad30Tom Cherry char* mycon = nullptr; 362bac3299720623f4226bca103b26260052732ad30Tom Cherry char* fcon = nullptr; 363bac3299720623f4226bca103b26260052732ad30Tom Cherry 364bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO("computing context for service '%s'\n", args_[0].c_str()); 365bac3299720623f4226bca103b26260052732ad30Tom Cherry int rc = getcon(&mycon); 366bac3299720623f4226bca103b26260052732ad30Tom Cherry if (rc < 0) { 367bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("could not get context while starting '%s'\n", name_.c_str()); 368bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 369bac3299720623f4226bca103b26260052732ad30Tom Cherry } 370bac3299720623f4226bca103b26260052732ad30Tom Cherry 371bac3299720623f4226bca103b26260052732ad30Tom Cherry rc = getfilecon(args_[0].c_str(), &fcon); 372bac3299720623f4226bca103b26260052732ad30Tom Cherry if (rc < 0) { 373bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("could not get context while starting '%s'\n", name_.c_str()); 374bac3299720623f4226bca103b26260052732ad30Tom Cherry free(mycon); 375bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 376bac3299720623f4226bca103b26260052732ad30Tom Cherry } 377bac3299720623f4226bca103b26260052732ad30Tom Cherry 378bac3299720623f4226bca103b26260052732ad30Tom Cherry char* ret_scon = nullptr; 379bac3299720623f4226bca103b26260052732ad30Tom Cherry rc = security_compute_create(mycon, fcon, string_to_security_class("process"), 380bac3299720623f4226bca103b26260052732ad30Tom Cherry &ret_scon); 381bac3299720623f4226bca103b26260052732ad30Tom Cherry if (rc == 0) { 382bac3299720623f4226bca103b26260052732ad30Tom Cherry scon = ret_scon; 383bac3299720623f4226bca103b26260052732ad30Tom Cherry free(ret_scon); 384bac3299720623f4226bca103b26260052732ad30Tom Cherry } 385bac3299720623f4226bca103b26260052732ad30Tom Cherry if (rc == 0 && scon == mycon) { 386bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("Service %s does not have a SELinux domain defined.\n", name_.c_str()); 387bac3299720623f4226bca103b26260052732ad30Tom Cherry free(mycon); 388bac3299720623f4226bca103b26260052732ad30Tom Cherry free(fcon); 389bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 390bac3299720623f4226bca103b26260052732ad30Tom Cherry } 391bac3299720623f4226bca103b26260052732ad30Tom Cherry free(mycon); 392bac3299720623f4226bca103b26260052732ad30Tom Cherry free(fcon); 393bac3299720623f4226bca103b26260052732ad30Tom Cherry if (rc < 0) { 394bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("could not get context while starting '%s'\n", name_.c_str()); 395bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 396bac3299720623f4226bca103b26260052732ad30Tom Cherry } 397bac3299720623f4226bca103b26260052732ad30Tom Cherry } 398bac3299720623f4226bca103b26260052732ad30Tom Cherry 399bac3299720623f4226bca103b26260052732ad30Tom Cherry NOTICE("Starting service '%s'...\n", name_.c_str()); 400bac3299720623f4226bca103b26260052732ad30Tom Cherry 401bac3299720623f4226bca103b26260052732ad30Tom Cherry pid_t pid = fork(); 402bac3299720623f4226bca103b26260052732ad30Tom Cherry if (pid == 0) { 403bac3299720623f4226bca103b26260052732ad30Tom Cherry umask(077); 404bac3299720623f4226bca103b26260052732ad30Tom Cherry 405bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& ei : envvars_) { 406bac3299720623f4226bca103b26260052732ad30Tom Cherry add_environment(ei.name.c_str(), ei.value.c_str()); 407bac3299720623f4226bca103b26260052732ad30Tom Cherry } 408bac3299720623f4226bca103b26260052732ad30Tom Cherry 409bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& si : sockets_) { 410bac3299720623f4226bca103b26260052732ad30Tom Cherry int socket_type = ((si.type == "stream" ? SOCK_STREAM : 411bac3299720623f4226bca103b26260052732ad30Tom Cherry (si.type == "dgram" ? SOCK_DGRAM : 412bac3299720623f4226bca103b26260052732ad30Tom Cherry SOCK_SEQPACKET))); 413bac3299720623f4226bca103b26260052732ad30Tom Cherry const char* socketcon = 414bac3299720623f4226bca103b26260052732ad30Tom Cherry !si.socketcon.empty() ? si.socketcon.c_str() : scon.c_str(); 415bac3299720623f4226bca103b26260052732ad30Tom Cherry 416bac3299720623f4226bca103b26260052732ad30Tom Cherry int s = create_socket(si.name.c_str(), socket_type, si.perm, 417bac3299720623f4226bca103b26260052732ad30Tom Cherry si.uid, si.gid, socketcon); 418bac3299720623f4226bca103b26260052732ad30Tom Cherry if (s >= 0) { 419bac3299720623f4226bca103b26260052732ad30Tom Cherry PublishSocket(si.name, s); 420bac3299720623f4226bca103b26260052732ad30Tom Cherry } 421bac3299720623f4226bca103b26260052732ad30Tom Cherry } 422bac3299720623f4226bca103b26260052732ad30Tom Cherry 423b702b46f688bc3ba7f8dc2d35c6eb25482366c4cAnestis Bechtsoudis std::string pid_str = StringPrintf("%d", getpid()); 424bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& file : writepid_files_) { 425b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (!WriteStringToFile(pid_str, file)) { 426bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("couldn't write %s to %s: %s\n", 427bac3299720623f4226bca103b26260052732ad30Tom Cherry pid_str.c_str(), file.c_str(), strerror(errno)); 428bac3299720623f4226bca103b26260052732ad30Tom Cherry } 429bac3299720623f4226bca103b26260052732ad30Tom Cherry } 430bac3299720623f4226bca103b26260052732ad30Tom Cherry 431bac3299720623f4226bca103b26260052732ad30Tom Cherry if (ioprio_class_ != IoSchedClass_NONE) { 432bac3299720623f4226bca103b26260052732ad30Tom Cherry if (android_set_ioprio(getpid(), ioprio_class_, ioprio_pri_)) { 433bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("Failed to set pid %d ioprio = %d,%d: %s\n", 434bac3299720623f4226bca103b26260052732ad30Tom Cherry getpid(), ioprio_class_, ioprio_pri_, strerror(errno)); 435bac3299720623f4226bca103b26260052732ad30Tom Cherry } 436bac3299720623f4226bca103b26260052732ad30Tom Cherry } 437bac3299720623f4226bca103b26260052732ad30Tom Cherry 438bac3299720623f4226bca103b26260052732ad30Tom Cherry if (needs_console) { 439bac3299720623f4226bca103b26260052732ad30Tom Cherry setsid(); 440bac3299720623f4226bca103b26260052732ad30Tom Cherry OpenConsole(); 441bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 442bac3299720623f4226bca103b26260052732ad30Tom Cherry ZapStdio(); 443bac3299720623f4226bca103b26260052732ad30Tom Cherry } 444bac3299720623f4226bca103b26260052732ad30Tom Cherry 445bac3299720623f4226bca103b26260052732ad30Tom Cherry setpgid(0, getpid()); 446bac3299720623f4226bca103b26260052732ad30Tom Cherry 447bac3299720623f4226bca103b26260052732ad30Tom Cherry // As requested, set our gid, supplemental gids, and uid. 448bac3299720623f4226bca103b26260052732ad30Tom Cherry if (gid_) { 449bac3299720623f4226bca103b26260052732ad30Tom Cherry if (setgid(gid_) != 0) { 450bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("setgid failed: %s\n", strerror(errno)); 451bac3299720623f4226bca103b26260052732ad30Tom Cherry _exit(127); 452bac3299720623f4226bca103b26260052732ad30Tom Cherry } 453bac3299720623f4226bca103b26260052732ad30Tom Cherry } 454bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!supp_gids_.empty()) { 455bac3299720623f4226bca103b26260052732ad30Tom Cherry if (setgroups(supp_gids_.size(), &supp_gids_[0]) != 0) { 456bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("setgroups failed: %s\n", strerror(errno)); 457bac3299720623f4226bca103b26260052732ad30Tom Cherry _exit(127); 458bac3299720623f4226bca103b26260052732ad30Tom Cherry } 459bac3299720623f4226bca103b26260052732ad30Tom Cherry } 460bac3299720623f4226bca103b26260052732ad30Tom Cherry if (uid_) { 461bac3299720623f4226bca103b26260052732ad30Tom Cherry if (setuid(uid_) != 0) { 462bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("setuid failed: %s\n", strerror(errno)); 463bac3299720623f4226bca103b26260052732ad30Tom Cherry _exit(127); 464bac3299720623f4226bca103b26260052732ad30Tom Cherry } 465bac3299720623f4226bca103b26260052732ad30Tom Cherry } 466bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!seclabel_.empty()) { 467bac3299720623f4226bca103b26260052732ad30Tom Cherry if (setexeccon(seclabel_.c_str()) < 0) { 468bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("cannot setexeccon('%s'): %s\n", 469bac3299720623f4226bca103b26260052732ad30Tom Cherry seclabel_.c_str(), strerror(errno)); 470bac3299720623f4226bca103b26260052732ad30Tom Cherry _exit(127); 471bac3299720623f4226bca103b26260052732ad30Tom Cherry } 472bac3299720623f4226bca103b26260052732ad30Tom Cherry } 473bac3299720623f4226bca103b26260052732ad30Tom Cherry 474bac3299720623f4226bca103b26260052732ad30Tom Cherry std::vector<char*> strs; 475bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& s : args_) { 476bac3299720623f4226bca103b26260052732ad30Tom Cherry strs.push_back(const_cast<char*>(s.c_str())); 477bac3299720623f4226bca103b26260052732ad30Tom Cherry } 478bac3299720623f4226bca103b26260052732ad30Tom Cherry strs.push_back(nullptr); 479bac3299720623f4226bca103b26260052732ad30Tom Cherry if (execve(args_[0].c_str(), (char**) &strs[0], (char**) ENV) < 0) { 480bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("cannot execve('%s'): %s\n", args_[0].c_str(), strerror(errno)); 481bac3299720623f4226bca103b26260052732ad30Tom Cherry } 482bac3299720623f4226bca103b26260052732ad30Tom Cherry 483bac3299720623f4226bca103b26260052732ad30Tom Cherry _exit(127); 484bac3299720623f4226bca103b26260052732ad30Tom Cherry } 485bac3299720623f4226bca103b26260052732ad30Tom Cherry 486bac3299720623f4226bca103b26260052732ad30Tom Cherry if (pid < 0) { 487bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("failed to start '%s'\n", name_.c_str()); 488bac3299720623f4226bca103b26260052732ad30Tom Cherry pid_ = 0; 489bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 490bac3299720623f4226bca103b26260052732ad30Tom Cherry } 491bac3299720623f4226bca103b26260052732ad30Tom Cherry 492bac3299720623f4226bca103b26260052732ad30Tom Cherry time_started_ = gettime(); 493bac3299720623f4226bca103b26260052732ad30Tom Cherry pid_ = pid; 494bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_RUNNING; 495f7e79b99c1e9e3128dd9921871f7740bebb755e6Collin Mulliner createProcessGroup(uid_, pid_); 496bac3299720623f4226bca103b26260052732ad30Tom Cherry 497bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((flags_ & SVC_EXEC) != 0) { 498bac3299720623f4226bca103b26260052732ad30Tom Cherry INFO("SVC_EXEC pid %d (uid %d gid %d+%zu context %s) started; waiting...\n", 499bac3299720623f4226bca103b26260052732ad30Tom Cherry pid_, uid_, gid_, supp_gids_.size(), 500bac3299720623f4226bca103b26260052732ad30Tom Cherry !seclabel_.empty() ? seclabel_.c_str() : "default"); 501bac3299720623f4226bca103b26260052732ad30Tom Cherry } 502bac3299720623f4226bca103b26260052732ad30Tom Cherry 503bac3299720623f4226bca103b26260052732ad30Tom Cherry NotifyStateChange("running"); 504bac3299720623f4226bca103b26260052732ad30Tom Cherry return true; 505bac3299720623f4226bca103b26260052732ad30Tom Cherry} 506bac3299720623f4226bca103b26260052732ad30Tom Cherry 507bac3299720623f4226bca103b26260052732ad30Tom Cherrybool Service::StartIfNotDisabled() { 508bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!(flags_ & SVC_DISABLED)) { 509bac3299720623f4226bca103b26260052732ad30Tom Cherry return Start(); 510bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 511bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_DISABLED_START; 512bac3299720623f4226bca103b26260052732ad30Tom Cherry } 513bac3299720623f4226bca103b26260052732ad30Tom Cherry return true; 514bac3299720623f4226bca103b26260052732ad30Tom Cherry} 515bac3299720623f4226bca103b26260052732ad30Tom Cherry 516bac3299720623f4226bca103b26260052732ad30Tom Cherrybool Service::Enable() { 517bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ &= ~(SVC_DISABLED | SVC_RC_DISABLED); 518bac3299720623f4226bca103b26260052732ad30Tom Cherry if (flags_ & SVC_DISABLED_START) { 519bac3299720623f4226bca103b26260052732ad30Tom Cherry return Start(); 520bac3299720623f4226bca103b26260052732ad30Tom Cherry } 521bac3299720623f4226bca103b26260052732ad30Tom Cherry return true; 522bac3299720623f4226bca103b26260052732ad30Tom Cherry} 523bac3299720623f4226bca103b26260052732ad30Tom Cherry 524bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::Reset() { 525bac3299720623f4226bca103b26260052732ad30Tom Cherry StopOrReset(SVC_RESET); 526bac3299720623f4226bca103b26260052732ad30Tom Cherry} 527bac3299720623f4226bca103b26260052732ad30Tom Cherry 528bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::Stop() { 529bac3299720623f4226bca103b26260052732ad30Tom Cherry StopOrReset(SVC_DISABLED); 530bac3299720623f4226bca103b26260052732ad30Tom Cherry} 531bac3299720623f4226bca103b26260052732ad30Tom Cherry 532b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNETvoid Service::Terminate() { 533b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET flags_ &= ~(SVC_RESTARTING | SVC_DISABLED_START); 534b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET flags_ |= SVC_DISABLED; 535b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET if (pid_) { 536b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET NOTICE("Sending SIGTERM to service '%s' (pid %d)...\n", name_.c_str(), 537b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET pid_); 538f7e79b99c1e9e3128dd9921871f7740bebb755e6Collin Mulliner killProcessGroup(uid_, pid_, SIGTERM); 539b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET NotifyStateChange("stopping"); 540b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } 541b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET} 542b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET 543bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::Restart() { 544bac3299720623f4226bca103b26260052732ad30Tom Cherry if (flags_ & SVC_RUNNING) { 545bac3299720623f4226bca103b26260052732ad30Tom Cherry /* Stop, wait, then start the service. */ 546bac3299720623f4226bca103b26260052732ad30Tom Cherry StopOrReset(SVC_RESTART); 547bac3299720623f4226bca103b26260052732ad30Tom Cherry } else if (!(flags_ & SVC_RESTARTING)) { 548bac3299720623f4226bca103b26260052732ad30Tom Cherry /* Just start the service since it's not running. */ 549bac3299720623f4226bca103b26260052732ad30Tom Cherry Start(); 550bac3299720623f4226bca103b26260052732ad30Tom Cherry } /* else: Service is restarting anyways. */ 551bac3299720623f4226bca103b26260052732ad30Tom Cherry} 552bac3299720623f4226bca103b26260052732ad30Tom Cherry 553bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::RestartIfNeeded(time_t& process_needs_restart) { 554bac3299720623f4226bca103b26260052732ad30Tom Cherry time_t next_start_time = time_started_ + 5; 555bac3299720623f4226bca103b26260052732ad30Tom Cherry 556bac3299720623f4226bca103b26260052732ad30Tom Cherry if (next_start_time <= gettime()) { 557bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ &= (~SVC_RESTARTING); 558bac3299720623f4226bca103b26260052732ad30Tom Cherry Start(); 559bac3299720623f4226bca103b26260052732ad30Tom Cherry return; 560bac3299720623f4226bca103b26260052732ad30Tom Cherry } 561bac3299720623f4226bca103b26260052732ad30Tom Cherry 562bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((next_start_time < process_needs_restart) || 563bac3299720623f4226bca103b26260052732ad30Tom Cherry (process_needs_restart == 0)) { 564bac3299720623f4226bca103b26260052732ad30Tom Cherry process_needs_restart = next_start_time; 565bac3299720623f4226bca103b26260052732ad30Tom Cherry } 566bac3299720623f4226bca103b26260052732ad30Tom Cherry} 567bac3299720623f4226bca103b26260052732ad30Tom Cherry 568bac3299720623f4226bca103b26260052732ad30Tom Cherry/* The how field should be either SVC_DISABLED, SVC_RESET, or SVC_RESTART */ 569bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::StopOrReset(int how) { 570bac3299720623f4226bca103b26260052732ad30Tom Cherry /* The service is still SVC_RUNNING until its process exits, but if it has 571bac3299720623f4226bca103b26260052732ad30Tom Cherry * already exited it shoudn't attempt a restart yet. */ 572bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ &= ~(SVC_RESTARTING | SVC_DISABLED_START); 573bac3299720623f4226bca103b26260052732ad30Tom Cherry 574bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((how != SVC_DISABLED) && (how != SVC_RESET) && (how != SVC_RESTART)) { 575bac3299720623f4226bca103b26260052732ad30Tom Cherry /* Hrm, an illegal flag. Default to SVC_DISABLED */ 576bac3299720623f4226bca103b26260052732ad30Tom Cherry how = SVC_DISABLED; 577bac3299720623f4226bca103b26260052732ad30Tom Cherry } 578bac3299720623f4226bca103b26260052732ad30Tom Cherry /* if the service has not yet started, prevent 579bac3299720623f4226bca103b26260052732ad30Tom Cherry * it from auto-starting with its class 580bac3299720623f4226bca103b26260052732ad30Tom Cherry */ 581bac3299720623f4226bca103b26260052732ad30Tom Cherry if (how == SVC_RESET) { 582bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= (flags_ & SVC_RC_DISABLED) ? SVC_DISABLED : SVC_RESET; 583bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 584bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= how; 585bac3299720623f4226bca103b26260052732ad30Tom Cherry } 586bac3299720623f4226bca103b26260052732ad30Tom Cherry 587bac3299720623f4226bca103b26260052732ad30Tom Cherry if (pid_) { 588bac3299720623f4226bca103b26260052732ad30Tom Cherry NOTICE("Service '%s' is being killed...\n", name_.c_str()); 589f7e79b99c1e9e3128dd9921871f7740bebb755e6Collin Mulliner killProcessGroup(uid_, pid_, SIGKILL); 590bac3299720623f4226bca103b26260052732ad30Tom Cherry NotifyStateChange("stopping"); 591bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 592bac3299720623f4226bca103b26260052732ad30Tom Cherry NotifyStateChange("stopped"); 593bac3299720623f4226bca103b26260052732ad30Tom Cherry } 594bac3299720623f4226bca103b26260052732ad30Tom Cherry} 595bac3299720623f4226bca103b26260052732ad30Tom Cherry 596bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::ZapStdio() const { 597bac3299720623f4226bca103b26260052732ad30Tom Cherry int fd; 598bac3299720623f4226bca103b26260052732ad30Tom Cherry fd = open("/dev/null", O_RDWR); 599bac3299720623f4226bca103b26260052732ad30Tom Cherry dup2(fd, 0); 600bac3299720623f4226bca103b26260052732ad30Tom Cherry dup2(fd, 1); 601bac3299720623f4226bca103b26260052732ad30Tom Cherry dup2(fd, 2); 602bac3299720623f4226bca103b26260052732ad30Tom Cherry close(fd); 603bac3299720623f4226bca103b26260052732ad30Tom Cherry} 604bac3299720623f4226bca103b26260052732ad30Tom Cherry 605bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::OpenConsole() const { 60670daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman int fd = open(console_.c_str(), O_RDWR); 60770daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman if (fd == -1) fd = open("/dev/null", O_RDWR); 608bac3299720623f4226bca103b26260052732ad30Tom Cherry ioctl(fd, TIOCSCTTY, 0); 609bac3299720623f4226bca103b26260052732ad30Tom Cherry dup2(fd, 0); 610bac3299720623f4226bca103b26260052732ad30Tom Cherry dup2(fd, 1); 611bac3299720623f4226bca103b26260052732ad30Tom Cherry dup2(fd, 2); 612bac3299720623f4226bca103b26260052732ad30Tom Cherry close(fd); 613bac3299720623f4226bca103b26260052732ad30Tom Cherry} 614bac3299720623f4226bca103b26260052732ad30Tom Cherry 615bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::PublishSocket(const std::string& name, int fd) const { 616b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string key = StringPrintf(ANDROID_SOCKET_ENV_PREFIX "%s", name.c_str()); 617b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string val = StringPrintf("%d", fd); 618bac3299720623f4226bca103b26260052732ad30Tom Cherry add_environment(key.c_str(), val.c_str()); 619bac3299720623f4226bca103b26260052732ad30Tom Cherry 620bac3299720623f4226bca103b26260052732ad30Tom Cherry /* make sure we don't close-on-exec */ 621bac3299720623f4226bca103b26260052732ad30Tom Cherry fcntl(fd, F_SETFD, 0); 622bac3299720623f4226bca103b26260052732ad30Tom Cherry} 623bac3299720623f4226bca103b26260052732ad30Tom Cherry 624bac3299720623f4226bca103b26260052732ad30Tom Cherryint ServiceManager::exec_count_ = 0; 625bac3299720623f4226bca103b26260052732ad30Tom Cherry 626bac3299720623f4226bca103b26260052732ad30Tom CherryServiceManager::ServiceManager() { 627bac3299720623f4226bca103b26260052732ad30Tom Cherry} 628bac3299720623f4226bca103b26260052732ad30Tom Cherry 629bac3299720623f4226bca103b26260052732ad30Tom CherryServiceManager& ServiceManager::GetInstance() { 630bac3299720623f4226bca103b26260052732ad30Tom Cherry static ServiceManager instance; 631bac3299720623f4226bca103b26260052732ad30Tom Cherry return instance; 632bac3299720623f4226bca103b26260052732ad30Tom Cherry} 633bac3299720623f4226bca103b26260052732ad30Tom Cherry 634b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryvoid ServiceManager::AddService(std::unique_ptr<Service> service) { 635b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry Service* old_service = FindServiceByName(service->name()); 636b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (old_service) { 637b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ERROR("ignored duplicate definition of service '%s'", 638b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry service->name().c_str()); 639b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return; 640bac3299720623f4226bca103b26260052732ad30Tom Cherry } 641b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry services_.emplace_back(std::move(service)); 642bac3299720623f4226bca103b26260052732ad30Tom Cherry} 643bac3299720623f4226bca103b26260052732ad30Tom Cherry 644bac3299720623f4226bca103b26260052732ad30Tom CherryService* ServiceManager::MakeExecOneshotService(const std::vector<std::string>& args) { 645bac3299720623f4226bca103b26260052732ad30Tom Cherry // Parse the arguments: exec [SECLABEL [UID [GID]*] --] COMMAND ARGS... 646bac3299720623f4226bca103b26260052732ad30Tom Cherry // SECLABEL can be a - to denote default 647bac3299720623f4226bca103b26260052732ad30Tom Cherry std::size_t command_arg = 1; 648bac3299720623f4226bca103b26260052732ad30Tom Cherry for (std::size_t i = 1; i < args.size(); ++i) { 649bac3299720623f4226bca103b26260052732ad30Tom Cherry if (args[i] == "--") { 650bac3299720623f4226bca103b26260052732ad30Tom Cherry command_arg = i + 1; 651bac3299720623f4226bca103b26260052732ad30Tom Cherry break; 652bac3299720623f4226bca103b26260052732ad30Tom Cherry } 653bac3299720623f4226bca103b26260052732ad30Tom Cherry } 654bac3299720623f4226bca103b26260052732ad30Tom Cherry if (command_arg > 4 + NR_SVC_SUPP_GIDS) { 655bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("exec called with too many supplementary group ids\n"); 656bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 657bac3299720623f4226bca103b26260052732ad30Tom Cherry } 658bac3299720623f4226bca103b26260052732ad30Tom Cherry 659bac3299720623f4226bca103b26260052732ad30Tom Cherry if (command_arg >= args.size()) { 660bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("exec called without command\n"); 661bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 662bac3299720623f4226bca103b26260052732ad30Tom Cherry } 663bac3299720623f4226bca103b26260052732ad30Tom Cherry std::vector<std::string> str_args(args.begin() + command_arg, args.end()); 664bac3299720623f4226bca103b26260052732ad30Tom Cherry 665bac3299720623f4226bca103b26260052732ad30Tom Cherry exec_count_++; 666b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string name = StringPrintf("exec %d (%s)", exec_count_, str_args[0].c_str()); 667bac3299720623f4226bca103b26260052732ad30Tom Cherry unsigned flags = SVC_EXEC | SVC_ONESHOT; 668bac3299720623f4226bca103b26260052732ad30Tom Cherry 669bac3299720623f4226bca103b26260052732ad30Tom Cherry std::string seclabel = ""; 670bac3299720623f4226bca103b26260052732ad30Tom Cherry if (command_arg > 2 && args[1] != "-") { 671bac3299720623f4226bca103b26260052732ad30Tom Cherry seclabel = args[1]; 672bac3299720623f4226bca103b26260052732ad30Tom Cherry } 673bac3299720623f4226bca103b26260052732ad30Tom Cherry uid_t uid = 0; 674bac3299720623f4226bca103b26260052732ad30Tom Cherry if (command_arg > 3) { 675bac3299720623f4226bca103b26260052732ad30Tom Cherry uid = decode_uid(args[2].c_str()); 676bac3299720623f4226bca103b26260052732ad30Tom Cherry } 677bac3299720623f4226bca103b26260052732ad30Tom Cherry gid_t gid = 0; 678bac3299720623f4226bca103b26260052732ad30Tom Cherry std::vector<gid_t> supp_gids; 679bac3299720623f4226bca103b26260052732ad30Tom Cherry if (command_arg > 4) { 680bac3299720623f4226bca103b26260052732ad30Tom Cherry gid = decode_uid(args[3].c_str()); 681bac3299720623f4226bca103b26260052732ad30Tom Cherry std::size_t nr_supp_gids = command_arg - 1 /* -- */ - 4 /* exec SECLABEL UID GID */; 682bac3299720623f4226bca103b26260052732ad30Tom Cherry for (size_t i = 0; i < nr_supp_gids; ++i) { 683bac3299720623f4226bca103b26260052732ad30Tom Cherry supp_gids.push_back(decode_uid(args[4 + i].c_str())); 684bac3299720623f4226bca103b26260052732ad30Tom Cherry } 685bac3299720623f4226bca103b26260052732ad30Tom Cherry } 686bac3299720623f4226bca103b26260052732ad30Tom Cherry 687bac3299720623f4226bca103b26260052732ad30Tom Cherry std::unique_ptr<Service> svc_p(new Service(name, "default", flags, uid, gid, 688bac3299720623f4226bca103b26260052732ad30Tom Cherry supp_gids, seclabel, str_args)); 689bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!svc_p) { 690bac3299720623f4226bca103b26260052732ad30Tom Cherry ERROR("Couldn't allocate service for exec of '%s'", 691bac3299720623f4226bca103b26260052732ad30Tom Cherry str_args[0].c_str()); 692bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 693bac3299720623f4226bca103b26260052732ad30Tom Cherry } 694bac3299720623f4226bca103b26260052732ad30Tom Cherry Service* svc = svc_p.get(); 695bac3299720623f4226bca103b26260052732ad30Tom Cherry services_.push_back(std::move(svc_p)); 696bac3299720623f4226bca103b26260052732ad30Tom Cherry 697bac3299720623f4226bca103b26260052732ad30Tom Cherry return svc; 698bac3299720623f4226bca103b26260052732ad30Tom Cherry} 699bac3299720623f4226bca103b26260052732ad30Tom Cherry 700bac3299720623f4226bca103b26260052732ad30Tom CherryService* ServiceManager::FindServiceByName(const std::string& name) const { 701bac3299720623f4226bca103b26260052732ad30Tom Cherry auto svc = std::find_if(services_.begin(), services_.end(), 702bac3299720623f4226bca103b26260052732ad30Tom Cherry [&name] (const std::unique_ptr<Service>& s) { 703bac3299720623f4226bca103b26260052732ad30Tom Cherry return name == s->name(); 704bac3299720623f4226bca103b26260052732ad30Tom Cherry }); 705bac3299720623f4226bca103b26260052732ad30Tom Cherry if (svc != services_.end()) { 706bac3299720623f4226bca103b26260052732ad30Tom Cherry return svc->get(); 707bac3299720623f4226bca103b26260052732ad30Tom Cherry } 708bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 709bac3299720623f4226bca103b26260052732ad30Tom Cherry} 710bac3299720623f4226bca103b26260052732ad30Tom Cherry 711bac3299720623f4226bca103b26260052732ad30Tom CherryService* ServiceManager::FindServiceByPid(pid_t pid) const { 712bac3299720623f4226bca103b26260052732ad30Tom Cherry auto svc = std::find_if(services_.begin(), services_.end(), 713bac3299720623f4226bca103b26260052732ad30Tom Cherry [&pid] (const std::unique_ptr<Service>& s) { 714bac3299720623f4226bca103b26260052732ad30Tom Cherry return s->pid() == pid; 715bac3299720623f4226bca103b26260052732ad30Tom Cherry }); 716bac3299720623f4226bca103b26260052732ad30Tom Cherry if (svc != services_.end()) { 717bac3299720623f4226bca103b26260052732ad30Tom Cherry return svc->get(); 718bac3299720623f4226bca103b26260052732ad30Tom Cherry } 719bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 720bac3299720623f4226bca103b26260052732ad30Tom Cherry} 721bac3299720623f4226bca103b26260052732ad30Tom Cherry 722bac3299720623f4226bca103b26260052732ad30Tom CherryService* ServiceManager::FindServiceByKeychord(int keychord_id) const { 723bac3299720623f4226bca103b26260052732ad30Tom Cherry auto svc = std::find_if(services_.begin(), services_.end(), 724bac3299720623f4226bca103b26260052732ad30Tom Cherry [&keychord_id] (const std::unique_ptr<Service>& s) { 725bac3299720623f4226bca103b26260052732ad30Tom Cherry return s->keychord_id() == keychord_id; 726bac3299720623f4226bca103b26260052732ad30Tom Cherry }); 727bac3299720623f4226bca103b26260052732ad30Tom Cherry 728bac3299720623f4226bca103b26260052732ad30Tom Cherry if (svc != services_.end()) { 729bac3299720623f4226bca103b26260052732ad30Tom Cherry return svc->get(); 730bac3299720623f4226bca103b26260052732ad30Tom Cherry } 731bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 732bac3299720623f4226bca103b26260052732ad30Tom Cherry} 733bac3299720623f4226bca103b26260052732ad30Tom Cherry 734b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNETvoid ServiceManager::ForEachService(std::function<void(Service*)> callback) const { 735bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& s : services_) { 736b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET callback(s.get()); 737bac3299720623f4226bca103b26260052732ad30Tom Cherry } 738bac3299720623f4226bca103b26260052732ad30Tom Cherry} 739bac3299720623f4226bca103b26260052732ad30Tom Cherry 740bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid ServiceManager::ForEachServiceInClass(const std::string& classname, 741bac3299720623f4226bca103b26260052732ad30Tom Cherry void (*func)(Service* svc)) const { 742bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& s : services_) { 743bac3299720623f4226bca103b26260052732ad30Tom Cherry if (classname == s->classname()) { 744bac3299720623f4226bca103b26260052732ad30Tom Cherry func(s.get()); 745bac3299720623f4226bca103b26260052732ad30Tom Cherry } 746bac3299720623f4226bca103b26260052732ad30Tom Cherry } 747bac3299720623f4226bca103b26260052732ad30Tom Cherry} 748bac3299720623f4226bca103b26260052732ad30Tom Cherry 749bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid ServiceManager::ForEachServiceWithFlags(unsigned matchflags, 750bac3299720623f4226bca103b26260052732ad30Tom Cherry void (*func)(Service* svc)) const { 751bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& s : services_) { 752bac3299720623f4226bca103b26260052732ad30Tom Cherry if (s->flags() & matchflags) { 753bac3299720623f4226bca103b26260052732ad30Tom Cherry func(s.get()); 754bac3299720623f4226bca103b26260052732ad30Tom Cherry } 755bac3299720623f4226bca103b26260052732ad30Tom Cherry } 756bac3299720623f4226bca103b26260052732ad30Tom Cherry} 757bac3299720623f4226bca103b26260052732ad30Tom Cherry 758b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryvoid ServiceManager::RemoveService(const Service& svc) { 759bac3299720623f4226bca103b26260052732ad30Tom Cherry auto svc_it = std::find_if(services_.begin(), services_.end(), 760bac3299720623f4226bca103b26260052732ad30Tom Cherry [&svc] (const std::unique_ptr<Service>& s) { 761bac3299720623f4226bca103b26260052732ad30Tom Cherry return svc.name() == s->name(); 762bac3299720623f4226bca103b26260052732ad30Tom Cherry }); 763bac3299720623f4226bca103b26260052732ad30Tom Cherry if (svc_it == services_.end()) { 764bac3299720623f4226bca103b26260052732ad30Tom Cherry return; 765bac3299720623f4226bca103b26260052732ad30Tom Cherry } 766bac3299720623f4226bca103b26260052732ad30Tom Cherry 767bac3299720623f4226bca103b26260052732ad30Tom Cherry services_.erase(svc_it); 768bac3299720623f4226bca103b26260052732ad30Tom Cherry} 769bac3299720623f4226bca103b26260052732ad30Tom Cherry 770b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryvoid ServiceManager::DumpState() const { 771b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry for (const auto& s : services_) { 772b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry s->DumpState(); 773b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 774b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry INFO("\n"); 775b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 776b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 777b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNETbool ServiceManager::ReapOneProcess() { 778b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET int status; 779b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG)); 780b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET if (pid == 0) { 781b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET return false; 782b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } else if (pid == -1) { 783b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET ERROR("waitpid failed: %s\n", strerror(errno)); 784b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET return false; 785b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } 786b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET 787b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET Service* svc = FindServiceByPid(pid); 788b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET 789b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET std::string name; 790b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET if (svc) { 791b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET name = android::base::StringPrintf("Service '%s' (pid %d)", 792b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET svc->name().c_str(), pid); 793b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } else { 794b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET name = android::base::StringPrintf("Untracked pid %d", pid); 795b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } 796b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET 797b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET if (WIFEXITED(status)) { 798b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET NOTICE("%s exited with status %d\n", name.c_str(), WEXITSTATUS(status)); 799b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } else if (WIFSIGNALED(status)) { 800b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET NOTICE("%s killed by signal %d\n", name.c_str(), WTERMSIG(status)); 801b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } else if (WIFSTOPPED(status)) { 802b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET NOTICE("%s stopped by signal %d\n", name.c_str(), WSTOPSIG(status)); 803b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } else { 804b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET NOTICE("%s state changed", name.c_str()); 805b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } 806b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET 807b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET if (!svc) { 808b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET return true; 809b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } 810b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET 811b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET if (svc->Reap()) { 812b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET waiting_for_exec = false; 813b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET RemoveService(*svc); 814b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } 815b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET 816b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET return true; 817b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET} 818b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET 819b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNETvoid ServiceManager::ReapAnyOutstandingChildren() { 820b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET while (ReapOneProcess()) { 821b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } 822b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET} 823b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET 824b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool ServiceParser::ParseSection(const std::vector<std::string>& args, 825b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string* err) { 826b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (args.size() < 3) { 827b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry *err = "services must have a name and a program"; 828b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return false; 829b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 830b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 831b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry const std::string& name = args[1]; 832b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (!IsValidName(name)) { 833b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry *err = StringPrintf("invalid service name '%s'", name.c_str()); 834b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return false; 835b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 836b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 837b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::vector<std::string> str_args(args.begin() + 2, args.end()); 838b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry service_ = std::make_unique<Service>(name, "default", str_args); 839b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 840b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 841b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 842b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool ServiceParser::ParseLineSection(const std::vector<std::string>& args, 843b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry const std::string& filename, int line, 844b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string* err) const { 845b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return service_ ? service_->HandleLine(args, err) : false; 846b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 847b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 848b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryvoid ServiceParser::EndSection() { 849b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (service_) { 850b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ServiceManager::GetInstance().AddService(std::move(service_)); 851b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 852b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 853b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 854b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool ServiceParser::IsValidName(const std::string& name) const { 855bac3299720623f4226bca103b26260052732ad30Tom Cherry if (name.size() > 16) { 856bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 857bac3299720623f4226bca103b26260052732ad30Tom Cherry } 858bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& c : name) { 859bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!isalnum(c) && (c != '_') && (c != '-')) { 860bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 861bac3299720623f4226bca103b26260052732ad30Tom Cherry } 862bac3299720623f4226bca103b26260052732ad30Tom Cherry } 863bac3299720623f4226bca103b26260052732ad30Tom Cherry return true; 864bac3299720623f4226bca103b26260052732ad30Tom Cherry} 865