Mount FUSE for appfuse directories.
BUG=25755834
Change-Id: Icb59b5096239fd3611b614a0870d0ec910cee277
diff --git a/CommandListener.cpp b/CommandListener.cpp
index c9123b0..766b936 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -29,6 +29,7 @@
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
+#include <ctype.h>
#define LOG_TAG "VoldCmdListener"
@@ -623,6 +624,8 @@
return sendGenericOkFail(cli, 0);
}
+static size_t kAppFuseMaxMountPointName = 32;
+
CommandListener::AppFuseCmd::AppFuseCmd() : VoldCommand("appfuse") {}
int CommandListener::AppFuseCmd::runCommand(SocketClient *cli,
@@ -639,19 +642,74 @@
if (command == "mount" && argc == 4) {
const uid_t uid = atoi(argv[2]);
const std::string name(argv[3]);
+
+ // Check mount point name.
+ bool invalidName = false;
+ if (name.size() > kAppFuseMaxMountPointName) {
+ invalidName = true;
+ }
+ for (size_t i = 0; i < name.size(); i++) {
+ if (!isalnum(name[i])) {
+ invalidName = true;
+ break;
+ }
+ }
+ if (invalidName) {
+ return cli->sendMsg(
+ ResponseCode::CommandParameterError,
+ "Invalid mount point name.",
+ false);
+ }
+
+ // Create directories.
+ char path[PATH_MAX];
+ {
+ snprintf(path, PATH_MAX, "/mnt/appfuse/%d_%s", uid, name.c_str());
+ umount2(path, UMOUNT_NOFOLLOW | MNT_DETACH);
+ const int result = android::vold::PrepareDir(path, 0700, 0, 0);
+ if (result != 0) {
+ return sendGenericOkFail(cli, result);
+ }
+ }
+
+ // Open device FD.
const int device_fd = open("/dev/fuse", O_RDWR);
if (device_fd < 0) {
sendGenericOkFail(cli, device_fd);
return 0;
}
- // TODO: Create appfuse directory and mount it.
+ // Mount.
+ {
+ char opts[256];
+ snprintf(
+ opts,
+ sizeof(opts),
+ "fd=%i,"
+ "rootmode=40000,"
+ "default_permissions,"
+ "user_id=%d,group_id=%d",
+ device_fd,
+ uid,
+ uid);
+ // TODO: Make it bound mount in application namespace.
+ // TODO: Add context= option to opts.
+ const int result = mount(
+ "/dev/fuse", path, "fuse",
+ MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts);
+ if (result != 0) {
+ sendGenericOkFail(cli, 1);
+ return 0;
+ }
+ }
+
const int result = sendFd(cli, device_fd);
close(device_fd);
return result;
}
- return cli->sendMsg(ResponseCode::CommandSyntaxError, nullptr, false);
+ return cli->sendMsg(
+ ResponseCode::CommandSyntaxError, "Unknown appfuse cmd", false);
}
int CommandListener::AppFuseCmd::sendFd(SocketClient *cli, int fd) {