Loading init/README.md +9 −0 Original line number Original line Diff line number Diff line Loading @@ -170,6 +170,8 @@ runs the service. be changed by setting the "androidboot.console" kernel parameter. In be changed by setting the "androidboot.console" kernel parameter. In all cases the leading "/dev/" should be omitted, so "/dev/tty0" would be all cases the leading "/dev/" should be omitted, so "/dev/tty0" would be specified as just "console tty0". specified as just "console tty0". This option connects stdin, stdout, and stderr to the console. It is mutually exclusive with the stdio_to_kmsg option, which only connects stdout and stderr to kmsg. `critical` `critical` > This is a device-critical service. If it exits more than four times in > This is a device-critical service. If it exits more than four times in Loading Loading @@ -313,6 +315,13 @@ runs the service. seclabel or computed based on the service executable file security context. seclabel or computed based on the service executable file security context. For native executables see libcutils android\_get\_control\_socket(). For native executables see libcutils android\_get\_control\_socket(). `stdio_to_kmsg` > Redirect stdout and stderr to /dev/kmsg_debug. This is useful for services that do not use native Android logging during early boot and whose logs messages we want to capture. This is only enabled when /dev/kmsg_debug is enabled, which is only enabled on userdebug and eng builds. This is mutually exclusive with the console option, which additionally connects stdin to the given console. `timeout_period <seconds>` `timeout_period <seconds>` > Provide a timeout after which point the service will be killed. The oneshot keyword is respected > Provide a timeout after which point the service will be killed. The oneshot keyword is respected here, so oneshot services do not automatically restart, however all other services will. here, so oneshot services do not automatically restart, however all other services will. Loading init/service_parser.cpp +12 −0 Original line number Original line Diff line number Diff line Loading @@ -83,6 +83,9 @@ Result<void> ServiceParser::ParseClass(std::vector<std::string>&& args) { } } Result<void> ServiceParser::ParseConsole(std::vector<std::string>&& args) { Result<void> ServiceParser::ParseConsole(std::vector<std::string>&& args) { if (service_->proc_attr_.stdio_to_kmsg) { return Error() << "'console' and 'stdio_to_kmsg' are mutually exclusive"; } service_->flags_ |= SVC_CONSOLE; service_->flags_ |= SVC_CONSOLE; service_->proc_attr_.console = args.size() > 1 ? "/dev/" + args[1] : ""; service_->proc_attr_.console = args.size() > 1 ? "/dev/" + args[1] : ""; return {}; return {}; Loading Loading @@ -429,6 +432,14 @@ Result<void> ServiceParser::ParseSocket(std::vector<std::string>&& args) { return {}; return {}; } } Result<void> ServiceParser::ParseStdioToKmsg(std::vector<std::string>&& args) { if (service_->flags_ & SVC_CONSOLE) { return Error() << "'stdio_to_kmsg' and 'console' are mutually exclusive"; } service_->proc_attr_.stdio_to_kmsg = true; return {}; } // name type // name type Result<void> ServiceParser::ParseFile(std::vector<std::string>&& args) { Result<void> ServiceParser::ParseFile(std::vector<std::string>&& args) { if (args[2] != "r" && args[2] != "w" && args[2] != "rw") { if (args[2] != "r" && args[2] != "w" && args[2] != "rw") { Loading Loading @@ -514,6 +525,7 @@ const KeywordMap<ServiceParser::OptionParser>& ServiceParser::GetParserMap() con {"shutdown", {1, 1, &ServiceParser::ParseShutdown}}, {"shutdown", {1, 1, &ServiceParser::ParseShutdown}}, {"sigstop", {0, 0, &ServiceParser::ParseSigstop}}, {"sigstop", {0, 0, &ServiceParser::ParseSigstop}}, {"socket", {3, 6, &ServiceParser::ParseSocket}}, {"socket", {3, 6, &ServiceParser::ParseSocket}}, {"stdio_to_kmsg", {0, 0, &ServiceParser::ParseStdioToKmsg}}, {"timeout_period", {1, 1, &ServiceParser::ParseTimeoutPeriod}}, {"timeout_period", {1, 1, &ServiceParser::ParseTimeoutPeriod}}, {"updatable", {0, 0, &ServiceParser::ParseUpdatable}}, {"updatable", {0, 0, &ServiceParser::ParseUpdatable}}, {"user", {1, 1, &ServiceParser::ParseUser}}, {"user", {1, 1, &ServiceParser::ParseUser}}, Loading init/service_parser.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -75,6 +75,7 @@ class ServiceParser : public SectionParser { Result<void> ParseShutdown(std::vector<std::string>&& args); Result<void> ParseShutdown(std::vector<std::string>&& args); Result<void> ParseSigstop(std::vector<std::string>&& args); Result<void> ParseSigstop(std::vector<std::string>&& args); Result<void> ParseSocket(std::vector<std::string>&& args); Result<void> ParseSocket(std::vector<std::string>&& args); Result<void> ParseStdioToKmsg(std::vector<std::string>&& args); Result<void> ParseTimeoutPeriod(std::vector<std::string>&& args); Result<void> ParseTimeoutPeriod(std::vector<std::string>&& args); Result<void> ParseFile(std::vector<std::string>&& args); Result<void> ParseFile(std::vector<std::string>&& args); Result<void> ParseUser(std::vector<std::string>&& args); Result<void> ParseUser(std::vector<std::string>&& args); Loading init/service_utils.cpp +11 −5 Original line number Original line Diff line number Diff line Loading @@ -16,10 +16,12 @@ #include "service_utils.h" #include "service_utils.h" #include <fcntl.h> #include <grp.h> #include <grp.h> #include <sys/mount.h> #include <sys/mount.h> #include <sys/prctl.h> #include <sys/prctl.h> #include <sys/wait.h> #include <sys/wait.h> #include <unistd.h> #include <android-base/file.h> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/logging.h> Loading Loading @@ -121,11 +123,15 @@ Result<void> SetUpPidNamespace(const char* name) { return {}; return {}; } } void ZapStdio() { void SetupStdio(bool stdio_to_kmsg) { auto fd = unique_fd{open("/dev/null", O_RDWR | O_CLOEXEC)}; auto fd = unique_fd{open("/dev/null", O_RDWR | O_CLOEXEC)}; dup2(fd, 0); dup2(fd, STDIN_FILENO); dup2(fd, 1); if (stdio_to_kmsg) { dup2(fd, 2); fd.reset(open("/dev/kmsg_debug", O_WRONLY | O_CLOEXEC)); if (fd == -1) fd.reset(open("/dev/null", O_WRONLY | O_CLOEXEC)); } dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); } } void OpenConsole(const std::string& console) { void OpenConsole(const std::string& console) { Loading Loading @@ -238,7 +244,7 @@ Result<void> SetProcessAttributes(const ProcessAttributes& attr) { if (setpgid(0, getpid()) == -1) { if (setpgid(0, getpid()) == -1) { return ErrnoError() << "setpgid failed"; return ErrnoError() << "setpgid failed"; } } ZapStdio(); SetupStdio(attr.stdio_to_kmsg); } } for (const auto& rlimit : attr.rlimits) { for (const auto& rlimit : attr.rlimits) { Loading init/service_utils.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -77,6 +77,7 @@ struct ProcessAttributes { gid_t gid; gid_t gid; std::vector<gid_t> supp_gids; std::vector<gid_t> supp_gids; int priority; int priority; bool stdio_to_kmsg; }; }; Result<void> SetProcessAttributes(const ProcessAttributes& attr); Result<void> SetProcessAttributes(const ProcessAttributes& attr); Loading Loading
init/README.md +9 −0 Original line number Original line Diff line number Diff line Loading @@ -170,6 +170,8 @@ runs the service. be changed by setting the "androidboot.console" kernel parameter. In be changed by setting the "androidboot.console" kernel parameter. In all cases the leading "/dev/" should be omitted, so "/dev/tty0" would be all cases the leading "/dev/" should be omitted, so "/dev/tty0" would be specified as just "console tty0". specified as just "console tty0". This option connects stdin, stdout, and stderr to the console. It is mutually exclusive with the stdio_to_kmsg option, which only connects stdout and stderr to kmsg. `critical` `critical` > This is a device-critical service. If it exits more than four times in > This is a device-critical service. If it exits more than four times in Loading Loading @@ -313,6 +315,13 @@ runs the service. seclabel or computed based on the service executable file security context. seclabel or computed based on the service executable file security context. For native executables see libcutils android\_get\_control\_socket(). For native executables see libcutils android\_get\_control\_socket(). `stdio_to_kmsg` > Redirect stdout and stderr to /dev/kmsg_debug. This is useful for services that do not use native Android logging during early boot and whose logs messages we want to capture. This is only enabled when /dev/kmsg_debug is enabled, which is only enabled on userdebug and eng builds. This is mutually exclusive with the console option, which additionally connects stdin to the given console. `timeout_period <seconds>` `timeout_period <seconds>` > Provide a timeout after which point the service will be killed. The oneshot keyword is respected > Provide a timeout after which point the service will be killed. The oneshot keyword is respected here, so oneshot services do not automatically restart, however all other services will. here, so oneshot services do not automatically restart, however all other services will. Loading
init/service_parser.cpp +12 −0 Original line number Original line Diff line number Diff line Loading @@ -83,6 +83,9 @@ Result<void> ServiceParser::ParseClass(std::vector<std::string>&& args) { } } Result<void> ServiceParser::ParseConsole(std::vector<std::string>&& args) { Result<void> ServiceParser::ParseConsole(std::vector<std::string>&& args) { if (service_->proc_attr_.stdio_to_kmsg) { return Error() << "'console' and 'stdio_to_kmsg' are mutually exclusive"; } service_->flags_ |= SVC_CONSOLE; service_->flags_ |= SVC_CONSOLE; service_->proc_attr_.console = args.size() > 1 ? "/dev/" + args[1] : ""; service_->proc_attr_.console = args.size() > 1 ? "/dev/" + args[1] : ""; return {}; return {}; Loading Loading @@ -429,6 +432,14 @@ Result<void> ServiceParser::ParseSocket(std::vector<std::string>&& args) { return {}; return {}; } } Result<void> ServiceParser::ParseStdioToKmsg(std::vector<std::string>&& args) { if (service_->flags_ & SVC_CONSOLE) { return Error() << "'stdio_to_kmsg' and 'console' are mutually exclusive"; } service_->proc_attr_.stdio_to_kmsg = true; return {}; } // name type // name type Result<void> ServiceParser::ParseFile(std::vector<std::string>&& args) { Result<void> ServiceParser::ParseFile(std::vector<std::string>&& args) { if (args[2] != "r" && args[2] != "w" && args[2] != "rw") { if (args[2] != "r" && args[2] != "w" && args[2] != "rw") { Loading Loading @@ -514,6 +525,7 @@ const KeywordMap<ServiceParser::OptionParser>& ServiceParser::GetParserMap() con {"shutdown", {1, 1, &ServiceParser::ParseShutdown}}, {"shutdown", {1, 1, &ServiceParser::ParseShutdown}}, {"sigstop", {0, 0, &ServiceParser::ParseSigstop}}, {"sigstop", {0, 0, &ServiceParser::ParseSigstop}}, {"socket", {3, 6, &ServiceParser::ParseSocket}}, {"socket", {3, 6, &ServiceParser::ParseSocket}}, {"stdio_to_kmsg", {0, 0, &ServiceParser::ParseStdioToKmsg}}, {"timeout_period", {1, 1, &ServiceParser::ParseTimeoutPeriod}}, {"timeout_period", {1, 1, &ServiceParser::ParseTimeoutPeriod}}, {"updatable", {0, 0, &ServiceParser::ParseUpdatable}}, {"updatable", {0, 0, &ServiceParser::ParseUpdatable}}, {"user", {1, 1, &ServiceParser::ParseUser}}, {"user", {1, 1, &ServiceParser::ParseUser}}, Loading
init/service_parser.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -75,6 +75,7 @@ class ServiceParser : public SectionParser { Result<void> ParseShutdown(std::vector<std::string>&& args); Result<void> ParseShutdown(std::vector<std::string>&& args); Result<void> ParseSigstop(std::vector<std::string>&& args); Result<void> ParseSigstop(std::vector<std::string>&& args); Result<void> ParseSocket(std::vector<std::string>&& args); Result<void> ParseSocket(std::vector<std::string>&& args); Result<void> ParseStdioToKmsg(std::vector<std::string>&& args); Result<void> ParseTimeoutPeriod(std::vector<std::string>&& args); Result<void> ParseTimeoutPeriod(std::vector<std::string>&& args); Result<void> ParseFile(std::vector<std::string>&& args); Result<void> ParseFile(std::vector<std::string>&& args); Result<void> ParseUser(std::vector<std::string>&& args); Result<void> ParseUser(std::vector<std::string>&& args); Loading
init/service_utils.cpp +11 −5 Original line number Original line Diff line number Diff line Loading @@ -16,10 +16,12 @@ #include "service_utils.h" #include "service_utils.h" #include <fcntl.h> #include <grp.h> #include <grp.h> #include <sys/mount.h> #include <sys/mount.h> #include <sys/prctl.h> #include <sys/prctl.h> #include <sys/wait.h> #include <sys/wait.h> #include <unistd.h> #include <android-base/file.h> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/logging.h> Loading Loading @@ -121,11 +123,15 @@ Result<void> SetUpPidNamespace(const char* name) { return {}; return {}; } } void ZapStdio() { void SetupStdio(bool stdio_to_kmsg) { auto fd = unique_fd{open("/dev/null", O_RDWR | O_CLOEXEC)}; auto fd = unique_fd{open("/dev/null", O_RDWR | O_CLOEXEC)}; dup2(fd, 0); dup2(fd, STDIN_FILENO); dup2(fd, 1); if (stdio_to_kmsg) { dup2(fd, 2); fd.reset(open("/dev/kmsg_debug", O_WRONLY | O_CLOEXEC)); if (fd == -1) fd.reset(open("/dev/null", O_WRONLY | O_CLOEXEC)); } dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); } } void OpenConsole(const std::string& console) { void OpenConsole(const std::string& console) { Loading Loading @@ -238,7 +244,7 @@ Result<void> SetProcessAttributes(const ProcessAttributes& attr) { if (setpgid(0, getpid()) == -1) { if (setpgid(0, getpid()) == -1) { return ErrnoError() << "setpgid failed"; return ErrnoError() << "setpgid failed"; } } ZapStdio(); SetupStdio(attr.stdio_to_kmsg); } } for (const auto& rlimit : attr.rlimits) { for (const auto& rlimit : attr.rlimits) { Loading
init/service_utils.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -77,6 +77,7 @@ struct ProcessAttributes { gid_t gid; gid_t gid; std::vector<gid_t> supp_gids; std::vector<gid_t> supp_gids; int priority; int priority; bool stdio_to_kmsg; }; }; Result<void> SetProcessAttributes(const ProcessAttributes& attr); Result<void> SetProcessAttributes(const ProcessAttributes& attr); Loading