From 79b03ff9e6766def10f0596664fa7bd260823433 Mon Sep 17 00:00:00 2001 From: Hyangseok Chae Date: Thu, 27 Feb 2020 18:21:50 +0900 Subject: [PATCH] umount /data/user/0 before umount /data FDE device has shut down and restart the framework. But restart is not triggered due to umount fail. umount /data fail with "device is busy" It is because bind mount /data/data to /data/user/0 We need umount /data/user/0 before umount /data Bug: 148004718 Test: Flash GSI and check boot with FDE and FBE device. Change-Id: I919f9e31a9d2d745b297a7ab99b399aa9b293b39 Merged-In: I919f9e31a9d2d745b297a7ab99b399aa9b293b39 (cherry picked from commit 3cf3233bac176744d43c682b7f9244db58c3402a) --- cryptfs.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/cryptfs.cpp b/cryptfs.cpp index 1431459..1ddb34b 100644 --- a/cryptfs.cpp +++ b/cryptfs.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -54,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -1396,8 +1398,46 @@ static int create_encrypted_random_key(const char* passwd, unsigned char* master return encrypt_master_key(passwd, salt, key_buf, master_key, crypt_ftr); } +static void ensure_subdirectory_unmounted(const char *prefix) { + std::vector umount_points; + std::unique_ptr mnts(setmntent("/proc/mounts", "r"), endmntent); + if (!mnts) { + SLOGW("could not read mount files"); + return; + } + + //Find sudirectory mount point + mntent* mentry; + std::string top_directory(prefix); + if (!android::base::EndsWith(prefix, "/")) { + top_directory = top_directory + "/"; + } + while ((mentry = getmntent(mnts.get())) != nullptr) { + if (strcmp(mentry->mnt_dir, top_directory.c_str()) == 0) { + continue; + } + + if (android::base::StartsWith(mentry->mnt_dir, top_directory)) { + SLOGW("found sub-directory mount %s - %s\n", prefix, mentry->mnt_dir); + umount_points.push_back(mentry->mnt_dir); + } + } + + //Sort by path length to umount longest path first + std::sort(std::begin(umount_points), std::end(umount_points), + [](const std::string& s1, const std::string& s2) {return s1.length() > s2.length(); }); + + for (std::string& mount_point : umount_points) { + umount(mount_point.c_str()); + SLOGW("umount sub-directory mount %s\n", mount_point.c_str()); + } +} + static int wait_and_unmount(const char* mountpoint, bool kill) { int i, err, rc; + + // Subdirectory mount will cause a failure of umount. + ensure_subdirectory_unmounted(mountpoint); #define WAIT_UNMOUNT_COUNT 20 /* Now umount the tmpfs filesystem */