| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2015 The Android Open Source Project | 
 | 3 |  * | 
 | 4 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 |  * you may not use this file except in compliance with the License. | 
 | 6 |  * You may obtain a copy of the License at | 
 | 7 |  * | 
 | 8 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 |  * | 
 | 10 |  * Unless required by applicable law or agreed to in writing, software | 
 | 11 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 |  * See the License for the specific language governing permissions and | 
 | 14 |  * limitations under the License. | 
 | 15 |  */ | 
 | 16 |  | 
 | 17 | #include "service.h" | 
 | 18 |  | 
| Bart Van Assche | 01e6669 | 2022-11-14 16:45:47 -0800 | [diff] [blame] | 19 | #include <errno.h> | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 20 | #include <fcntl.h> | 
| Elliott Hughes | 9605a94 | 2016-11-10 17:43:47 -0800 | [diff] [blame] | 21 | #include <inttypes.h> | 
| Jorge Lucangeli Obes | 24b2913 | 2016-10-27 10:33:03 -0400 | [diff] [blame] | 22 | #include <linux/securebits.h> | 
| Jorge Lucangeli Obes | 1b3fa3d | 2016-04-21 15:35:09 -0700 | [diff] [blame] | 23 | #include <sched.h> | 
| Jorge Lucangeli Obes | 1b3fa3d | 2016-04-21 15:35:09 -0700 | [diff] [blame] | 24 | #include <sys/prctl.h> | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 25 | #include <sys/stat.h> | 
| Vitalii Tomkiv | 081705c | 2016-05-18 17:36:30 -0700 | [diff] [blame] | 26 | #include <sys/time.h> | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 27 | #include <termios.h> | 
| Dan Albert | af9ba4d | 2015-08-11 16:37:04 -0700 | [diff] [blame] | 28 | #include <unistd.h> | 
| Daniel Rosenberg | de76688 | 2022-12-01 15:44:31 -0800 | [diff] [blame] | 29 | #include <thread> | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 30 |  | 
| Elliott Hughes | 4f71319 | 2015-12-04 22:00:26 -0800 | [diff] [blame] | 31 | #include <android-base/file.h> | 
| Tom Cherry | 3f5eaae5 | 2017-04-06 16:30:22 -0700 | [diff] [blame] | 32 | #include <android-base/logging.h> | 
| Elliott Hughes | dc80312 | 2018-05-24 18:00:39 -0700 | [diff] [blame] | 33 | #include <android-base/properties.h> | 
| Tom Cherry | 60971e6 | 2019-09-10 10:40:47 -0700 | [diff] [blame] | 34 | #include <android-base/scopeguard.h> | 
| Elliott Hughes | 4f71319 | 2015-12-04 22:00:26 -0800 | [diff] [blame] | 35 | #include <android-base/stringprintf.h> | 
| Elliott Hughes | f86b5a6 | 2016-06-24 15:12:21 -0700 | [diff] [blame] | 36 | #include <android-base/strings.h> | 
| Tom Cherry | 2e4c85f | 2019-07-09 13:33:36 -0700 | [diff] [blame] | 37 | #include <cutils/sockets.h> | 
| Tom Cherry | 3f5eaae5 | 2017-04-06 16:30:22 -0700 | [diff] [blame] | 38 | #include <processgroup/processgroup.h> | 
 | 39 | #include <selinux/selinux.h> | 
| Bart Van Assche | 97047b5 | 2023-11-16 12:42:35 -0800 | [diff] [blame] | 40 | #include <sys/signalfd.h> | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 41 |  | 
| Florian Mayer | 2ef47f8 | 2022-05-10 17:55:08 -0700 | [diff] [blame] | 42 | #include <string> | 
 | 43 |  | 
| Bart Van Assche | 1693f42 | 2022-10-19 16:30:15 -0700 | [diff] [blame] | 44 | #include "interprocess_fifo.h" | 
| Suren Baghdasaryan | c29c2ba | 2019-10-22 17:18:42 -0700 | [diff] [blame] | 45 | #include "lmkd_service.h" | 
| Tom Cherry | 2aeb1ad | 2019-06-26 10:46:20 -0700 | [diff] [blame] | 46 | #include "service_list.h" | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 47 | #include "util.h" | 
 | 48 |  | 
| Florian Mayer | d705c2d | 2022-09-12 18:19:47 -0700 | [diff] [blame] | 49 | #if defined(__BIONIC__) | 
 | 50 | #include <bionic/reserved_signals.h> | 
 | 51 | #endif | 
 | 52 |  | 
| Tom Cherry | a2f9136 | 2020-02-20 10:50:00 -0800 | [diff] [blame] | 53 | #ifdef INIT_FULL_SOURCES | 
| Tom Cherry | d89ed13 | 2019-11-19 14:19:40 -0800 | [diff] [blame] | 54 | #include <android/api-level.h> | 
| Tom Cherry | de6bd50 | 2018-02-13 16:50:08 -0800 | [diff] [blame] | 55 |  | 
| Jiyong Park | 6866041 | 2019-01-16 23:00:59 +0900 | [diff] [blame] | 56 | #include "mount_namespace.h" | 
| Woody Lin | 45215ae | 2019-12-26 22:22:28 +0800 | [diff] [blame] | 57 | #include "reboot_utils.h" | 
| Tom Cherry | d89ed13 | 2019-11-19 14:19:40 -0800 | [diff] [blame] | 58 | #include "selinux.h" | 
| Tom Cherry | de6bd50 | 2018-02-13 16:50:08 -0800 | [diff] [blame] | 59 | #else | 
 | 60 | #include "host_init_stubs.h" | 
 | 61 | #endif | 
 | 62 |  | 
| James Hawkins | e78ea77 | 2017-03-24 11:43:02 -0700 | [diff] [blame] | 63 | using android::base::boot_clock; | 
| Woody Lin | ef9d460 | 2021-01-20 12:28:33 +0800 | [diff] [blame] | 64 | using android::base::GetBoolProperty; | 
| Florian Mayer | 2ef47f8 | 2022-05-10 17:55:08 -0700 | [diff] [blame] | 65 | using android::base::GetIntProperty; | 
| Tom Cherry | 81f5d3e | 2017-06-22 12:53:17 -0700 | [diff] [blame] | 66 | using android::base::GetProperty; | 
 | 67 | using android::base::Join; | 
| Tom Cherry | 60971e6 | 2019-09-10 10:40:47 -0700 | [diff] [blame] | 68 | using android::base::make_scope_guard; | 
| Tom Cherry | c88d8f9 | 2019-08-19 15:21:25 -0700 | [diff] [blame] | 69 | using android::base::SetProperty; | 
| Tom Cherry | 81f5d3e | 2017-06-22 12:53:17 -0700 | [diff] [blame] | 70 | using android::base::StartsWith; | 
| Tom Cherry | b734990 | 2015-08-26 11:43:36 -0700 | [diff] [blame] | 71 | using android::base::StringPrintf; | 
| Bart Van Assche | 97047b5 | 2023-11-16 12:42:35 -0800 | [diff] [blame] | 72 | using android::base::unique_fd; | 
| Tom Cherry | b734990 | 2015-08-26 11:43:36 -0700 | [diff] [blame] | 73 | using android::base::WriteStringToFile; | 
 | 74 |  | 
