FsCrypt update: support fscrypt policies v1 and v2

This patchset introduces support decryption for Android 11.

In this update we deprecate ext4crypt. To specify the
policy version to use, use TW_USE_FSCRYPT_POLICY := 1 or
TW_USE_FSCRYPT_POLICY := 2. By default policy version will
be set to 2 if this variable is omitted.

Change-Id: I62a29c1bef36c259ec4b11259f71be613d20a112
diff --git a/crypto/fscrypt/Utils.cpp b/crypto/fscrypt/Utils.cpp
index aa71d8f..3b0eda0 100755
--- a/crypto/fscrypt/Utils.cpp
+++ b/crypto/fscrypt/Utils.cpp
@@ -29,23 +29,29 @@
 #include <cutils/fs.h>
 #include <logwrap/logwrap.h>
 #include <private/android_filesystem_config.h>
+#include <private/android_projectid_config.h>
 
 #include <dirent.h>
 #include <fcntl.h>
 #include <linux/fs.h>
+#include <linux/posix_acl.h>
+#include <linux/posix_acl_xattr.h>
 #include <mntent.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <unistd.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
 #include <sys/statvfs.h>
 #include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <sys/xattr.h>
+#include <unistd.h>
 
+#include <filesystem>
 #include <list>
 #include <mutex>
+#include <regex>
 #include <thread>
 
 #ifndef UMOUNT_NOFOLLOW
@@ -53,33 +59,47 @@
 #endif
 
 using namespace std::chrono_literals;
+using android::base::EndsWith;
 using android::base::ReadFileToString;
+using android::base::StartsWith;
 using android::base::StringPrintf;
+using android::base::unique_fd;
 
