summaryrefslogtreecommitdiff
path: root/init
diff options
context:
space:
mode:
Diffstat (limited to 'init')
-rw-r--r--init/README.md7
-rw-r--r--init/devices.cpp6
-rw-r--r--init/property_service.cpp3
-rw-r--r--init/reboot.cpp6
-rw-r--r--init/reboot_utils.cpp9
-rw-r--r--init/reboot_utils.h3
-rw-r--r--init/service_parser.cpp9
-rw-r--r--init/service_utils.cpp3
-rw-r--r--init/service_utils.h1
-rw-r--r--init/util.cpp7
-rw-r--r--init/util.h4
11 files changed, 38 insertions, 20 deletions
diff --git a/init/README.md b/init/README.md
index 13c6ebdfa..aaafe7887 100644
--- a/init/README.md
+++ b/init/README.md
@@ -352,9 +352,10 @@ runs the service.
`socket <name> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ]`
> Create a UNIX domain socket named /dev/socket/_name_ and pass its fd to the
- launched process. _type_ must be "dgram", "stream" or "seqpacket". _type_
- may end with "+passcred" to enable SO_PASSCRED on the socket. User and
- group default to 0. 'seclabel' is the SELinux security context for the
+ launched process. The socket is created synchronously when the service starts.
+ _type_ must be "dgram", "stream" or "seqpacket". _type_ may end with "+passcred"
+ to enable SO_PASSCRED on the socket or "+listen" to synchronously make it a listening socket.
+ User and group default to 0. 'seclabel' is the SELinux security context for the
socket. It defaults to the service security context, as specified by
seclabel or computed based on the service executable file security context.
For native executables see libcutils android\_get\_control\_socket().
diff --git a/init/devices.cpp b/init/devices.cpp
index d4a3cb9d3..ee8738c2a 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -465,7 +465,11 @@ void DeviceHandler::HandleDevice(const std::string& action, const std::string& d
MakeDevice(devpath, block, major, minor, links);
}
- // We don't have full device-mapper information until a change event is fired.
+ // Handle device-mapper nodes.
+ // On kernels <= 5.10, the "add" event is fired on DM_DEV_CREATE, but does not contain name
+ // information until DM_TABLE_LOAD - thus, we wait for a "change" event.
+ // On kernels >= 5.15, the "add" event is fired on DM_TABLE_LOAD, followed by a "change"
+ // event.
if (action == "add" || (action == "change" && StartsWith(devpath, "/dev/block/dm-"))) {
for (const auto& link : links) {
if (!mkdir_recursive(Dirname(link), 0755)) {
diff --git a/init/property_service.cpp b/init/property_service.cpp
index f9b4de94a..392d35c5b 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -1519,7 +1519,8 @@ void StartPropertyService(int* epoll_socket) {
StartSendingMessages();
if (auto result = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
- false, 0666, 0, 0, {});
+ /*passcred=*/false, /*should_listen=*/false, 0666, /*uid=*/0,
+ /*gid=*/0, /*socketcon=*/{});
result.ok()) {
property_set_fd = *result;
} else {
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 580d8a67a..9edc32808 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -616,7 +616,7 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str
if (sem_init(&reboot_semaphore, false, 0) == -1) {
// These should never fail, but if they do, skip the graceful reboot and reboot immediately.
LOG(ERROR) << "sem_init() fail and RebootSystem() return!";
- RebootSystem(cmd, reboot_target);
+ RebootSystem(cmd, reboot_target, reason);
}
// Start a thread to monitor init shutdown process
@@ -644,7 +644,7 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str
// worry about unmounting it.
if (!IsDataMounted("*")) {
sync();
- RebootSystem(cmd, reboot_target);
+ RebootSystem(cmd, reboot_target, reason);
abort();
}
@@ -777,7 +777,7 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str
LOG(INFO) << "Shutdown /data";
}
}
- RebootSystem(cmd, reboot_target);
+ RebootSystem(cmd, reboot_target, reason);
abort();
}
diff --git a/init/reboot_utils.cpp b/init/reboot_utils.cpp
index b3fa9fd3b..1f411636c 100644
--- a/init/reboot_utils.cpp
+++ b/init/reboot_utils.cpp
@@ -106,7 +106,8 @@ bool IsRebootCapable() {
return value == CAP_SET;
}
-void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& rebootTarget) {
+void __attribute__((noreturn))
+RebootSystem(unsigned int cmd, const std::string& rebootTarget, const std::string& reboot_reason) {
LOG(INFO) << "Reboot ending, jumping to kernel";
if (!IsRebootCapable()) {
@@ -127,10 +128,12 @@ void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string&
case ANDROID_RB_THERMOFF:
if (android::base::GetBoolProperty("ro.thermal_warmreset", false)) {
+ std::string reason = "shutdown,thermal";
+ if (!reboot_reason.empty()) reason = reboot_reason;
+
LOG(INFO) << "Try to trigger a warm reset for thermal shutdown";
- static constexpr const char kThermalShutdownTarget[] = "shutdown,thermal";
syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
- LINUX_REBOOT_CMD_RESTART2, kThermalShutdownTarget);
+ LINUX_REBOOT_CMD_RESTART2, reason.c_str());
} else {
reboot(RB_POWER_OFF);
}
diff --git a/init/reboot_utils.h b/init/reboot_utils.h
index a0023b9bb..09e87ef67 100644
--- a/init/reboot_utils.h
+++ b/init/reboot_utils.h
@@ -29,7 +29,8 @@ void SetFatalRebootTarget(const std::optional<std::string>& reboot_target = std:
// so if any of the attempts to determine this fail, it will still return true.
bool IsRebootCapable();
// This is a wrapper around the actual reboot calls.
-void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& reboot_target);
+void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& reboot_target,
+ const std::string& reboot_reason = "");
void __attribute__((noreturn)) InitFatalReboot(int signal_number);
void InstallRebootSignalHandlers();
diff --git a/init/service_parser.cpp b/init/service_parser.cpp
index 9e914ee7c..1ee309d98 100644
--- a/init/service_parser.cpp
+++ b/init/service_parser.cpp
@@ -434,11 +434,14 @@ Result<void> ServiceParser::ParseSocket(std::vector<std::string>&& args) {
<< "' instead.";
}
- if (types.size() > 1) {
- if (types.size() == 2 && types[1] == "passcred") {
+ for (size_t i = 1; i < types.size(); i++) {
+ if (types[i] == "passcred") {
socket.passcred = true;
+ } else if (types[i] == "listen") {
+ socket.listen = true;
} else {
- return Error() << "Only 'passcred' may be used to modify the socket type";
+ return Error() << "Unknown socket type decoration '" << types[i]
+ << "'. Known values are ['passcred', 'listen']";
}
}
diff --git a/init/service_utils.cpp b/init/service_utils.cpp
index eed5c65db..d19f5eef5 100644
--- a/init/service_utils.cpp
+++ b/init/service_utils.cpp
@@ -168,7 +168,8 @@ void Descriptor::Publish() const {
Result<Descriptor> SocketDescriptor::Create(const std::string& global_context) const {
const auto& socket_context = context.empty() ? global_context : context;
- auto result = CreateSocket(name, type | SOCK_CLOEXEC, passcred, perm, uid, gid, socket_context);
+ auto result = CreateSocket(name, type | SOCK_CLOEXEC, passcred, listen, perm, uid, gid,
+ socket_context);
if (!result.ok()) {
return result.error();
}
diff --git a/init/service_utils.h b/init/service_utils.h
index 9b65dca74..65a2012ff 100644
--- a/init/service_utils.h
+++ b/init/service_utils.h
@@ -54,6 +54,7 @@ struct SocketDescriptor {
int perm = 0;
std::string context;
bool passcred = false;
+ bool listen = false;
bool persist = false;
// Create() creates the named unix domain socket in /dev/socket and returns a Descriptor object.
diff --git a/init/util.cpp b/init/util.cpp
index d1e518b57..5b3a73c0d 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -86,8 +86,8 @@ Result<uid_t> DecodeUid(const std::string& name) {
* daemon. We communicate the file descriptor's value via the environment
* variable ANDROID_SOCKET_ENV_PREFIX<name> ("ANDROID_SOCKET_foo").
*/
-Result<int> CreateSocket(const std::string& name, int type, bool passcred, mode_t perm, uid_t uid,
- gid_t gid, const std::string& socketcon) {
+Result<int> CreateSocket(const std::string& name, int type, bool passcred, bool should_listen,
+ mode_t perm, uid_t uid, gid_t gid, const std::string& socketcon) {
if (!socketcon.empty()) {
if (setsockcreatecon(socketcon.c_str()) == -1) {
return ErrnoError() << "setsockcreatecon(\"" << socketcon << "\") failed";
@@ -142,6 +142,9 @@ Result<int> CreateSocket(const std::string& name, int type, bool passcred, mode_
if (fchmodat(AT_FDCWD, addr.sun_path, perm, AT_SYMLINK_NOFOLLOW)) {
return ErrnoError() << "Failed to fchmodat socket '" << addr.sun_path << "'";
}
+ if (should_listen && listen(fd, /* use OS maximum */ 1 << 30)) {
+ return ErrnoError() << "Failed to listen on socket '" << addr.sun_path << "'";
+ }
LOG(INFO) << "Created socket '" << addr.sun_path << "'"
<< ", mode " << std::oct << perm << std::dec
diff --git a/init/util.h b/init/util.h
index bf5367531..1e2eef090 100644
--- a/init/util.h
+++ b/init/util.h
@@ -44,8 +44,8 @@ static const char kColdBootDoneProp[] = "ro.cold_boot_done";
extern void (*trigger_shutdown)(const std::string& command);
-Result<int> CreateSocket(const std::string& name, int type, bool passcred, mode_t perm, uid_t uid,
- gid_t gid, const std::string& socketcon);
+Result<int> CreateSocket(const std::string& name, int type, bool passcred, bool should_listen,
+ mode_t perm, uid_t uid, gid_t gid, const std::string& socketcon);
Result<std::string> ReadFile(const std::string& path);
Result<void> WriteFile(const std::string& path, const std::string& content);