| Tom Cherry | 81f5d3e | 2017-06-22 12:53:17 -0700 | [diff] [blame] | 75 | namespace android { | 
 | 76 | namespace init { | 
 | 77 |  | 
| Tom Cherry | aead51b | 2018-04-20 16:18:12 -0700 | [diff] [blame] | 78 | static Result<std::string> ComputeContextFromExecutable(const std::string& service_path) { | 
| Jorge Lucangeli Obes | 344d01f | 2016-07-08 13:32:26 -0400 | [diff] [blame] | 79 |     std::string computed_context; | 
 | 80 |  | 
 | 81 |     char* raw_con = nullptr; | 
 | 82 |     char* raw_filecon = nullptr; | 
 | 83 |  | 
 | 84 |     if (getcon(&raw_con) == -1) { | 
| Tom Cherry | 76af7e6 | 2017-08-22 16:13:59 -0700 | [diff] [blame] | 85 |         return Error() << "Could not get security context"; | 
| Jorge Lucangeli Obes | 344d01f | 2016-07-08 13:32:26 -0400 | [diff] [blame] | 86 |     } | 
| Elliott Hughes | d92c6a1 | 2020-12-08 22:30:17 -0800 | [diff] [blame] | 87 |     std::unique_ptr<char, decltype(&freecon)> mycon(raw_con, freecon); | 
| Jorge Lucangeli Obes | 344d01f | 2016-07-08 13:32:26 -0400 | [diff] [blame] | 88 |  | 
 | 89 |     if (getfilecon(service_path.c_str(), &raw_filecon) == -1) { | 
| Tom Cherry | 76af7e6 | 2017-08-22 16:13:59 -0700 | [diff] [blame] | 90 |         return Error() << "Could not get file context"; | 
| Jorge Lucangeli Obes | 344d01f | 2016-07-08 13:32:26 -0400 | [diff] [blame] | 91 |     } | 
| Elliott Hughes | d92c6a1 | 2020-12-08 22:30:17 -0800 | [diff] [blame] | 92 |     std::unique_ptr<char, decltype(&freecon)> filecon(raw_filecon, freecon); | 
| Jorge Lucangeli Obes | 344d01f | 2016-07-08 13:32:26 -0400 | [diff] [blame] | 93 |  | 
 | 94 |     char* new_con = nullptr; | 
 | 95 |     int rc = security_compute_create(mycon.get(), filecon.get(), | 
 | 96 |                                      string_to_security_class("process"), &new_con); | 
 | 97 |     if (rc == 0) { | 
 | 98 |         computed_context = new_con; | 
 | 99 |         free(new_con); | 
 | 100 |     } | 
 | 101 |     if (rc == 0 && computed_context == mycon.get()) { | 
| Nick Kralevich | 1ea19eb | 2017-08-25 12:08:57 -0700 | [diff] [blame] | 102 |         return Error() << "File " << service_path << "(labeled \"" << filecon.get() | 
 | 103 |                        << "\") has incorrect label or no domain transition from " << mycon.get() | 
 | 104 |                        << " to another SELinux domain defined. Have you configured your " | 
 | 105 |                           "service correctly? https://source.android.com/security/selinux/" | 
| Steven Moreland | 9e987cb | 2020-04-09 12:45:03 -0700 | [diff] [blame] | 106 |                           "device-policy#label_new_services_and_address_denials. Note: this " | 
 | 107 |                           "error shows up even in permissive mode in order to make auditing " | 
 | 108 |                           "denials possible."; | 
| Jorge Lucangeli Obes | 344d01f | 2016-07-08 13:32:26 -0400 | [diff] [blame] | 109 |     } | 
 | 110 |     if (rc < 0) { | 
| Tom Cherry | 76af7e6 | 2017-08-22 16:13:59 -0700 | [diff] [blame] | 111 |         return Error() << "Could not get process context"; | 
| Jorge Lucangeli Obes | 344d01f | 2016-07-08 13:32:26 -0400 | [diff] [blame] | 112 |     } | 
 | 113 |     return computed_context; | 
 | 114 | } | 
 | 115 |  | 
| Tom Cherry | 8f38048 | 2018-04-17 14:48:44 -0700 | [diff] [blame] | 116 | static bool ExpandArgsAndExecv(const std::vector<std::string>& args, bool sigstop) { | 
| Jorge Lucangeli Obes | 344d01f | 2016-07-08 13:32:26 -0400 | [diff] [blame] | 117 |     std::vector<std::string> expanded_args; | 
| Tom Cherry | 5e405ca | 2017-09-11 16:08:54 -0700 | [diff] [blame] | 118 |     std::vector<char*> c_strings; | 
 | 119 |  | 
| Jorge Lucangeli Obes | 344d01f | 2016-07-08 13:32:26 -0400 | [diff] [blame] | 120 |     expanded_args.resize(args.size()); | 
| Tom Cherry | 5e405ca | 2017-09-11 16:08:54 -0700 | [diff] [blame] | 121 |     c_strings.push_back(const_cast<char*>(args[0].data())); | 
| Jorge Lucangeli Obes | 344d01f | 2016-07-08 13:32:26 -0400 | [diff] [blame] | 122 |     for (std::size_t i = 1; i < args.size(); ++i) { | 
| Tom Cherry | c5cf85d | 2019-07-31 13:59:15 -0700 | [diff] [blame] | 123 |         auto expanded_arg = ExpandProps(args[i]); | 
| Bernie Innocenti | cecebbb | 2020-02-06 03:49:33 +0900 | [diff] [blame] | 124 |         if (!expanded_arg.ok()) { | 
| Tom Cherry | c5cf85d | 2019-07-31 13:59:15 -0700 | [diff] [blame] | 125 |             LOG(FATAL) << args[0] << ": cannot expand arguments': " << expanded_arg.error(); | 
| Jorge Lucangeli Obes | 344d01f | 2016-07-08 13:32:26 -0400 | [diff] [blame] | 126 |         } | 
| Tom Cherry | c5cf85d | 2019-07-31 13:59:15 -0700 | [diff] [blame] | 127 |         expanded_args[i] = *expanded_arg; | 
| Tom Cherry | 5e405ca | 2017-09-11 16:08:54 -0700 | [diff] [blame] | 128 |         c_strings.push_back(expanded_args[i].data()); | 
| Jorge Lucangeli Obes | 344d01f | 2016-07-08 13:32:26 -0400 | [diff] [blame] | 129 |     } | 
| Tom Cherry | 5e405ca | 2017-09-11 16:08:54 -0700 | [diff] [blame] | 130 |     c_strings.push_back(nullptr); | 
 | 131 |  | 
| Tom Cherry | 8f38048 | 2018-04-17 14:48:44 -0700 | [diff] [blame] | 132 |     if (sigstop) { | 
 | 133 |         kill(getpid(), SIGSTOP); | 
 | 134 |     } | 
 | 135 |  | 
| Tom Cherry | 5e405ca | 2017-09-11 16:08:54 -0700 | [diff] [blame] | 136 |     return execv(c_strings[0], c_strings.data()) == 0; | 
| Jorge Lucangeli Obes | 344d01f | 2016-07-08 13:32:26 -0400 | [diff] [blame] | 137 | } | 
 | 138 |  | 
| Tom Cherry | 5938379 | 2017-07-26 16:09:09 -0700 | [diff] [blame] | 139 | unsigned long Service::next_start_order_ = 1; | 
| Tom Cherry | 3b81f2d | 2017-07-28 14:48:41 -0700 | [diff] [blame] | 140 | bool Service::is_exec_service_running_ = false; | 
| Tom Cherry | 5938379 | 2017-07-26 16:09:09 -0700 | [diff] [blame] | 141 |  | 
| Tom Cherry | cb0f9bb | 2017-09-12 15:58:47 -0700 | [diff] [blame] | 142 | Service::Service(const std::string& name, Subcontext* subcontext_for_restart_commands, | 
| Deyao Ren | df40ed1 | 2022-07-14 22:51:10 +0000 | [diff] [blame] | 143 |                  const std::string& filename, const std::vector<std::string>& args) | 
| Steven Moreland | f5d22ef | 2023-04-03 23:29:22 +0000 | [diff] [blame] | 144 |     : Service(name, 0, std::nullopt, 0, {}, 0, "", subcontext_for_restart_commands, filename, | 
 | 145 |               args) {} | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 146 |  | 
| Steven Moreland | f5d22ef | 2023-04-03 23:29:22 +0000 | [diff] [blame] | 147 | Service::Service(const std::string& name, unsigned flags, std::optional<uid_t> uid, gid_t gid, | 
| Tom Cherry | 247ffbf | 2019-07-08 15:09:36 -0700 | [diff] [blame] | 148 |                  const std::vector<gid_t>& supp_gids, int namespace_flags, | 
| Tom Cherry | 1cd082d | 2019-02-06 10:45:56 -0800 | [diff] [blame] | 149 |                  const std::string& seclabel, Subcontext* subcontext_for_restart_commands, | 
| Deyao Ren | df40ed1 | 2022-07-14 22:51:10 +0000 | [diff] [blame] | 150 |                  const std::string& filename, const std::vector<std::string>& args) | 
| Wei Wang | 641ff0a | 2017-03-27 10:59:11 -0700 | [diff] [blame] | 151 |     : name_(name), | 
 | 152 |       classnames_({"default"}), | 
 | 153 |       flags_(flags), | 
 | 154 |       pid_(0), | 
 | 155 |       crash_count_(0), | 
| Vic Yang | e01ca4d | 2019-05-29 15:58:32 -0700 | [diff] [blame] | 156 |       proc_attr_{.ioprio_class = IoSchedClass_NONE, | 
 | 157 |                  .ioprio_pri = 0, | 
| Steven Moreland | f5d22ef | 2023-04-03 23:29:22 +0000 | [diff] [blame] | 158 |                  .parsed_uid = uid, | 
| Vic Yang | e01ca4d | 2019-05-29 15:58:32 -0700 | [diff] [blame] | 159 |                  .gid = gid, | 
 | 160 |                  .supp_gids = supp_gids, | 
 | 161 |                  .priority = 0}, | 
 | 162 |       namespaces_{.flags = namespace_flags}, | 
| Wei Wang | 641ff0a | 2017-03-27 10:59:11 -0700 | [diff] [blame] | 163 |       seclabel_(seclabel), | 
| Daniel Norman | f597fa5 | 2020-11-09 17:28:24 -0800 | [diff] [blame] | 164 |       subcontext_(subcontext_for_restart_commands), | 
| Tom Cherry | 9cbf570 | 2018-02-13 16:24:51 -0800 | [diff] [blame] | 165 |       onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0, | 
 | 166 |                  "onrestart", {}), | 
| Suren Baghdasaryan | c29c2ba | 2019-10-22 17:18:42 -0700 | [diff] [blame] | 167 |       oom_score_adjust_(DEFAULT_OOM_SCORE_ADJUST), | 
| Tom Cherry | 5938379 | 2017-07-26 16:09:09 -0700 | [diff] [blame] | 168 |       start_order_(0), | 
| Nikita Ioffe | 091c4d1 | 2019-12-05 12:35:19 +0000 | [diff] [blame] | 169 |       args_(args), | 
| Deyao Ren | df40ed1 | 2022-07-14 22:51:10 +0000 | [diff] [blame] | 170 |       filename_(filename) {} | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 171 |  | 
 | 172 | void Service::NotifyStateChange(const std::string& new_state) const { | 
| Tom Cherry | b27004a | 2017-03-27 16:27:30 -0700 | [diff] [blame] | 173 |     if ((flags_ & SVC_TEMPORARY) != 0) { | 
 | 174 |         // Services created by 'exec' are temporary and don't have properties tracking their state. | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 175 |         return; | 
 | 176 |     } | 
 | 177 |  | 
| Tom Cherry | 1c3a53f | 2017-06-22 16:50:31 -0700 | [diff] [blame] | 178 |     std::string prop_name = "init.svc." + name_; | 
| Tom Cherry | c88d8f9 | 2019-08-19 15:21:25 -0700 | [diff] [blame] | 179 |     SetProperty(prop_name, new_state); | 
| Elliott Hughes | 9605a94 | 2016-11-10 17:43:47 -0800 | [diff] [blame] | 180 |  | 
 | 181 |     if (new_state == "running") { | 
| Elliott Hughes | 9605a94 | 2016-11-10 17:43:47 -0800 | [diff] [blame] | 182 |         uint64_t start_ns = time_started_.time_since_epoch().count(); | 
| Tom Cherry | fed3373 | 2017-08-18 10:47:46 -0700 | [diff] [blame] | 183 |         std::string boottime_property = "ro.boottime." + name_; | 
 | 184 |         if (GetProperty(boottime_property, "").empty()) { | 
| Tom Cherry | c88d8f9 | 2019-08-19 15:21:25 -0700 | [diff] [blame] | 185 |             SetProperty(boottime_property, std::to_string(start_ns)); | 
| Tom Cherry | fed3373 | 2017-08-18 10:47:46 -0700 | [diff] [blame] | 186 |         } | 
| Elliott Hughes | 9605a94 | 2016-11-10 17:43:47 -0800 | [diff] [blame] | 187 |     } | 
| Daniel Norman | c788771 | 2019-07-19 11:04:01 -0700 | [diff] [blame] | 188 |  | 
 | 189 |     // init.svc_debug_pid.* properties are only for tests, and should not be used | 
 | 190 |     // on device for security checks. | 
 | 191 |     std::string pid_property = "init.svc_debug_pid." + name_; | 
 | 192 |     if (new_state == "running") { | 
| Tom Cherry | c88d8f9 | 2019-08-19 15:21:25 -0700 | [diff] [blame] | 193 |         SetProperty(pid_property, std::to_string(pid_)); | 
| Daniel Norman | c788771 | 2019-07-19 11:04:01 -0700 | [diff] [blame] | 194 |     } else if (new_state == "stopped") { | 
| Tom Cherry | c88d8f9 | 2019-08-19 15:21:25 -0700 | [diff] [blame] | 195 |         SetProperty(pid_property, ""); | 
| Daniel Norman | c788771 | 2019-07-19 11:04:01 -0700 | [diff] [blame] | 196 |     } | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 197 | } | 
 | 198 |  | 
| T.J. Mercier | 599d979 | 2023-10-26 20:46:21 +0000 | [diff] [blame] | 199 | void Service::KillProcessGroup(int signal) { | 
| Kelvin Zhang | 1099321 | 2023-11-13 13:42:13 -0800 | [diff] [blame] | 200 |     // Always attempt the process kill if process is still running. | 
 | 201 |     // Cgroup clean up routines are idempotent. It's safe to call | 
 | 202 |     // killProcessGroup repeatedly. During shutdown, `init` will | 
 | 203 |     // call this function to send SIGTERM/SIGKILL to all processes. | 
 | 204 |     // These signals must be sent for a successful shutdown. | 
 | 205 |     if (!process_cgroup_empty_ || IsRunning()) { | 
| Tom Cherry | 33838b1 | 2017-05-04 11:32:36 -0700 | [diff] [blame] | 206 |         LOG(INFO) << "Sending signal " << signal << " to service '" << name_ << "' (pid " << pid_ | 
 | 207 |                   << ") process group..."; | 
 | 208 |         int r; | 
 | 209 |         if (signal == SIGTERM) { | 
| T.J. Mercier | 599d979 | 2023-10-26 20:46:21 +0000 | [diff] [blame] | 210 |             r = killProcessGroupOnce(uid(), pid_, signal); | 
| Tom Cherry | 33838b1 | 2017-05-04 11:32:36 -0700 | [diff] [blame] | 211 |         } else { | 
| T.J. Mercier | 599d979 | 2023-10-26 20:46:21 +0000 | [diff] [blame] | 212 |             r = killProcessGroup(uid(), pid_, signal); | 
| Tom Cherry | 33838b1 | 2017-05-04 11:32:36 -0700 | [diff] [blame] | 213 |         } | 
 | 214 |  | 
 | 215 |         if (r == 0) process_cgroup_empty_ = true; | 
 | 216 |     } | 
| Suren Baghdasaryan | c29c2ba | 2019-10-22 17:18:42 -0700 | [diff] [blame] | 217 |  | 
 | 218 |     if (oom_score_adjust_ != DEFAULT_OOM_SCORE_ADJUST) { | 
 | 219 |         LmkdUnregister(name_, pid_); | 
 | 220 |     } | 
| Elliott Hughes | ad8e94e | 2016-06-15 14:49:57 -0700 | [diff] [blame] | 221 | } | 
 | 222 |  | 
| Bart Van Assche | 01e6669 | 2022-11-14 16:45:47 -0800 | [diff] [blame] | 223 | void Service::SetProcessAttributesAndCaps(InterprocessFifo setsid_finished) { | 
| Jorge Lucangeli Obes | 24b2913 | 2016-10-27 10:33:03 -0400 | [diff] [blame] | 224 |     // Keep capabilites on uid change. | 
| Steven Moreland | f5d22ef | 2023-04-03 23:29:22 +0000 | [diff] [blame] | 225 |     if (capabilities_ && uid()) { | 
| Luis Hector Chavez | f596551 | 2017-06-30 14:04:20 -0700 | [diff] [blame] | 226 |         // If Android is running in a container, some securebits might already | 
 | 227 |         // be locked, so don't change those. | 
| Ben Fennema | a724360 | 2017-07-25 14:37:21 -0700 | [diff] [blame] | 228 |         unsigned long securebits = prctl(PR_GET_SECUREBITS); | 
 | 229 |         if (securebits == -1UL) { | 
| Luis Hector Chavez | f596551 | 2017-06-30 14:04:20 -0700 | [diff] [blame] | 230 |             PLOG(FATAL) << "prctl(PR_GET_SECUREBITS) failed for " << name_; | 
 | 231 |         } | 
 | 232 |         securebits |= SECBIT_KEEP_CAPS | SECBIT_KEEP_CAPS_LOCKED; | 
 | 233 |         if (prctl(PR_SET_SECUREBITS, securebits) != 0) { | 
 | 234 |             PLOG(FATAL) << "prctl(PR_SET_SECUREBITS) failed for " << name_; | 
| Jorge Lucangeli Obes | 24b2913 | 2016-10-27 10:33:03 -0400 | [diff] [blame] | 235 |         } | 
 | 236 |     } | 
 | 237 |  | 
| Bart Van Assche | 01e6669 | 2022-11-14 16:45:47 -0800 | [diff] [blame] | 238 |     if (auto result = SetProcessAttributes(proc_attr_, std::move(setsid_finished)); !result.ok()) { | 
| Vic Yang | e01ca4d | 2019-05-29 15:58:32 -0700 | [diff] [blame] | 239 |         LOG(FATAL) << "cannot set attribute for " << name_ << ": " << result.error(); | 
 | 240 |     } | 
| Jorge Lucangeli Obes | 344d01f | 2016-07-08 13:32:26 -0400 | [diff] [blame] | 241 |  | 
| Jorge Lucangeli Obes | 344d01f | 2016-07-08 13:32:26 -0400 | [diff] [blame] | 242 |     if (!seclabel_.empty()) { | 
 | 243 |         if (setexeccon(seclabel_.c_str()) < 0) { | 
| Elliott Hughes | e18e7e5 | 2016-07-25 18:18:16 -0700 | [diff] [blame] | 244 |             PLOG(FATAL) << "cannot setexeccon('" << seclabel_ << "') for " << name_; | 
| Jorge Lucangeli Obes | 344d01f | 2016-07-08 13:32:26 -0400 | [diff] [blame] | 245 |         } | 
 | 246 |     } | 
| Vic Yang | e01ca4d | 2019-05-29 15:58:32 -0700 | [diff] [blame] | 247 |  | 
| Tom Cherry | 1cd082d | 2019-02-06 10:45:56 -0800 | [diff] [blame] | 248 |     if (capabilities_) { | 
 | 249 |         if (!SetCapsForExec(*capabilities_)) { | 
| Jorge Lucangeli Obes | 24b2913 | 2016-10-27 10:33:03 -0400 | [diff] [blame] | 250 |             LOG(FATAL) << "cannot set capabilities for " << name_; | 
 | 251 |         } | 
| Steven Moreland | f5d22ef | 2023-04-03 23:29:22 +0000 | [diff] [blame] | 252 |     } else if (uid()) { | 
| Luis Hector Chavez | 94fb5b0 | 2017-11-16 15:52:00 -0800 | [diff] [blame] | 253 |         // Inheritable caps can be non-zero when running in a container. | 
 | 254 |         if (!DropInheritableCaps()) { | 
 | 255 |             LOG(FATAL) << "cannot drop inheritable caps for " << name_; | 
 | 256 |         } | 
| Jorge Lucangeli Obes | 24b2913 | 2016-10-27 10:33:03 -0400 | [diff] [blame] | 257 |     } | 
| Jorge Lucangeli Obes | 344d01f | 2016-07-08 13:32:26 -0400 | [diff] [blame] | 258 | } | 
 | 259 |  | 
| Paul Crowley | c73b215 | 2018-04-13 17:38:57 +0000 | [diff] [blame] | 260 | void Service::Reap(const siginfo_t& siginfo) { | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 261 |     if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) { | 
| T.J. Mercier | 599d979 | 2023-10-26 20:46:21 +0000 | [diff] [blame] | 262 |         KillProcessGroup(SIGKILL); | 
| Tom Cherry | d89ed13 | 2019-11-19 14:19:40 -0800 | [diff] [blame] | 263 |     } else { | 
 | 264 |         // Legacy behavior from ~2007 until Android R: this else branch did not exist and we did not | 
 | 265 |         // kill the process group in this case. | 
 | 266 |         if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_R__) { | 
 | 267 |             // The new behavior in Android R is to kill these process groups in all cases.  The | 
 | 268 |             // 'true' parameter instructions KillProcessGroup() to report a warning message where it | 
 | 269 |             // detects a difference in behavior has occurred. | 
| T.J. Mercier | 599d979 | 2023-10-26 20:46:21 +0000 | [diff] [blame] | 270 |             KillProcessGroup(SIGKILL); | 
| Tom Cherry | d89ed13 | 2019-11-19 14:19:40 -0800 | [diff] [blame] | 271 |         } | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 272 |     } | 
 | 273 |  | 