-namespace android {
-namespace vold {
+struct selabel_handle* sehandle;
 
 security_context_t sBlkidContext = nullptr;
 security_context_t sBlkidUntrustedContext = nullptr;
 security_context_t sFsckContext = nullptr;
 security_context_t sFsckUntrustedContext = nullptr;
-struct selabel_handle* sehandle;
 
 bool sSleepOnUnmount = true;
 
 static const char* kBlkidPath = "/system/bin/blkid";
 static const char* kKeyPath = "/data/misc/vold";
 
+static const char* kProcDevices = "/proc/devices";
 static const char* kProcFilesystems = "/proc/filesystems";
 
+static const char* kAndroidDir = "/Android/";
+static const char* kAppDataDir = "/Android/data/";
+static const char* kAppMediaDir = "/Android/media/";
+static const char* kAppObbDir = "/Android/obb/";
+
+static const char* kMediaProviderCtx = "u:r:mediaprovider:";
+static const char* kMediaProviderAppCtx = "u:r:mediaprovider_app:";
+
 // Lock used to protect process-level SELinux changes from racing with each
 // other between multiple threads.
 static std::mutex kSecurityLock;
 
-status_t CreateDeviceNode(const std::string& path, dev_t dev) {
+std::string GetFuseMountPathForUser(userid_t user_id, const std::string& relative_upper_path) {
+    return StringPrintf("/mnt/user/%d/%s", user_id, relative_upper_path.c_str());
+}
+
+android::status_t CreateDeviceNode(const std::string& path, dev_t dev) {
     std::lock_guard<std::mutex> lock(kSecurityLock);
     const char* cpath = path.c_str();
-    status_t res = 0;
+    android::status_t res = 0;
 
     char* secontext = nullptr;
     if (sehandle) {
@@ -105,16 +125,297 @@
     return res;
 }
 
-status_t DestroyDeviceNode(const std::string& path) {
+android::status_t DestroyDeviceNode(const std::string& path) {
     const char* cpath = path.c_str();
     if (TEMP_FAILURE_RETRY(unlink(cpath))) {
         return -errno;
     } else {
-        return OK;
+        return android::OK;
     }
 }
 
-status_t PrepareDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid) {
+// Sets a default ACL on the directory.
+int SetDefaultAcl(const std::string& path, mode_t mode, uid_t uid, gid_t gid,
+                  std::vector<gid_t> additionalGids) {
+    if (IsSdcardfsUsed()) {
+        // sdcardfs magically takes care of this
+        return android::OK;
+    }
+
+    size_t num_entries = 3 + (additionalGids.size() > 0 ? additionalGids.size() + 1 : 0);
+    size_t size = sizeof(posix_acl_xattr_header) + num_entries * sizeof(posix_acl_xattr_entry);
+    auto buf = std::make_unique<uint8_t[]>(size);
+
+    posix_acl_xattr_header* acl_header = reinterpret_cast<posix_acl_xattr_header*>(buf.get());
+    acl_header->a_version = POSIX_ACL_XATTR_VERSION;
+
+    posix_acl_xattr_entry* entry =
+            reinterpret_cast<posix_acl_xattr_entry*>(buf.get() + sizeof(posix_acl_xattr_header));
+
+    int tag_index = 0;
+
+    entry[tag_index].e_tag = ACL_USER_OBJ;
+    // The existing mode_t mask has the ACL in the lower 9 bits:
+    // the lowest 3 for "other", the next 3 the group, the next 3 for the owner
+    // Use the mode_t masks to get these bits out, and shift them to get the
+    // correct value per entity.
+    //
+    // Eg if mode_t = 0700, rwx for the owner, then & S_IRWXU >> 6 results in 7
+    entry[tag_index].e_perm = (mode & S_IRWXU) >> 6;
+    entry[tag_index].e_id = uid;
+    tag_index++;
+
+    entry[tag_index].e_tag = ACL_GROUP_OBJ;
+    entry[tag_index].e_perm = (mode & S_IRWXG) >> 3;
+    entry[tag_index].e_id = gid;
+    tag_index++;
+
+    if (additionalGids.size() > 0) {
+        for (gid_t additional_gid : additionalGids) {
+            entry[tag_index].e_tag = ACL_GROUP;
+            entry[tag_index].e_perm = (mode & S_IRWXG) >> 3;
+            entry[tag_index].e_id = additional_gid;
+            tag_index++;
+        }
+
+        entry[tag_index].e_tag = ACL_MASK;
+        entry[tag_index].e_perm = (mode & S_IRWXG) >> 3;
+        entry[tag_index].e_id = 0;
+        tag_index++;
+    }
+
+    entry[tag_index].e_tag = ACL_OTHER;
+    entry[tag_index].e_perm = mode & S_IRWXO;
+    entry[tag_index].e_id = 0;
+
+    int ret = setxattr(path.c_str(), XATTR_NAME_POSIX_ACL_DEFAULT, acl_header, size, 0);
+
+    if (ret != 0) {
+        PLOG(ERROR) << "Failed to set default ACL on " << path;
+    }
+
+    return ret;
+}
+
+int SetQuotaInherit(const std::string& path) {
+    unsigned long flags;
+
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
+    if (fd == -1) {
+        PLOG(ERROR) << "Failed to open " << path << " to set project id inheritance.";
+        return -1;
+    }
+
+    int ret = ioctl(fd, FS_IOC_GETFLAGS, &flags);
+    if (ret == -1) {
+        PLOG(ERROR) << "Failed to get flags for " << path << " to set project id inheritance.";
+        return ret;
+    }
+
+    flags |= FS_PROJINHERIT_FL;
+
+    ret = ioctl(fd, FS_IOC_SETFLAGS, &flags);
+    if (ret == -1) {
+        PLOG(ERROR) << "Failed to set flags for " << path << " to set project id inheritance.";
+        return ret;
+    }
+
+    return 0;
+}
+
+int SetQuotaProjectId(const std::string& path, long projectId) {
+    struct fsxattr fsx;
+
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
+    if (fd == -1) {
+        PLOG(ERROR) << "Failed to open " << path << " to set project id.";
+        return -1;
+    }
+
+    int ret = ioctl(fd, FS_IOC_FSGETXATTR, &fsx);
+    if (ret == -1) {
+        PLOG(ERROR) << "Failed to get extended attributes for " << path << " to get project id.";
+        return ret;
+    }
+
+    fsx.fsx_projid = projectId;
+    return ioctl(fd, FS_IOC_FSSETXATTR, &fsx);
+}
+
+int PrepareDirWithProjectId(const std::string& path, mode_t mode, uid_t uid, gid_t gid,
+                            long projectId) {
+    int ret = fs_prepare_dir(path.c_str(), mode, uid, gid);
+
+    if (ret != 0) {
+        return ret;
+    }
+
+    if (!IsSdcardfsUsed()) {
+        ret = SetQuotaProjectId(path, projectId);
+    }
+
+    return ret;
+}
+
+static int FixupAppDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid, long projectId) {
+    namespace fs = std::filesystem;
+
+    // Setup the directory itself correctly
+    int ret = PrepareDirWithProjectId(path, mode, uid, gid, projectId);
+    if (ret != android::OK) {
+        return ret;
+    }
+
+    // Fixup all of its file entries
+    for (const auto& itEntry : fs::directory_iterator(path)) {
+        ret = lchown(itEntry.path().c_str(), uid, gid);
+        if (ret != 0) {
+            return ret;
+        }
+
+        ret = chmod(itEntry.path().c_str(), mode);
+        if (ret != 0) {
+            return ret;
+        }
+
+        if (!IsSdcardfsUsed()) {
+            ret = SetQuotaProjectId(itEntry.path(), projectId);
+            if (ret != 0) {
+                return ret;
+            }
+        }
+    }
+
+    return android::OK;
+}
+
+int PrepareAppDirFromRoot(const std::string& path, const std::string& root, int appUid,
+                          bool fixupExisting) {
+    long projectId;
+    size_t pos;
+    int ret = 0;
+    bool sdcardfsSupport = IsSdcardfsUsed();
+
+    // Make sure the Android/ directories exist and are setup correctly
+    ret = PrepareAndroidDirs(root);
+    if (ret != 0) {
+        LOG(ERROR) << "Failed to prepare Android/ directories.";
+        return ret;
+    }
+
+    // Now create the application-specific subdir(s)
+    // path is something like /data/media/0/Android/data/com.foo/files
+    // First, chop off the volume root, eg /data/media/0
+    std::string pathFromRoot = path.substr(root.length());
+
+    uid_t uid = appUid;
+    gid_t gid = AID_MEDIA_RW;
+    std::vector<gid_t> additionalGids;
+    std::string appDir;
+
+    // Check that the next part matches one of the allowed Android/ dirs
+    if (StartsWith(pathFromRoot, kAppDataDir)) {
+        appDir = kAppDataDir;
+        if (!sdcardfsSupport) {
+            gid = AID_EXT_DATA_RW;
+            // Also add the app's own UID as a group; since apps belong to a group
+            // that matches their UID, this ensures that they will always have access to
+            // the files created in these dirs, even if they are created by other processes
+            additionalGids.push_back(uid);
+        }
+    } else if (StartsWith(pathFromRoot, kAppMediaDir)) {
+        appDir = kAppMediaDir;
+        if (!sdcardfsSupport) {
+            gid = AID_MEDIA_RW;
+        }
+    } else if (StartsWith(pathFromRoot, kAppObbDir)) {
+        appDir = kAppObbDir;
+        if (!sdcardfsSupport) {
+            gid = AID_EXT_OBB_RW;
+            // See comments for kAppDataDir above
+            additionalGids.push_back(uid);
+        }
+    } else {
+        LOG(ERROR) << "Invalid application directory: " << path;
+        return -EINVAL;
+    }
+
+    // mode = 770, plus sticky bit on directory to inherit GID when apps
+    // create subdirs
+    mode_t mode = S_IRWXU | S_IRWXG | S_ISGID;
+    // the project ID for application-specific directories is directly
+    // derived from their uid
+
+    // Chop off the generic application-specific part, eg /Android/data/
+    // this leaves us with something like com.foo/files/
+    std::string leftToCreate = pathFromRoot.substr(appDir.length());
+    if (!EndsWith(leftToCreate, "/")) {
+        leftToCreate += "/";
+    }
+    std::string pathToCreate = root + appDir;
+    int depth = 0;
+    // Derive initial project ID
+    if (appDir == kAppDataDir || appDir == kAppMediaDir) {
+        projectId = uid - AID_APP_START + PROJECT_ID_EXT_DATA_START;
+    } else if (appDir == kAppObbDir) {
+        projectId = uid - AID_APP_START + PROJECT_ID_EXT_OBB_START;
+    }
+
+    while ((pos = leftToCreate.find('/')) != std::string::npos) {
+        std::string component = leftToCreate.substr(0, pos + 1);
+        leftToCreate = leftToCreate.erase(0, pos + 1);
+        pathToCreate = pathToCreate + component;
+
+        if (appDir == kAppDataDir && depth == 1 && component == "cache/") {
+            // All dirs use the "app" project ID, except for the cache dirs in
+            // Android/data, eg Android/data/com.foo/cache
+            // Note that this "sticks" - eg subdirs of this dir need the same
+            // project ID.
+            projectId = uid - AID_APP_START + PROJECT_ID_EXT_CACHE_START;
+        }
+
+        if (fixupExisting && access(pathToCreate.c_str(), F_OK) == 0) {
+            // Fixup all files in this existing directory with the correct UID/GID
+            // and project ID.
+            ret = FixupAppDir(pathToCreate, mode, uid, gid, projectId);
+        } else {
+            ret = PrepareDirWithProjectId(pathToCreate, mode, uid, gid, projectId);
+        }
+
+        if (ret != 0) {
+            return ret;
+        }
+
+        if (depth == 0) {
+            // Set the default ACL on the top-level application-specific directories,
+            // to ensure that even if applications run with a umask of 0077,
+            // new directories within these directories will allow the GID
+            // specified here to write; this is necessary for apps like
+            // installers and MTP, that require access here.
+            //
+            // See man (5) acl for more details.
+            ret = SetDefaultAcl(pathToCreate, mode, uid, gid, additionalGids);
+            if (ret != 0) {
+                return ret;
+            }
+
+            if (!sdcardfsSupport) {
+                // Set project ID inheritance, so that future subdirectories inherit the
+                // same project ID
+                ret = SetQuotaInherit(pathToCreate);
+                if (ret != 0) {
+                    return ret;
+                }
+            }
+        }
+
+        depth++;
+    }
+
+    return android::OK;
+}
+
+android::status_t PrepareDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid) {
     std::lock_guard<std::mutex> lock(kSecurityLock);
     const char* cpath = path.c_str();
 
@@ -133,68 +434,93 @@
     }
 
     if (res == 0) {
-        return OK;
+        return android::OK;
     } else {
         return -errno;
     }
 }
 
-status_t ForceUnmount(const std::string& path) {
+android::status_t ForceUnmount(const std::string& path) {
     const char* cpath = path.c_str();
     if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
-        return OK;
+        return android::OK;
     }
     // Apps might still be handling eject request, so wait before
     // we start sending signals
     if (sSleepOnUnmount) sleep(5);
 
-    KillProcessesWithOpenFiles(path, SIGINT);
+    android::vold::KillProcessesWithOpenFiles(path, SIGINT);
     if (sSleepOnUnmount) sleep(5);
     if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
-        return OK;
+        return android::OK;
     }
 
-    KillProcessesWithOpenFiles(path, SIGTERM);
+    android::vold::KillProcessesWithOpenFiles(path, SIGTERM);
     if (sSleepOnUnmount) sleep(5);
     if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
-        return OK;
+        return android::OK;
     }
 
-    KillProcessesWithOpenFiles(path, SIGKILL);
+    android::vold::KillProcessesWithOpenFiles(path, SIGKILL);
     if (sSleepOnUnmount) sleep(5);
     if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
-        return OK;
+        return android::OK;
     }
