first_stage_mount: mount point must be canonical path

Ban weird paths such as /../system or //vendor in first stage mount.
Add utility function fs_mgr_create_canonical_mount_point() that:

* mkdir(mount_point) to ensure mount_point's existence
* Test that realpath(mount_point) =?= mount_point

Bug: 188898525
Test: Presubmit
Test: Boot CF
Change-Id: Iaf2ec52701277f26cc81f3e15a47b6083a788334
Merged-In: Iaf2ec52701277f26cc81f3e15a47b6083a788334
(cherry picked from commit 3431d52675f25020b279c9fbcda6b8648f9cf67b)
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 08ead7a..af71fe6 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -2266,6 +2266,26 @@
     return LP_METADATA_DEFAULT_PARTITION_NAME;
 }
 
+bool fs_mgr_create_canonical_mount_point(const std::string& mount_point) {
+    auto saved_errno = errno;
+    auto ok = true;
+    auto created_mount_point = !mkdir(mount_point.c_str(), 0755);
+    std::string real_mount_point;
+    if (!Realpath(mount_point, &real_mount_point)) {
+        ok = false;
+        PERROR << "failed to realpath(" << mount_point << ")";
+    } else if (mount_point != real_mount_point) {
+        ok = false;
+        LERROR << "mount point is not canonical: realpath(" << mount_point << ") -> "
+               << real_mount_point;
+    }
+    if (!ok && created_mount_point) {
+        rmdir(mount_point.c_str());
+    }
+    errno = saved_errno;
+    return ok;
+}
+
 bool fs_mgr_mount_overlayfs_fstab_entry(const FstabEntry& entry) {
     auto overlayfs_valid_result = fs_mgr_overlayfs_valid();
     if (overlayfs_valid_result == OverlayfsValidResult::kNotSupported) {
@@ -2298,18 +2318,7 @@
     }
 #endif  // ALLOW_ADBD_DISABLE_VERITY == 0
 
-    // Create the mount point in case it doesn't exist.
-    mkdir(entry.mount_point.c_str(), 0755);
-
-    // Ensure that mount point exists and doesn't contain symbolic link or /../.
-    std::string mount_point;
-    if (!Realpath(entry.mount_point, &mount_point)) {
-        PERROR << __FUNCTION__ << "(): failed to realpath " << entry.mount_point;
-        return false;
-    }
-    if (entry.mount_point != mount_point) {
-        LERROR << __FUNCTION__ << "(): mount point must be a canonicalized path: realpath "
-               << entry.mount_point << " = " << mount_point;
+    if (!fs_mgr_create_canonical_mount_point(entry.mount_point)) {
         return false;
     }
 
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index b8ebd63..4d3ecc9 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -132,6 +132,10 @@
 // empty string
 std::string fs_mgr_find_bow_device(const std::string& block_device);
 
+// Creates mount point if not already existed, and checks that mount point is a
+// canonical path that doesn't contain any symbolic link or /../.
+bool fs_mgr_create_canonical_mount_point(const std::string& mount_point);
+
 // Like fs_mgr_do_mount_one() but for overlayfs fstab entries.
 // Unlike fs_mgr_overlayfs, mount overlayfs without upperdir and workdir, so the
 // filesystem cannot be remount read-write.
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 546ea8e..f5c10bb 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -420,6 +420,10 @@
         *end = begin + 1;
     }
 
+    if (!fs_mgr_create_canonical_mount_point(begin->mount_point)) {
+        return false;
+    }
+
     if (begin->fs_mgr_flags.logical) {
         if (!fs_mgr_update_logical_partition(&(*begin))) {
             return false;