| Tom Cherry | 2e4c85f | 2019-07-09 13:33:36 -0700 | [diff] [blame] | 274 |     // Remove any socket resources we may have created. | 
 | 275 |     for (const auto& socket : sockets_) { | 
| David Anderson | 0e5ad5a | 2021-07-21 21:53:28 -0700 | [diff] [blame] | 276 |         if (socket.persist) { | 
 | 277 |             continue; | 
 | 278 |         } | 
| Tom Cherry | 2e4c85f | 2019-07-09 13:33:36 -0700 | [diff] [blame] | 279 |         auto path = ANDROID_SOCKET_DIR "/" + socket.name; | 
 | 280 |         unlink(path.c_str()); | 
 | 281 |     } | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 282 |  | 
| Paul Crowley | c73b215 | 2018-04-13 17:38:57 +0000 | [diff] [blame] | 283 |     for (const auto& f : reap_callbacks_) { | 
 | 284 |         f(siginfo); | 
 | 285 |     } | 
 | 286 |  | 
| Eric Biggers | d14a178 | 2021-07-22 12:56:39 -0700 | [diff] [blame] | 287 |     if ((siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) && on_failure_reboot_target_) { | 
| Bart Van Assche | 42764c4 | 2022-12-02 19:04:22 -0800 | [diff] [blame] | 288 |         LOG(ERROR) << "Service " << name_ | 
 | 289 |                    << " has 'reboot_on_failure' option and failed, shutting down system."; | 
| Tom Cherry | 18278d2 | 2019-11-12 16:21:20 -0800 | [diff] [blame] | 290 |         trigger_shutdown(*on_failure_reboot_target_); | 
| Tom Cherry | 60971e6 | 2019-09-10 10:40:47 -0700 | [diff] [blame] | 291 |     } | 
 | 292 |  | 
| Tom Cherry | 3b81f2d | 2017-07-28 14:48:41 -0700 | [diff] [blame] | 293 |     if (flags_ & SVC_EXEC) UnSetExec(); | 
 | 294 |  | 
| Suren Baghdasaryan | af64077 | 2022-04-28 13:26:59 -0700 | [diff] [blame] | 295 |     if (name_ == "zygote" || name_ == "zygote64") { | 
 | 296 |         removeAllEmptyProcessGroups(); | 
 | 297 |     } | 
 | 298 |  | 
| Tom Cherry | 3b81f2d | 2017-07-28 14:48:41 -0700 | [diff] [blame] | 299 |     if (flags_ & SVC_TEMPORARY) return; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 300 |  | 
 | 301 |     pid_ = 0; | 
| Eric Biggers | d14a178 | 2021-07-22 12:56:39 -0700 | [diff] [blame] | 302 |     flags_ &= (~SVC_RUNNING); | 
| Tom Cherry | 5938379 | 2017-07-26 16:09:09 -0700 | [diff] [blame] | 303 |     start_order_ = 0; | 
| Jiyong Park | 0d277d7 | 2023-06-09 09:52:49 +0900 | [diff] [blame] | 304 |     was_last_exit_ok_ = siginfo.si_code == CLD_EXITED && siginfo.si_status == 0; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 305 |  | 
 | 306 |     // Oneshot processes go into the disabled state on exit, | 
 | 307 |     // except when manually restarted. | 
| Martijn Coenen | 70788f9 | 2019-04-23 16:26:01 +0200 | [diff] [blame] | 308 |     if ((flags_ & SVC_ONESHOT) && !(flags_ & SVC_RESTART) && !(flags_ & SVC_RESET)) { | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 309 |         flags_ |= SVC_DISABLED; | 
 | 310 |     } | 
 | 311 |  | 
 | 312 |     // Disabled and reset processes do not get restarted automatically. | 
 | 313 |     if (flags_ & (SVC_DISABLED | SVC_RESET))  { | 
 | 314 |         NotifyStateChange("stopped"); | 
| Tom Cherry | b27004a | 2017-03-27 16:27:30 -0700 | [diff] [blame] | 315 |         return; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 316 |     } | 
 | 317 |  | 
| Tom Cherry | a2f9136 | 2020-02-20 10:50:00 -0800 | [diff] [blame] | 318 | #if INIT_FULL_SOURCES | 
| Jooyung Han | 918971c | 2023-06-23 14:16:31 +0900 | [diff] [blame] | 319 |     static bool is_apex_updatable = true; | 
| Jiyong Park | d7f7c20 | 2019-05-10 21:12:15 +0900 | [diff] [blame] | 320 | #else | 
 | 321 |     static bool is_apex_updatable = false; | 
 | 322 | #endif | 
| Jooyung Han | c5fa15e | 2022-07-14 11:23:59 +0900 | [diff] [blame] | 323 |     const bool use_default_mount_ns = | 
 | 324 |             mount_namespace_.has_value() && *mount_namespace_ == NS_DEFAULT; | 
 | 325 |     const bool is_process_updatable = use_default_mount_ns && is_apex_updatable; | 
| Jiyong Park | d7f7c20 | 2019-05-10 21:12:15 +0900 | [diff] [blame] | 326 |  | 
| Florian Mayer | d705c2d | 2022-09-12 18:19:47 -0700 | [diff] [blame] | 327 | #if defined(__BIONIC__) && defined(SEGV_MTEAERR) | 
| Florian Mayer | 2ef47f8 | 2022-05-10 17:55:08 -0700 | [diff] [blame] | 328 |     // As a precaution, we only upgrade a service once per reboot, to limit | 
 | 329 |     // the potential impact. | 
| Florian Mayer | d705c2d | 2022-09-12 18:19:47 -0700 | [diff] [blame] | 330 |     // | 
 | 331 |     // BIONIC_SIGNAL_ART_PROFILER is a magic value used by deuggerd to signal | 
 | 332 |     // that the process crashed with SIGSEGV and SEGV_MTEAERR. This signal will | 
 | 333 |     // never be seen otherwise in a crash, because it always gets handled by the | 
 | 334 |     // profiling signal handlers in bionic. See also | 
 | 335 |     // debuggerd/handler/debuggerd_handler.cpp. | 
 | 336 |     bool should_upgrade_mte = siginfo.si_code != CLD_EXITED && | 
 | 337 |                               siginfo.si_status == BIONIC_SIGNAL_ART_PROFILER && !upgraded_mte_; | 
