Loading fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp +7 −2 Original line number Diff line number Diff line Loading @@ -599,8 +599,13 @@ bool UserSnapshotServer::WaitForSocket() { return false; } // We must re-initialize property service access, since we launched before // second-stage init. // This initialization of system property is important. When daemon is // launched post selinux transition (before init second stage), // bionic libc initializes system property as part of __libc_init_common(); // however that initialization fails silently given that fact that we don't // have /dev/__properties__ setup which is created at init second stage. // // At this point, we have the handlers setup and is safe to setup property. __system_properties_init(); if (!android::base::WaitForProperty("snapuserd.proxy_ready", "true")) { Loading init/snapuserd_transition.cpp +58 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #include <android-base/strings.h> #include <android-base/unique_fd.h> #include <cutils/sockets.h> #include <fs_avb/fs_avb.h> #include <libsnapshot/snapshot.h> #include <private/android_filesystem_config.h> #include <procinfo/process_map.h> Loading Loading @@ -247,6 +248,56 @@ void SnapuserdSelinuxHelper::FinishTransition() { } } /* * Before starting init second stage, we will wait * for snapuserd daemon to be up and running; bionic libc * may read /system/etc/selinux/plat_property_contexts file * before invoking main() function. This will happen if * init initializes property during second stage. Any access * to /system without snapuserd daemon will lead to a deadlock. * * Thus, we do a simple probe by reading system partition. This * read will eventually be serviced by daemon confirming that * daemon is up and running. Furthermore, we are still in the kernel * domain and sepolicy has not been enforced yet. Thus, access * to these device mapper block devices are ok even though * we may see audit logs. */ bool SnapuserdSelinuxHelper::TestSnapuserdIsReady() { std::string dev = "/dev/block/mapper/system"s + fs_mgr_get_slot_suffix(); android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_DIRECT)); if (fd < 0) { PLOG(ERROR) << "open " << dev << " failed"; return false; } void* addr; ssize_t page_size = getpagesize(); if (posix_memalign(&addr, page_size, page_size) < 0) { PLOG(ERROR) << "posix_memalign with page size " << page_size; return false; } std::unique_ptr<void, decltype(&::free)> buffer(addr, ::free); int iter = 0; while (iter < 10) { ssize_t n = TEMP_FAILURE_RETRY(pread(fd.get(), buffer.get(), page_size, 0)); if (n < 0) { // Wait for sometime before retry std::this_thread::sleep_for(100ms); } else if (n == page_size) { return true; } else { LOG(ERROR) << "pread returned: " << n << " from: " << dev << " expected: " << page_size; } iter += 1; } return false; } void SnapuserdSelinuxHelper::RelaunchFirstStageSnapuserd() { auto fd = GetRamdiskSnapuserdFd(); if (!fd) { Loading @@ -268,6 +319,13 @@ void SnapuserdSelinuxHelper::RelaunchFirstStageSnapuserd() { setenv(kSnapuserdFirstStagePidVar, std::to_string(pid).c_str(), 1); LOG(INFO) << "Relaunched snapuserd with pid: " << pid; if (!TestSnapuserdIsReady()) { PLOG(FATAL) << "snapuserd daemon failed to launch"; } else { LOG(INFO) << "snapuserd daemon is up and running"; } return; } Loading init/snapuserd_transition.h +1 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ class SnapuserdSelinuxHelper final { private: void RelaunchFirstStageSnapuserd(); void ExecSnapuserd(); bool TestSnapuserdIsReady(); std::unique_ptr<SnapshotManager> sm_; BlockDevInitializer block_dev_init_; Loading Loading
fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp +7 −2 Original line number Diff line number Diff line Loading @@ -599,8 +599,13 @@ bool UserSnapshotServer::WaitForSocket() { return false; } // We must re-initialize property service access, since we launched before // second-stage init. // This initialization of system property is important. When daemon is // launched post selinux transition (before init second stage), // bionic libc initializes system property as part of __libc_init_common(); // however that initialization fails silently given that fact that we don't // have /dev/__properties__ setup which is created at init second stage. // // At this point, we have the handlers setup and is safe to setup property. __system_properties_init(); if (!android::base::WaitForProperty("snapuserd.proxy_ready", "true")) { Loading
init/snapuserd_transition.cpp +58 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #include <android-base/strings.h> #include <android-base/unique_fd.h> #include <cutils/sockets.h> #include <fs_avb/fs_avb.h> #include <libsnapshot/snapshot.h> #include <private/android_filesystem_config.h> #include <procinfo/process_map.h> Loading Loading @@ -247,6 +248,56 @@ void SnapuserdSelinuxHelper::FinishTransition() { } } /* * Before starting init second stage, we will wait * for snapuserd daemon to be up and running; bionic libc * may read /system/etc/selinux/plat_property_contexts file * before invoking main() function. This will happen if * init initializes property during second stage. Any access * to /system without snapuserd daemon will lead to a deadlock. * * Thus, we do a simple probe by reading system partition. This * read will eventually be serviced by daemon confirming that * daemon is up and running. Furthermore, we are still in the kernel * domain and sepolicy has not been enforced yet. Thus, access * to these device mapper block devices are ok even though * we may see audit logs. */ bool SnapuserdSelinuxHelper::TestSnapuserdIsReady() { std::string dev = "/dev/block/mapper/system"s + fs_mgr_get_slot_suffix(); android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_DIRECT)); if (fd < 0) { PLOG(ERROR) << "open " << dev << " failed"; return false; } void* addr; ssize_t page_size = getpagesize(); if (posix_memalign(&addr, page_size, page_size) < 0) { PLOG(ERROR) << "posix_memalign with page size " << page_size; return false; } std::unique_ptr<void, decltype(&::free)> buffer(addr, ::free); int iter = 0; while (iter < 10) { ssize_t n = TEMP_FAILURE_RETRY(pread(fd.get(), buffer.get(), page_size, 0)); if (n < 0) { // Wait for sometime before retry std::this_thread::sleep_for(100ms); } else if (n == page_size) { return true; } else { LOG(ERROR) << "pread returned: " << n << " from: " << dev << " expected: " << page_size; } iter += 1; } return false; } void SnapuserdSelinuxHelper::RelaunchFirstStageSnapuserd() { auto fd = GetRamdiskSnapuserdFd(); if (!fd) { Loading @@ -268,6 +319,13 @@ void SnapuserdSelinuxHelper::RelaunchFirstStageSnapuserd() { setenv(kSnapuserdFirstStagePidVar, std::to_string(pid).c_str(), 1); LOG(INFO) << "Relaunched snapuserd with pid: " << pid; if (!TestSnapuserdIsReady()) { PLOG(FATAL) << "snapuserd daemon failed to launch"; } else { LOG(INFO) << "snapuserd daemon is up and running"; } return; } Loading
init/snapuserd_transition.h +1 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ class SnapuserdSelinuxHelper final { private: void RelaunchFirstStageSnapuserd(); void ExecSnapuserd(); bool TestSnapuserdIsReady(); std::unique_ptr<SnapshotManager> sm_; BlockDevInitializer block_dev_init_; Loading