diff options
Diffstat (limited to 'init')
| -rw-r--r-- | init/block_dev_initializer.cpp | 16 | ||||
| -rw-r--r-- | init/block_dev_initializer.h | 3 | ||||
| -rw-r--r-- | init/init.cpp | 7 | ||||
| -rw-r--r-- | init/mount_namespace.cpp | 59 | ||||
| -rw-r--r-- | init/property_service.cpp | 6 | ||||
| -rw-r--r-- | init/service_utils.cpp | 11 | ||||
| -rw-r--r-- | init/test_kill_services/init_kill_services_test.cpp | 2 | ||||
| -rw-r--r-- | init/uevent_listener.cpp | 20 | ||||
| -rw-r--r-- | init/uevent_listener.h | 10 |
9 files changed, 66 insertions, 68 deletions
diff --git a/init/block_dev_initializer.cpp b/init/block_dev_initializer.cpp index b423f864e3..8db9793f5e 100644 --- a/init/block_dev_initializer.cpp +++ b/init/block_dev_initializer.cpp @@ -37,7 +37,15 @@ BlockDevInitializer::BlockDevInitializer() : uevent_listener_(16 * 1024 * 1024) } bool BlockDevInitializer::InitDeviceMapper() { - const std::string dm_path = "/devices/virtual/misc/device-mapper"; + return InitMiscDevice("device-mapper"); +} + +bool BlockDevInitializer::InitDmUser() { + return InitMiscDevice("dm-user"); +} + +bool BlockDevInitializer::InitMiscDevice(const std::string& name) { + const std::string dm_path = "/devices/virtual/misc/" + name; bool found = false; auto dm_callback = [this, &dm_path, &found](const Uevent& uevent) { if (uevent.path == dm_path) { @@ -49,13 +57,13 @@ bool BlockDevInitializer::InitDeviceMapper() { }; uevent_listener_.RegenerateUeventsForPath("/sys" + dm_path, dm_callback); if (!found) { - LOG(INFO) << "device-mapper device not found in /sys, waiting for its uevent"; + LOG(INFO) << name << " device not found in /sys, waiting for its uevent"; Timer t; uevent_listener_.Poll(dm_callback, 10s); - LOG(INFO) << "Wait for device-mapper returned after " << t; + LOG(INFO) << "Wait for " << name << " returned after " << t; } if (!found) { - LOG(ERROR) << "device-mapper device not found after polling timeout"; + LOG(ERROR) << name << " device not found after polling timeout"; return false; } return true; diff --git a/init/block_dev_initializer.h b/init/block_dev_initializer.h index 0d4c6e9fc8..b8dd3f172f 100644 --- a/init/block_dev_initializer.h +++ b/init/block_dev_initializer.h @@ -27,12 +27,15 @@ class BlockDevInitializer final { BlockDevInitializer(); bool InitDeviceMapper(); + bool InitDmUser(); bool InitDevices(std::set<std::string> devices); bool InitDmDevice(const std::string& device); private: ListenerAction HandleUevent(const Uevent& uevent, std::set<std::string>* devices); + bool InitMiscDevice(const std::string& name); + std::unique_ptr<DeviceHandler> device_handler_; UeventListener uevent_listener_; }; diff --git a/init/init.cpp b/init/init.cpp index ba880ea32f..cb5bbbab97 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -18,6 +18,7 @@ #include <dirent.h> #include <fcntl.h> +#include <paths.h> #include <pthread.h> #include <signal.h> #include <stdlib.h> @@ -727,6 +728,12 @@ int SecondStageMain(int argc, char** argv) { InitSecondStageLogging(argv); LOG(INFO) << "init second stage started!"; + // Update $PATH in the case the second stage init is newer than first stage init, where it is + // first set. + if (setenv("PATH", _PATH_DEFPATH, 1) != 0) { + PLOG(FATAL) << "Could not set $PATH to '" << _PATH_DEFPATH << "' in second stage"; + } + // Init should not crash because of a dependence on any other process, therefore we ignore // SIGPIPE and handle EPIPE at the call site directly. Note that setting a signal to SIG_IGN // is inherited across exec, but custom signal handlers are not. Since we do not want to diff --git a/init/mount_namespace.cpp b/init/mount_namespace.cpp index f8359bc64c..59cc140e42 100644 --- a/init/mount_namespace.cpp +++ b/init/mount_namespace.cpp @@ -44,50 +44,17 @@ namespace android { namespace init { namespace { -static bool BindMount(const std::string& source, const std::string& mount_point, - bool recursive = false) { - unsigned long mountflags = MS_BIND; - if (recursive) { - mountflags |= MS_REC; - } - if (mount(source.c_str(), mount_point.c_str(), nullptr, mountflags, nullptr) == -1) { +static bool BindMount(const std::string& source, const std::string& mount_point) { + if (mount(source.c_str(), mount_point.c_str(), nullptr, MS_BIND | MS_REC, nullptr) == -1) { PLOG(ERROR) << "Failed to bind mount " << source; return false; } return true; } -static bool MakeShared(const std::string& mount_point, bool recursive = false) { - unsigned long mountflags = MS_SHARED; - if (recursive) { - mountflags |= MS_REC; - } - if (mount(nullptr, mount_point.c_str(), nullptr, mountflags, nullptr) == -1) { - PLOG(ERROR) << "Failed to change propagation type to shared"; - return false; - } - return true; -} - -static bool MakeSlave(const std::string& mount_point, bool recursive = false) { - unsigned long mountflags = MS_SLAVE; - if (recursive) { - mountflags |= MS_REC; - } - if (mount(nullptr, mount_point.c_str(), nullptr, mountflags, nullptr) == -1) { - PLOG(ERROR) << "Failed to change propagation type to slave"; - return false; - } - return true; -} - -static bool MakePrivate(const std::string& mount_point, bool recursive = false) { - unsigned long mountflags = MS_PRIVATE; - if (recursive) { - mountflags |= MS_REC; - } +static bool ChangeMount(const std::string& mount_point, unsigned long mountflags) { if (mount(nullptr, mount_point.c_str(), nullptr, mountflags, nullptr) == -1) { - PLOG(ERROR) << "Failed to change propagation type to private"; + PLOG(ERROR) << "Failed to remount " << mount_point << " as " << std::hex << mountflags; return false; } return true; @@ -225,17 +192,17 @@ bool SetupMountNamespaces() { // needed for /foo/bar, then we will make /foo/bar as a mount point (by // bind-mounting by to itself) and set the propagation type of the mount // point to private. - if (!MakeShared("/", true /*recursive*/)) return false; + if (!ChangeMount("/", MS_SHARED | MS_REC)) return false; // /apex is a private mountpoint to give different sets of APEXes for // the bootstrap and default mount namespaces. The processes running with // the bootstrap namespace get APEXes from the read-only partition. - if (!(MakePrivate("/apex"))) return false; + if (!(ChangeMount("/apex", MS_PRIVATE))) return false; // /linkerconfig is a private mountpoint to give a different linker configuration // based on the mount namespace. Subdirectory will be bind-mounted based on current mount // namespace - if (!(MakePrivate("/linkerconfig"))) return false; + if (!(ChangeMount("/linkerconfig", MS_PRIVATE))) return false; // The two mount namespaces present challenges for scoped storage, because // vold, which is responsible for most of the mounting, lives in the @@ -266,15 +233,15 @@ bool SetupMountNamespaces() { if (!mkdir_recursive("/mnt/user", 0755)) return false; if (!mkdir_recursive("/mnt/installer", 0755)) return false; if (!mkdir_recursive("/mnt/androidwritable", 0755)) return false; - if (!(BindMount("/mnt/user", "/mnt/installer", true))) return false; - if (!(BindMount("/mnt/user", "/mnt/androidwritable", true))) return false; + if (!(BindMount("/mnt/user", "/mnt/installer"))) return false; + if (!(BindMount("/mnt/user", "/mnt/androidwritable"))) return false; // First, make /mnt/installer and /mnt/androidwritable a slave bind mount - if (!(MakeSlave("/mnt/installer"))) return false; - if (!(MakeSlave("/mnt/androidwritable"))) return false; + if (!(ChangeMount("/mnt/installer", MS_SLAVE))) return false; + if (!(ChangeMount("/mnt/androidwritable", MS_SLAVE))) return false; // Then, make it shared again - effectively creating a new peer group, that // will be inherited by new mount namespaces. - if (!(MakeShared("/mnt/installer"))) return false; - if (!(MakeShared("/mnt/androidwritable"))) return false; + if (!(ChangeMount("/mnt/installer", MS_SHARED))) return false; + if (!(ChangeMount("/mnt/androidwritable", MS_SHARED))) return false; bootstrap_ns_fd.reset(OpenMountNamespace()); bootstrap_ns_id = GetMountNamespaceId(); diff --git a/init/property_service.cpp b/init/property_service.cpp index 0c4a3c4989..a1e0969ede 100644 --- a/init/property_service.cpp +++ b/init/property_service.cpp @@ -632,10 +632,11 @@ static void LoadProperties(char* data, const char* filter, const char* filename, char *key, *value, *eol, *sol, *tmp, *fn; size_t flen = 0; - static constexpr const char* const kVendorPathPrefixes[3] = { + static constexpr const char* const kVendorPathPrefixes[4] = { "/vendor", "/odm", "/vendor_dlkm", + "/odm_dlkm", }; const char* context = kInitContext; @@ -941,6 +942,7 @@ void PropertyLoadBootDefaults() { // } load_properties_from_file("/vendor/build.prop", nullptr, &properties); load_properties_from_file("/vendor_dlkm/etc/build.prop", nullptr, &properties); + load_properties_from_file("/odm_dlkm/etc/build.prop", nullptr, &properties); load_properties_from_partition("odm", /* support_legacy_path_until */ 28); load_properties_from_partition("product", /* support_legacy_path_until */ 30); @@ -992,7 +994,7 @@ void CreateSerializedPropertyInfo() { &property_infos)) { return; } - // Don't check for failure here, so we always have a sane list of properties. + // Don't check for failure here, since we don't always have all of these partitions. // E.g. In case of recovery, the vendor partition will not have mounted and we // still need the system / platform properties to function. if (access("/system_ext/etc/selinux/system_ext_property_contexts", R_OK) != -1) { diff --git a/init/service_utils.cpp b/init/service_utils.cpp index 05e632b68c..f2383d7a6e 100644 --- a/init/service_utils.cpp +++ b/init/service_utils.cpp @@ -60,13 +60,14 @@ Result<void> EnterNamespace(int nstype, const char* path) { Result<void> SetUpMountNamespace(bool remount_proc, bool remount_sys) { constexpr unsigned int kSafeFlags = MS_NODEV | MS_NOEXEC | MS_NOSUID; - // Recursively remount / as slave like zygote does so unmounting and mounting /proc - // doesn't interfere with the parent namespace's /proc mount. This will also - // prevent any other mounts/unmounts initiated by the service from interfering - // with the parent namespace but will still allow mount events from the parent + // Recursively remount / as MS_SLAVE like zygote does so that + // unmounting and mounting /proc doesn't interfere with the parent + // namespace's /proc mount. This will also prevent any other + // mounts/unmounts initiated by the service from interfering with the + // parent namespace but will still allow mount events from the parent // namespace to propagate to the child. if (mount("rootfs", "/", nullptr, (MS_SLAVE | MS_REC), nullptr) == -1) { - return ErrnoError() << "Could not remount(/) recursively as slave"; + return ErrnoError() << "Could not remount(/) recursively as MS_SLAVE"; } // umount() then mount() /proc and/or /sys diff --git a/init/test_kill_services/init_kill_services_test.cpp b/init/test_kill_services/init_kill_services_test.cpp index 7e543f232c..66a332892d 100644 --- a/init/test_kill_services/init_kill_services_test.cpp +++ b/init/test_kill_services/init_kill_services_test.cpp @@ -54,7 +54,7 @@ class InitKillServicesTest : public ::testing::TestWithParam<std::string> {}; TEST_P(InitKillServicesTest, KillCriticalProcesses) { ExpectKillingServiceRecovers(GetParam()); - // sanity check init is still responding + // Ensure that init is still responding EXPECT_TRUE(SetProperty("test.death.test", "asdf")); EXPECT_EQ(GetProperty("test.death.test", ""), "asdf"); EXPECT_TRUE(SetProperty("test.death.test", "")); diff --git a/init/uevent_listener.cpp b/init/uevent_listener.cpp index d8d9b36ff4..7cd396a8b0 100644 --- a/init/uevent_listener.cpp +++ b/init/uevent_listener.cpp @@ -95,20 +95,18 @@ UeventListener::UeventListener(size_t uevent_socket_rcvbuf_size) { fcntl(device_fd_, F_SETFL, O_NONBLOCK); } -bool UeventListener::ReadUevent(Uevent* uevent) const { +ReadUeventResult UeventListener::ReadUevent(Uevent* uevent) const { char msg[UEVENT_MSG_LEN + 2]; int n = uevent_kernel_multicast_recv(device_fd_, msg, UEVENT_MSG_LEN); if (n <= 0) { if (errno != EAGAIN && errno != EWOULDBLOCK) { PLOG(ERROR) << "Error reading from Uevent Fd"; } - return false; + return ReadUeventResult::kFailed; } if (n >= UEVENT_MSG_LEN) { LOG(ERROR) << "Uevent overflowed buffer, discarding"; - // Return true here even if we discard as we may have more uevents pending and we - // want to keep processing them. - return true; + return ReadUeventResult::kInvalid; } msg[n] = '\0'; @@ -116,7 +114,7 @@ bool UeventListener::ReadUevent(Uevent* uevent) const { ParseEvent(msg, uevent); - return true; + return ReadUeventResult::kSuccess; } // RegenerateUevents*() walks parts of the /sys tree and pokes the uevent files to cause the kernel @@ -137,7 +135,10 @@ ListenerAction UeventListener::RegenerateUeventsForDir(DIR* d, close(fd); Uevent uevent; - while (ReadUevent(&uevent)) { + ReadUeventResult result; + while ((result = ReadUevent(&uevent)) != ReadUeventResult::kFailed) { + // Skip processing the uevent if it is invalid. + if (result == ReadUeventResult::kInvalid) continue; if (callback(uevent) == ListenerAction::kStop) return ListenerAction::kStop; } } @@ -212,7 +213,10 @@ void UeventListener::Poll(const ListenerCallback& callback, // We're non-blocking, so if we receive a poll event keep processing until // we have exhausted all uevent messages. Uevent uevent; - while (ReadUevent(&uevent)) { + ReadUeventResult result; + while ((result = ReadUevent(&uevent)) != ReadUeventResult::kFailed) { + // Skip processing the uevent if it is invalid. + if (result == ReadUeventResult::kInvalid) continue; if (callback(uevent) == ListenerAction::kStop) return; } } diff --git a/init/uevent_listener.h b/init/uevent_listener.h index aea094e776..2772860642 100644 --- a/init/uevent_listener.h +++ b/init/uevent_listener.h @@ -27,7 +27,7 @@ #include "uevent.h" -#define UEVENT_MSG_LEN 2048 +#define UEVENT_MSG_LEN 8192 namespace android { namespace init { @@ -37,6 +37,12 @@ enum class ListenerAction { kContinue, // Continue regenerating uevents as we haven't seen the one(s) we're interested in. }; +enum class ReadUeventResult { + kSuccess = 0, // Uevent was successfully read. + kFailed, // Uevent reading has failed. + kInvalid, // An Invalid Uevent was read (like say, the msg received is >= UEVENT_MSG_LEN). +}; + using ListenerCallback = std::function<ListenerAction(const Uevent&)>; class UeventListener { @@ -50,7 +56,7 @@ class UeventListener { const std::optional<std::chrono::milliseconds> relative_timeout = {}) const; private: - bool ReadUevent(Uevent* uevent) const; + ReadUeventResult ReadUevent(Uevent* uevent) const; ListenerAction RegenerateUeventsForDir(DIR* d, const ListenerCallback& callback) const; android::base::unique_fd device_fd_; |