| Florian Mayer | 2ef47f8 | 2022-05-10 17:55:08 -0700 | [diff] [blame] | 338 |  | 
 | 339 |     if (should_upgrade_mte) { | 
| Florian Mayer | caa7a60 | 2022-09-15 18:10:54 -0700 | [diff] [blame] | 340 |         constexpr int kDefaultUpgradeSecs = 60; | 
 | 341 |         int secs = GetIntProperty("persist.device_config.memory_safety_native.upgrade_secs.default", | 
 | 342 |                                   kDefaultUpgradeSecs); | 
 | 343 |         secs = GetIntProperty( | 
 | 344 |                 "persist.device_config.memory_safety_native.upgrade_secs.service." + name_, secs); | 
 | 345 |         if (secs > 0) { | 
 | 346 |             LOG(INFO) << "Upgrading service " << name_ << " to sync MTE for " << secs << " seconds"; | 
 | 347 |             once_environment_vars_.emplace_back("BIONIC_MEMTAG_UPGRADE_SECS", std::to_string(secs)); | 
 | 348 |             upgraded_mte_ = true; | 
 | 349 |         } else { | 
 | 350 |             LOG(INFO) << "Not upgrading service " << name_ << " to sync MTE due to device config"; | 
 | 351 |         } | 
| Florian Mayer | 2ef47f8 | 2022-05-10 17:55:08 -0700 | [diff] [blame] | 352 |     } | 
 | 353 | #endif | 
 | 354 |  | 
| Woody Lin | 45215ae | 2019-12-26 22:22:28 +0800 | [diff] [blame] | 355 |     // If we crash > 4 times in 'fatal_crash_window_' minutes or before boot_completed, | 
| Zimuzo | 88de80f | 2019-04-27 21:10:35 +0100 | [diff] [blame] | 356 |     // reboot into bootloader or set crashing property | 
| Elliott Hughes | 9605a94 | 2016-11-10 17:43:47 -0800 | [diff] [blame] | 357 |     boot_clock::time_point now = boot_clock::now(); | 
| Jiyong Park | 0d277d7 | 2023-06-09 09:52:49 +0900 | [diff] [blame] | 358 |     if (((flags_ & SVC_CRITICAL) || is_process_updatable) && !(flags_ & SVC_RESTART) && | 
 | 359 |         !was_last_exit_ok_) { | 
| Woody Lin | ef9d460 | 2021-01-20 12:28:33 +0800 | [diff] [blame] | 360 |         bool boot_completed = GetBoolProperty("sys.boot_completed", false); | 
| Woody Lin | 45215ae | 2019-12-26 22:22:28 +0800 | [diff] [blame] | 361 |         if (now < time_crashed_ + fatal_crash_window_ || !boot_completed) { | 
| Elliott Hughes | 9605a94 | 2016-11-10 17:43:47 -0800 | [diff] [blame] | 362 |             if (++crash_count_ > 4) { | 
| Woody Lin | 45215ae | 2019-12-26 22:22:28 +0800 | [diff] [blame] | 363 |                 auto exit_reason = boot_completed ? | 
 | 364 |                     "in " + std::to_string(fatal_crash_window_.count()) + " minutes" : | 
 | 365 |                     "before boot completed"; | 
| Zimuzo | c55a8c6 | 2019-01-07 10:19:02 +0000 | [diff] [blame] | 366 |                 if (flags_ & SVC_CRITICAL) { | 
| Woody Lin | ef9d460 | 2021-01-20 12:28:33 +0800 | [diff] [blame] | 367 |                     if (!GetBoolProperty("init.svc_debug.no_fatal." + name_, false)) { | 
 | 368 |                         // Aborts into `fatal_reboot_target_'. | 
 | 369 |                         SetFatalRebootTarget(fatal_reboot_target_); | 
 | 370 |                         LOG(FATAL) << "critical process '" << name_ << "' exited 4 times " | 
 | 371 |                                    << exit_reason; | 
 | 372 |                     } | 
| Zimuzo | c55a8c6 | 2019-01-07 10:19:02 +0000 | [diff] [blame] | 373 |                 } else { | 
| Steven Moreland | abc5f88 | 2020-11-06 17:00:58 +0000 | [diff] [blame] | 374 |                     LOG(ERROR) << "process with updatable components '" << name_ | 
 | 375 |                                << "' exited 4 times " << exit_reason; | 
| Zimuzo | c55a8c6 | 2019-01-07 10:19:02 +0000 | [diff] [blame] | 376 |                     // Notifies update_verifier and apexd | 
| Gavin Corkery | 5d0deb5 | 2019-12-10 23:00:24 +0000 | [diff] [blame] | 377 |                     SetProperty("sys.init.updatable_crashing_process_name", name_); | 
| Nikita Ioffe | 018ddd7 | 2019-12-20 16:34:48 +0000 | [diff] [blame] | 378 |                     SetProperty("sys.init.updatable_crashing", "1"); | 
| Zimuzo | c55a8c6 | 2019-01-07 10:19:02 +0000 | [diff] [blame] | 379 |                 } | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 380 |             } | 
 | 381 |         } else { | 
 | 382 |             time_crashed_ = now; | 
| Elliott Hughes | 9605a94 | 2016-11-10 17:43:47 -0800 | [diff] [blame] | 383 |             crash_count_ = 1; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 384 |         } | 
 | 385 |     } | 
 | 386 |  | 
 | 387 |     flags_ &= (~SVC_RESTART); | 
 | 388 |     flags_ |= SVC_RESTARTING; | 
 | 389 |  | 
 | 390 |     // Execute all onrestart commands for this service. | 
 | 391 |     onrestart_.ExecuteAllCommands(); | 
 | 392 |  | 
 | 393 |     NotifyStateChange("restarting"); | 
| Tom Cherry | b27004a | 2017-03-27 16:27:30 -0700 | [diff] [blame] | 394 |     return; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 395 | } | 
 | 396 |  | 
 | 397 | void Service::DumpState() const { | 
| Elliott Hughes | f86b5a6 | 2016-06-24 15:12:21 -0700 | [diff] [blame] | 398 |     LOG(INFO) << "service " << name_; | 
| Tom Cherry | 81f5d3e | 2017-06-22 12:53:17 -0700 | [diff] [blame] | 399 |     LOG(INFO) << "  class '" << Join(classnames_, " ") << "'"; | 
 | 400 |     LOG(INFO) << "  exec " << Join(args_, " "); | 
| Tom Cherry | 2e4c85f | 2019-07-09 13:33:36 -0700 | [diff] [blame] | 401 |     for (const auto& socket : sockets_) { | 
 | 402 |         LOG(INFO) << "  socket " << socket.name; | 
 | 403 |     } | 
 | 404 |     for (const auto& file : files_) { | 
 | 405 |         LOG(INFO) << "  file " << file.name; | 
 | 406 |     } | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 407 | } | 
 | 408 |  | 
| Tom Cherry | b734990 | 2015-08-26 11:43:36 -0700 | [diff] [blame] | 409 |  | 
| Tom Cherry | bbcbc2f | 2019-06-10 11:08:01 -0700 | [diff] [blame] | 410 | Result<void> Service::ExecStart() { | 
| Tom Cherry | 60971e6 | 2019-09-10 10:40:47 -0700 | [diff] [blame] | 411 |     auto reboot_on_failure = make_scope_guard([this] { | 
 | 412 |         if (on_failure_reboot_target_) { | 
| Tom Cherry | 18278d2 | 2019-11-12 16:21:20 -0800 | [diff] [blame] | 413 |             trigger_shutdown(*on_failure_reboot_target_); | 
| Tom Cherry | 60971e6 | 2019-09-10 10:40:47 -0700 | [diff] [blame] | 414 |         } | 
 | 415 |     }); | 
 | 416 |  | 
| Jooyung Han | 646e001 | 2023-08-21 17:34:37 +0900 | [diff] [blame] | 417 |     if (is_updatable() && !IsDefaultMountNamespaceReady()) { | 
| Jiyong Park | 80aa447 | 2018-11-12 12:08:41 +0900 | [diff] [blame] | 418 |         // Don't delay the service for ExecStart() as the semantic is that | 
 | 419 |         // the caller might depend on the side effect of the execution. | 
 | 420 |         return Error() << "Cannot start an updatable service '" << name_ | 
 | 421 |                        << "' before configs from APEXes are all loaded"; | 
 | 422 |     } | 
 | 423 |  | 
| Tom Cherry | 3b81f2d | 2017-07-28 14:48:41 -0700 | [diff] [blame] | 424 |     flags_ |= SVC_ONESHOT; | 
| Tom Cherry | b27004a | 2017-03-27 16:27:30 -0700 | [diff] [blame] | 425 |  | 
| Bernie Innocenti | cecebbb | 2020-02-06 03:49:33 +0900 | [diff] [blame] | 426 |     if (auto result = Start(); !result.ok()) { | 
| Tom Cherry | 76af7e6 | 2017-08-22 16:13:59 -0700 | [diff] [blame] | 427 |         return result; | 
| Tom Cherry | b27004a | 2017-03-27 16:27:30 -0700 | [diff] [blame] | 428 |     } | 
| Tom Cherry | 3b81f2d | 2017-07-28 14:48:41 -0700 | [diff] [blame] | 429 |  | 
 | 430 |     flags_ |= SVC_EXEC; | 
 | 431 |     is_exec_service_running_ = true; | 
 | 432 |  | 
| Steven Moreland | f5d22ef | 2023-04-03 23:29:22 +0000 | [diff] [blame] | 433 |     LOG(INFO) << "SVC_EXEC service '" << name_ << "' pid " << pid_ << " (uid " << uid() << " gid " | 
 | 434 |               << proc_attr_.gid << "+" << proc_attr_.supp_gids.size() << " context " | 
| Wei Wang | 2c4ee75 | 2018-06-20 14:54:52 -0700 | [diff] [blame] | 435 |               << (!seclabel_.empty() ? seclabel_ : "default") << ") started; waiting..."; | 
| Tom Cherry | 3b81f2d | 2017-07-28 14:48:41 -0700 | [diff] [blame] | 436 |  | 
| Tom Cherry | 60971e6 | 2019-09-10 10:40:47 -0700 | [diff] [blame] | 437 |     reboot_on_failure.Disable(); | 
| Tom Cherry | bbcbc2f | 2019-06-10 11:08:01 -0700 | [diff] [blame] | 438 |     return {}; | 
| Tom Cherry | b27004a | 2017-03-27 16:27:30 -0700 | [diff] [blame] | 439 | } | 
 | 440 |  | 
