service.cpp revision 1b3fa3d6506d04570aab60147b0ec743e38c8796
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> 201b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes#include <sched.h> 211b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes#include <sys/mount.h> 221b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes#include <sys/prctl.h> 23081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv#include <sys/resource.h> 24bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <sys/stat.h> 25081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv#include <sys/time.h> 26bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <sys/types.h> 27b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET#include <sys/wait.h> 28bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <termios.h> 29af9ba4dc6ca98e136e887b0baa59b72fb8302dd3Dan Albert#include <unistd.h> 30bac3299720623f4226bca103b26260052732ad30Tom Cherry 31bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <selinux/selinux.h> 32bac3299720623f4226bca103b26260052732ad30Tom Cherry 334f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/file.h> 344f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/stringprintf.h> 35f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes#include <android-base/strings.h> 36bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <cutils/android_reboot.h> 37bac3299720623f4226bca103b26260052732ad30Tom Cherry#include <cutils/sockets.h> 38081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv#include <system/thread_defs.h> 39bac3299720623f4226bca103b26260052732ad30Tom Cherry 40f7e79b99c1e9e3128dd9921871f7740bebb755e6Collin Mulliner#include <processgroup/processgroup.h> 41f7e79b99c1e9e3128dd9921871f7740bebb755e6Collin Mulliner 42bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "action.h" 43bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "init.h" 44bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "init_parser.h" 45bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "log.h" 46bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "property_service.h" 47bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "util.h" 48bac3299720623f4226bca103b26260052732ad30Tom Cherry 49b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryusing android::base::StringPrintf; 50b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryusing android::base::WriteStringToFile; 51b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 52bac3299720623f4226bca103b26260052732ad30Tom Cherry#define CRITICAL_CRASH_THRESHOLD 4 // if we crash >4 times ... 53bac3299720623f4226bca103b26260052732ad30Tom Cherry#define CRITICAL_CRASH_WINDOW (4*60) // ... in 4 minutes, goto recovery 54bac3299720623f4226bca103b26260052732ad30Tom Cherry 551b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obesstatic void SetUpPidNamespace(const std::string& service_name) { 561b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes constexpr unsigned int kSafeFlags = MS_NODEV | MS_NOEXEC | MS_NOSUID; 571b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes 581b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes // It's OK to LOG(FATAL) in this function since it's running in the first 591b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes // child process. 601b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes if (mount("", "/proc", "proc", kSafeFlags | MS_REMOUNT, "") == -1) { 611b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes PLOG(FATAL) << "couldn't remount(/proc)"; 621b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes } 631b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes 641b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes if (prctl(PR_SET_NAME, service_name.c_str()) == -1) { 651b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes PLOG(FATAL) << "couldn't set name"; 661b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes } 671b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes 681b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes pid_t child_pid = fork(); 691b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes if (child_pid == -1) { 701b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes PLOG(FATAL) << "couldn't fork init inside the PID namespace"; 711b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes } 721b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes 731b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes if (child_pid > 0) { 741b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes // So that we exit with the right status. 751b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes static int init_exitstatus = 0; 761b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes signal(SIGTERM, [](int) { _exit(init_exitstatus); }); 771b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes 781b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes pid_t waited_pid; 791b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes int status; 801b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes while ((waited_pid = wait(&status)) > 0) { 811b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes // This loop will end when there are no processes left inside the 821b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes // PID namespace or when the init process inside the PID namespace 831b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes // gets a signal. 841b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes if (waited_pid == child_pid) { 851b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes init_exitstatus = status; 861b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes } 871b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes } 881b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes if (!WIFEXITED(init_exitstatus)) { 891b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes _exit(EXIT_FAILURE); 901b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes } 911b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes _exit(WEXITSTATUS(init_exitstatus)); 921b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes } 931b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes} 941b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes 95bac3299720623f4226bca103b26260052732ad30Tom CherrySocketInfo::SocketInfo() : uid(0), gid(0), perm(0) { 96bac3299720623f4226bca103b26260052732ad30Tom Cherry} 97bac3299720623f4226bca103b26260052732ad30Tom Cherry 98bac3299720623f4226bca103b26260052732ad30Tom CherrySocketInfo::SocketInfo(const std::string& name, const std::string& type, uid_t uid, 99bac3299720623f4226bca103b26260052732ad30Tom Cherry gid_t gid, int perm, const std::string& socketcon) 100bac3299720623f4226bca103b26260052732ad30Tom Cherry : name(name), type(type), uid(uid), gid(gid), perm(perm), socketcon(socketcon) { 101bac3299720623f4226bca103b26260052732ad30Tom Cherry} 102bac3299720623f4226bca103b26260052732ad30Tom Cherry 103bac3299720623f4226bca103b26260052732ad30Tom CherryServiceEnvironmentInfo::ServiceEnvironmentInfo() { 104bac3299720623f4226bca103b26260052732ad30Tom Cherry} 105bac3299720623f4226bca103b26260052732ad30Tom Cherry 106bac3299720623f4226bca103b26260052732ad30Tom CherryServiceEnvironmentInfo::ServiceEnvironmentInfo(const std::string& name, 107bac3299720623f4226bca103b26260052732ad30Tom Cherry const std::string& value) 108bac3299720623f4226bca103b26260052732ad30Tom Cherry : name(name), value(value) { 109bac3299720623f4226bca103b26260052732ad30Tom Cherry} 110bac3299720623f4226bca103b26260052732ad30Tom Cherry 111bac3299720623f4226bca103b26260052732ad30Tom CherryService::Service(const std::string& name, const std::string& classname, 112bac3299720623f4226bca103b26260052732ad30Tom Cherry const std::vector<std::string>& args) 113bac3299720623f4226bca103b26260052732ad30Tom Cherry : name_(name), classname_(classname), flags_(0), pid_(0), time_started_(0), 1141b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes time_crashed_(0), nr_crashed_(0), uid_(0), gid_(0), namespace_flags_(0), 1151b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes seclabel_(""), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), 1161b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes priority_(0), args_(args) { 117bac3299720623f4226bca103b26260052732ad30Tom Cherry onrestart_.InitSingleTrigger("onrestart"); 118bac3299720623f4226bca103b26260052732ad30Tom Cherry} 119bac3299720623f4226bca103b26260052732ad30Tom Cherry 120bac3299720623f4226bca103b26260052732ad30Tom CherryService::Service(const std::string& name, const std::string& classname, 1211b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes unsigned flags, uid_t uid, gid_t gid, 1221b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes const std::vector<gid_t>& supp_gids, unsigned namespace_flags, 1231b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes const std::string& seclabel, 1241b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes const std::vector<std::string>& args) 1251b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes : name_(name), classname_(classname), flags_(flags), pid_(0), 1261b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes time_started_(0), time_crashed_(0), nr_crashed_(0), uid_(uid), gid_(gid), 1271b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes supp_gids_(supp_gids), namespace_flags_(namespace_flags), 1281b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes seclabel_(seclabel), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), 1291b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes priority_(0), args_(args) { 130bac3299720623f4226bca103b26260052732ad30Tom Cherry onrestart_.InitSingleTrigger("onrestart"); 131bac3299720623f4226bca103b26260052732ad30Tom Cherry} 132bac3299720623f4226bca103b26260052732ad30Tom Cherry 133bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::NotifyStateChange(const std::string& new_state) const { 134bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((flags_ & SVC_EXEC) != 0) { 135bac3299720623f4226bca103b26260052732ad30Tom Cherry // 'exec' commands don't have properties tracking their state. 136bac3299720623f4226bca103b26260052732ad30Tom Cherry return; 137bac3299720623f4226bca103b26260052732ad30Tom Cherry } 138bac3299720623f4226bca103b26260052732ad30Tom Cherry 139b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string prop_name = StringPrintf("init.svc.%s", name_.c_str()); 140bac3299720623f4226bca103b26260052732ad30Tom Cherry if (prop_name.length() >= PROP_NAME_MAX) { 141bac3299720623f4226bca103b26260052732ad30Tom Cherry // If the property name would be too long, we can't set it. 142f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(ERROR) << "Property name \"init.svc." << name_ << "\" too long; not setting to " << new_state; 143bac3299720623f4226bca103b26260052732ad30Tom Cherry return; 144bac3299720623f4226bca103b26260052732ad30Tom Cherry } 145bac3299720623f4226bca103b26260052732ad30Tom Cherry 146bac3299720623f4226bca103b26260052732ad30Tom Cherry property_set(prop_name.c_str(), new_state.c_str()); 147bac3299720623f4226bca103b26260052732ad30Tom Cherry} 148bac3299720623f4226bca103b26260052732ad30Tom Cherry 149ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughesvoid Service::KillProcessGroup(int signal) { 150f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(VERBOSE) << "Sending signal " << signal 151f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes << " to service '" << name_ 152f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes << "' (pid " << pid_ << ") process group...\n", 153ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes kill(pid_, signal); 154ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes killProcessGroup(uid_, pid_, signal); 155ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes} 156ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes 157bac3299720623f4226bca103b26260052732ad30Tom Cherrybool Service::Reap() { 158bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) { 159ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes KillProcessGroup(SIGKILL); 160bac3299720623f4226bca103b26260052732ad30Tom Cherry } 161bac3299720623f4226bca103b26260052732ad30Tom Cherry 162bac3299720623f4226bca103b26260052732ad30Tom Cherry // Remove any sockets we may have created. 163bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& si : sockets_) { 164b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string tmp = StringPrintf(ANDROID_SOCKET_DIR "/%s", si.name.c_str()); 165bac3299720623f4226bca103b26260052732ad30Tom Cherry unlink(tmp.c_str()); 166bac3299720623f4226bca103b26260052732ad30Tom Cherry } 167bac3299720623f4226bca103b26260052732ad30Tom Cherry 168bac3299720623f4226bca103b26260052732ad30Tom Cherry if (flags_ & SVC_EXEC) { 169f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(INFO) << "SVC_EXEC pid " << pid_ << " finished..."; 170bac3299720623f4226bca103b26260052732ad30Tom Cherry return true; 171bac3299720623f4226bca103b26260052732ad30Tom Cherry } 172bac3299720623f4226bca103b26260052732ad30Tom Cherry 173bac3299720623f4226bca103b26260052732ad30Tom Cherry pid_ = 0; 174bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ &= (~SVC_RUNNING); 175bac3299720623f4226bca103b26260052732ad30Tom Cherry 176bac3299720623f4226bca103b26260052732ad30Tom Cherry // Oneshot processes go into the disabled state on exit, 177bac3299720623f4226bca103b26260052732ad30Tom Cherry // except when manually restarted. 178bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((flags_ & SVC_ONESHOT) && !(flags_ & SVC_RESTART)) { 179bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_DISABLED; 180bac3299720623f4226bca103b26260052732ad30Tom Cherry } 181bac3299720623f4226bca103b26260052732ad30Tom Cherry 182bac3299720623f4226bca103b26260052732ad30Tom Cherry // Disabled and reset processes do not get restarted automatically. 183bac3299720623f4226bca103b26260052732ad30Tom Cherry if (flags_ & (SVC_DISABLED | SVC_RESET)) { 184bac3299720623f4226bca103b26260052732ad30Tom Cherry NotifyStateChange("stopped"); 185bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 186bac3299720623f4226bca103b26260052732ad30Tom Cherry } 187bac3299720623f4226bca103b26260052732ad30Tom Cherry 188bac3299720623f4226bca103b26260052732ad30Tom Cherry time_t now = gettime(); 189bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((flags_ & SVC_CRITICAL) && !(flags_ & SVC_RESTART)) { 190bac3299720623f4226bca103b26260052732ad30Tom Cherry if (time_crashed_ + CRITICAL_CRASH_WINDOW >= now) { 191bac3299720623f4226bca103b26260052732ad30Tom Cherry if (++nr_crashed_ > CRITICAL_CRASH_THRESHOLD) { 192f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(ERROR) << "critical process '" << name_ << "' exited " 193f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes << CRITICAL_CRASH_THRESHOLD << " times in " 194f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes << (CRITICAL_CRASH_WINDOW / 60) << " minutes; " 195f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes << "rebooting into recovery mode"; 196bac3299720623f4226bca103b26260052732ad30Tom Cherry android_reboot(ANDROID_RB_RESTART2, 0, "recovery"); 197bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 198bac3299720623f4226bca103b26260052732ad30Tom Cherry } 199bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 200bac3299720623f4226bca103b26260052732ad30Tom Cherry time_crashed_ = now; 201bac3299720623f4226bca103b26260052732ad30Tom Cherry nr_crashed_ = 1; 202bac3299720623f4226bca103b26260052732ad30Tom Cherry } 203bac3299720623f4226bca103b26260052732ad30Tom Cherry } 204bac3299720623f4226bca103b26260052732ad30Tom Cherry 205bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ &= (~SVC_RESTART); 206bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_RESTARTING; 207bac3299720623f4226bca103b26260052732ad30Tom Cherry 208bac3299720623f4226bca103b26260052732ad30Tom Cherry // Execute all onrestart commands for this service. 209bac3299720623f4226bca103b26260052732ad30Tom Cherry onrestart_.ExecuteAllCommands(); 210bac3299720623f4226bca103b26260052732ad30Tom Cherry 211bac3299720623f4226bca103b26260052732ad30Tom Cherry NotifyStateChange("restarting"); 212bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 213bac3299720623f4226bca103b26260052732ad30Tom Cherry} 214bac3299720623f4226bca103b26260052732ad30Tom Cherry 215bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::DumpState() const { 216f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(INFO) << "service " << name_; 217f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(INFO) << " class '" << classname_ << "'"; 218f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(INFO) << " exec "<< android::base::Join(args_, " "); 219bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& si : sockets_) { 220f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(INFO) << " socket " << si.name << " " << si.type << " " << std::oct << si.perm; 221bac3299720623f4226bca103b26260052732ad30Tom Cherry } 222bac3299720623f4226bca103b26260052732ad30Tom Cherry} 223bac3299720623f4226bca103b26260052732ad30Tom Cherry 224b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleClass(const std::vector<std::string>& args, std::string* err) { 225b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry classname_ = args[1]; 226b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 227b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 228bac3299720623f4226bca103b26260052732ad30Tom Cherry 229b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleConsole(const std::vector<std::string>& args, std::string* err) { 230b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry flags_ |= SVC_CONSOLE; 23170daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman console_ = args.size() > 1 ? "/dev/" + args[1] : ""; 232b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 233b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 234bac3299720623f4226bca103b26260052732ad30Tom Cherry 235b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleCritical(const std::vector<std::string>& args, std::string* err) { 236b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry flags_ |= SVC_CRITICAL; 237b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 238b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 239bac3299720623f4226bca103b26260052732ad30Tom Cherry 240b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleDisabled(const std::vector<std::string>& args, std::string* err) { 241b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry flags_ |= SVC_DISABLED; 242b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry flags_ |= SVC_RC_DISABLED; 243b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 244b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 245bac3299720623f4226bca103b26260052732ad30Tom Cherry 246b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleGroup(const std::vector<std::string>& args, std::string* err) { 247b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry gid_ = decode_uid(args[1].c_str()); 248b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry for (std::size_t n = 2; n < args.size(); n++) { 249b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry supp_gids_.emplace_back(decode_uid(args[n].c_str())); 250b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 251b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 252b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 253bac3299720623f4226bca103b26260052732ad30Tom Cherry 254081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkivbool Service::HandlePriority(const std::vector<std::string>& args, std::string* err) { 255081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv priority_ = std::stoi(args[1]); 256081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv 257081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv if (priority_ < ANDROID_PRIORITY_HIGHEST || priority_ > ANDROID_PRIORITY_LOWEST) { 258081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv priority_ = 0; 259081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv *err = StringPrintf("process priority value must be range %d - %d", 260081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv ANDROID_PRIORITY_HIGHEST, ANDROID_PRIORITY_LOWEST); 261081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv return false; 262081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv } 263081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv 264081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv return true; 265081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv} 266081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv 267b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleIoprio(const std::vector<std::string>& args, std::string* err) { 268b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ioprio_pri_ = std::stoul(args[2], 0, 8); 269b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 270b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (ioprio_pri_ < 0 || ioprio_pri_ > 7) { 271b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry *err = "priority value must be range 0 - 7"; 272b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return false; 273b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 274b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 275b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (args[1] == "rt") { 276b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ioprio_class_ = IoSchedClass_RT; 277b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } else if (args[1] == "be") { 278b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ioprio_class_ = IoSchedClass_BE; 279b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } else if (args[1] == "idle") { 280b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ioprio_class_ = IoSchedClass_IDLE; 281b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } else { 282b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry *err = "ioprio option usage: ioprio <rt|be|idle> <0-7>"; 283b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return false; 284bac3299720623f4226bca103b26260052732ad30Tom Cherry } 285bac3299720623f4226bca103b26260052732ad30Tom Cherry 286b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 287b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 288bac3299720623f4226bca103b26260052732ad30Tom Cherry 289b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleKeycodes(const std::vector<std::string>& args, std::string* err) { 290b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry for (std::size_t i = 1; i < args.size(); i++) { 291b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry keycodes_.emplace_back(std::stoi(args[i])); 292bac3299720623f4226bca103b26260052732ad30Tom Cherry } 293b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 294b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 295b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 296b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleOneshot(const std::vector<std::string>& args, std::string* err) { 297b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry flags_ |= SVC_ONESHOT; 298b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 299b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 300b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 301b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleOnrestart(const std::vector<std::string>& args, std::string* err) { 302b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::vector<std::string> str_args(args.begin() + 1, args.end()); 303b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry onrestart_.AddCommand(str_args, "", 0, err); 304b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 305b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 306bac3299720623f4226bca103b26260052732ad30Tom Cherry 3071b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obesbool Service::HandleNamespace(const std::vector<std::string>& args, std::string* err) { 3081b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes for (size_t i = 1; i < args.size(); i++) { 3091b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes if (args[i] == "pid") { 3101b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes namespace_flags_ |= CLONE_NEWPID; 3111b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes // PID namespaces require mount namespaces. 3121b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes namespace_flags_ |= CLONE_NEWNS; 3131b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes } else if (args[i] == "mnt") { 3141b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes namespace_flags_ |= CLONE_NEWNS; 3151b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes } else { 3161b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes *err = "namespace must be 'pid' or 'mnt'"; 3171b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes return false; 3181b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes } 3191b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes } 3201b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes return true; 3211b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes} 3221b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes 323b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleSeclabel(const std::vector<std::string>& args, std::string* err) { 324b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry seclabel_ = args[1]; 325b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 326b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 327b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 328b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleSetenv(const std::vector<std::string>& args, std::string* err) { 329b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry envvars_.emplace_back(args[1], args[2]); 330b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 331b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 332b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 333b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry/* name type perm [ uid gid context ] */ 334b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleSocket(const std::vector<std::string>& args, std::string* err) { 335b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (args[2] != "dgram" && args[2] != "stream" && args[2] != "seqpacket") { 336b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry *err = "socket type must be 'dgram', 'stream' or 'seqpacket'"; 337bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 338bac3299720623f4226bca103b26260052732ad30Tom Cherry } 339b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 340b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry int perm = std::stoul(args[3], 0, 8); 341b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry uid_t uid = args.size() > 4 ? decode_uid(args[4].c_str()) : 0; 342b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry gid_t gid = args.size() > 5 ? decode_uid(args[5].c_str()) : 0; 343b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string socketcon = args.size() > 6 ? args[6] : ""; 344b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 345b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry sockets_.emplace_back(args[1], args[2], uid, gid, perm, socketcon); 346bac3299720623f4226bca103b26260052732ad30Tom Cherry return true; 347bac3299720623f4226bca103b26260052732ad30Tom Cherry} 348bac3299720623f4226bca103b26260052732ad30Tom Cherry 349b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleUser(const std::vector<std::string>& args, std::string* err) { 350b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry uid_ = decode_uid(args[1].c_str()); 351b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 352b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 353b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 354b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleWritepid(const std::vector<std::string>& args, std::string* err) { 355b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry writepid_files_.assign(args.begin() + 1, args.end()); 356b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 357b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 358b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 359b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryclass Service::OptionHandlerMap : public KeywordMap<OptionHandler> { 360b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrypublic: 361b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry OptionHandlerMap() { 362b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 363b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryprivate: 364b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry Map& map() const override; 365b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry}; 366b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 367b7349902a945903f9e36a569051f5131beb0bc24Tom CherryService::OptionHandlerMap::Map& Service::OptionHandlerMap::map() const { 368b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max(); 369b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry static const Map option_handlers = { 370b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"class", {1, 1, &Service::HandleClass}}, 37170daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman {"console", {0, 1, &Service::HandleConsole}}, 372b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"critical", {0, 0, &Service::HandleCritical}}, 373b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"disabled", {0, 0, &Service::HandleDisabled}}, 374b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"group", {1, NR_SVC_SUPP_GIDS + 1, &Service::HandleGroup}}, 375b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"ioprio", {2, 2, &Service::HandleIoprio}}, 376081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv {"priority", {1, 1, &Service::HandlePriority}}, 377b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"keycodes", {1, kMax, &Service::HandleKeycodes}}, 378b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"oneshot", {0, 0, &Service::HandleOneshot}}, 379b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"onrestart", {1, kMax, &Service::HandleOnrestart}}, 3801b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes {"namespace", {1, 2, &Service::HandleNamespace}}, 381b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"seclabel", {1, 1, &Service::HandleSeclabel}}, 382b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"setenv", {2, 2, &Service::HandleSetenv}}, 383b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"socket", {3, 6, &Service::HandleSocket}}, 384b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"user", {1, 1, &Service::HandleUser}}, 385b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry {"writepid", {1, kMax, &Service::HandleWritepid}}, 386b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry }; 387b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return option_handlers; 388b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 389b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 390b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Service::HandleLine(const std::vector<std::string>& args, std::string* err) { 391b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (args.empty()) { 392b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry *err = "option needed, but not provided"; 393b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return false; 394b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 395b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 396b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry static const OptionHandlerMap handler_map; 397b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry auto handler = handler_map.FindFunction(args[0], args.size() - 1, err); 398b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 399b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (!handler) { 400b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return false; 401b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 402b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 403b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return (this->*handler)(args, err); 404b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 405b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 406bdeac39a42c1b9c7195ada1c30fe12f94314490fElliott Hughesbool Service::Start() { 407bac3299720623f4226bca103b26260052732ad30Tom Cherry // Starting a service removes it from the disabled or reset state and 408bac3299720623f4226bca103b26260052732ad30Tom Cherry // immediately takes it out of the restarting state if it was in there. 409bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START)); 410bac3299720623f4226bca103b26260052732ad30Tom Cherry time_started_ = 0; 411bac3299720623f4226bca103b26260052732ad30Tom Cherry 412bac3299720623f4226bca103b26260052732ad30Tom Cherry // Running processes require no additional work --- if they're in the 413bac3299720623f4226bca103b26260052732ad30Tom Cherry // process of exiting, we've ensured that they will immediately restart 414bac3299720623f4226bca103b26260052732ad30Tom Cherry // on exit, unless they are ONESHOT. 415bac3299720623f4226bca103b26260052732ad30Tom Cherry if (flags_ & SVC_RUNNING) { 416bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 417bac3299720623f4226bca103b26260052732ad30Tom Cherry } 418bac3299720623f4226bca103b26260052732ad30Tom Cherry 419bac3299720623f4226bca103b26260052732ad30Tom Cherry bool needs_console = (flags_ & SVC_CONSOLE); 42070daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman if (needs_console) { 42170daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman if (console_.empty()) { 42270daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman console_ = default_console; 42370daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman } 42470daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman 42570daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman bool have_console = (open(console_.c_str(), O_RDWR | O_CLOEXEC) != -1); 42670daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman if (!have_console) { 427f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes PLOG(ERROR) << "service '" << name_ << "' couldn't open console '" << console_ << "'"; 42870daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman flags_ |= SVC_DISABLED; 42970daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman return false; 43070daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman } 431bac3299720623f4226bca103b26260052732ad30Tom Cherry } 432bac3299720623f4226bca103b26260052732ad30Tom Cherry 433bac3299720623f4226bca103b26260052732ad30Tom Cherry struct stat sb; 434bac3299720623f4226bca103b26260052732ad30Tom Cherry if (stat(args_[0].c_str(), &sb) == -1) { 435f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes PLOG(ERROR) << "cannot find '" << args_[0] << "', disabling '" << name_ << "'"; 436bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_DISABLED; 437bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 438bac3299720623f4226bca103b26260052732ad30Tom Cherry } 439bac3299720623f4226bca103b26260052732ad30Tom Cherry 440bac3299720623f4226bca103b26260052732ad30Tom Cherry std::string scon; 441bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!seclabel_.empty()) { 442bac3299720623f4226bca103b26260052732ad30Tom Cherry scon = seclabel_; 443bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 444bac3299720623f4226bca103b26260052732ad30Tom Cherry char* mycon = nullptr; 445bac3299720623f4226bca103b26260052732ad30Tom Cherry char* fcon = nullptr; 446bac3299720623f4226bca103b26260052732ad30Tom Cherry 447f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(INFO) << "computing context for service '" << args_[0] << "'"; 448bac3299720623f4226bca103b26260052732ad30Tom Cherry int rc = getcon(&mycon); 449bac3299720623f4226bca103b26260052732ad30Tom Cherry if (rc < 0) { 450f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(ERROR) << "could not get context while starting '" << name_ << "'"; 451bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 452bac3299720623f4226bca103b26260052732ad30Tom Cherry } 453bac3299720623f4226bca103b26260052732ad30Tom Cherry 454bac3299720623f4226bca103b26260052732ad30Tom Cherry rc = getfilecon(args_[0].c_str(), &fcon); 455bac3299720623f4226bca103b26260052732ad30Tom Cherry if (rc < 0) { 4561b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes LOG(ERROR) << "could not get file context while starting '" << name_ << "'"; 457bac3299720623f4226bca103b26260052732ad30Tom Cherry free(mycon); 458bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 459bac3299720623f4226bca103b26260052732ad30Tom Cherry } 460bac3299720623f4226bca103b26260052732ad30Tom Cherry 461bac3299720623f4226bca103b26260052732ad30Tom Cherry char* ret_scon = nullptr; 462bac3299720623f4226bca103b26260052732ad30Tom Cherry rc = security_compute_create(mycon, fcon, string_to_security_class("process"), 463bac3299720623f4226bca103b26260052732ad30Tom Cherry &ret_scon); 464bac3299720623f4226bca103b26260052732ad30Tom Cherry if (rc == 0) { 465bac3299720623f4226bca103b26260052732ad30Tom Cherry scon = ret_scon; 466bac3299720623f4226bca103b26260052732ad30Tom Cherry free(ret_scon); 467bac3299720623f4226bca103b26260052732ad30Tom Cherry } 468bac3299720623f4226bca103b26260052732ad30Tom Cherry if (rc == 0 && scon == mycon) { 469f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(ERROR) << "Service " << name_ << " does not have a SELinux domain defined."; 470bac3299720623f4226bca103b26260052732ad30Tom Cherry free(mycon); 471bac3299720623f4226bca103b26260052732ad30Tom Cherry free(fcon); 472bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 473bac3299720623f4226bca103b26260052732ad30Tom Cherry } 474bac3299720623f4226bca103b26260052732ad30Tom Cherry free(mycon); 475bac3299720623f4226bca103b26260052732ad30Tom Cherry free(fcon); 476bac3299720623f4226bca103b26260052732ad30Tom Cherry if (rc < 0) { 477f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(ERROR) << "could not get context while starting '" << name_ << "'"; 478bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 479bac3299720623f4226bca103b26260052732ad30Tom Cherry } 480bac3299720623f4226bca103b26260052732ad30Tom Cherry } 481bac3299720623f4226bca103b26260052732ad30Tom Cherry 482f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(VERBOSE) << "Starting service '" << name_ << "'..."; 483bac3299720623f4226bca103b26260052732ad30Tom Cherry 4841b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes pid_t pid = -1; 4851b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes if (namespace_flags_) { 4861b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, 4871b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes nullptr); 4881b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes } else { 4891b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes pid = fork(); 4901b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes } 4911b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes 492bac3299720623f4226bca103b26260052732ad30Tom Cherry if (pid == 0) { 493bac3299720623f4226bca103b26260052732ad30Tom Cherry umask(077); 494bac3299720623f4226bca103b26260052732ad30Tom Cherry 4951b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes if (namespace_flags_ & CLONE_NEWPID) { 4961b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes // This will fork again to run an init process inside the PID 4971b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes // namespace. 4981b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes SetUpPidNamespace(name_); 4991b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes } 5001b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes 501bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& ei : envvars_) { 502bac3299720623f4226bca103b26260052732ad30Tom Cherry add_environment(ei.name.c_str(), ei.value.c_str()); 503bac3299720623f4226bca103b26260052732ad30Tom Cherry } 504bac3299720623f4226bca103b26260052732ad30Tom Cherry 505bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& si : sockets_) { 506bac3299720623f4226bca103b26260052732ad30Tom Cherry int socket_type = ((si.type == "stream" ? SOCK_STREAM : 507bac3299720623f4226bca103b26260052732ad30Tom Cherry (si.type == "dgram" ? SOCK_DGRAM : 508bac3299720623f4226bca103b26260052732ad30Tom Cherry SOCK_SEQPACKET))); 509bac3299720623f4226bca103b26260052732ad30Tom Cherry const char* socketcon = 510bac3299720623f4226bca103b26260052732ad30Tom Cherry !si.socketcon.empty() ? si.socketcon.c_str() : scon.c_str(); 511bac3299720623f4226bca103b26260052732ad30Tom Cherry 512bac3299720623f4226bca103b26260052732ad30Tom Cherry int s = create_socket(si.name.c_str(), socket_type, si.perm, 513bac3299720623f4226bca103b26260052732ad30Tom Cherry si.uid, si.gid, socketcon); 514bac3299720623f4226bca103b26260052732ad30Tom Cherry if (s >= 0) { 515bac3299720623f4226bca103b26260052732ad30Tom Cherry PublishSocket(si.name, s); 516bac3299720623f4226bca103b26260052732ad30Tom Cherry } 517bac3299720623f4226bca103b26260052732ad30Tom Cherry } 518bac3299720623f4226bca103b26260052732ad30Tom Cherry 519b702b46f688bc3ba7f8dc2d35c6eb25482366c4cAnestis Bechtsoudis std::string pid_str = StringPrintf("%d", getpid()); 520bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& file : writepid_files_) { 521b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (!WriteStringToFile(pid_str, file)) { 522f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes PLOG(ERROR) << "couldn't write " << pid_str << " to " << file; 523bac3299720623f4226bca103b26260052732ad30Tom Cherry } 524bac3299720623f4226bca103b26260052732ad30Tom Cherry } 525bac3299720623f4226bca103b26260052732ad30Tom Cherry 526bac3299720623f4226bca103b26260052732ad30Tom Cherry if (ioprio_class_ != IoSchedClass_NONE) { 527bac3299720623f4226bca103b26260052732ad30Tom Cherry if (android_set_ioprio(getpid(), ioprio_class_, ioprio_pri_)) { 528f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes PLOG(ERROR) << "Failed to set pid " << getpid() 529f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes << " ioprio=" << ioprio_class_ << "," << ioprio_pri_; 530bac3299720623f4226bca103b26260052732ad30Tom Cherry } 531bac3299720623f4226bca103b26260052732ad30Tom Cherry } 532bac3299720623f4226bca103b26260052732ad30Tom Cherry 533bac3299720623f4226bca103b26260052732ad30Tom Cherry if (needs_console) { 534bac3299720623f4226bca103b26260052732ad30Tom Cherry setsid(); 535bac3299720623f4226bca103b26260052732ad30Tom Cherry OpenConsole(); 536bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 537bac3299720623f4226bca103b26260052732ad30Tom Cherry ZapStdio(); 538bac3299720623f4226bca103b26260052732ad30Tom Cherry } 539bac3299720623f4226bca103b26260052732ad30Tom Cherry 540bac3299720623f4226bca103b26260052732ad30Tom Cherry setpgid(0, getpid()); 541bac3299720623f4226bca103b26260052732ad30Tom Cherry 542bac3299720623f4226bca103b26260052732ad30Tom Cherry // As requested, set our gid, supplemental gids, and uid. 543bac3299720623f4226bca103b26260052732ad30Tom Cherry if (gid_) { 544bac3299720623f4226bca103b26260052732ad30Tom Cherry if (setgid(gid_) != 0) { 545f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes PLOG(ERROR) << "setgid failed"; 546bac3299720623f4226bca103b26260052732ad30Tom Cherry _exit(127); 547bac3299720623f4226bca103b26260052732ad30Tom Cherry } 548bac3299720623f4226bca103b26260052732ad30Tom Cherry } 549bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!supp_gids_.empty()) { 550bac3299720623f4226bca103b26260052732ad30Tom Cherry if (setgroups(supp_gids_.size(), &supp_gids_[0]) != 0) { 551f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes PLOG(ERROR) << "setgroups failed"; 552bac3299720623f4226bca103b26260052732ad30Tom Cherry _exit(127); 553bac3299720623f4226bca103b26260052732ad30Tom Cherry } 554bac3299720623f4226bca103b26260052732ad30Tom Cherry } 555bac3299720623f4226bca103b26260052732ad30Tom Cherry if (uid_) { 556bac3299720623f4226bca103b26260052732ad30Tom Cherry if (setuid(uid_) != 0) { 557f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes PLOG(ERROR) << "setuid failed"; 558bac3299720623f4226bca103b26260052732ad30Tom Cherry _exit(127); 559bac3299720623f4226bca103b26260052732ad30Tom Cherry } 560bac3299720623f4226bca103b26260052732ad30Tom Cherry } 561bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!seclabel_.empty()) { 562bac3299720623f4226bca103b26260052732ad30Tom Cherry if (setexeccon(seclabel_.c_str()) < 0) { 563f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes PLOG(ERROR) << "cannot setexeccon('" << seclabel_ << "')"; 564bac3299720623f4226bca103b26260052732ad30Tom Cherry _exit(127); 565bac3299720623f4226bca103b26260052732ad30Tom Cherry } 566bac3299720623f4226bca103b26260052732ad30Tom Cherry } 567081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv if (priority_ != 0) { 568081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv if (setpriority(PRIO_PROCESS, 0, priority_) != 0) { 569f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes PLOG(ERROR) << "setpriority failed"; 570081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv _exit(127); 571081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv } 572081705c258efbe938d71c2022528d809fa6d42c5Vitalii Tomkiv } 573bac3299720623f4226bca103b26260052732ad30Tom Cherry 574bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry std::vector<std::string> expanded_args; 575bac3299720623f4226bca103b26260052732ad30Tom Cherry std::vector<char*> strs; 576bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry expanded_args.resize(args_.size()); 577bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry strs.push_back(const_cast<char*>(args_[0].c_str())); 578bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry for (std::size_t i = 1; i < args_.size(); ++i) { 579bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry if (!expand_props(args_[i], &expanded_args[i])) { 580f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(ERROR) << args_[0] << ": cannot expand '" << args_[i] << "'"; 581bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry _exit(127); 582bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry } 583bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry strs.push_back(const_cast<char*>(expanded_args[i].c_str())); 584bac3299720623f4226bca103b26260052732ad30Tom Cherry } 585bac3299720623f4226bca103b26260052732ad30Tom Cherry strs.push_back(nullptr); 586bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry 587bac3536cc949b3af0185e7b8f9b18318b37ac8b0Tom Cherry if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) { 588f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes PLOG(ERROR) << "cannot execve('" << strs[0] << "')"; 589bac3299720623f4226bca103b26260052732ad30Tom Cherry } 590bac3299720623f4226bca103b26260052732ad30Tom Cherry 591bac3299720623f4226bca103b26260052732ad30Tom Cherry _exit(127); 592bac3299720623f4226bca103b26260052732ad30Tom Cherry } 593bac3299720623f4226bca103b26260052732ad30Tom Cherry 594bac3299720623f4226bca103b26260052732ad30Tom Cherry if (pid < 0) { 595f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes PLOG(ERROR) << "failed to fork for '" << name_ << "'"; 596bac3299720623f4226bca103b26260052732ad30Tom Cherry pid_ = 0; 597bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 598bac3299720623f4226bca103b26260052732ad30Tom Cherry } 599bac3299720623f4226bca103b26260052732ad30Tom Cherry 600bac3299720623f4226bca103b26260052732ad30Tom Cherry time_started_ = gettime(); 601bac3299720623f4226bca103b26260052732ad30Tom Cherry pid_ = pid; 602bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_RUNNING; 603ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes 604ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes errno = -createProcessGroup(uid_, pid_); 605ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes if (errno != 0) { 606f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes PLOG(ERROR) << "createProcessGroup(" << uid_ << ", " << pid_ << ") failed for service '" << name_ << "'"; 607ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes } 608bac3299720623f4226bca103b26260052732ad30Tom Cherry 609bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((flags_ & SVC_EXEC) != 0) { 610f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(INFO) << android::base::StringPrintf("SVC_EXEC pid %d (uid %d gid %d+%zu context %s) started; waiting...", 611f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes pid_, uid_, gid_, supp_gids_.size(), 612f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes !seclabel_.empty() ? seclabel_.c_str() : "default"); 613bac3299720623f4226bca103b26260052732ad30Tom Cherry } 614bac3299720623f4226bca103b26260052732ad30Tom Cherry 615bac3299720623f4226bca103b26260052732ad30Tom Cherry NotifyStateChange("running"); 616bac3299720623f4226bca103b26260052732ad30Tom Cherry return true; 617bac3299720623f4226bca103b26260052732ad30Tom Cherry} 618bac3299720623f4226bca103b26260052732ad30Tom Cherry 619bac3299720623f4226bca103b26260052732ad30Tom Cherrybool Service::StartIfNotDisabled() { 620bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!(flags_ & SVC_DISABLED)) { 621bac3299720623f4226bca103b26260052732ad30Tom Cherry return Start(); 622bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 623bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= SVC_DISABLED_START; 624bac3299720623f4226bca103b26260052732ad30Tom Cherry } 625bac3299720623f4226bca103b26260052732ad30Tom Cherry return true; 626bac3299720623f4226bca103b26260052732ad30Tom Cherry} 627bac3299720623f4226bca103b26260052732ad30Tom Cherry 628bac3299720623f4226bca103b26260052732ad30Tom Cherrybool Service::Enable() { 629bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ &= ~(SVC_DISABLED | SVC_RC_DISABLED); 630bac3299720623f4226bca103b26260052732ad30Tom Cherry if (flags_ & SVC_DISABLED_START) { 631bac3299720623f4226bca103b26260052732ad30Tom Cherry return Start(); 632bac3299720623f4226bca103b26260052732ad30Tom Cherry } 633bac3299720623f4226bca103b26260052732ad30Tom Cherry return true; 634bac3299720623f4226bca103b26260052732ad30Tom Cherry} 635bac3299720623f4226bca103b26260052732ad30Tom Cherry 636bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::Reset() { 637bac3299720623f4226bca103b26260052732ad30Tom Cherry StopOrReset(SVC_RESET); 638bac3299720623f4226bca103b26260052732ad30Tom Cherry} 639bac3299720623f4226bca103b26260052732ad30Tom Cherry 640bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::Stop() { 641bac3299720623f4226bca103b26260052732ad30Tom Cherry StopOrReset(SVC_DISABLED); 642bac3299720623f4226bca103b26260052732ad30Tom Cherry} 643bac3299720623f4226bca103b26260052732ad30Tom Cherry 644b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNETvoid Service::Terminate() { 645b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET flags_ &= ~(SVC_RESTARTING | SVC_DISABLED_START); 646b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET flags_ |= SVC_DISABLED; 647b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET if (pid_) { 648ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes KillProcessGroup(SIGTERM); 649b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET NotifyStateChange("stopping"); 650b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } 651b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET} 652b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET 653bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::Restart() { 654bac3299720623f4226bca103b26260052732ad30Tom Cherry if (flags_ & SVC_RUNNING) { 655bac3299720623f4226bca103b26260052732ad30Tom Cherry /* Stop, wait, then start the service. */ 656bac3299720623f4226bca103b26260052732ad30Tom Cherry StopOrReset(SVC_RESTART); 657bac3299720623f4226bca103b26260052732ad30Tom Cherry } else if (!(flags_ & SVC_RESTARTING)) { 658bac3299720623f4226bca103b26260052732ad30Tom Cherry /* Just start the service since it's not running. */ 659bac3299720623f4226bca103b26260052732ad30Tom Cherry Start(); 660bac3299720623f4226bca103b26260052732ad30Tom Cherry } /* else: Service is restarting anyways. */ 661bac3299720623f4226bca103b26260052732ad30Tom Cherry} 662bac3299720623f4226bca103b26260052732ad30Tom Cherry 663bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::RestartIfNeeded(time_t& process_needs_restart) { 664bac3299720623f4226bca103b26260052732ad30Tom Cherry time_t next_start_time = time_started_ + 5; 665bac3299720623f4226bca103b26260052732ad30Tom Cherry 666bac3299720623f4226bca103b26260052732ad30Tom Cherry if (next_start_time <= gettime()) { 667bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ &= (~SVC_RESTARTING); 668bac3299720623f4226bca103b26260052732ad30Tom Cherry Start(); 669bac3299720623f4226bca103b26260052732ad30Tom Cherry return; 670bac3299720623f4226bca103b26260052732ad30Tom Cherry } 671bac3299720623f4226bca103b26260052732ad30Tom Cherry 672bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((next_start_time < process_needs_restart) || 673bac3299720623f4226bca103b26260052732ad30Tom Cherry (process_needs_restart == 0)) { 674bac3299720623f4226bca103b26260052732ad30Tom Cherry process_needs_restart = next_start_time; 675bac3299720623f4226bca103b26260052732ad30Tom Cherry } 676bac3299720623f4226bca103b26260052732ad30Tom Cherry} 677bac3299720623f4226bca103b26260052732ad30Tom Cherry 678ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes// The how field should be either SVC_DISABLED, SVC_RESET, or SVC_RESTART. 679bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::StopOrReset(int how) { 680ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes // The service is still SVC_RUNNING until its process exits, but if it has 681ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes // already exited it shoudn't attempt a restart yet. 682bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ &= ~(SVC_RESTARTING | SVC_DISABLED_START); 683bac3299720623f4226bca103b26260052732ad30Tom Cherry 684bac3299720623f4226bca103b26260052732ad30Tom Cherry if ((how != SVC_DISABLED) && (how != SVC_RESET) && (how != SVC_RESTART)) { 685ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes // An illegal flag: default to SVC_DISABLED. 686bac3299720623f4226bca103b26260052732ad30Tom Cherry how = SVC_DISABLED; 687bac3299720623f4226bca103b26260052732ad30Tom Cherry } 688ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes 689ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes // If the service has not yet started, prevent it from auto-starting with its class. 690bac3299720623f4226bca103b26260052732ad30Tom Cherry if (how == SVC_RESET) { 691bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= (flags_ & SVC_RC_DISABLED) ? SVC_DISABLED : SVC_RESET; 692bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 693bac3299720623f4226bca103b26260052732ad30Tom Cherry flags_ |= how; 694bac3299720623f4226bca103b26260052732ad30Tom Cherry } 695bac3299720623f4226bca103b26260052732ad30Tom Cherry 696bac3299720623f4226bca103b26260052732ad30Tom Cherry if (pid_) { 697ad8e94e017173471e90c704eb7d8de5a14712aa7Elliott Hughes KillProcessGroup(SIGKILL); 698bac3299720623f4226bca103b26260052732ad30Tom Cherry NotifyStateChange("stopping"); 699bac3299720623f4226bca103b26260052732ad30Tom Cherry } else { 700bac3299720623f4226bca103b26260052732ad30Tom Cherry NotifyStateChange("stopped"); 701bac3299720623f4226bca103b26260052732ad30Tom Cherry } 702bac3299720623f4226bca103b26260052732ad30Tom Cherry} 703bac3299720623f4226bca103b26260052732ad30Tom Cherry 704bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::ZapStdio() const { 705bac3299720623f4226bca103b26260052732ad30Tom Cherry int fd; 706bac3299720623f4226bca103b26260052732ad30Tom Cherry fd = open("/dev/null", O_RDWR); 707bac3299720623f4226bca103b26260052732ad30Tom Cherry dup2(fd, 0); 708bac3299720623f4226bca103b26260052732ad30Tom Cherry dup2(fd, 1); 709bac3299720623f4226bca103b26260052732ad30Tom Cherry dup2(fd, 2); 710bac3299720623f4226bca103b26260052732ad30Tom Cherry close(fd); 711bac3299720623f4226bca103b26260052732ad30Tom Cherry} 712bac3299720623f4226bca103b26260052732ad30Tom Cherry 713bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::OpenConsole() const { 71470daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman int fd = open(console_.c_str(), O_RDWR); 71570daa67062c016eea1a30be2e1de0dcba1d23a13Viorel Suman if (fd == -1) fd = open("/dev/null", O_RDWR); 716bac3299720623f4226bca103b26260052732ad30Tom Cherry ioctl(fd, TIOCSCTTY, 0); 717bac3299720623f4226bca103b26260052732ad30Tom Cherry dup2(fd, 0); 718bac3299720623f4226bca103b26260052732ad30Tom Cherry dup2(fd, 1); 719bac3299720623f4226bca103b26260052732ad30Tom Cherry dup2(fd, 2); 720bac3299720623f4226bca103b26260052732ad30Tom Cherry close(fd); 721bac3299720623f4226bca103b26260052732ad30Tom Cherry} 722bac3299720623f4226bca103b26260052732ad30Tom Cherry 723bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid Service::PublishSocket(const std::string& name, int fd) const { 724b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string key = StringPrintf(ANDROID_SOCKET_ENV_PREFIX "%s", name.c_str()); 725b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string val = StringPrintf("%d", fd); 726bac3299720623f4226bca103b26260052732ad30Tom Cherry add_environment(key.c_str(), val.c_str()); 727bac3299720623f4226bca103b26260052732ad30Tom Cherry 728bac3299720623f4226bca103b26260052732ad30Tom Cherry /* make sure we don't close-on-exec */ 729bac3299720623f4226bca103b26260052732ad30Tom Cherry fcntl(fd, F_SETFD, 0); 730bac3299720623f4226bca103b26260052732ad30Tom Cherry} 731bac3299720623f4226bca103b26260052732ad30Tom Cherry 732bac3299720623f4226bca103b26260052732ad30Tom Cherryint ServiceManager::exec_count_ = 0; 733bac3299720623f4226bca103b26260052732ad30Tom Cherry 734bac3299720623f4226bca103b26260052732ad30Tom CherryServiceManager::ServiceManager() { 735bac3299720623f4226bca103b26260052732ad30Tom Cherry} 736bac3299720623f4226bca103b26260052732ad30Tom Cherry 737bac3299720623f4226bca103b26260052732ad30Tom CherryServiceManager& ServiceManager::GetInstance() { 738bac3299720623f4226bca103b26260052732ad30Tom Cherry static ServiceManager instance; 739bac3299720623f4226bca103b26260052732ad30Tom Cherry return instance; 740bac3299720623f4226bca103b26260052732ad30Tom Cherry} 741bac3299720623f4226bca103b26260052732ad30Tom Cherry 742b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryvoid ServiceManager::AddService(std::unique_ptr<Service> service) { 743b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry Service* old_service = FindServiceByName(service->name()); 744b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (old_service) { 745f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(ERROR) << "ignored duplicate definition of service '" << service->name() << "'"; 746b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return; 747bac3299720623f4226bca103b26260052732ad30Tom Cherry } 748b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry services_.emplace_back(std::move(service)); 749bac3299720623f4226bca103b26260052732ad30Tom Cherry} 750bac3299720623f4226bca103b26260052732ad30Tom Cherry 751bac3299720623f4226bca103b26260052732ad30Tom CherryService* ServiceManager::MakeExecOneshotService(const std::vector<std::string>& args) { 752bac3299720623f4226bca103b26260052732ad30Tom Cherry // Parse the arguments: exec [SECLABEL [UID [GID]*] --] COMMAND ARGS... 753bac3299720623f4226bca103b26260052732ad30Tom Cherry // SECLABEL can be a - to denote default 754bac3299720623f4226bca103b26260052732ad30Tom Cherry std::size_t command_arg = 1; 755bac3299720623f4226bca103b26260052732ad30Tom Cherry for (std::size_t i = 1; i < args.size(); ++i) { 756bac3299720623f4226bca103b26260052732ad30Tom Cherry if (args[i] == "--") { 757bac3299720623f4226bca103b26260052732ad30Tom Cherry command_arg = i + 1; 758bac3299720623f4226bca103b26260052732ad30Tom Cherry break; 759bac3299720623f4226bca103b26260052732ad30Tom Cherry } 760bac3299720623f4226bca103b26260052732ad30Tom Cherry } 761bac3299720623f4226bca103b26260052732ad30Tom Cherry if (command_arg > 4 + NR_SVC_SUPP_GIDS) { 762f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(ERROR) << "exec called with too many supplementary group ids"; 763bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 764bac3299720623f4226bca103b26260052732ad30Tom Cherry } 765bac3299720623f4226bca103b26260052732ad30Tom Cherry 766bac3299720623f4226bca103b26260052732ad30Tom Cherry if (command_arg >= args.size()) { 767f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(ERROR) << "exec called without command"; 768bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 769bac3299720623f4226bca103b26260052732ad30Tom Cherry } 770bac3299720623f4226bca103b26260052732ad30Tom Cherry std::vector<std::string> str_args(args.begin() + command_arg, args.end()); 771bac3299720623f4226bca103b26260052732ad30Tom Cherry 772bac3299720623f4226bca103b26260052732ad30Tom Cherry exec_count_++; 773b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string name = StringPrintf("exec %d (%s)", exec_count_, str_args[0].c_str()); 774bac3299720623f4226bca103b26260052732ad30Tom Cherry unsigned flags = SVC_EXEC | SVC_ONESHOT; 7751b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes unsigned namespace_flags = 0; 776bac3299720623f4226bca103b26260052732ad30Tom Cherry 777bac3299720623f4226bca103b26260052732ad30Tom Cherry std::string seclabel = ""; 778bac3299720623f4226bca103b26260052732ad30Tom Cherry if (command_arg > 2 && args[1] != "-") { 779bac3299720623f4226bca103b26260052732ad30Tom Cherry seclabel = args[1]; 780bac3299720623f4226bca103b26260052732ad30Tom Cherry } 781bac3299720623f4226bca103b26260052732ad30Tom Cherry uid_t uid = 0; 782bac3299720623f4226bca103b26260052732ad30Tom Cherry if (command_arg > 3) { 783bac3299720623f4226bca103b26260052732ad30Tom Cherry uid = decode_uid(args[2].c_str()); 784bac3299720623f4226bca103b26260052732ad30Tom Cherry } 785bac3299720623f4226bca103b26260052732ad30Tom Cherry gid_t gid = 0; 786bac3299720623f4226bca103b26260052732ad30Tom Cherry std::vector<gid_t> supp_gids; 787bac3299720623f4226bca103b26260052732ad30Tom Cherry if (command_arg > 4) { 788bac3299720623f4226bca103b26260052732ad30Tom Cherry gid = decode_uid(args[3].c_str()); 789bac3299720623f4226bca103b26260052732ad30Tom Cherry std::size_t nr_supp_gids = command_arg - 1 /* -- */ - 4 /* exec SECLABEL UID GID */; 790bac3299720623f4226bca103b26260052732ad30Tom Cherry for (size_t i = 0; i < nr_supp_gids; ++i) { 791bac3299720623f4226bca103b26260052732ad30Tom Cherry supp_gids.push_back(decode_uid(args[4 + i].c_str())); 792bac3299720623f4226bca103b26260052732ad30Tom Cherry } 793bac3299720623f4226bca103b26260052732ad30Tom Cherry } 794bac3299720623f4226bca103b26260052732ad30Tom Cherry 795bac3299720623f4226bca103b26260052732ad30Tom Cherry std::unique_ptr<Service> svc_p(new Service(name, "default", flags, uid, gid, 7961b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes supp_gids, namespace_flags, 7971b3fa3d6506d04570aab60147b0ec743e38c8796Jorge Lucangeli Obes seclabel, str_args)); 798bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!svc_p) { 799f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(ERROR) << "Couldn't allocate service for exec of '" << str_args[0] << "'"; 800bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 801bac3299720623f4226bca103b26260052732ad30Tom Cherry } 802bac3299720623f4226bca103b26260052732ad30Tom Cherry Service* svc = svc_p.get(); 803bac3299720623f4226bca103b26260052732ad30Tom Cherry services_.push_back(std::move(svc_p)); 804bac3299720623f4226bca103b26260052732ad30Tom Cherry 805bac3299720623f4226bca103b26260052732ad30Tom Cherry return svc; 806bac3299720623f4226bca103b26260052732ad30Tom Cherry} 807bac3299720623f4226bca103b26260052732ad30Tom Cherry 808bac3299720623f4226bca103b26260052732ad30Tom CherryService* ServiceManager::FindServiceByName(const std::string& name) const { 809bac3299720623f4226bca103b26260052732ad30Tom Cherry auto svc = std::find_if(services_.begin(), services_.end(), 810bac3299720623f4226bca103b26260052732ad30Tom Cherry [&name] (const std::unique_ptr<Service>& s) { 811bac3299720623f4226bca103b26260052732ad30Tom Cherry return name == s->name(); 812bac3299720623f4226bca103b26260052732ad30Tom Cherry }); 813bac3299720623f4226bca103b26260052732ad30Tom Cherry if (svc != services_.end()) { 814bac3299720623f4226bca103b26260052732ad30Tom Cherry return svc->get(); 815bac3299720623f4226bca103b26260052732ad30Tom Cherry } 816bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 817bac3299720623f4226bca103b26260052732ad30Tom Cherry} 818bac3299720623f4226bca103b26260052732ad30Tom Cherry 819bac3299720623f4226bca103b26260052732ad30Tom CherryService* ServiceManager::FindServiceByPid(pid_t pid) const { 820bac3299720623f4226bca103b26260052732ad30Tom Cherry auto svc = std::find_if(services_.begin(), services_.end(), 821bac3299720623f4226bca103b26260052732ad30Tom Cherry [&pid] (const std::unique_ptr<Service>& s) { 822bac3299720623f4226bca103b26260052732ad30Tom Cherry return s->pid() == pid; 823bac3299720623f4226bca103b26260052732ad30Tom Cherry }); 824bac3299720623f4226bca103b26260052732ad30Tom Cherry if (svc != services_.end()) { 825bac3299720623f4226bca103b26260052732ad30Tom Cherry return svc->get(); 826bac3299720623f4226bca103b26260052732ad30Tom Cherry } 827bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 828bac3299720623f4226bca103b26260052732ad30Tom Cherry} 829bac3299720623f4226bca103b26260052732ad30Tom Cherry 830bac3299720623f4226bca103b26260052732ad30Tom CherryService* ServiceManager::FindServiceByKeychord(int keychord_id) const { 831bac3299720623f4226bca103b26260052732ad30Tom Cherry auto svc = std::find_if(services_.begin(), services_.end(), 832bac3299720623f4226bca103b26260052732ad30Tom Cherry [&keychord_id] (const std::unique_ptr<Service>& s) { 833bac3299720623f4226bca103b26260052732ad30Tom Cherry return s->keychord_id() == keychord_id; 834bac3299720623f4226bca103b26260052732ad30Tom Cherry }); 835bac3299720623f4226bca103b26260052732ad30Tom Cherry 836bac3299720623f4226bca103b26260052732ad30Tom Cherry if (svc != services_.end()) { 837bac3299720623f4226bca103b26260052732ad30Tom Cherry return svc->get(); 838bac3299720623f4226bca103b26260052732ad30Tom Cherry } 839bac3299720623f4226bca103b26260052732ad30Tom Cherry return nullptr; 840bac3299720623f4226bca103b26260052732ad30Tom Cherry} 841bac3299720623f4226bca103b26260052732ad30Tom Cherry 842b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNETvoid ServiceManager::ForEachService(std::function<void(Service*)> callback) const { 843bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& s : services_) { 844b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET callback(s.get()); 845bac3299720623f4226bca103b26260052732ad30Tom Cherry } 846bac3299720623f4226bca103b26260052732ad30Tom Cherry} 847bac3299720623f4226bca103b26260052732ad30Tom Cherry 848bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid ServiceManager::ForEachServiceInClass(const std::string& classname, 849bac3299720623f4226bca103b26260052732ad30Tom Cherry void (*func)(Service* svc)) const { 850bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& s : services_) { 851bac3299720623f4226bca103b26260052732ad30Tom Cherry if (classname == s->classname()) { 852bac3299720623f4226bca103b26260052732ad30Tom Cherry func(s.get()); 853bac3299720623f4226bca103b26260052732ad30Tom Cherry } 854bac3299720623f4226bca103b26260052732ad30Tom Cherry } 855bac3299720623f4226bca103b26260052732ad30Tom Cherry} 856bac3299720623f4226bca103b26260052732ad30Tom Cherry 857bac3299720623f4226bca103b26260052732ad30Tom Cherryvoid ServiceManager::ForEachServiceWithFlags(unsigned matchflags, 858bac3299720623f4226bca103b26260052732ad30Tom Cherry void (*func)(Service* svc)) const { 859bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& s : services_) { 860bac3299720623f4226bca103b26260052732ad30Tom Cherry if (s->flags() & matchflags) { 861bac3299720623f4226bca103b26260052732ad30Tom Cherry func(s.get()); 862bac3299720623f4226bca103b26260052732ad30Tom Cherry } 863bac3299720623f4226bca103b26260052732ad30Tom Cherry } 864bac3299720623f4226bca103b26260052732ad30Tom Cherry} 865bac3299720623f4226bca103b26260052732ad30Tom Cherry 866b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryvoid ServiceManager::RemoveService(const Service& svc) { 867bac3299720623f4226bca103b26260052732ad30Tom Cherry auto svc_it = std::find_if(services_.begin(), services_.end(), 868bac3299720623f4226bca103b26260052732ad30Tom Cherry [&svc] (const std::unique_ptr<Service>& s) { 869bac3299720623f4226bca103b26260052732ad30Tom Cherry return svc.name() == s->name(); 870bac3299720623f4226bca103b26260052732ad30Tom Cherry }); 871bac3299720623f4226bca103b26260052732ad30Tom Cherry if (svc_it == services_.end()) { 872bac3299720623f4226bca103b26260052732ad30Tom Cherry return; 873bac3299720623f4226bca103b26260052732ad30Tom Cherry } 874bac3299720623f4226bca103b26260052732ad30Tom Cherry 875bac3299720623f4226bca103b26260052732ad30Tom Cherry services_.erase(svc_it); 876bac3299720623f4226bca103b26260052732ad30Tom Cherry} 877bac3299720623f4226bca103b26260052732ad30Tom Cherry 878b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryvoid ServiceManager::DumpState() const { 879b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry for (const auto& s : services_) { 880b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry s->DumpState(); 881b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 882b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 883b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 884b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNETbool ServiceManager::ReapOneProcess() { 885b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET int status; 886b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG)); 887b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET if (pid == 0) { 888b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET return false; 889b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } else if (pid == -1) { 890f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes PLOG(ERROR) << "waitpid failed"; 891b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET return false; 892b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } 893b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET 894b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET Service* svc = FindServiceByPid(pid); 895b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET 896b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET std::string name; 897b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET if (svc) { 898b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET name = android::base::StringPrintf("Service '%s' (pid %d)", 899b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET svc->name().c_str(), pid); 900b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } else { 901b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET name = android::base::StringPrintf("Untracked pid %d", pid); 902b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } 903b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET 904b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET if (WIFEXITED(status)) { 905f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(VERBOSE) << name << " exited with status " << WEXITSTATUS(status); 906b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } else if (WIFSIGNALED(status)) { 907f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(VERBOSE) << name << " killed by signal " << WTERMSIG(status); 908b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } else if (WIFSTOPPED(status)) { 909f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(VERBOSE) << name << " stopped by signal " << WSTOPSIG(status); 910b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } else { 911f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(VERBOSE) << name << " state changed"; 912b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } 913b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET 914b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET if (!svc) { 915b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET return true; 916b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } 917b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET 918b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET if (svc->Reap()) { 919b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET waiting_for_exec = false; 920b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET RemoveService(*svc); 921b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } 922b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET 923b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET return true; 924b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET} 925b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET 926b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNETvoid ServiceManager::ReapAnyOutstandingChildren() { 927b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET while (ReapOneProcess()) { 928b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET } 929b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET} 930b7e03e82b89a30b09fea88eaf2a5638df1017cf6Bertrand SIMONNET 931b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool ServiceParser::ParseSection(const std::vector<std::string>& args, 932b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string* err) { 933b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (args.size() < 3) { 934b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry *err = "services must have a name and a program"; 935b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return false; 936b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 937b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 938b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry const std::string& name = args[1]; 939b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (!IsValidName(name)) { 940b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry *err = StringPrintf("invalid service name '%s'", name.c_str()); 941b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return false; 942b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 943b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 944b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::vector<std::string> str_args(args.begin() + 2, args.end()); 945b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry service_ = std::make_unique<Service>(name, "default", str_args); 946b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return true; 947b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 948b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 949b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool ServiceParser::ParseLineSection(const std::vector<std::string>& args, 950b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry const std::string& filename, int line, 951b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string* err) const { 952b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return service_ ? service_->HandleLine(args, err) : false; 953b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 954b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 955b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryvoid ServiceParser::EndSection() { 956b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (service_) { 957b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ServiceManager::GetInstance().AddService(std::move(service_)); 958b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 959b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry} 960b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry 961b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool ServiceParser::IsValidName(const std::string& name) const { 962bac3299720623f4226bca103b26260052732ad30Tom Cherry if (name.size() > 16) { 963bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 964bac3299720623f4226bca103b26260052732ad30Tom Cherry } 965bac3299720623f4226bca103b26260052732ad30Tom Cherry for (const auto& c : name) { 966bac3299720623f4226bca103b26260052732ad30Tom Cherry if (!isalnum(c) && (c != '_') && (c != '-')) { 967bac3299720623f4226bca103b26260052732ad30Tom Cherry return false; 968bac3299720623f4226bca103b26260052732ad30Tom Cherry } 969bac3299720623f4226bca103b26260052732ad30Tom Cherry } 970bac3299720623f4226bca103b26260052732ad30Tom Cherry return true; 971bac3299720623f4226bca103b26260052732ad30Tom Cherry} 972