Change AppFuse mount location to vold namespace

Previously, AppFuse is mounted in system_server's mount namespace. This
CL moves the mount location to vold namespace.

Bug: 110379912
Test: testOpenProxyFileDescriptor passes
Change-Id: Id93c26d5a98842c78f27850c83e15df619cec1ab
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 1fb7ce7..21136cf 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -648,7 +648,7 @@
     return android::OK;
 }
 
-static android::status_t mountInNamespace(uid_t uid, int device_fd, const std::string& path) {
+static android::status_t mount(int device_fd, const std::string& path) {
     // Remove existing mount.
     android::vold::ForceUnmount(path);
 
@@ -657,10 +657,10 @@
         "rootmode=40000,"
         "default_permissions,"
         "allow_other,"
-        "user_id=%d,group_id=%d,"
+        "user_id=0,group_id=0,"
         "context=\"u:object_r:app_fuse_file:s0\","
         "fscontext=u:object_r:app_fusefs:s0",
-        device_fd, uid, uid);
+        device_fd);
 
     const int result =
         TEMP_FAILURE_RETRY(mount("/dev/fuse", path.c_str(), "fuse",
@@ -673,101 +673,34 @@
     return android::OK;
 }
 
-static android::status_t runCommandInNamespace(const std::string& command, uid_t uid, pid_t pid,
-                                               const std::string& path, int device_fd) {
+static android::status_t runCommand(const std::string& command, uid_t uid, const std::string& path,
+                                    int device_fd) {
     if (DEBUG_APPFUSE) {
-        LOG(DEBUG) << "Run app fuse command " << command << " for the path " << path
-                   << " in namespace " << uid;
+        LOG(DEBUG) << "Run app fuse command " << command << " for the path " << path << " and uid "
+                   << uid;
     }
 
-    unique_fd dir(open("/proc", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
-    if (dir.get() == -1) {
-        PLOG(ERROR) << "Failed to open /proc";
-        return -errno;
-    }
-
-    // Obtains process file descriptor.
-    const std::string pid_str = StringPrintf("%d", pid);
-    const unique_fd pid_fd(openat(dir.get(), pid_str.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
-    if (pid_fd.get() == -1) {
-        PLOG(ERROR) << "Failed to open /proc/" << pid;
-        return -errno;
-    }
-
-    // Check UID of process.
-    {
-        struct stat sb;
-        const int result = fstat(pid_fd.get(), &sb);
-        if (result == -1) {
-            PLOG(ERROR) << "Failed to stat /proc/" << pid;
+    if (command == "mount") {
+        return mount(device_fd, path);
+    } else if (command == "unmount") {
+        // If it's just after all FD opened on mount point are closed, umount2 can fail with
+        // EBUSY. To avoid the case, specify MNT_DETACH.
+        if (umount2(path.c_str(), UMOUNT_NOFOLLOW | MNT_DETACH) != 0 && errno != EINVAL &&
+            errno != ENOENT) {
+            PLOG(ERROR) << "Failed to unmount directory.";
             return -errno;
         }
-        if (sb.st_uid != AID_SYSTEM) {
-            LOG(ERROR) << "Only system can mount appfuse. UID expected=" << AID_SYSTEM
-                       << ", actual=" << sb.st_uid;
-            return -EPERM;
+        if (rmdir(path.c_str()) != 0) {
+            PLOG(ERROR) << "Failed to remove the mount directory.";
+            return -errno;
         }
+        return android::OK;
+    } else {
+        LOG(ERROR) << "Unknown appfuse command " << command;
+        return -EPERM;
     }
 
-    // Matches so far, but refuse to touch if in root namespace
-    {
-        std::string rootName;
-        std::string pidName;
-        if (!android::vold::Readlinkat(dir.get(), "1/ns/mnt", &rootName) ||
-            !android::vold::Readlinkat(pid_fd.get(), "ns/mnt", &pidName)) {
-            PLOG(ERROR) << "Failed to read namespaces";
-            return -EPERM;
-        }
-        if (rootName == pidName) {
-            LOG(ERROR) << "Don't mount appfuse in root namespace";
-            return -EPERM;
-        }
-    }
-
-    // We purposefully leave the namespace open across the fork
-    unique_fd ns_fd(openat(pid_fd.get(), "ns/mnt", O_RDONLY));  // not O_CLOEXEC
-    if (ns_fd.get() < 0) {
-        PLOG(ERROR) << "Failed to open namespace for /proc/" << pid << "/ns/mnt";
-        return -errno;
-    }
-
-    int child = fork();
-    if (child == 0) {
-        if (setns(ns_fd.get(), CLONE_NEWNS) != 0) {
-            PLOG(ERROR) << "Failed to setns";
-            _exit(-errno);
-        }
-
-        if (command == "mount") {
-            _exit(mountInNamespace(uid, device_fd, path));
-        } else if (command == "unmount") {
-            // If it's just after all FD opened on mount point are closed, umount2 can fail with
-            // EBUSY. To avoid the case, specify MNT_DETACH.
-            if (umount2(path.c_str(), UMOUNT_NOFOLLOW | MNT_DETACH) != 0 && errno != EINVAL &&
-                errno != ENOENT) {
-                PLOG(ERROR) << "Failed to unmount directory.";
-                _exit(-errno);
-            }
-            if (rmdir(path.c_str()) != 0) {
-                PLOG(ERROR) << "Failed to remove the mount directory.";
-                _exit(-errno);
-            }
-            _exit(android::OK);
-        } else {
-            LOG(ERROR) << "Unknown appfuse command " << command;
-            _exit(-EPERM);
-        }
-    }
-
-    if (child == -1) {
-        PLOG(ERROR) << "Failed to folk child process";
-        return -errno;
-    }
-
-    android::status_t status;
-    TEMP_FAILURE_RETRY(waitpid(child, &status, 0));
-
-    return status;
+    return android::OK;
 }
 
 int VolumeManager::createObb(const std::string& sourcePath, const std::string& sourceKey,
@@ -822,7 +755,7 @@
     return android::OK;
 }
 
-int VolumeManager::mountAppFuse(uid_t uid, pid_t pid, int mountId, unique_fd* device_fd) {
+int VolumeManager::mountAppFuse(uid_t uid, int mountId, unique_fd* device_fd) {
     std::string name = std::to_string(mountId);
 
     // Check mount point name.
@@ -847,10 +780,10 @@
     }
 
     // Mount.
-    return runCommandInNamespace("mount", uid, pid, path, device_fd->get());
+    return runCommand("mount", uid, path, device_fd->get());
 }
 
-int VolumeManager::unmountAppFuse(uid_t uid, pid_t pid, int mountId) {
+int VolumeManager::unmountAppFuse(uid_t uid, int mountId) {
     std::string name = std::to_string(mountId);
 
     // Check mount point name.
@@ -860,5 +793,19 @@
         return -1;
     }
 
-    return runCommandInNamespace("unmount", uid, pid, path, -1 /* device_fd */);
+    return runCommand("unmount", uid, path, -1 /* device_fd */);
+}
+
+int VolumeManager::openAppFuseFile(uid_t uid, int mountId, int fileId, int flags) {
+    std::string name = std::to_string(mountId);
+
+    // Check mount point name.
+    std::string mountPoint;
+    if (getMountPath(uid, name, &mountPoint) != android::OK) {
+        LOG(ERROR) << "Invalid mount point name";
+        return -1;
+    }
+
+    std::string path = StringPrintf("%s/%d", mountPoint.c_str(), fileId);
+    return TEMP_FAILURE_RETRY(open(path.c_str(), flags));
 }