| Bart Van Assche | 847b80a | 2022-02-25 23:28:59 +0000 | [diff] [blame] | 441 | Result<void> Service::CheckConsole() { | 
 | 442 |     if (!(flags_ & SVC_CONSOLE)) { | 
 | 443 |         return {}; | 
 | 444 |     } | 
 | 445 |  | 
| Alistair Delva | 5591f12 | 2023-02-22 14:31:23 -0800 | [diff] [blame] | 446 |     // On newer kernels, /dev/console will always exist because | 
 | 447 |     // "console=ttynull" is hard-coded in CONFIG_CMDLINE. This new boot | 
 | 448 |     // property should be set via "androidboot.serialconsole=0" to explicitly | 
 | 449 |     // disable services requiring the console. For older kernels and boot | 
 | 450 |     // images, not setting this at all will fall back to the old behavior | 
 | 451 |     if (GetProperty("ro.boot.serialconsole", "") == "0") { | 
| Alistair Delva | f9bfe0d | 2023-03-13 16:09:16 -0700 | [diff] [blame] | 452 |         flags_ |= SVC_DISABLED; | 
| Alistair Delva | 5591f12 | 2023-02-22 14:31:23 -0800 | [diff] [blame] | 453 |         return {}; | 
 | 454 |     } | 
 | 455 |  | 
| Bart Van Assche | 847b80a | 2022-02-25 23:28:59 +0000 | [diff] [blame] | 456 |     if (proc_attr_.console.empty()) { | 
 | 457 |         proc_attr_.console = "/dev/" + GetProperty("ro.boot.console", "console"); | 
 | 458 |     } | 
 | 459 |  | 
 | 460 |     // Make sure that open call succeeds to ensure a console driver is | 
 | 461 |     // properly registered for the device node | 
 | 462 |     int console_fd = open(proc_attr_.console.c_str(), O_RDWR | O_CLOEXEC); | 
 | 463 |     if (console_fd < 0) { | 
 | 464 |         flags_ |= SVC_DISABLED; | 
 | 465 |         return ErrnoError() << "Couldn't open console '" << proc_attr_.console << "'"; | 
 | 466 |     } | 
 | 467 |     close(console_fd); | 
 | 468 |     return {}; | 
 | 469 | } | 
 | 470 |  | 
| Bart Van Assche | f2222aa | 2022-02-25 22:44:40 +0000 | [diff] [blame] | 471 | // Configures the memory cgroup properties for the service. | 
 | 472 | void Service::ConfigureMemcg() { | 
 | 473 |     if (swappiness_ != -1) { | 
| Steven Moreland | f5d22ef | 2023-04-03 23:29:22 +0000 | [diff] [blame] | 474 |         if (!setProcessGroupSwappiness(uid(), pid_, swappiness_)) { | 
| Bart Van Assche | f2222aa | 2022-02-25 22:44:40 +0000 | [diff] [blame] | 475 |             PLOG(ERROR) << "setProcessGroupSwappiness failed"; | 
 | 476 |         } | 
 | 477 |     } | 
 | 478 |  | 
 | 479 |     if (soft_limit_in_bytes_ != -1) { | 
| Steven Moreland | f5d22ef | 2023-04-03 23:29:22 +0000 | [diff] [blame] | 480 |         if (!setProcessGroupSoftLimit(uid(), pid_, soft_limit_in_bytes_)) { | 
| Bart Van Assche | f2222aa | 2022-02-25 22:44:40 +0000 | [diff] [blame] | 481 |             PLOG(ERROR) << "setProcessGroupSoftLimit failed"; | 
 | 482 |         } | 
 | 483 |     } | 
 | 484 |  | 
 | 485 |     size_t computed_limit_in_bytes = limit_in_bytes_; | 
 | 486 |     if (limit_percent_ != -1) { | 
 | 487 |         long page_size = sysconf(_SC_PAGESIZE); | 
 | 488 |         long num_pages = sysconf(_SC_PHYS_PAGES); | 
 | 489 |         if (page_size > 0 && num_pages > 0) { | 
 | 490 |             size_t max_mem = SIZE_MAX; | 
 | 491 |             if (size_t(num_pages) < SIZE_MAX / size_t(page_size)) { | 
 | 492 |                 max_mem = size_t(num_pages) * size_t(page_size); | 
 | 493 |             } | 
 | 494 |             computed_limit_in_bytes = | 
 | 495 |                     std::min(computed_limit_in_bytes, max_mem / 100 * limit_percent_); | 
 | 496 |         } | 
 | 497 |     } | 
 | 498 |  | 
 | 499 |     if (!limit_property_.empty()) { | 
 | 500 |         // This ends up overwriting computed_limit_in_bytes but only if the | 
 | 501 |         // property is defined. | 
 | 502 |         computed_limit_in_bytes = | 
 | 503 |                 android::base::GetUintProperty(limit_property_, computed_limit_in_bytes, SIZE_MAX); | 
 | 504 |     } | 
 | 505 |  | 
 | 506 |     if (computed_limit_in_bytes != size_t(-1)) { | 
| Steven Moreland | f5d22ef | 2023-04-03 23:29:22 +0000 | [diff] [blame] | 507 |         if (!setProcessGroupLimit(uid(), pid_, computed_limit_in_bytes)) { | 
| Bart Van Assche | f2222aa | 2022-02-25 22:44:40 +0000 | [diff] [blame] | 508 |             PLOG(ERROR) << "setProcessGroupLimit failed"; | 
 | 509 |         } | 
 | 510 |     } | 
 | 511 | } | 
 | 512 |  | 
| Bart Van Assche | bd73665 | 2022-02-25 22:52:52 +0000 | [diff] [blame] | 513 | // Enters namespaces, sets environment variables, writes PID files and runs the service executable. | 
| Bart Van Assche | 4178723 | 2022-11-14 16:45:42 -0800 | [diff] [blame] | 514 | void Service::RunService(const std::vector<Descriptor>& descriptors, | 
| Bart Van Assche | 01e6669 | 2022-11-14 16:45:47 -0800 | [diff] [blame] | 515 |                          InterprocessFifo cgroups_activated, InterprocessFifo setsid_finished) { | 
| Jooyung Han | c5fa15e | 2022-07-14 11:23:59 +0900 | [diff] [blame] | 516 |     if (auto result = EnterNamespaces(namespaces_, name_, mount_namespace_); !result.ok()) { | 
| Bart Van Assche | bd73665 | 2022-02-25 22:52:52 +0000 | [diff] [blame] | 517 |         LOG(FATAL) << "Service '" << name_ << "' failed to set up namespaces: " << result.error(); | 
 | 518 |     } | 
 | 519 |  | 
| Florian Mayer | 2ef47f8 | 2022-05-10 17:55:08 -0700 | [diff] [blame] | 520 |     for (const auto& [key, value] : once_environment_vars_) { | 
 | 521 |         setenv(key.c_str(), value.c_str(), 1); | 
 | 522 |     } | 
| Bart Van Assche | bd73665 | 2022-02-25 22:52:52 +0000 | [diff] [blame] | 523 |     for (const auto& [key, value] : environment_vars_) { | 
 | 524 |         setenv(key.c_str(), value.c_str(), 1); | 
 | 525 |     } | 
 | 526 |  | 
 | 527 |     for (const auto& descriptor : descriptors) { | 
 | 528 |         descriptor.Publish(); | 
 | 529 |     } | 
 | 530 |  | 
 | 531 |     if (auto result = WritePidToFiles(&writepid_files_); !result.ok()) { | 
 | 532 |         LOG(ERROR) << "failed to write pid to files: " << result.error(); | 
 | 533 |     } | 
 | 534 |  | 
 | 535 |     // Wait until the cgroups have been created and until the cgroup controllers have been | 
 | 536 |     // activated. | 
| Bart Van Assche | 4178723 | 2022-11-14 16:45:42 -0800 | [diff] [blame] | 537 |     Result<uint8_t> byte = cgroups_activated.Read(); | 
| Bart Van Assche | 1693f42 | 2022-10-19 16:30:15 -0700 | [diff] [blame] | 538 |     if (!byte.ok()) { | 
 | 539 |         LOG(ERROR) << name_ << ": failed to read from notification channel: " << byte.error(); | 
| Bart Van Assche | bd73665 | 2022-02-25 22:52:52 +0000 | [diff] [blame] | 540 |     } | 
| Bart Van Assche | 4178723 | 2022-11-14 16:45:42 -0800 | [diff] [blame] | 541 |     cgroups_activated.Close(); | 
| Bart Van Assche | c8f3425 | 2022-11-18 09:12:52 -0800 | [diff] [blame] | 542 |     if (*byte != kCgroupsActivated) { | 
| Suren Baghdasaryan | 1bd1746 | 2022-03-31 21:18:20 -0700 | [diff] [blame] | 543 |         LOG(FATAL) << "Service '" << name_  << "' failed to start due to a fatal error"; | 
 | 544 |         _exit(EXIT_FAILURE); | 
 | 545 |     } | 
| Bart Van Assche | bd73665 | 2022-02-25 22:52:52 +0000 | [diff] [blame] | 546 |  | 
| Bart Van Assche | 77f3fe5 | 2022-10-12 12:25:46 -0700 | [diff] [blame] | 547 |     if (task_profiles_.size() > 0) { | 
 | 548 |         bool succeeded = SelinuxGetVendorAndroidVersion() < __ANDROID_API_U__ | 
 | 549 |                                  ? | 
 | 550 |                                  // Compatibility mode: apply the task profiles to the current | 
 | 551 |                                  // thread. | 
 | 552 |                                  SetTaskProfiles(getpid(), task_profiles_) | 
 | 553 |                                  : | 
 | 554 |                                  // Apply the task profiles to the current process. | 
 | 555 |                                  SetProcessProfiles(getuid(), getpid(), task_profiles_); | 
 | 556 |         if (!succeeded) { | 
 | 557 |             LOG(ERROR) << "failed to set task profiles"; | 
 | 558 |         } | 
| Bart Van Assche | bd73665 | 2022-02-25 22:52:52 +0000 | [diff] [blame] | 559 |     } | 
 | 560 |  | 
 | 561 |     // As requested, set our gid, supplemental gids, uid, context, and | 
 | 562 |     // priority. Aborts on failure. | 
| Bart Van Assche | 01e6669 | 2022-11-14 16:45:47 -0800 | [diff] [blame] | 563 |     SetProcessAttributesAndCaps(std::move(setsid_finished)); | 
| Bart Van Assche | bd73665 | 2022-02-25 22:52:52 +0000 | [diff] [blame] | 564 |  | 
 | 565 |     if (!ExpandArgsAndExecv(args_, sigstop_)) { | 
 | 566 |         PLOG(ERROR) << "cannot execv('" << args_[0] | 
 | 567 |                     << "'). See the 'Debugging init' section of init's README.md for tips"; | 
 | 568 |     } | 
 | 569 | } | 
 | 570 |  | 
| Tom Cherry | bbcbc2f | 2019-06-10 11:08:01 -0700 | [diff] [blame] | 571 | Result<void> Service::Start() { | 
| Tom Cherry | 60971e6 | 2019-09-10 10:40:47 -0700 | [diff] [blame] | 572 |     auto reboot_on_failure = make_scope_guard([this] { | 
 | 573 |         if (on_failure_reboot_target_) { | 
| Tom Cherry | 18278d2 | 2019-11-12 16:21:20 -0800 | [diff] [blame] | 574 |             trigger_shutdown(*on_failure_reboot_target_); | 
| Tom Cherry | 60971e6 | 2019-09-10 10:40:47 -0700 | [diff] [blame] | 575 |         } | 
 | 576 |     }); | 
 | 577 |  | 
| Jooyung Han | 646e001 | 2023-08-21 17:34:37 +0900 | [diff] [blame] | 578 |     if (is_updatable() && !IsDefaultMountNamespaceReady()) { | 
| Jiyong Park | 80aa447 | 2018-11-12 12:08:41 +0900 | [diff] [blame] | 579 |         ServiceList::GetInstance().DelayService(*this); | 
 | 580 |         return Error() << "Cannot start an updatable service '" << name_ | 
 | 581 |                        << "' before configs from APEXes are all loaded. " | 
 | 582 |                        << "Queued for execution."; | 
 | 583 |     } | 
 | 584 |  | 
| Tao Wu | 990d43c | 2017-10-26 10:43:10 -0700 | [diff] [blame] | 585 |     bool disabled = (flags_ & (SVC_DISABLED | SVC_RESET)); | 
| David Anderson | 0e5ad5a | 2021-07-21 21:53:28 -0700 | [diff] [blame] | 586 |     ResetFlagsForStart(); | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 587 |  | 
 | 588 |     // Running processes require no additional work --- if they're in the | 
 | 589 |     // process of exiting, we've ensured that they will immediately restart | 
| Tao Wu | 990d43c | 2017-10-26 10:43:10 -0700 | [diff] [blame] | 590 |     // on exit, unless they are ONESHOT. For ONESHOT service, if it's in | 
 | 591 |     // stopping status, we just set SVC_RESTART flag so it will get restarted | 
 | 592 |     // in Reap(). | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 593 |     if (flags_ & SVC_RUNNING) { | 
| Tao Wu | 990d43c | 2017-10-26 10:43:10 -0700 | [diff] [blame] | 594 |         if ((flags_ & SVC_ONESHOT) && disabled) { | 
 | 595 |             flags_ |= SVC_RESTART; | 
 | 596 |         } | 
| Steven Moreland | 61169c7 | 2022-05-17 22:53:11 +0000 | [diff] [blame] | 597 |  | 
 | 598 |         LOG(INFO) << "service '" << name_ | 
 | 599 |                   << "' requested start, but it is already running (flags: " << flags_ << ")"; | 
 | 600 |  | 
| Tom Cherry | 76af7e6 | 2017-08-22 16:13:59 -0700 | [diff] [blame] | 601 |         // It is not an error to try to start a service that is already running. | 
| Tom Cherry | 60971e6 | 2019-09-10 10:40:47 -0700 | [diff] [blame] | 602 |         reboot_on_failure.Disable(); | 
| Tom Cherry | bbcbc2f | 2019-06-10 11:08:01 -0700 | [diff] [blame] | 603 |         return {}; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 604 |     } | 
 | 605 |  | 
