Merge cherrypicks of [16718400] into sc-d2-release.

Change-Id: I199c886a26c85b51d769f9f3006bd60054df2e3b
diff --git a/init/snapuserd_transition.cpp b/init/snapuserd_transition.cpp
index 40467b7..7fd3f65 100644
--- a/init/snapuserd_transition.cpp
+++ b/init/snapuserd_transition.cpp
@@ -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 <libsnapshot/snapuserd_client.h>
 #include <private/android_filesystem_config.h>
@@ -227,6 +228,56 @@
     }
 }
 
+/*
+ * 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) {
@@ -248,6 +299,13 @@
         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;
     }
 
diff --git a/init/snapuserd_transition.h b/init/snapuserd_transition.h
index a5ab652..757af13 100644
--- a/init/snapuserd_transition.h
+++ b/init/snapuserd_transition.h
@@ -51,6 +51,7 @@
   private:
     void RelaunchFirstStageSnapuserd();
     void ExecSnapuserd();
+    bool TestSnapuserdIsReady();
 
     std::unique_ptr<SnapshotManager> sm_;
     BlockDevInitializer block_dev_init_;