Mount /dev/fuse on /mnt/user/<userid>/<volumeid>
Since system_server cannot mount devices by itself,
add a binder interface to vold that system_server
can call to initiate this mount when required.
BUG: 135341433
Test: manual
Test: atest --test-mapping packages/providers/MediaProvider
Test: ExternalStorageHostTest DownloadProviderTests
Change-Id: If4fd02a1f1a8d921a3f96783d8c73e085c5b7ca1
diff --git a/Utils.cpp b/Utils.cpp
index 1616d80..bd3d452 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -165,7 +165,7 @@
if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
return OK;
}
-
+ PLOG(INFO) << "ForceUnmount failed";
return -errno;
}
@@ -985,5 +985,50 @@
return true;
}
+int MountUserFuse(userid_t user_id, const std::string& relative_path, int* device_fd) {
+ std::string path(StringPrintf("/mnt/user/%d/%s", user_id, relative_path.c_str()));
+
+ // Force remove the existing mount before we attempt to prepare the
+ // directory. If we have a dangling mount, then PrepareDir may fail if the
+ // indirection to FUSE doesn't work.
+ android::status_t result = android::vold::ForceUnmount(path);
+ if (result != android::OK) {
+ PLOG(ERROR) << "Failed to unmount " << path;
+ return -1;
+ }
+
+ // Create directories.
+ result = android::vold::PrepareDir(path, 0700, AID_ROOT, AID_ROOT);
+ if (result != android::OK) {
+ PLOG(ERROR) << "Failed to prepare directory " << path;
+ return -1;
+ }
+
+ // Open device fd.
+ *device_fd = open("/dev/fuse", O_RDWR | O_CLOEXEC);
+ if (*device_fd == -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,",
+ *device_fd);
+
+ const int result_int =
+ TEMP_FAILURE_RETRY(mount("/dev/fuse", path.c_str(), "fuse",
+ MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str()));
+ if (result_int != 0) {
+ PLOG(ERROR) << "Failed to mount " << path;
+ return -errno;
+ }
+ return 0;
+}
+
} // namespace vold
} // namespace android