| Bart Van Assche | 01e6669 | 2022-11-14 16:45:47 -0800 | [diff] [blame] | 606 |     // cgroups_activated is used for communication from the parent to the child | 
 | 607 |     // while setsid_finished is used for communication from the child process to | 
 | 608 |     // the parent process. These two communication channels are separate because | 
 | 609 |     // combining these into a single communication channel would introduce a | 
 | 610 |     // race between the Write() calls by the parent and by the child. | 
 | 611 |     InterprocessFifo cgroups_activated, setsid_finished; | 
 | 612 |     OR_RETURN(cgroups_activated.Initialize()); | 
 | 613 |     OR_RETURN(setsid_finished.Initialize()); | 
| Bart Van Assche | ee36ba3 | 2022-01-26 20:52:52 +0000 | [diff] [blame] | 614 |  | 
| Bart Van Assche | 847b80a | 2022-02-25 23:28:59 +0000 | [diff] [blame] | 615 |     if (Result<void> result = CheckConsole(); !result.ok()) { | 
 | 616 |         return result; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 617 |     } | 
 | 618 |  | 
 | 619 |     struct stat sb; | 
 | 620 |     if (stat(args_[0].c_str(), &sb) == -1) { | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 621 |         flags_ |= SVC_DISABLED; | 
| Tom Cherry | 76af7e6 | 2017-08-22 16:13:59 -0700 | [diff] [blame] | 622 |         return ErrnoError() << "Cannot find '" << args_[0] << "'"; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 623 |     } | 
 | 624 |  | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 625 |     std::string scon; | 
 | 626 |     if (!seclabel_.empty()) { | 
 | 627 |         scon = seclabel_; | 
 | 628 |     } else { | 
| Tom Cherry | aead51b | 2018-04-20 16:18:12 -0700 | [diff] [blame] | 629 |         auto result = ComputeContextFromExecutable(args_[0]); | 
| Bernie Innocenti | cecebbb | 2020-02-06 03:49:33 +0900 | [diff] [blame] | 630 |         if (!result.ok()) { | 
| Tom Cherry | 76af7e6 | 2017-08-22 16:13:59 -0700 | [diff] [blame] | 631 |             return result.error(); | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 632 |         } | 
| Tom Cherry | 76af7e6 | 2017-08-22 16:13:59 -0700 | [diff] [blame] | 633 |         scon = *result; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 634 |     } | 
 | 635 |  | 
| Jooyung Han | c5fa15e | 2022-07-14 11:23:59 +0900 | [diff] [blame] | 636 |     if (!mount_namespace_.has_value()) { | 
 | 637 |         // remember from which mount namespace the service should start | 
 | 638 |         SetMountNamespace(); | 
| Jooyung Han | 4f23d5a | 2020-06-09 13:44:17 +0900 | [diff] [blame] | 639 |     } | 
 | 640 |  | 
| Martijn Coenen | 70788f9 | 2019-04-23 16:26:01 +0200 | [diff] [blame] | 641 |     post_data_ = ServiceList::GetInstance().IsPostData(); | 
 | 642 |  | 
| Wei Wang | a285dac | 2016-10-04 14:05:39 -0700 | [diff] [blame] | 643 |     LOG(INFO) << "starting service '" << name_ << "'..."; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 644 |  | 
| Tom Cherry | 5241d10 | 2019-09-10 14:20:35 -0700 | [diff] [blame] | 645 |     std::vector<Descriptor> descriptors; | 
 | 646 |     for (const auto& socket : sockets_) { | 
| Bernie Innocenti | cecebbb | 2020-02-06 03:49:33 +0900 | [diff] [blame] | 647 |         if (auto result = socket.Create(scon); result.ok()) { | 
| Tom Cherry | 5241d10 | 2019-09-10 14:20:35 -0700 | [diff] [blame] | 648 |             descriptors.emplace_back(std::move(*result)); | 
 | 649 |         } else { | 
 | 650 |             LOG(INFO) << "Could not create socket '" << socket.name << "': " << result.error(); | 
 | 651 |         } | 
 | 652 |     } | 
 | 653 |  | 
 | 654 |     for (const auto& file : files_) { | 
| Bernie Innocenti | cecebbb | 2020-02-06 03:49:33 +0900 | [diff] [blame] | 655 |         if (auto result = file.Create(); result.ok()) { | 
| Tom Cherry | 5241d10 | 2019-09-10 14:20:35 -0700 | [diff] [blame] | 656 |             descriptors.emplace_back(std::move(*result)); | 
 | 657 |         } else { | 
 | 658 |             LOG(INFO) << "Could not open file '" << file.name << "': " << result.error(); | 
 | 659 |         } | 
 | 660 |     } | 
 | 661 |  | 
| Jorge Lucangeli Obes | 1b3fa3d | 2016-04-21 15:35:09 -0700 | [diff] [blame] | 662 |     pid_t pid = -1; | 
| Vic Yang | e01ca4d | 2019-05-29 15:58:32 -0700 | [diff] [blame] | 663 |     if (namespaces_.flags) { | 
 | 664 |         pid = clone(nullptr, nullptr, namespaces_.flags | SIGCHLD, nullptr); | 
| Jorge Lucangeli Obes | 1b3fa3d | 2016-04-21 15:35:09 -0700 | [diff] [blame] | 665 |     } else { | 
 | 666 |         pid = fork(); | 
 | 667 |     } | 
 | 668 |  | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 669 |     if (pid == 0) { | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 670 |         umask(077); | 
| Bart Van Assche | 4178723 | 2022-11-14 16:45:42 -0800 | [diff] [blame] | 671 |         cgroups_activated.CloseWriteFd(); | 
| Bart Van Assche | 01e6669 | 2022-11-14 16:45:47 -0800 | [diff] [blame] | 672 |         setsid_finished.CloseReadFd(); | 
 | 673 |         RunService(descriptors, std::move(cgroups_activated), std::move(setsid_finished)); | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 674 |         _exit(127); | 
| Bart Van Assche | f26e59e | 2022-11-15 00:24:39 +0000 | [diff] [blame] | 675 |     } else { | 
| Bart Van Assche | 4178723 | 2022-11-14 16:45:42 -0800 | [diff] [blame] | 676 |         cgroups_activated.CloseReadFd(); | 
| Bart Van Assche | 01e6669 | 2022-11-14 16:45:47 -0800 | [diff] [blame] | 677 |         setsid_finished.CloseWriteFd(); | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 678 |     } | 
 | 679 |  | 
 | 680 |     if (pid < 0) { | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 681 |         pid_ = 0; | 
| Tom Cherry | 76af7e6 | 2017-08-22 16:13:59 -0700 | [diff] [blame] | 682 |         return ErrnoError() << "Failed to fork"; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 683 |     } | 
 | 684 |  | 
| Florian Mayer | 2ef47f8 | 2022-05-10 17:55:08 -0700 | [diff] [blame] | 685 |     once_environment_vars_.clear(); | 
 | 686 |  | 
| Suren Baghdasaryan | c29c2ba | 2019-10-22 17:18:42 -0700 | [diff] [blame] | 687 |     if (oom_score_adjust_ != DEFAULT_OOM_SCORE_ADJUST) { | 
| Tom Cherry | 1c3a53f | 2017-06-22 16:50:31 -0700 | [diff] [blame] | 688 |         std::string oom_str = std::to_string(oom_score_adjust_); | 
| Marco Nelissen | 310f670 | 2016-07-22 12:07:06 -0700 | [diff] [blame] | 689 |         std::string oom_file = StringPrintf("/proc/%d/oom_score_adj", pid); | 
 | 690 |         if (!WriteStringToFile(oom_str, oom_file)) { | 
| Elliott Hughes | 076305e | 2019-03-08 12:34:53 -0800 | [diff] [blame] | 691 |             PLOG(ERROR) << "couldn't write oom_score_adj"; | 
| Marco Nelissen | 310f670 | 2016-07-22 12:07:06 -0700 | [diff] [blame] | 692 |         } | 
 | 693 |     } | 
 | 694 |  | 
| Elliott Hughes | 9605a94 | 2016-11-10 17:43:47 -0800 | [diff] [blame] | 695 |     time_started_ = boot_clock::now(); | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 696 |     pid_ = pid; | 
 | 697 |     flags_ |= SVC_RUNNING; | 
| Tom Cherry | 5938379 | 2017-07-26 16:09:09 -0700 | [diff] [blame] | 698 |     start_order_ = next_start_order_++; | 
| Tom Cherry | 33838b1 | 2017-05-04 11:32:36 -0700 | [diff] [blame] | 699 |     process_cgroup_empty_ = false; | 
| Elliott Hughes | ad8e94e | 2016-06-15 14:49:57 -0700 | [diff] [blame] | 700 |  | 
| Nikita Ioffe | c2b1654 | 2022-10-20 14:14:39 +0100 | [diff] [blame] | 701 |     if (CgroupsAvailable()) { | 
 | 702 |         bool use_memcg = swappiness_ != -1 || soft_limit_in_bytes_ != -1 || limit_in_bytes_ != -1 || | 
 | 703 |                          limit_percent_ != -1 || !limit_property_.empty(); | 
| Steven Moreland | f5d22ef | 2023-04-03 23:29:22 +0000 | [diff] [blame] | 704 |         errno = -createProcessGroup(uid(), pid_, use_memcg); | 
| Nikita Ioffe | c2b1654 | 2022-10-20 14:14:39 +0100 | [diff] [blame] | 705 |         if (errno != 0) { | 
| Bart Van Assche | c8f3425 | 2022-11-18 09:12:52 -0800 | [diff] [blame] | 706 |             Result<void> result = cgroups_activated.Write(kActivatingCgroupsFailed); | 
| Bart Van Assche | 1693f42 | 2022-10-19 16:30:15 -0700 | [diff] [blame] | 707 |             if (!result.ok()) { | 
 | 708 |                 return Error() << "Sending notification failed: " << result.error(); | 
| Nikita Ioffe | c2b1654 | 2022-10-20 14:14:39 +0100 | [diff] [blame] | 709 |             } | 
| Steven Moreland | f5d22ef | 2023-04-03 23:29:22 +0000 | [diff] [blame] | 710 |             return Error() << "createProcessGroup(" << uid() << ", " << pid_ << ", " << use_memcg | 
 | 711 |                            << ") failed for service '" << name_ << "': " << strerror(errno); | 
| Suren Baghdasaryan | 1bd1746 | 2022-03-31 21:18:20 -0700 | [diff] [blame] | 712 |         } | 
| Suren Baghdasaryan | 1bd1746 | 2022-03-31 21:18:20 -0700 | [diff] [blame] | 713 |  | 
| Nikita Ioffe | c2b1654 | 2022-10-20 14:14:39 +0100 | [diff] [blame] | 714 |         // When the blkio controller is mounted in the v1 hierarchy, NormalIoPriority is | 
 | 715 |         // the default (/dev/blkio). When the blkio controller is mounted in the v2 hierarchy, the | 
 | 716 |         // NormalIoPriority profile has to be applied explicitly. | 
| Steven Moreland | f5d22ef | 2023-04-03 23:29:22 +0000 | [diff] [blame] | 717 |         SetProcessProfiles(uid(), pid_, {"NormalIoPriority"}); | 
| Bart Van Assche | fcf0471 | 2022-08-01 16:09:13 -0700 | [diff] [blame] | 718 |  | 
| Nikita Ioffe | c2b1654 | 2022-10-20 14:14:39 +0100 | [diff] [blame] | 719 |         if (use_memcg) { | 
 | 720 |             ConfigureMemcg(); | 
 | 721 |         } | 
| Elliott Hughes | ad8e94e | 2016-06-15 14:49:57 -0700 | [diff] [blame] | 722 |     } | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 723 |  | 
| Suren Baghdasaryan | c29c2ba | 2019-10-22 17:18:42 -0700 | [diff] [blame] | 724 |     if (oom_score_adjust_ != DEFAULT_OOM_SCORE_ADJUST) { | 
| Steven Moreland | f5d22ef | 2023-04-03 23:29:22 +0000 | [diff] [blame] | 725 |         LmkdRegister(name_, uid(), pid_, oom_score_adjust_); | 
| Suren Baghdasaryan | c29c2ba | 2019-10-22 17:18:42 -0700 | [diff] [blame] | 726 |     } | 
 | 727 |  | 