-
+    PLOG(INFO) << "ForceUnmount failed";
     return -errno;
 }
 
-status_t KillProcessesUsingPath(const std::string& path) {
-    if (KillProcessesWithOpenFiles(path, SIGINT) == 0) {
-        return OK;
+android::status_t KillProcessesWithMountPrefix(const std::string& path) {
+    if (android::vold::KillProcessesWithMounts(path, SIGINT) == 0) {
+        return android::OK;
     }
     if (sSleepOnUnmount) sleep(5);
 
-    if (KillProcessesWithOpenFiles(path, SIGTERM) == 0) {
-        return OK;
+    if (android::vold::KillProcessesWithMounts(path, SIGTERM) == 0) {
+        return android::OK;
     }
     if (sSleepOnUnmount) sleep(5);
 
-    if (KillProcessesWithOpenFiles(path, SIGKILL) == 0) {
-        return OK;
+    if (android::vold::KillProcessesWithMounts(path, SIGKILL) == 0) {
+        return android::OK;
     }
     if (sSleepOnUnmount) sleep(5);
 
     // Send SIGKILL a second time to determine if we've
-    // actually killed everyone with open files
-    if (KillProcessesWithOpenFiles(path, SIGKILL) == 0) {
-        return OK;
+    // actually killed everyone mount
+    if (android::vold::KillProcessesWithMounts(path, SIGKILL) == 0) {
+        return android::OK;
     }
     PLOG(ERROR) << "Failed to kill processes using " << path;
     return -EBUSY;
 }
 
-status_t BindMount(const std::string& source, const std::string& target) {
+android::status_t KillProcessesUsingPath(const std::string& path) {
+    if (android::vold::KillProcessesWithOpenFiles(path, SIGINT) == 0) {
+        return android::OK;
+    }
+    if (sSleepOnUnmount) sleep(5);
+
+    if (android::vold::KillProcessesWithOpenFiles(path, SIGTERM) == 0) {
+        return android::OK;
+    }
+    if (sSleepOnUnmount) sleep(5);
+
+    if (android::vold::KillProcessesWithOpenFiles(path, SIGKILL) == 0) {
+        return android::OK;
+    }
+    if (sSleepOnUnmount) sleep(5);
+
+    // Send SIGKILL a second time to determine if we've
+    // actually killed everyone with open files
+    if (android::vold::KillProcessesWithOpenFiles(path, SIGKILL) == 0) {
+        return android::OK;
+    }
+    PLOG(ERROR) << "Failed to kill processes using " << path;
+    return -EBUSY;
+}
+
+android::status_t BindMount(const std::string& source, const std::string& target) {
     if (UnmountTree(target) < 0) {
         return -errno;
     }
@@ -202,10 +528,10 @@
         PLOG(ERROR) << "Failed to bind mount " << source << " to " << target;
         return -errno;
     }
-    return OK;
+    return android::OK;
 }
 
-status_t Symlink(const std::string& target, const std::string& linkpath) {
+android::status_t Symlink(const std::string& target, const std::string& linkpath) {
     if (Unlink(linkpath) < 0) {
         return -errno;
     }
@@ -213,22 +539,22 @@
         PLOG(ERROR) << "Failed to create symlink " << linkpath << " to " << target;
         return -errno;
     }
-    return OK;
+    return android::OK;
 }
 
-status_t Unlink(const std::string& linkpath) {
+android::status_t Unlink(const std::string& linkpath) {
     if (TEMP_FAILURE_RETRY(unlink(linkpath.c_str())) < 0 && errno != EINVAL && errno != ENOENT) {
         PLOG(ERROR) << "Failed to unlink " << linkpath;
         return -errno;
     }
-    return OK;
+    return android::OK;
 }
 
-status_t CreateDir(const std::string& dir, mode_t mode) {
+android::status_t CreateDir(const std::string& dir, mode_t mode) {
     struct stat sb;
     if (TEMP_FAILURE_RETRY(stat(dir.c_str(), &sb)) == 0) {
         if (S_ISDIR(sb.st_mode)) {
-            return OK;
+            return android::OK;
         } else if (TEMP_FAILURE_RETRY(unlink(dir.c_str())) == -1) {
             PLOG(ERROR) << "Failed to unlink " << dir;
             return -errno;
@@ -241,7 +567,7 @@
         PLOG(ERROR) << "Failed to mkdir " << dir;
         return -errno;
     }
-    return OK;
+    return android::OK;
 }
 
 bool FindValue(const std::string& raw, const std::string& key, std::string* value) {
@@ -264,7 +590,7 @@
     return true;
 }
 
-static status_t readMetadata(const std::string& path, std::string* fsType, std::string* fsUuid,
+static android::status_t readMetadata(const std::string& path, std::string* fsType, std::string* fsUuid,
                              std::string* fsLabel, bool untrusted) {
     fsType->clear();
     fsUuid->clear();
@@ -283,8 +609,8 @@
     cmd.push_back(path);
 
     std::vector<std::string> output;
-    status_t res = ForkExecvp(cmd, &output, untrusted ? sBlkidUntrustedContext : sBlkidContext);
-    if (res != OK) {
+    android::status_t res = ForkExecvp(cmd, &output, untrusted ? sBlkidUntrustedContext : sBlkidContext);
+    if (res != android::OK) {
         LOG(WARNING) << "blkid failed to identify " << path;
         return res;
     }
@@ -296,15 +622,15 @@
         FindValue(line, "LABEL", fsLabel);
     }
 
-    return OK;
+    return android::OK;
 }
 
-status_t ReadMetadata(const std::string& path, std::string* fsType, std::string* fsUuid,
+android::status_t ReadMetadata(const std::string& path, std::string* fsType, std::string* fsUuid,
                       std::string* fsLabel) {
     return readMetadata(path, fsType, fsUuid, fsLabel, false);
 }
 
-status_t ReadMetadataUntrusted(const std::string& path, std::string* fsType, std::string* fsUuid,
+android::status_t ReadMetadataUntrusted(const std::string& path, std::string* fsType, std::string* fsUuid,
                                std::string* fsLabel) {
     return readMetadata(path, fsType, fsUuid, fsLabel, true);
 }
@@ -324,7 +650,7 @@
     return argv;
 }
 
-static status_t ReadLinesFromFdAndLog(std::vector<std::string>* output,
+static android::status_t ReadLinesFromFdAndLog(std::vector<std::string>* output,
                                       android::base::unique_fd ufd) {
     std::unique_ptr<FILE, int (*)(FILE*)> fp(android::base::Fdopen(std::move(ufd), "r"), fclose);
     if (!fp) {
@@ -337,10 +663,10 @@
         LOG(DEBUG) << line;
         if (output) output->emplace_back(line);
     }
-    return OK;
+    return android::OK;
 }
 
-status_t ForkExecvp(const std::vector<std::string>& args, std::vector<std::string>* output,
+android::status_t ForkExecvp(const std::vector<std::string>& args, std::vector<std::string>* output,
                     security_context_t context) {
     auto argv = ConvertToArgv(args);
 
@@ -365,7 +691,7 @@
         }
         pipe_write.reset();
         execvp(argv[0], const_cast<char**>(argv.data()));
-        PLOG(ERROR) << "exec in ForkExecvp" << " cmd: " << argv[0];
+        PLOG(ERROR) << "exec in ForkExecvp";
         _exit(EXIT_FAILURE);
     }
     if (pid == -1) {
@@ -390,7 +716,7 @@
         LOG(ERROR) << "Process exited with code: " << WEXITSTATUS(status);
         return WEXITSTATUS(status);
     }
-    return OK;
+    return android::OK;
 }
 
 pid_t ForkExecvpAsync(const std::vector<std::string>& args) {
@@ -413,12 +739,12 @@
     return pid;
 }
 
-status_t ReadRandomBytes(size_t bytes, std::string& out) {
+android::status_t ReadRandomBytes(size_t bytes, std::string& out) {
     out.resize(bytes);
     return ReadRandomBytes(bytes, &out[0]);
 }
 
-status_t ReadRandomBytes(size_t bytes, char* buf) {
+android::status_t ReadRandomBytes(size_t bytes, char* buf) {
     int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
     if (fd == -1) {
         return -errno;
@@ -432,15 +758,15 @@
     close(fd);
 
     if (bytes == 0) {
-        return OK;
+        return android::OK;
     } else {
         return -EIO;
     }
 }
 
-status_t GenerateRandomUuid(std::string& out) {
-    status_t res = ReadRandomBytes(16, out);
-    if (res == OK) {
+android::status_t GenerateRandomUuid(std::string& out) {
+    android::status_t res = ReadRandomBytes(16, out);
+    if (res == android::OK) {
         out[6] &= 0x0f; /* clear version        */
         out[6] |= 0x40; /* set to version 4     */
         out[8] &= 0x3f; /* clear variant        */
@@ -449,7 +775,7 @@
     return res;
 }
 
-status_t HexToStr(const std::string& hex, std::string& str) {
+android::status_t HexToStr(const std::string& hex, std::string& str) {
     str.clear();
     bool even = true;
     char cur = 0;
@@ -487,30 +813,30 @@
         }
         even = !even;
     }
-    return even ? OK : -EINVAL;
+    return even ? android::OK : -EINVAL;
 }
 
 static const char* kLookup = "0123456789abcdef";
 
-status_t StrToHex(const std::string& str, std::string& hex) {
+android::status_t StrToHex(const std::string& str, std::string& hex) {
     hex.clear();
     for (size_t i = 0; i < str.size(); i++) {
         hex.push_back(kLookup[(str[i] & 0xF0) >> 4]);
         hex.push_back(kLookup[str[i] & 0x0F]);
     }
-    return OK;
+    return android::OK;
 }
 
-status_t StrToHex(const KeyBuffer& str, KeyBuffer& hex) {
+android::status_t StrToHex(const KeyBuffer& str, KeyBuffer& hex) {
     hex.clear();
     for (size_t i = 0; i < str.size(); i++) {
         hex.push_back(kLookup[(str.data()[i] & 0xF0) >> 4]);
         hex.push_back(kLookup[str.data()[i] & 0x0F]);
     }
-    return OK;
+    return android::OK;
 }
 
-status_t NormalizeHex(const std::string& in, std::string& out) {
+android::status_t NormalizeHex(const std::string& in, std::string& out) {
     std::string tmp;
     if (HexToStr(in, tmp)) {
         return -EINVAL;
@@ -518,17 +844,17 @@
     return StrToHex(tmp, out);
 }
 
-status_t GetBlockDevSize(int fd, uint64_t* size) {
+android::status_t GetBlockDevSize(int fd, uint64_t* size) {
     if (ioctl(fd, BLKGETSIZE64, size)) {
         return -errno;
     }
 
-    return OK;
+    return android::OK;
 }
 
-status_t GetBlockDevSize(const std::string& path, uint64_t* size) {
+android::status_t GetBlockDevSize(const std::string& path, uint64_t* size) {
     int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
-    status_t res = OK;
+    android::status_t res = android::OK;
 
     if (fd < 0) {
         return -errno;
@@ -541,17 +867,17 @@
     return res;
 }
 
-status_t GetBlockDev512Sectors(const std::string& path, uint64_t* nr_sec) {
+android::status_t GetBlockDev512Sectors(const std::string& path, uint64_t* nr_sec) {
     uint64_t size;
-    status_t res = GetBlockDevSize(path, &size);
+    android::status_t res = GetBlockDevSize(path, &size);
 
-    if (res != OK) {
+    if (res != android::OK) {
         return res;
     }
 
     *nr_sec = size / 512;
 
-    return OK;
+    return android::OK;
 }
 
 uint64_t GetFreeBytes(const std::string& path) {
@@ -626,6 +952,19 @@
     }
 }
 
+// TODO: Use a better way to determine if it's media provider app.
+bool IsFuseDaemon(const pid_t pid) {
+    auto path = StringPrintf("/proc/%d/mounts", pid);
+    char* tmp;
+    if (lgetfilecon(path.c_str(), &tmp) < 0) {
+        return false;
+    }
+    bool result = android::base::StartsWith(tmp, kMediaProviderAppCtx)
+            || android::base::StartsWith(tmp, kMediaProviderCtx);
+    freecon(tmp);
+    return result;
+}
+
 bool IsFilesystemSupported(const std::string& fsType) {
     std::string supported;
     if (!ReadFileToString(kProcFilesystems, &supported)) {
@@ -635,8 +974,13 @@
     return supported.find(fsType + "\n") != std::string::npos;
 }
 
-status_t WipeBlockDevice(const std::string& path) {
-    status_t res = -1;
+bool IsSdcardfsUsed() {
+    return IsFilesystemSupported("sdcardfs") &&
+           android::base::GetBoolProperty(kExternalStorageSdcardfs, true);
+}
+
+android::status_t WipeBlockDevice(const std::string& path) {
+    android::status_t res = -1;
     const char* c_path = path.c_str();
     uint64_t range[2] = {0, 0};
 
@@ -646,7 +990,7 @@
         goto done;
     }
 
-    if (GetBlockDevSize(fd, &range[1]) != OK) {
+    if (GetBlockDevSize(fd, &range[1]) != android::OK) {
         PLOG(ERROR) << "Failed to determine size of " << path;
         goto done;
     }
@@ -759,7 +1103,7 @@
     }
 }
 
-status_t RestoreconRecursive(const std::string& path) {
+android::status_t RestoreconRecursive(const std::string& path) {
     LOG(DEBUG) << "Starting restorecon of " << path;
 
     static constexpr const char* kRestoreconString = "selinux.restorecon_recursive";
@@ -770,7 +1114,7 @@
     android::base::WaitForProperty(kRestoreconString, path);
 
     LOG(DEBUG) << "Finished restorecon of " << path;
-    return OK;
+    return android::OK;
 }
 
 bool Readlinkat(int dirfd, const std::string& path, std::string* result) {
@@ -796,11 +1140,42 @@
     }
 }
 
-bool IsRunningInEmulator() {
-    return android::base::GetBoolProperty("ro.kernel.qemu", false);
+static unsigned int GetMajorBlockVirtioBlk() {
+    std::string devices;
+    if (!ReadFileToString(kProcDevices, &devices)) {
+        PLOG(ERROR) << "Unable to open /proc/devices";
+        return 0;
+    }
+
+    bool blockSection = false;
+    for (auto line : android::base::Split(devices, "\n")) {
+        if (line == "Block devices:") {
+            blockSection = true;
+        } else if (line == "Character devices:") {
+            blockSection = false;
+        } else if (blockSection) {
+            auto tokens = android::base::Split(line, " ");
+            if (tokens.size() == 2 && tokens[1] == "virtblk") {
+                return std::stoul(tokens[0]);
+            }
+        }
+    }
+
+    return 0;
 }
 
-static status_t findMountPointsWithPrefix(const std::string& prefix,
+bool IsVirtioBlkDevice(unsigned int major) {
+    // Most virtualized platforms expose block devices with the virtio-blk
+    // block device driver. Unfortunately, this driver does not use a fixed
+    // major number, but relies on the kernel to assign one from a specific
+    // range of block majors, which are allocated for "LOCAL/EXPERIMENAL USE"
+    // per Documentation/devices.txt. This is true even for the latest Linux
+    // kernel (4.4; see init() in drivers/block/virtio_blk.c).
+    static unsigned int kMajorBlockVirtioBlk = GetMajorBlockVirtioBlk();
+    return kMajorBlockVirtioBlk && major == kMajorBlockVirtioBlk;
+}
+
+static android::status_t findMountPointsWithPrefix(const std::string& prefix,
                                           std::list<std::string>& mountPoints) {
     // Add a trailing slash if the client didn't provide one so that we don't match /foo/barbaz
     // when the prefix is /foo/bar
@@ -824,13 +1199,13 @@
             mountPoints.push_front(mountPoint);
         }
     }
-    return OK;
+    return android::OK;
 }
 
 // Unmount all mountpoints that start with prefix. prefix itself doesn't need to be a mountpoint.
-status_t UnmountTreeWithPrefix(const std::string& prefix) {
+android::status_t UnmountTreeWithPrefix(const std::string& prefix) {
     std::list<std::string> toUnmount;
-    status_t result = findMountPointsWithPrefix(prefix, toUnmount);
+    android::status_t result = findMountPointsWithPrefix(prefix, toUnmount);
     if (result < 0) {
         return result;
     }
@@ -843,23 +1218,23 @@
     return result;
 }
 
-status_t UnmountTree(const std::string& mountPoint) {
+android::status_t UnmountTree(const std::string& mountPoint) {
     if (TEMP_FAILURE_RETRY(umount2(mountPoint.c_str(), MNT_DETACH)) < 0 && errno != EINVAL &&
         errno != ENOENT) {
         PLOG(ERROR) << "Failed to unmount " << mountPoint;
         return -errno;
     }
-    return OK;
+    return android::OK;
 }
 
-static status_t delete_dir_contents(DIR* dir) {
+static android::status_t delete_dir_contents(DIR* dir) {
     // Shamelessly borrowed from android::installd
     int dfd = dirfd(dir);
     if (dfd < 0) {
         return -errno;
     }
 
-    status_t result = OK;
+    android::status_t result = android::OK;
     struct dirent* de;
     while ((de = readdir(dir))) {
         const char* name = de->d_name;
@@ -899,8 +1274,8 @@
     return result;
 }
 
-status_t DeleteDirContentsAndDir(const std::string& pathname) {
-    status_t res = DeleteDirContents(pathname);
+android::status_t DeleteDirContentsAndDir(const std::string& pathname) {
+    android::status_t res = DeleteDirContents(pathname);
     if (res < 0) {
         return res;
     }
@@ -909,15 +1284,15 @@
         return -errno;
     }
     LOG(VERBOSE) << "Success: rmdir on " << pathname;
-    return OK;
+    return android::OK;
 }
 
-status_t DeleteDirContents(const std::string& pathname) {
+android::status_t DeleteDirContents(const std::string& pathname) {
     // Shamelessly borrowed from android::installd
     std::unique_ptr<DIR, decltype(&closedir)> dirp(opendir(pathname.c_str()), closedir);
     if (!dirp) {
         if (errno == ENOENT) {
-            return OK;
+            return android::OK;
         }
         PLOG(ERROR) << "Failed to opendir " << pathname;
         return -errno;
@@ -926,7 +1301,7 @@
 }
 
 // TODO(118708649): fix duplication with init/util.h
-status_t WaitForFile(const char* filename, std::chrono::nanoseconds timeout) {
+android::status_t WaitForFile(const char* filename, std::chrono::nanoseconds timeout) {
     android::base::Timer t;
     while (t.duration() < timeout) {
         struct stat sb;
@@ -985,5 +1360,263 @@
     return true;
 }
 
-}  // namespace vold
-}  // namespace android
+android::status_t AbortFuseConnections() {
+    namespace fs = std::filesystem;
+
+    for (const auto& itEntry : fs::directory_iterator("/sys/fs/fuse/connections")) {
+        std::string abortPath = itEntry.path().string() + "/abort";
+        LOG(DEBUG) << "Aborting fuse connection entry " << abortPath;
+        bool ret = writeStringToFile("1", abortPath);
+        if (!ret) {
+            LOG(WARNING) << "Failed to write to " << abortPath;
+        }
+    }
+
+    return android::OK;
+}
+
+android::status_t EnsureDirExists(const std::string& path, mode_t mode, uid_t uid, gid_t gid) {
+    if (access(path.c_str(), F_OK) != 0) {
+        PLOG(WARNING) << "Dir does not exist: " << path;
+        if (fs_prepare_dir(path.c_str(), mode, uid, gid) != 0) {
+            return -errno;
+        }
+    }
+    return android::OK;
+}
+
+// Gets the sysfs path for parameters of the backing device info (bdi)
+static std::string getBdiPathForMount(const std::string& mount) {
+    // First figure out MAJOR:MINOR of mount. Simplest way is to stat the path.
+    struct stat info;
+    if (stat(mount.c_str(), &info) != 0) {
+        PLOG(ERROR) << "Failed to stat " << mount;
+        return "";
+    }
+    unsigned int maj = major(info.st_dev);
+    unsigned int min = minor(info.st_dev);
+
+    return StringPrintf("/sys/class/bdi/%u:%u", maj, min);
+}
+
+// Configures max_ratio for the FUSE filesystem.
+void ConfigureMaxDirtyRatioForFuse(const std::string& fuse_mount, unsigned int max_ratio) {
+    LOG(INFO) << "Configuring max_ratio of " << fuse_mount << " fuse filesystem to " << max_ratio;
+    if (max_ratio > 100) {
+        LOG(ERROR) << "Invalid max_ratio: " << max_ratio;
+        return;
+    }
+    std::string fuseBdiPath = getBdiPathForMount(fuse_mount);
+    if (fuseBdiPath == "") {
+        return;
+    }
+    std::string max_ratio_file = StringPrintf("%s/max_ratio", fuseBdiPath.c_str());
+    unique_fd fd(TEMP_FAILURE_RETRY(open(max_ratio_file.c_str(), O_WRONLY | O_CLOEXEC)));
+    if (fd.get() == -1) {
+        PLOG(ERROR) << "Failed to open " << max_ratio_file;
+        return;
+    }
+    LOG(INFO) << "Writing " << max_ratio << " to " << max_ratio_file;
+    if (!WriteStringToFd(std::to_string(max_ratio), fd)) {
+        PLOG(ERROR) << "Failed to write to " << max_ratio_file;
+    }
+}
+
+// Configures read ahead property of the fuse filesystem with the mount point |fuse_mount| by
+// writing |read_ahead_kb| to the /sys/class/bdi/MAJOR:MINOR/read_ahead_kb.
+void ConfigureReadAheadForFuse(const std::string& fuse_mount, size_t read_ahead_kb) {
+    LOG(INFO) << "Configuring read_ahead of " << fuse_mount << " fuse filesystem to "
+              << read_ahead_kb << "kb";
+    std::string fuseBdiPath = getBdiPathForMount(fuse_mount);
+    if (fuseBdiPath == "") {
+        return;
+    }
+    // We found the bdi path for our filesystem, time to configure read ahead!
+    std::string read_ahead_file = StringPrintf("%s/read_ahead_kb", fuseBdiPath.c_str());
+    unique_fd fd(TEMP_FAILURE_RETRY(open(read_ahead_file.c_str(), O_WRONLY | O_CLOEXEC)));
+    if (fd.get() == -1) {
+        PLOG(ERROR) << "Failed to open " << read_ahead_file;
+        return;
+    }
+    LOG(INFO) << "Writing " << read_ahead_kb << " to " << read_ahead_file;
+    if (!WriteStringToFd(std::to_string(read_ahead_kb), fd)) {
+        PLOG(ERROR) << "Failed to write to " << read_ahead_file;
+    }
+}
+
+android::status_t MountUserFuse(userid_t user_id, const std::string& absolute_lower_path,
+                       const std::string& relative_upper_path, android::base::unique_fd* fuse_fd) {
+    std::string pre_fuse_path(StringPrintf("/mnt/user/%d", user_id));
+    std::string fuse_path(
+            StringPrintf("%s/%s", pre_fuse_path.c_str(), relative_upper_path.c_str()));
+
+    std::string pre_pass_through_path(StringPrintf("/mnt/pass_through/%d", user_id));
+    std::string pass_through_path(
+            StringPrintf("%s/%s", pre_pass_through_path.c_str(), relative_upper_path.c_str()));
+
+    // Ensure that /mnt/user is 0700. With FUSE, apps don't need access to /mnt/user paths directly.
+    // Without FUSE however, apps need /mnt/user access so /mnt/user in init.rc is 0755 until here
+    auto result = PrepareDir("/mnt/user", 0750, AID_ROOT, AID_MEDIA_RW);
+    if (result != android::OK) {
+        PLOG(ERROR) << "Failed to prepare directory /mnt/user";
+        return -1;
+    }
+
+    // Shell is neither AID_ROOT nor AID_EVERYBODY. Since it equally needs 'execute' access to
+    // /mnt/user/0 to 'adb shell ls /sdcard' for instance, we set the uid bit of /mnt/user/0 to
+    // AID_SHELL. This gives shell access along with apps running as group everybody (user 0 apps)
+    // These bits should be consistent with what is set in zygote in
+    // com_android_internal_os_Zygote#MountEmulatedStorage on volume bind mount during app fork
+    result = PrepareDir(pre_fuse_path, 0710, user_id ? AID_ROOT : AID_SHELL,
+                             multiuser_get_uid(user_id, AID_EVERYBODY));
+    if (result != android::OK) {
+        PLOG(ERROR) << "Failed to prepare directory " << pre_fuse_path;
+        return -1;
+    }
+
+    result = PrepareDir(fuse_path, 0700, AID_ROOT, AID_ROOT);
+    if (result != android::OK) {
+        PLOG(ERROR) << "Failed to prepare directory " << fuse_path;
+        return -1;
+    }
+
+    result = PrepareDir(pre_pass_through_path, 0710, AID_ROOT, AID_MEDIA_RW);
+    if (result != android::OK) {
+        PLOG(ERROR) << "Failed to prepare directory " << pre_pass_through_path;
+        return -1;
+    }
+
+    result = PrepareDir(pass_through_path, 0710, AID_ROOT, AID_MEDIA_RW);
+    if (result != android::OK) {
+        PLOG(ERROR) << "Failed to prepare directory " << pass_through_path;
+        return -1;
+    }
+
+    if (relative_upper_path == "emulated") {
+        std::string linkpath(StringPrintf("/mnt/user/%d/self", user_id));
+        result = PrepareDir(linkpath, 0755, AID_ROOT, AID_ROOT);
+        if (result != android::OK) {
+            PLOG(ERROR) << "Failed to prepare directory " << linkpath;
+            return -1;
+        }
+        linkpath += "/primary";
+        Symlink("/storage/emulated/" + std::to_string(user_id), linkpath);
+
+        std::string pass_through_linkpath(StringPrintf("/mnt/pass_through/%d/self", user_id));
+        result = PrepareDir(pass_through_linkpath, 0710, AID_ROOT, AID_MEDIA_RW);
+        if (result != android::OK) {
+            PLOG(ERROR) << "Failed to prepare directory " << pass_through_linkpath;
+            return -1;
+        }
+        pass_through_linkpath += "/primary";
+        Symlink("/storage/emulated/" + std::to_string(user_id), pass_through_linkpath);
+    }
+
+    // Open fuse fd.
+    fuse_fd->reset(open("/dev/fuse", O_RDWR | O_CLOEXEC));
+    if (fuse_fd->get() == -1) {
+        PLOG(ERROR) << "Failed to open /dev/fuse";
+        return -1;
+    }
+
+    // Note: leaving out default_permissions since we don't want kernel to do lower filesystem
+    // permission checks before routing to FUSE daemon.
+    const auto opts = StringPrintf(
+        "fd=%i,"
+        "rootmode=40000,"
+        "allow_other,"
+        "user_id=0,group_id=0,",
+        fuse_fd->get());
+
+    result = TEMP_FAILURE_RETRY(mount("/dev/fuse", fuse_path.c_str(), "fuse",
+                                      MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME | MS_LAZYTIME,
+                                      opts.c_str()));
+    if (result != 0) {
+        PLOG(ERROR) << "Failed to mount " << fuse_path;
+        return -errno;
+    }
+
+    if (IsSdcardfsUsed()) {
+        std::string sdcardfs_path(
+                StringPrintf("/mnt/runtime/full/%s", relative_upper_path.c_str()));
+
+        LOG(INFO) << "Bind mounting " << sdcardfs_path << " to " << pass_through_path;
+        return BindMount(sdcardfs_path, pass_through_path);
+    } else {
+        LOG(INFO) << "Bind mounting " << absolute_lower_path << " to " << pass_through_path;
+        return BindMount(absolute_lower_path, pass_through_path);
+    }
+}
+
+android::status_t UnmountUserFuse(userid_t user_id, const std::string& absolute_lower_path,
+                         const std::string& relative_upper_path) {
+    std::string fuse_path(StringPrintf("/mnt/user/%d/%s", user_id, relative_upper_path.c_str()));
+    std::string pass_through_path(
+            StringPrintf("/mnt/pass_through/%d/%s", user_id, relative_upper_path.c_str()));
+
+    // Best effort unmount pass_through path
+    sSleepOnUnmount = false;
+    LOG(INFO) << "Unmounting pass_through_path " << pass_through_path;
+    auto status = ForceUnmount(pass_through_path);
+    if (status != android::OK) {
+        LOG(ERROR) << "Failed to unmount " << pass_through_path;
+    }
+    rmdir(pass_through_path.c_str());
+
+    LOG(INFO) << "Unmounting fuse path " << fuse_path;
+    android::status_t result = ForceUnmount(fuse_path);
+    sSleepOnUnmount = true;
+    if (result != android::OK) {
+        // TODO(b/135341433): MNT_DETACH is needed for fuse because umount2 can fail with EBUSY.
+        // Figure out why we get EBUSY and remove this special casing if possible.
+        PLOG(ERROR) << "Failed to unmount. Trying MNT_DETACH " << fuse_path << " ...";
+        if (umount2(fuse_path.c_str(), UMOUNT_NOFOLLOW | MNT_DETACH) && errno != EINVAL &&
+            errno != ENOENT) {
+            PLOG(ERROR) << "Failed to unmount with MNT_DETACH " << fuse_path;
+            return -errno;
+        }
+        result = android::OK;
+    }
+    rmdir(fuse_path.c_str());
+
+    return result;
+}
+
+android::status_t PrepareAndroidDirs(const std::string& volumeRoot) {
+    std::string androidDir = volumeRoot + kAndroidDir;
+    std::string androidDataDir = volumeRoot + kAppDataDir;
+    std::string androidObbDir = volumeRoot + kAppObbDir;
+    std::string androidMediaDir = volumeRoot + kAppMediaDir;
+
+    bool useSdcardFs = IsSdcardfsUsed();
+
+    // mode 0771 + sticky bit for inheriting GIDs
+    mode_t mode = S_IRWXU | S_IRWXG | S_IXOTH | S_ISGID;
+    if (fs_prepare_dir(androidDir.c_str(), mode, AID_MEDIA_RW, AID_MEDIA_RW) != 0) {
+        PLOG(ERROR) << "Failed to create " << androidDir;
+        return -errno;
+    }
+
+    gid_t dataGid = useSdcardFs ? AID_MEDIA_RW : AID_EXT_DATA_RW;
+    if (fs_prepare_dir(androidDataDir.c_str(), mode, AID_MEDIA_RW, dataGid) != 0) {
+        PLOG(ERROR) << "Failed to create " << androidDataDir;
+        return -errno;
+    }
+
+    gid_t obbGid = useSdcardFs ? AID_MEDIA_RW : AID_EXT_OBB_RW;
+    if (fs_prepare_dir(androidObbDir.c_str(), mode, AID_MEDIA_RW, obbGid) != 0) {
+        PLOG(ERROR) << "Failed to create " << androidObbDir;
+        return -errno;
+    }
+    // Some other apps, like installers, have write access to the OBB directory
+    // to pre-download them. To make sure newly created folders in this directory
+    // have the right permissions, set a default ACL.
+    SetDefaultAcl(androidObbDir, mode, AID_MEDIA_RW, obbGid, {});
+
+    if (fs_prepare_dir(androidMediaDir.c_str(), mode, AID_MEDIA_RW, AID_MEDIA_RW) != 0) {
+        PLOG(ERROR) << "Failed to create " << androidMediaDir;
+        return -errno;
+    }
+
+    return android::OK;
+}