| Bart Van Assche | c8f3425 | 2022-11-18 09:12:52 -0800 | [diff] [blame] | 728 |     if (Result<void> result = cgroups_activated.Write(kCgroupsActivated); !result.ok()) { | 
| Bart Van Assche | 1693f42 | 2022-10-19 16:30:15 -0700 | [diff] [blame] | 729 |         return Error() << "Sending cgroups activated notification failed: " << result.error(); | 
| Bart Van Assche | ee36ba3 | 2022-01-26 20:52:52 +0000 | [diff] [blame] | 730 |     } | 
 | 731 |  | 
| Bart Van Assche | 01e6669 | 2022-11-14 16:45:47 -0800 | [diff] [blame] | 732 |     cgroups_activated.Close(); | 
 | 733 |  | 
 | 734 |     // Call setpgid() from the parent process to make sure that this call has | 
 | 735 |     // finished before the parent process calls kill(-pgid, ...). | 
 | 736 |     if (!RequiresConsole(proc_attr_)) { | 
 | 737 |         if (setpgid(pid, pid) < 0) { | 
 | 738 |             switch (errno) { | 
 | 739 |                 case EACCES:  // Child has already performed setpgid() followed by execve(). | 
 | 740 |                 case ESRCH:   // Child process no longer exists. | 
 | 741 |                     break; | 
 | 742 |                 default: | 
 | 743 |                     PLOG(ERROR) << "setpgid() from parent failed"; | 
 | 744 |             } | 
 | 745 |         } | 
 | 746 |     } else { | 
 | 747 |         // The Read() call below will return an error if the child is killed. | 
 | 748 |         if (Result<uint8_t> result = setsid_finished.Read(); | 
 | 749 |             !result.ok() || *result != kSetSidFinished) { | 
 | 750 |             if (!result.ok()) { | 
 | 751 |                 return Error() << "Waiting for setsid() failed: " << result.error(); | 
 | 752 |             } else { | 
 | 753 |                 return Error() << "Waiting for setsid() failed: " << static_cast<uint32_t>(*result) | 
 | 754 |                                << " <> " << static_cast<uint32_t>(kSetSidFinished); | 
 | 755 |             } | 
 | 756 |         } | 
 | 757 |     } | 
 | 758 |  | 
 | 759 |     setsid_finished.Close(); | 
 | 760 |  | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 761 |     NotifyStateChange("running"); | 
| Tom Cherry | 60971e6 | 2019-09-10 10:40:47 -0700 | [diff] [blame] | 762 |     reboot_on_failure.Disable(); | 
| Steven Moreland | 8e25d9c | 2023-02-28 01:42:08 +0000 | [diff] [blame] | 763 |  | 
 | 764 |     LOG(INFO) << "... started service '" << name_ << "' has pid " << pid_; | 
 | 765 |  | 
| Tom Cherry | bbcbc2f | 2019-06-10 11:08:01 -0700 | [diff] [blame] | 766 |     return {}; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 767 | } | 
 | 768 |  | 
| Jooyung Han | c5fa15e | 2022-07-14 11:23:59 +0900 | [diff] [blame] | 769 | // Set mount namespace for the service. | 
 | 770 | // The reason why remember the mount namespace: | 
 | 771 | //   If this service is started before APEXes and corresponding linker configuration | 
 | 772 | //   get available, mark it as pre-apexd one. Note that this marking is | 
 | 773 | //   permanent. So for example, if the service is re-launched (e.g., due | 
 | 774 | //   to crash), it is still recognized as pre-apexd... for consistency. | 
 | 775 | void Service::SetMountNamespace() { | 
 | 776 |     // APEXd is always started in the "current" namespace because it is the process to set up | 
 | 777 |     // the current namespace. So, leave mount_namespace_ as empty. | 
 | 778 |     if (args_[0] == "/system/bin/apexd") { | 
 | 779 |         return; | 
 | 780 |     } | 
 | 781 |     // Services in the following list start in the "default" mount namespace. | 
 | 782 |     // Note that they should use bootstrap bionic if they start before APEXes are ready. | 
 | 783 |     static const std::set<std::string> kUseDefaultMountNamespace = { | 
 | 784 |             "ueventd",           // load firmwares from APEXes | 
 | 785 |             "hwservicemanager",  // load VINTF fragments from APEXes | 
 | 786 |             "servicemanager",    // load VINTF fragments from APEXes | 
 | 787 |     }; | 
 | 788 |     if (kUseDefaultMountNamespace.find(name_) != kUseDefaultMountNamespace.end()) { | 
 | 789 |         mount_namespace_ = NS_DEFAULT; | 
 | 790 |         return; | 
 | 791 |     } | 
 | 792 |     // Use the "default" mount namespace only if it's ready | 
 | 793 |     mount_namespace_ = IsDefaultMountNamespaceReady() ? NS_DEFAULT : NS_BOOTSTRAP; | 
 | 794 | } | 
 | 795 |  | 
| Bart Van Assche | 97047b5 | 2023-11-16 12:42:35 -0800 | [diff] [blame] | 796 | static int ThreadCount() { | 
 | 797 |     std::unique_ptr<DIR, decltype(&closedir)> dir(opendir("/proc/self/task"), closedir); | 
 | 798 |     if (!dir) { | 
 | 799 |         return -1; | 
 | 800 |     } | 
 | 801 |  | 
 | 802 |     int count = 0; | 
 | 803 |     dirent* entry; | 
 | 804 |     while ((entry = readdir(dir.get())) != nullptr) { | 
 | 805 |         if (entry->d_name[0] != '.') { | 
 | 806 |             count++; | 
 | 807 |         } | 
 | 808 |     } | 
 | 809 |     return count; | 
 | 810 | } | 
 | 811 |  | 
 | 812 | // Must be called BEFORE any threads are created. See also the sigprocmask() man page. | 
 | 813 | unique_fd Service::CreateSigchldFd() { | 
 | 814 |     CHECK_EQ(ThreadCount(), 1); | 
 | 815 |     sigset_t mask; | 
 | 816 |     sigemptyset(&mask); | 
 | 817 |     sigaddset(&mask, SIGCHLD); | 
 | 818 |     if (sigprocmask(SIG_BLOCK, &mask, nullptr) < 0) { | 
 | 819 |         PLOG(FATAL) << "Failed to block SIGCHLD"; | 
 | 820 |     } | 
 | 821 |  | 
 | 822 |     return unique_fd(signalfd(-1, &mask, SFD_CLOEXEC)); | 
 | 823 | } | 
 | 824 |  | 
| David Anderson | 0e5ad5a | 2021-07-21 21:53:28 -0700 | [diff] [blame] | 825 | void Service::SetStartedInFirstStage(pid_t pid) { | 
 | 826 |     LOG(INFO) << "adding first-stage service '" << name_ << "'..."; | 
 | 827 |  | 
 | 828 |     time_started_ = boot_clock::now();  // not accurate, but doesn't matter here | 
 | 829 |     pid_ = pid; | 
 | 830 |     flags_ |= SVC_RUNNING; | 
 | 831 |     start_order_ = next_start_order_++; | 
 | 832 |  | 
 | 833 |     NotifyStateChange("running"); | 
 | 834 | } | 
 | 835 |  | 
 | 836 | void Service::ResetFlagsForStart() { | 
 | 837 |     // Starting a service removes it from the disabled or reset state and | 
 | 838 |     // immediately takes it out of the restarting state if it was in there. | 
 | 839 |     flags_ &= ~(SVC_DISABLED | SVC_RESTARTING | SVC_RESET | SVC_RESTART | SVC_DISABLED_START); | 
 | 840 | } | 
 | 841 |  | 
| Tom Cherry | bbcbc2f | 2019-06-10 11:08:01 -0700 | [diff] [blame] | 842 | Result<void> Service::StartIfNotDisabled() { | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 843 |     if (!(flags_ & SVC_DISABLED)) { | 
 | 844 |         return Start(); | 
 | 845 |     } else { | 
 | 846 |         flags_ |= SVC_DISABLED_START; | 
 | 847 |     } | 
| Tom Cherry | bbcbc2f | 2019-06-10 11:08:01 -0700 | [diff] [blame] | 848 |     return {}; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 849 | } | 
 | 850 |  | 
| Tom Cherry | bbcbc2f | 2019-06-10 11:08:01 -0700 | [diff] [blame] | 851 | Result<void> Service::Enable() { | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 852 |     flags_ &= ~(SVC_DISABLED | SVC_RC_DISABLED); | 
 | 853 |     if (flags_ & SVC_DISABLED_START) { | 
 | 854 |         return Start(); | 
 | 855 |     } | 
| Tom Cherry | bbcbc2f | 2019-06-10 11:08:01 -0700 | [diff] [blame] | 856 |     return {}; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 857 | } | 
 | 858 |  | 
 | 859 | void Service::Reset() { | 
 | 860 |     StopOrReset(SVC_RESET); | 
 | 861 | } | 
 | 862 |  | 
 | 863 | void Service::Stop() { | 
 | 864 |     StopOrReset(SVC_DISABLED); | 
 | 865 | } | 
 | 866 |  | 
| Bertrand SIMONNET | b7e03e8 | 2015-12-18 11:39:59 -0800 | [diff] [blame] | 867 | void Service::Terminate() { | 
 | 868 |     flags_ &= ~(SVC_RESTARTING | SVC_DISABLED_START); | 
 | 869 |     flags_ |= SVC_DISABLED; | 
 | 870 |     if (pid_) { | 
| Elliott Hughes | ad8e94e | 2016-06-15 14:49:57 -0700 | [diff] [blame] | 871 |         KillProcessGroup(SIGTERM); | 
| Bertrand SIMONNET | b7e03e8 | 2015-12-18 11:39:59 -0800 | [diff] [blame] | 872 |         NotifyStateChange("stopping"); | 
 | 873 |     } | 
 | 874 | } | 
 | 875 |  | 
| Tom Cherry | 73f535e | 2018-09-27 16:10:46 -0700 | [diff] [blame] | 876 | void Service::Timeout() { | 
 | 877 |     // All process state flags will be taken care of in Reap(), we really just want to kill the | 
 | 878 |     // process here when it times out.  Oneshot processes will transition to be disabled, and | 
 | 879 |     // all other processes will transition to be restarting. | 
 | 880 |     LOG(INFO) << "Service '" << name_ << "' expired its timeout of " << timeout_period_->count() | 
 | 881 |               << " seconds and will now be killed"; | 
 | 882 |     if (pid_) { | 
 | 883 |         KillProcessGroup(SIGKILL); | 
 | 884 |         NotifyStateChange("stopping"); | 
 | 885 |     } | 
 | 886 | } | 
 | 887 |  | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 888 | void Service::Restart() { | 
 | 889 |     if (flags_ & SVC_RUNNING) { | 
 | 890 |         /* Stop, wait, then start the service. */ | 
 | 891 |         StopOrReset(SVC_RESTART); | 
 | 892 |     } else if (!(flags_ & SVC_RESTARTING)) { | 
 | 893 |         /* Just start the service since it's not running. */ | 
| Bernie Innocenti | cecebbb | 2020-02-06 03:49:33 +0900 | [diff] [blame] | 894 |         if (auto result = Start(); !result.ok()) { | 
| Tom Cherry | 76af7e6 | 2017-08-22 16:13:59 -0700 | [diff] [blame] | 895 |             LOG(ERROR) << "Could not restart '" << name_ << "': " << result.error(); | 
 | 896 |         } | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 897 |     } /* else: Service is restarting anyways. */ | 
 | 898 | } | 
 | 899 |  | 
| Elliott Hughes | ad8e94e | 2016-06-15 14:49:57 -0700 | [diff] [blame] | 900 | // The how field should be either SVC_DISABLED, SVC_RESET, or SVC_RESTART. | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 901 | void Service::StopOrReset(int how) { | 
| Elliott Hughes | ad8e94e | 2016-06-15 14:49:57 -0700 | [diff] [blame] | 902 |     // The service is still SVC_RUNNING until its process exits, but if it has | 
 | 903 |     // already exited it shoudn't attempt a restart yet. | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 904 |     flags_ &= ~(SVC_RESTARTING | SVC_DISABLED_START); | 
 | 905 |  | 
 | 906 |     if ((how != SVC_DISABLED) && (how != SVC_RESET) && (how != SVC_RESTART)) { | 
| Elliott Hughes | ad8e94e | 2016-06-15 14:49:57 -0700 | [diff] [blame] | 907 |         // An illegal flag: default to SVC_DISABLED. | 
| Steven Moreland | 507209b | 2022-12-07 20:55:35 +0000 | [diff] [blame] | 908 |         LOG(ERROR) << "service '" << name_ << "' requested unknown flag " << how | 
 | 909 |                    << ", defaulting to disabling it."; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 910 |         how = SVC_DISABLED; | 
 | 911 |     } | 
| Elliott Hughes | ad8e94e | 2016-06-15 14:49:57 -0700 | [diff] [blame] | 912 |  | 
 | 913 |     // If the service has not yet started, prevent it from auto-starting with its class. | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 914 |     if (how == SVC_RESET) { | 
 | 915 |         flags_ |= (flags_ & SVC_RC_DISABLED) ? SVC_DISABLED : SVC_RESET; | 
 | 916 |     } else { | 
 | 917 |         flags_ |= how; | 
 | 918 |     } | 
| Tao Wu | 84b856d | 2017-10-27 11:29:13 -0700 | [diff] [blame] | 919 |     // Make sure it's in right status when a restart immediately follow a | 
 | 920 |     // stop/reset or vice versa. | 
 | 921 |     if (how == SVC_RESTART) { | 
 | 922 |         flags_ &= (~(SVC_DISABLED | SVC_RESET)); | 
 | 923 |     } else { | 
 | 924 |         flags_ &= (~SVC_RESTART); | 
 | 925 |     } | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 926 |  | 
 | 927 |     if (pid_) { | 
| Daniel Rosenberg | de76688 | 2022-12-01 15:44:31 -0800 | [diff] [blame] | 928 |         if (flags_ & SVC_GENTLE_KILL) { | 
 | 929 |             KillProcessGroup(SIGTERM); | 
 | 930 |             if (!process_cgroup_empty()) std::this_thread::sleep_for(200ms); | 
 | 931 |         } | 
| Elliott Hughes | ad8e94e | 2016-06-15 14:49:57 -0700 | [diff] [blame] | 932 |         KillProcessGroup(SIGKILL); | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 933 |         NotifyStateChange("stopping"); | 
 | 934 |     } else { | 
 | 935 |         NotifyStateChange("stopped"); | 
 | 936 |     } | 
 | 937 | } | 
 | 938 |  | 
| Tom Cherry | 4772f1d | 2019-07-30 09:34:41 -0700 | [diff] [blame] | 939 | Result<std::unique_ptr<Service>> Service::MakeTemporaryOneshotService( | 
 | 940 |         const std::vector<std::string>& args) { | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 941 |     // Parse the arguments: exec [SECLABEL [UID [GID]*] --] COMMAND ARGS... | 
 | 942 |     // SECLABEL can be a - to denote default | 
 | 943 |     std::size_t command_arg = 1; | 
 | 944 |     for (std::size_t i = 1; i < args.size(); ++i) { | 
 | 945 |         if (args[i] == "--") { | 
 | 946 |             command_arg = i + 1; | 
 | 947 |             break; | 
 | 948 |         } | 
 | 949 |     } | 
 | 950 |     if (command_arg > 4 + NR_SVC_SUPP_GIDS) { | 
| Tom Cherry | 4772f1d | 2019-07-30 09:34:41 -0700 | [diff] [blame] | 951 |         return Error() << "exec called with too many supplementary group ids"; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 952 |     } | 
 | 953 |  | 
 | 954 |     if (command_arg >= args.size()) { | 
| Tom Cherry | 4772f1d | 2019-07-30 09:34:41 -0700 | [diff] [blame] | 955 |         return Error() << "exec called without command"; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 956 |     } | 
 | 957 |     std::vector<std::string> str_args(args.begin() + command_arg, args.end()); | 
 | 958 |  | 
| Tom Cherry | 3b81f2d | 2017-07-28 14:48:41 -0700 | [diff] [blame] | 959 |     static size_t exec_count = 0; | 
 | 960 |     exec_count++; | 
 | 961 |     std::string name = "exec " + std::to_string(exec_count) + " (" + Join(str_args, " ") + ")"; | 
| Tom Cherry | 86e31a8 | 2017-04-25 17:31:06 -0700 | [diff] [blame] | 962 |  | 
| Tom Cherry | 3b81f2d | 2017-07-28 14:48:41 -0700 | [diff] [blame] | 963 |     unsigned flags = SVC_ONESHOT | SVC_TEMPORARY; | 
| Jorge Lucangeli Obes | 1b3fa3d | 2016-04-21 15:35:09 -0700 | [diff] [blame] | 964 |     unsigned namespace_flags = 0; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 965 |  | 
 | 966 |     std::string seclabel = ""; | 
 | 967 |     if (command_arg > 2 && args[1] != "-") { | 
 | 968 |         seclabel = args[1]; | 
 | 969 |     } | 
| Tom Cherry | 11a3aee | 2017-08-03 12:54:07 -0700 | [diff] [blame] | 970 |     Result<uid_t> uid = 0; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 971 |     if (command_arg > 3) { | 
| Tom Cherry | 11a3aee | 2017-08-03 12:54:07 -0700 | [diff] [blame] | 972 |         uid = DecodeUid(args[2]); | 
| Bernie Innocenti | cecebbb | 2020-02-06 03:49:33 +0900 | [diff] [blame] | 973 |         if (!uid.ok()) { | 
| Tom Cherry | 4772f1d | 2019-07-30 09:34:41 -0700 | [diff] [blame] | 974 |             return Error() << "Unable to decode UID for '" << args[2] << "': " << uid.error(); | 
| Tom Cherry | 517e1f1 | 2017-05-04 17:40:33 -0700 | [diff] [blame] | 975 |         } | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 976 |     } | 
| Tom Cherry | 11a3aee | 2017-08-03 12:54:07 -0700 | [diff] [blame] | 977 |     Result<gid_t> gid = 0; | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 978 |     std::vector<gid_t> supp_gids; | 
 | 979 |     if (command_arg > 4) { | 
| Tom Cherry | 11a3aee | 2017-08-03 12:54:07 -0700 | [diff] [blame] | 980 |         gid = DecodeUid(args[3]); | 
| Bernie Innocenti | cecebbb | 2020-02-06 03:49:33 +0900 | [diff] [blame] | 981 |         if (!gid.ok()) { | 
| Tom Cherry | 4772f1d | 2019-07-30 09:34:41 -0700 | [diff] [blame] | 982 |             return Error() << "Unable to decode GID for '" << args[3] << "': " << gid.error(); | 
| Tom Cherry | 517e1f1 | 2017-05-04 17:40:33 -0700 | [diff] [blame] | 983 |         } | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 984 |         std::size_t nr_supp_gids = command_arg - 1 /* -- */ - 4 /* exec SECLABEL UID GID */; | 
 | 985 |         for (size_t i = 0; i < nr_supp_gids; ++i) { | 
| Tom Cherry | 11a3aee | 2017-08-03 12:54:07 -0700 | [diff] [blame] | 986 |             auto supp_gid = DecodeUid(args[4 + i]); | 
| Bernie Innocenti | cecebbb | 2020-02-06 03:49:33 +0900 | [diff] [blame] | 987 |             if (!supp_gid.ok()) { | 
| Tom Cherry | 4772f1d | 2019-07-30 09:34:41 -0700 | [diff] [blame] | 988 |                 return Error() << "Unable to decode GID for '" << args[4 + i] | 
 | 989 |                                << "': " << supp_gid.error(); | 
| Tom Cherry | 517e1f1 | 2017-05-04 17:40:33 -0700 | [diff] [blame] | 990 |             } | 
| Tom Cherry | 11a3aee | 2017-08-03 12:54:07 -0700 | [diff] [blame] | 991 |             supp_gids.push_back(*supp_gid); | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 992 |         } | 
 | 993 |     } | 
 | 994 |  | 
| Tom Cherry | 1cd082d | 2019-02-06 10:45:56 -0800 | [diff] [blame] | 995 |     return std::make_unique<Service>(name, flags, *uid, *gid, supp_gids, namespace_flags, seclabel, | 
| Deyao Ren | df40ed1 | 2022-07-14 22:51:10 +0000 | [diff] [blame] | 996 |                                      nullptr, /*filename=*/"", str_args); | 
| Tom Cherry | bac3299 | 2015-07-31 12:45:25 -0700 | [diff] [blame] | 997 | } | 
 | 998 |  | 
| David Anderson | 0e5ad5a | 2021-07-21 21:53:28 -0700 | [diff] [blame] | 999 | // This is used for snapuserd_proxy, which hands off a socket to snapuserd. It's | 
 | 1000 | // a special case to support the daemon launched in first-stage init. The persist | 
 | 1001 | // feature is not part of the init language and is only used here. | 
 | 1002 | bool Service::MarkSocketPersistent(const std::string& socket_name) { | 
 | 1003 |     for (auto& socket : sockets_) { | 
 | 1004 |         if (socket.name == socket_name) { | 
 | 1005 |             socket.persist = true; | 
 | 1006 |             return true; | 
 | 1007 |         } | 
 | 1008 |     } | 
 | 1009 |     return false; | 
 | 1010 | } | 
 | 1011 |  | 
| Tom Cherry | 81f5d3e | 2017-06-22 12:53:17 -0700 | [diff] [blame] | 1012 | }  // namespace init | 
 | 1013 | }  // namespace android |