From cbe69fc060d021be972af44904dd76ed1aa2a5a2 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 15 Sep 2017 16:50:28 -0600 Subject: [PATCH] Destroy vold socket interface completely. Long live Binder. Test: yes Bug: 13758960 Change-Id: If6be379b5a873f1b0c66dd1522b87413ad10fc46 --- Android.mk | 4 - Asec.h | 43 -- BenchmarkTask.cpp | 1 - CommandListener.cpp | 689 ----------------- CommandListener.h | 87 --- CryptCommandListener.cpp | 448 ----------- CryptCommandListener.h | 42 -- Devmapper.cpp | 77 -- Devmapper.h | 3 - Loop.cpp | 87 --- Loop.h | 5 - MoveTask.cpp | 1 - ResponseCode.cpp | 42 -- ResponseCode.h | 91 --- TrimTask.cpp | 1 - Utils.h | 2 - VoldCommand.cpp | 21 - VoldCommand.h | 28 - VoldNativeService.cpp | 14 + VoldNativeService.h | 1 + VolumeManager.cpp | 1353 ---------------------------------- VolumeManager.h | 83 --- binder/android/os/IVold.aidl | 1 + main.cpp | 27 - model/Disk.cpp | 41 +- model/Disk.h | 3 - model/PrivateVolume.cpp | 9 +- model/PublicVolume.cpp | 9 +- model/VolumeBase.cpp | 43 +- model/VolumeBase.h | 3 - tests/VolumeManager_test.cpp | 27 - vdc.cpp | 129 +--- vold.rc | 3 - 33 files changed, 40 insertions(+), 3378 deletions(-) delete mode 100644 Asec.h delete mode 100644 CommandListener.cpp delete mode 100644 CommandListener.h delete mode 100644 CryptCommandListener.cpp delete mode 100644 CryptCommandListener.h delete mode 100644 ResponseCode.cpp delete mode 100644 ResponseCode.h delete mode 100644 VoldCommand.cpp delete mode 100644 VoldCommand.h diff --git a/Android.mk b/Android.mk index 78d60df..5957df7 100644 --- a/Android.mk +++ b/Android.mk @@ -2,9 +2,6 @@ LOCAL_PATH:= $(call my-dir) common_src_files := \ VolumeManager.cpp \ - CommandListener.cpp \ - CryptCommandListener.cpp \ - VoldCommand.cpp \ NetlinkManager.cpp \ NetlinkHandler.cpp \ Process.cpp \ @@ -13,7 +10,6 @@ common_src_files := \ fs/Vfat.cpp \ Loop.cpp \ Devmapper.cpp \ - ResponseCode.cpp \ CheckBattery.cpp \ Ext4Crypt.cpp \ VoldUtil.c \ diff --git a/Asec.h b/Asec.h deleted file mode 100644 index dd64fd0..0000000 --- a/Asec.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _ASEC_H -#define _ASEC_H - -struct asec_superblock { -#define ASEC_SB_MAGIC 0xc0def00d - unsigned int magic; - -#define ASEC_SB_VER 1 - unsigned char ver; - -#define ASEC_SB_C_CIPHER_NONE 0 -#define ASEC_SB_C_CIPHER_TWOFISH 1 -#define ASEC_SB_C_CIPHER_AES 2 - unsigned char c_cipher; - -#define ASEC_SB_C_CHAIN_NONE 0 - unsigned char c_chain; - -#define ASEC_SB_C_OPTS_NONE 0 -#define ASEC_SB_C_OPTS_EXT4 1 - unsigned char c_opts; - -#define ASEC_SB_C_MODE_NONE 0 - unsigned char c_mode; -} __attribute__((packed)); - -#endif diff --git a/BenchmarkTask.cpp b/BenchmarkTask.cpp index 5ec249a..d10d792 100644 --- a/BenchmarkTask.cpp +++ b/BenchmarkTask.cpp @@ -17,7 +17,6 @@ #include "BenchmarkTask.h" #include "BenchmarkGen.h" #include "VolumeManager.h" -#include "ResponseCode.h" #include #include diff --git a/CommandListener.cpp b/CommandListener.cpp deleted file mode 100644 index a402ffa..0000000 --- a/CommandListener.cpp +++ /dev/null @@ -1,689 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define LOG_TAG "VoldCmdListener" - -#include -#include -#include -#include - -#include -#include - -#include "CommandListener.h" -#include "VolumeManager.h" -#include "model/VolumeBase.h" -#include "ResponseCode.h" -#include "Process.h" -#include "Loop.h" -#include "Devmapper.h" -#include "MoveTask.h" -#include "TrimTask.h" - -#define DUMP_ARGS 0 - -using android::base::unique_fd; - -CommandListener::CommandListener() : - FrameworkListener("vold", true) { - registerCmd(new DumpCmd()); - registerCmd(new VolumeCmd()); - registerCmd(new AsecCmd()); - registerCmd(new ObbCmd()); - registerCmd(new StorageCmd()); - registerCmd(new FstrimCmd()); - registerCmd(new AppFuseCmd()); -} - -#if DUMP_ARGS -void CommandListener::dumpArgs(int argc, char **argv, int argObscure) { - char buffer[4096]; - char *p = buffer; - - memset(buffer, 0, sizeof(buffer)); - int i; - for (i = 0; i < argc; i++) { - unsigned int len = strlen(argv[i]) + 1; // Account for space - if (i == argObscure) { - len += 2; // Account for {} - } - if (((p - buffer) + len) < (sizeof(buffer)-1)) { - if (i == argObscure) { - *p++ = '{'; - *p++ = '}'; - *p++ = ' '; - continue; - } - strcpy(p, argv[i]); - p+= strlen(argv[i]); - if (i != (argc -1)) { - *p++ = ' '; - } - } - } - SLOGD("%s", buffer); -} -#else -void CommandListener::dumpArgs(int /*argc*/, char ** /*argv*/, int /*argObscure*/) { } -#endif - -int CommandListener::sendGenericOkFail(SocketClient *cli, int cond) { - if (!cond) { - return cli->sendMsg(ResponseCode::CommandOkay, "Command succeeded", false); - } else { - return cli->sendMsg(ResponseCode::OperationFailed, "Command failed", false); - } -} - -CommandListener::DumpCmd::DumpCmd() : - VoldCommand("dump") { -} - -int CommandListener::DumpCmd::runCommand(SocketClient *cli, - int /*argc*/, char ** /*argv*/) { - cli->sendMsg(0, "Dumping loop status", false); - if (Loop::dumpState(cli)) { - cli->sendMsg(ResponseCode::CommandOkay, "Loop dump failed", true); - } - cli->sendMsg(0, "Dumping DM status", false); - if (Devmapper::dumpState(cli)) { - cli->sendMsg(ResponseCode::CommandOkay, "Devmapper dump failed", true); - } - cli->sendMsg(0, "Dumping mounted filesystems", false); - FILE *fp = fopen("/proc/mounts", "re"); - if (fp) { - char line[1024]; - while (fgets(line, sizeof(line), fp)) { - line[strlen(line)-1] = '\0'; - cli->sendMsg(0, line, false);; - } - fclose(fp); - } - - cli->sendMsg(ResponseCode::CommandOkay, "dump complete", false); - return 0; -} - -CommandListener::VolumeCmd::VolumeCmd() : - VoldCommand("volume") { -} - -int CommandListener::VolumeCmd::runCommand(SocketClient *cli, - int argc, char **argv) { - dumpArgs(argc, argv, -1); - - if (argc < 2) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false); - return 0; - } - - VolumeManager *vm = VolumeManager::Instance(); - std::lock_guard lock(vm->getLock()); - - // TODO: tease out methods not directly related to volumes - - std::string cmd(argv[1]); - if (cmd == "reset") { - return sendGenericOkFail(cli, vm->reset()); - - } else if (cmd == "shutdown") { - return sendGenericOkFail(cli, vm->shutdown()); - - } else if (cmd == "debug") { - return sendGenericOkFail(cli, vm->setDebug(true)); - - } else if (cmd == "partition" && argc > 3) { - // partition [diskId] [public|private|mixed] [ratio] - std::string id(argv[2]); - auto disk = vm->findDisk(id); - if (disk == nullptr) { - return cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown disk", false); - } - - std::string type(argv[3]); - if (type == "public") { - return sendGenericOkFail(cli, disk->partitionPublic()); - } else if (type == "private") { - return sendGenericOkFail(cli, disk->partitionPrivate()); - } else if (type == "mixed") { - if (argc < 4) { - return cli->sendMsg(ResponseCode::CommandSyntaxError, nullptr, false); - } - int frac = atoi(argv[4]); - return sendGenericOkFail(cli, disk->partitionMixed(frac)); - } else { - return cli->sendMsg(ResponseCode::CommandSyntaxError, nullptr, false); - } - - } else if (cmd == "mkdirs" && argc > 2) { - // mkdirs [path] - return sendGenericOkFail(cli, vm->mkdirs(argv[2])); - - } else if (cmd == "user_added" && argc > 3) { - // user_added [user] [serial] - return sendGenericOkFail(cli, vm->onUserAdded(atoi(argv[2]), atoi(argv[3]))); - - } else if (cmd == "user_removed" && argc > 2) { - // user_removed [user] - return sendGenericOkFail(cli, vm->onUserRemoved(atoi(argv[2]))); - - } else if (cmd == "user_started" && argc > 2) { - // user_started [user] - return sendGenericOkFail(cli, vm->onUserStarted(atoi(argv[2]))); - - } else if (cmd == "user_stopped" && argc > 2) { - // user_stopped [user] - return sendGenericOkFail(cli, vm->onUserStopped(atoi(argv[2]))); - - } else if (cmd == "mount" && argc > 2) { - // mount [volId] [flags] [user] - std::string id(argv[2]); - auto vol = vm->findVolume(id); - if (vol == nullptr) { - return cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume", false); - } - - int mountFlags = (argc > 3) ? atoi(argv[3]) : 0; - userid_t mountUserId = (argc > 4) ? atoi(argv[4]) : -1; - - vol->setMountFlags(mountFlags); - vol->setMountUserId(mountUserId); - - int res = vol->mount(); - if (mountFlags & android::vold::VolumeBase::MountFlags::kPrimary) { - vm->setPrimary(vol); - } - return sendGenericOkFail(cli, res); - - } else if (cmd == "unmount" && argc > 2) { - // unmount [volId] - std::string id(argv[2]); - auto vol = vm->findVolume(id); - if (vol == nullptr) { - return cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume", false); - } - - return sendGenericOkFail(cli, vol->unmount()); - - } else if (cmd == "format" && argc > 3) { - // format [volId] [fsType|auto] - std::string id(argv[2]); - std::string fsType(argv[3]); - auto vol = vm->findVolume(id); - if (vol == nullptr) { - return cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume", false); - } - - return sendGenericOkFail(cli, vol->format(fsType)); - - } else if (cmd == "move_storage" && argc > 3) { - // move_storage [fromVolId] [toVolId] - auto fromVol = vm->findVolume(std::string(argv[2])); - auto toVol = vm->findVolume(std::string(argv[3])); - if (fromVol == nullptr || toVol == nullptr) { - return cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume", false); - } - - (new android::vold::MoveTask(fromVol, toVol, nullptr))->start(); - return sendGenericOkFail(cli, 0); - - } else if (cmd == "benchmark" && argc > 2) { - // benchmark [volId] - std::string id(argv[2]); - LOG(WARNING) << "Benchmarking has moved to Binder interface"; - nsecs_t res = 0; - return cli->sendMsg(ResponseCode::CommandOkay, - android::base::StringPrintf("%" PRId64, res).c_str(), false); - - } else if (cmd == "forget_partition" && argc > 2) { - // forget_partition [partGuid] - std::string partGuid(argv[2]); - return sendGenericOkFail(cli, vm->forgetPartition(partGuid)); - - } else if (cmd == "remount_uid" && argc > 3) { - // remount_uid [uid] [none|default|read|write] - uid_t uid = atoi(argv[2]); - std::string mode(argv[3]); - return sendGenericOkFail(cli, vm->remountUid(uid, mode)); - } - - return cli->sendMsg(ResponseCode::CommandSyntaxError, nullptr, false); -} - -CommandListener::StorageCmd::StorageCmd() : - VoldCommand("storage") { -} - -int CommandListener::StorageCmd::runCommand(SocketClient *cli, - int argc, char **argv) { - /* Guarantied to be initialized by vold's main() before the CommandListener is active */ - extern struct fstab *fstab; - - dumpArgs(argc, argv, -1); - - if (argc < 2) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false); - return 0; - } - - if (!strcmp(argv[1], "mountall")) { - if (argc != 2) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: mountall", false); - return 0; - } - fs_mgr_mount_all(fstab, MOUNT_MODE_DEFAULT); - cli->sendMsg(ResponseCode::CommandOkay, "Mountall ran successfully", false); - return 0; - } - if (!strcmp(argv[1], "users")) { - DIR *dir; - struct dirent *de; - - if (argc < 3) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument: user ", false); - return 0; - } - if (!(dir = opendir("/proc"))) { - cli->sendMsg(ResponseCode::OperationFailed, "Failed to open /proc", true); - return 0; - } - - while ((de = readdir(dir))) { - int pid = Process::getPid(de->d_name); - - if (pid < 0) { - continue; - } - - std::string processName; - Process::getProcessName(pid, processName); - - if (Process::checkFileDescriptorSymLinks(pid, argv[2]) || - Process::checkFileMaps(pid, argv[2]) || - Process::checkSymLink(pid, argv[2], "cwd") || - Process::checkSymLink(pid, argv[2], "root") || - Process::checkSymLink(pid, argv[2], "exe")) { - - char msg[1024]; - snprintf(msg, sizeof(msg), "%d %s", pid, processName.c_str()); - cli->sendMsg(ResponseCode::StorageUsersListResult, msg, false); - } - } - closedir(dir); - cli->sendMsg(ResponseCode::CommandOkay, "Storage user list complete", false); - } else { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown storage cmd", false); - } - return 0; -} - -CommandListener::AsecCmd::AsecCmd() : - VoldCommand("asec") { -} - -void CommandListener::AsecCmd::listAsecsInDirectory(SocketClient *cli, const char *directory) { - DIR *d = opendir(directory); - - if (!d) { - cli->sendMsg(ResponseCode::OperationFailed, "Failed to open asec dir", true); - return; - } - - dirent* dent; - while ((dent = readdir(d)) != NULL) { - if (dent->d_name[0] == '.') - continue; - if (dent->d_type != DT_REG) - continue; - size_t name_len = strlen(dent->d_name); - if (name_len > 5 && name_len < 260 && - !strcmp(&dent->d_name[name_len - 5], ".asec")) { - char id[255]; - memset(id, 0, sizeof(id)); - strlcpy(id, dent->d_name, name_len - 4); - cli->sendMsg(ResponseCode::AsecListResult, id, false); - } - } - closedir(d); -} - -int CommandListener::AsecCmd::runCommand(SocketClient *cli, - int argc, char **argv) { - if (argc < 2) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false); - return 0; - } - - VolumeManager *vm = VolumeManager::Instance(); - int rc = 0; - - if (!strcmp(argv[1], "list")) { - dumpArgs(argc, argv, -1); - - listAsecsInDirectory(cli, VolumeManager::SEC_ASECDIR_EXT); - listAsecsInDirectory(cli, VolumeManager::SEC_ASECDIR_INT); - } else if (!strcmp(argv[1], "create")) { - dumpArgs(argc, argv, 5); - if (argc != 8) { - cli->sendMsg(ResponseCode::CommandSyntaxError, - "Usage: asec create " - "", false); - return 0; - } - - unsigned long numSectors = (atoi(argv[3]) * (1024 * 1024)) / 512; - const bool isExternal = (atoi(argv[7]) == 1); - rc = vm->createAsec(argv[2], numSectors, argv[4], argv[5], atoi(argv[6]), isExternal); - } else if (!strcmp(argv[1], "resize")) { - dumpArgs(argc, argv, -1); - if (argc != 5) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec resize ", false); - return 0; - } - unsigned long numSectors = (atoi(argv[3]) * (1024 * 1024)) / 512; - rc = vm->resizeAsec(argv[2], numSectors, argv[4]); - } else if (!strcmp(argv[1], "finalize")) { - dumpArgs(argc, argv, -1); - if (argc != 3) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec finalize ", false); - return 0; - } - rc = vm->finalizeAsec(argv[2]); - } else if (!strcmp(argv[1], "fixperms")) { - dumpArgs(argc, argv, -1); - if (argc != 5) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec fixperms ", false); - return 0; - } - - char *endptr; - gid_t gid = (gid_t) strtoul(argv[3], &endptr, 10); - if (*endptr != '\0') { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec fixperms ", false); - return 0; - } - - rc = vm->fixupAsecPermissions(argv[2], gid, argv[4]); - } else if (!strcmp(argv[1], "destroy")) { - dumpArgs(argc, argv, -1); - if (argc < 3) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec destroy [force]", false); - return 0; - } - bool force = false; - if (argc > 3 && !strcmp(argv[3], "force")) { - force = true; - } - rc = vm->destroyAsec(argv[2], force); - } else if (!strcmp(argv[1], "mount")) { - dumpArgs(argc, argv, 3); - if (argc != 6) { - cli->sendMsg(ResponseCode::CommandSyntaxError, - "Usage: asec mount ", false); - return 0; - } - bool readOnly = true; - if (!strcmp(argv[5], "rw")) { - readOnly = false; - } - rc = vm->mountAsec(argv[2], argv[3], atoi(argv[4]), readOnly); - } else if (!strcmp(argv[1], "unmount")) { - dumpArgs(argc, argv, -1); - if (argc < 3) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec unmount [force]", false); - return 0; - } - bool force = false; - if (argc > 3 && !strcmp(argv[3], "force")) { - force = true; - } - rc = vm->unmountAsec(argv[2], force); - } else if (!strcmp(argv[1], "rename")) { - dumpArgs(argc, argv, -1); - if (argc != 4) { - cli->sendMsg(ResponseCode::CommandSyntaxError, - "Usage: asec rename ", false); - return 0; - } - rc = vm->renameAsec(argv[2], argv[3]); - } else if (!strcmp(argv[1], "path")) { - dumpArgs(argc, argv, -1); - if (argc != 3) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec path ", false); - return 0; - } - char path[255]; - - if (!(rc = vm->getAsecMountPath(argv[2], path, sizeof(path)))) { - cli->sendMsg(ResponseCode::AsecPathResult, path, false); - return 0; - } - } else if (!strcmp(argv[1], "fspath")) { - dumpArgs(argc, argv, -1); - if (argc != 3) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec fspath ", false); - return 0; - } - char path[255]; - - if (!(rc = vm->getAsecFilesystemPath(argv[2], path, sizeof(path)))) { - cli->sendMsg(ResponseCode::AsecPathResult, path, false); - return 0; - } - } else { - dumpArgs(argc, argv, -1); - cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown asec cmd", false); - } - - if (!rc) { - cli->sendMsg(ResponseCode::CommandOkay, "asec operation succeeded", false); - } else { - rc = ResponseCode::convertFromErrno(); - cli->sendMsg(rc, "asec operation failed", true); - } - - return 0; -} - -CommandListener::ObbCmd::ObbCmd() : - VoldCommand("obb") { -} - -int CommandListener::ObbCmd::runCommand(SocketClient *cli, - int argc, char **argv) { - if (argc < 2) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false); - return 0; - } - - VolumeManager *vm = VolumeManager::Instance(); - int rc = 0; - - if (!strcmp(argv[1], "list")) { - dumpArgs(argc, argv, -1); - - rc = vm->listMountedObbs(cli); - } else if (!strcmp(argv[1], "mount")) { - dumpArgs(argc, argv, 3); - if (argc != 5) { - cli->sendMsg(ResponseCode::CommandSyntaxError, - "Usage: obb mount ", false); - return 0; - } - rc = vm->mountObb(argv[2], argv[3], atoi(argv[4])); - } else if (!strcmp(argv[1], "unmount")) { - dumpArgs(argc, argv, -1); - if (argc < 3) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: obb unmount [force]", false); - return 0; - } - bool force = false; - if (argc > 3 && !strcmp(argv[3], "force")) { - force = true; - } - rc = vm->unmountObb(argv[2], force); - } else if (!strcmp(argv[1], "path")) { - dumpArgs(argc, argv, -1); - if (argc != 3) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: obb path ", false); - return 0; - } - char path[255]; - - if (!(rc = vm->getObbMountPath(argv[2], path, sizeof(path)))) { - cli->sendMsg(ResponseCode::AsecPathResult, path, false); - return 0; - } - } else { - dumpArgs(argc, argv, -1); - cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown obb cmd", false); - } - - if (!rc) { - cli->sendMsg(ResponseCode::CommandOkay, "obb operation succeeded", false); - } else { - rc = ResponseCode::convertFromErrno(); - cli->sendMsg(rc, "obb operation failed", true); - } - - return 0; -} - -CommandListener::FstrimCmd::FstrimCmd() : - VoldCommand("fstrim") { -} -int CommandListener::FstrimCmd::runCommand(SocketClient *cli, - int argc, char **argv) { - if ((cli->getUid() != 0) && (cli->getUid() != AID_SYSTEM)) { - cli->sendMsg(ResponseCode::CommandNoPermission, "No permission to run fstrim commands", false); - return 0; - } - - if (argc < 2) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false); - return 0; - } - - VolumeManager *vm = VolumeManager::Instance(); - std::lock_guard lock(vm->getLock()); - - int flags = 0; - - std::string cmd(argv[1]); - if (cmd == "dotrim") { - flags = 0; - } else if (cmd == "dodtrim") { - flags = android::vold::TrimTask::Flags::kDeepTrim; - } else if (cmd == "dodtrimbench") { - flags = android::vold::TrimTask::Flags::kDeepTrim; - } - - (new android::vold::TrimTask(flags, nullptr))->start(); - return sendGenericOkFail(cli, 0); -} - - -CommandListener::AppFuseCmd::AppFuseCmd() : VoldCommand("appfuse") {} - -int CommandListener::AppFuseCmd::runCommand(SocketClient *cli, int argc, char **argv) { - if (argc < 2) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); - return 0; - } - - VolumeManager *vm = VolumeManager::Instance(); - std::lock_guard lock(vm->getLock()); - - const std::string command(argv[1]); - if (command == "mount" && argc == 5) { - const uid_t uid = atoi(argv[2]); - const pid_t pid = atoi(argv[3]); - const int mountId = atoi(argv[4]); - - unique_fd device_fd; - int result = vm->mountAppFuse(uid, pid, mountId, &device_fd); - if (result != 0) { - return sendGenericOkFail(cli, result); - } else { - return sendFd(cli, device_fd.get()); - } - } else if (command == "unmount" && argc == 5) { - const uid_t uid = atoi(argv[2]); - const uid_t pid = atoi(argv[3]); - const int mountId = atoi(argv[4]); - - int result = vm->unmountAppFuse(uid, pid, mountId); - return sendGenericOkFail(cli, result); - } - - return cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown appfuse cmd", false); -} - -android::status_t CommandListener::AppFuseCmd::sendFd(SocketClient *cli, int fd) { - struct iovec data; - char dataBuffer[128]; - char controlBuffer[CMSG_SPACE(sizeof(int))]; - struct msghdr message; - - // Message. - memset(&message, 0, sizeof(struct msghdr)); - message.msg_iov = &data; - message.msg_iovlen = 1; - message.msg_control = controlBuffer; - message.msg_controllen = CMSG_SPACE(sizeof(int)); - - // Data. - data.iov_base = dataBuffer; - data.iov_len = snprintf(dataBuffer, - sizeof(dataBuffer), - "200 %d AppFuse command succeeded", - cli->getCmdNum()) + 1; - - // Control. - struct cmsghdr* const controlMessage = CMSG_FIRSTHDR(&message); - memset(controlBuffer, 0, CMSG_SPACE(sizeof(int))); - controlMessage->cmsg_level = SOL_SOCKET; - controlMessage->cmsg_type = SCM_RIGHTS; - controlMessage->cmsg_len = CMSG_LEN(sizeof(int)); - *((int *) CMSG_DATA(controlMessage)) = fd; - - const int result = TEMP_FAILURE_RETRY(sendmsg(cli->getSocket(), &message, 0)); - if (result == -1) { - PLOG(ERROR) << "Failed to send FD from vold"; - return -errno; - } - - return android::OK; -} diff --git a/CommandListener.h b/CommandListener.h deleted file mode 100644 index f858ac0..0000000 --- a/CommandListener.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _COMMANDLISTENER_H__ -#define _COMMANDLISTENER_H__ - -#include -#include -#include "VoldCommand.h" - -class CommandListener : public FrameworkListener { -public: - CommandListener(); - virtual ~CommandListener() {} - -private: - static void dumpArgs(int argc, char **argv, int argObscure); - static int sendGenericOkFail(SocketClient *cli, int cond); - - class DumpCmd : public VoldCommand { - public: - DumpCmd(); - virtual ~DumpCmd() {} - int runCommand(SocketClient *c, int argc, char ** argv); - }; - - class VolumeCmd : public VoldCommand { - public: - VolumeCmd(); - virtual ~VolumeCmd() {} - int runCommand(SocketClient *c, int argc, char ** argv); - }; - - class AsecCmd : public VoldCommand { - public: - AsecCmd(); - virtual ~AsecCmd() {} - int runCommand(SocketClient *c, int argc, char ** argv); - private: - void listAsecsInDirectory(SocketClient *c, const char *directory); - }; - - class ObbCmd : public VoldCommand { - public: - ObbCmd(); - virtual ~ObbCmd() {} - int runCommand(SocketClient *c, int argc, char ** argv); - }; - - class StorageCmd : public VoldCommand { - public: - StorageCmd(); - virtual ~StorageCmd() {} - int runCommand(SocketClient *c, int argc, char ** argv); - }; - - class FstrimCmd : public VoldCommand { - public: - FstrimCmd(); - virtual ~FstrimCmd() {} - int runCommand(SocketClient *c, int argc, char ** argv); - }; - - class AppFuseCmd : public VoldCommand { - public: - AppFuseCmd(); - virtual ~AppFuseCmd() {} - int runCommand(SocketClient *c, int argc, char ** argv); - private: - android::status_t sendFd(SocketClient *c, int fd); - }; -}; - -#endif diff --git a/CryptCommandListener.cpp b/CryptCommandListener.cpp deleted file mode 100644 index 779338f..0000000 --- a/CryptCommandListener.cpp +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define LOG_TAG "VoldCryptCmdListener" - -#include -#include - -#include -#include -#include - -#include -#include - -#include "CryptCommandListener.h" -#include "Process.h" -#include "ResponseCode.h" -#include "cryptfs.h" -#include "Ext4Crypt.h" -#include "MetadataCrypt.h" -#include "Utils.h" - -#define DUMP_ARGS 0 - -CryptCommandListener::CryptCommandListener() : -FrameworkListener("cryptd", true) { - registerCmd(new CryptfsCmd()); -} - -#if DUMP_ARGS -void CryptCommandListener::dumpArgs(int argc, char **argv, int argObscure) { - char buffer[4096]; - char *p = buffer; - - memset(buffer, 0, sizeof(buffer)); - int i; - for (i = 0; i < argc; i++) { - unsigned int len = strlen(argv[i]) + 1; // Account for space - if (i == argObscure) { - len += 2; // Account for {} - } - if (((p - buffer) + len) < (sizeof(buffer)-1)) { - if (i == argObscure) { - *p++ = '{'; - *p++ = '}'; - *p++ = ' '; - continue; - } - strcpy(p, argv[i]); - p+= strlen(argv[i]); - if (i != (argc -1)) { - *p++ = ' '; - } - } - } - SLOGD("%s", buffer); -} -#else -void CryptCommandListener::dumpArgs(int /*argc*/, char ** /*argv*/, int /*argObscure*/) { } -#endif - -int CryptCommandListener::sendGenericOkFailOnBool(SocketClient *cli, bool success) { - if (success) { - return cli->sendMsg(ResponseCode::CommandOkay, "Command succeeded", false); - } else { - return cli->sendMsg(ResponseCode::OperationFailed, "Command failed", false); - } -} - -CryptCommandListener::CryptfsCmd::CryptfsCmd() : - VoldCommand("cryptfs") { -} - -static int getType(const char* type) -{ - if (!strcmp(type, "default")) { - return CRYPT_TYPE_DEFAULT; - } else if (!strcmp(type, "password")) { - return CRYPT_TYPE_PASSWORD; - } else if (!strcmp(type, "pin")) { - return CRYPT_TYPE_PIN; - } else if (!strcmp(type, "pattern")) { - return CRYPT_TYPE_PATTERN; - } else { - return -1; - } -} - -static char* parseNull(char* arg) { - if (strcmp(arg, "!") == 0) { - return nullptr; - } else { - return arg; - } -} - -static bool check_argc(SocketClient *cli, const std::string &subcommand, int argc, - int expected, std::string usage) { - assert(expected >= 2); - if (expected == 2) { - assert(usage.empty()); - } else { - assert(!usage.empty()); - assert(std::count(usage.begin(), usage.end(), ' ') + 3 == expected); - } - if (argc == expected) { - return true; - } - auto message = std::string() + "Usage: cryptfs " + subcommand; - if (!usage.empty()) { - message += " " + usage; - } - cli->sendMsg(ResponseCode::CommandSyntaxError, message.c_str(), false); - return false; -} - -static int do_enablecrypto(char* arg2, char* arg4, int type, bool no_ui) { - int rc; - int tries; - for (tries = 0; tries < 2; ++tries) { - if (type == CRYPT_TYPE_DEFAULT) { - rc = cryptfs_enable_default(arg2, no_ui); - } else { - rc = cryptfs_enable(arg2, type, arg4, no_ui); - } - - if (rc == 0) { - free(arg2); - free(arg4); - return 0; - } else if (tries == 0) { - Process::killProcessesWithOpenFiles(DATA_MNT_POINT, SIGKILL); - } - } - - free(arg2); - free(arg4); - return -1; -} - -int CryptCommandListener::CryptfsCmd::runCommand(SocketClient *cli, - int argc, char **argv) { - if ((cli->getUid() != 0) && (cli->getUid() != AID_SYSTEM)) { - cli->sendMsg(ResponseCode::CommandNoPermission, "No permission to run cryptfs commands", false); - return 0; - } - - if (argc < 2) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing subcommand", false); - return 0; - } - - int rc = 0; - - std::string subcommand(argv[1]); - if (subcommand == "checkpw") { - if (!check_argc(cli, subcommand, argc, 3, "")) return 0; - dumpArgs(argc, argv, 2); - rc = cryptfs_check_passwd(argv[2]); - } else if (subcommand == "restart") { - if (!check_argc(cli, subcommand, argc, 2, "")) return 0; - dumpArgs(argc, argv, -1); - - // Spawn as thread so init can issue commands back to vold without - // causing deadlock, usually as a result of prep_data_fs. - std::thread(&cryptfs_restart).detach(); - } else if (subcommand == "cryptocomplete") { - if (!check_argc(cli, subcommand, argc, 2, "")) return 0; - dumpArgs(argc, argv, -1); - rc = cryptfs_crypto_complete(); - } else if (subcommand == "enablecrypto") { - if (e4crypt_is_native()) { - if (argc != 5 || strcmp(argv[2], "inplace") || strcmp(argv[3], "default") - || strcmp(argv[4], "noui")) { - cli->sendMsg(ResponseCode::CommandSyntaxError, - "Usage with ext4crypt: cryptfs enablecrypto inplace default noui", false); - return 0; - } - return sendGenericOkFailOnBool(cli, e4crypt_enable_crypto()); - } - const char* syntax = "Usage: cryptfs enablecrypto " - "default|password|pin|pattern [passwd] [noui]"; - - // This should be replaced with a command line parser if more options - // are added - bool valid = true; - bool no_ui = false; - int type = CRYPT_TYPE_DEFAULT; - int options = 4; // Optional parameters are at this offset - if (argc < 4) { - // Minimum 4 parameters - valid = false; - } else if (strcmp(argv[2], "wipe") && strcmp(argv[2], "inplace") ) { - // Second parameter must be wipe or inplace - valid = false; - } else { - // Third parameter must be valid type - type = getType(argv[3]); - if (type == -1) { - valid = false; - } else if (type != CRYPT_TYPE_DEFAULT) { - options++; - } - } - - if (valid) { - if(argc < options) { - // Too few parameters - valid = false; - } else if (argc == options) { - // No more, done - } else if (argc == options + 1) { - // One option, must be noui - if (!strcmp(argv[options], "noui")) { - no_ui = true; - } else { - valid = false; - } - } else { - // Too many options - valid = false; - } - } - - if (!valid) { - cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false); - return 0; - } - - dumpArgs(argc, argv, 4); - - // Spawn as thread so init can issue commands back to vold without - // causing deadlock, usually as a result of prep_data_fs. - char* arg2 = argc > 2 ? strdup(argv[2]) : NULL; - char* arg4 = argc > 4 ? strdup(argv[4]) : NULL; - std::thread(&do_enablecrypto, arg2, arg4, type, no_ui).detach(); - } else if (subcommand == "enablefilecrypto") { - if (!check_argc(cli, subcommand, argc, 2, "")) return 0; - dumpArgs(argc, argv, -1); - rc = e4crypt_initialize_global_de(); - } else if (subcommand == "changepw") { - const char* syntax = "Usage: cryptfs changepw " - "default|password|pin|pattern [newpasswd]"; - const char* password; - if (argc == 3) { - password = ""; - } else if (argc == 4) { - password = argv[3]; - } else { - cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false); - return 0; - } - int type = getType(argv[2]); - if (type == -1) { - cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false); - return 0; - } - SLOGD("cryptfs changepw %s {}", argv[2]); - rc = cryptfs_changepw(type, password); - } else if (subcommand == "verifypw") { - if (!check_argc(cli, subcommand, argc, 3, "")) return 0; - SLOGD("cryptfs verifypw {}"); - rc = cryptfs_verify_passwd(argv[2]); - } else if (subcommand == "getfield") { - if (!check_argc(cli, subcommand, argc, 3, "")) return 0; - char *valbuf; - int valbuf_len = PROPERTY_VALUE_MAX; - - dumpArgs(argc, argv, -1); - - // Increase the buffer size until it is big enough for the field value stored. - while (1) { - valbuf = (char*)malloc(valbuf_len); - if (valbuf == NULL) { - cli->sendMsg(ResponseCode::OperationFailed, "Failed to allocate memory", false); - return 0; - } - rc = cryptfs_getfield(argv[2], valbuf, valbuf_len); - if (rc != CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL) { - break; - } - free(valbuf); - valbuf_len *= 2; - } - if (rc == CRYPTO_GETFIELD_OK) { - cli->sendMsg(ResponseCode::CryptfsGetfieldResult, valbuf, false); - } - free(valbuf); - } else if (subcommand == "setfield") { - if (!check_argc(cli, subcommand, argc, 4, " ")) return 0; - dumpArgs(argc, argv, -1); - rc = cryptfs_setfield(argv[2], argv[3]); - } else if (subcommand == "mountdefaultencrypted") { - if (!check_argc(cli, subcommand, argc, 2, "")) return 0; - SLOGD("cryptfs mountdefaultencrypted"); - dumpArgs(argc, argv, -1); - - if (e4crypt_is_native()) { - return sendGenericOkFailOnBool(cli, e4crypt_mount_metadata_encrypted()); - } - // Spawn as thread so init can issue commands back to vold without - // causing deadlock, usually as a result of prep_data_fs. - std::thread(&cryptfs_mount_default_encrypted).detach(); - } else if (subcommand == "getpwtype") { - if (!check_argc(cli, subcommand, argc, 2, "")) return 0; - SLOGD("cryptfs getpwtype"); - dumpArgs(argc, argv, -1); - switch(cryptfs_get_password_type()) { - case CRYPT_TYPE_PASSWORD: - cli->sendMsg(ResponseCode::PasswordTypeResult, "password", false); - return 0; - case CRYPT_TYPE_PATTERN: - cli->sendMsg(ResponseCode::PasswordTypeResult, "pattern", false); - return 0; - case CRYPT_TYPE_PIN: - cli->sendMsg(ResponseCode::PasswordTypeResult, "pin", false); - return 0; - case CRYPT_TYPE_DEFAULT: - cli->sendMsg(ResponseCode::PasswordTypeResult, "default", false); - return 0; - default: - /** @TODO better error and make sure handled by callers */ - cli->sendMsg(ResponseCode::OpFailedStorageNotFound, "Error", false); - return 0; - } - } else if (subcommand == "getpw") { - if (!check_argc(cli, subcommand, argc, 2, "")) return 0; - SLOGD("cryptfs getpw"); - dumpArgs(argc, argv, -1); - const char* password = cryptfs_get_password(); - if (password) { - char* message = 0; - int size = asprintf(&message, "{{sensitive}} %s", password); - if (size != -1) { - cli->sendMsg(ResponseCode::CommandOkay, message, false); - memset(message, 0, size); - free (message); - return 0; - } - } - rc = -1; - } else if (subcommand == "clearpw") { - if (!check_argc(cli, subcommand, argc, 2, "")) return 0; - SLOGD("cryptfs clearpw"); - dumpArgs(argc, argv, -1); - cryptfs_clear_password(); - rc = 0; - - } else if (subcommand == "isConvertibleToFBE") { - if (!check_argc(cli, subcommand, argc, 2, "")) return 0; - // ext4enc:TODO: send a CommandSyntaxError if argv[2] not an integer - SLOGD("cryptfs isConvertibleToFBE"); - dumpArgs(argc, argv, -1); - rc = cryptfs_isConvertibleToFBE(); - - } else if (subcommand == "init_user0") { - if (!check_argc(cli, subcommand, argc, 2, "")) return 0; - return sendGenericOkFailOnBool(cli, e4crypt_init_user0()); - - } else if (subcommand == "create_user_key") { - if (!check_argc(cli, subcommand, argc, 5, " ")) return 0; - return sendGenericOkFailOnBool(cli, e4crypt_vold_create_user_key( - atoi(argv[2]), atoi(argv[3]), atoi(argv[4]) != 0)); - - } else if (subcommand == "destroy_user_key") { - if (!check_argc(cli, subcommand, argc, 3, "")) return 0; - return sendGenericOkFailOnBool(cli, e4crypt_destroy_user_key(atoi(argv[2]))); - - } else if (subcommand == "add_user_key_auth") { - if (!check_argc(cli, subcommand, argc, 6, " ")) return 0; - return sendGenericOkFailOnBool(cli, e4crypt_add_user_key_auth( - atoi(argv[2]), atoi(argv[3]), argv[4], argv[5])); - - } else if (subcommand == "fixate_newest_user_key_auth") { - if (!check_argc(cli, subcommand, argc, 3, "")) return 0; - return sendGenericOkFailOnBool(cli, e4crypt_fixate_newest_user_key_auth(atoi(argv[2]))); - - } else if (subcommand == "unlock_user_key") { - if (!check_argc(cli, subcommand, argc, 6, " ")) return 0; - return sendGenericOkFailOnBool(cli, e4crypt_unlock_user_key( - atoi(argv[2]), atoi(argv[3]), argv[4], argv[5])); - - } else if (subcommand == "lock_user_key") { - if (!check_argc(cli, subcommand, argc, 3, "")) return 0; - return sendGenericOkFailOnBool(cli, e4crypt_lock_user_key(atoi(argv[2]))); - - } else if (subcommand == "prepare_user_storage") { - if (!check_argc(cli, subcommand, argc, 6, " ")) return 0; - return sendGenericOkFailOnBool(cli, e4crypt_prepare_user_storage( - parseNull(argv[2]), atoi(argv[3]), atoi(argv[4]), atoi(argv[5]))); - - } else if (subcommand == "destroy_user_storage") { - if (!check_argc(cli, subcommand, argc, 5, " ")) return 0; - return sendGenericOkFailOnBool(cli, - e4crypt_destroy_user_storage(parseNull(argv[2]), atoi(argv[3]), atoi(argv[4]))); - - } else if (subcommand == "secdiscard") { - if (!check_argc(cli, subcommand, argc, 3, "")) return 0; - return sendGenericOkFailOnBool(cli, - e4crypt_secdiscard(parseNull(argv[2]))); - - } else { - dumpArgs(argc, argv, -1); - cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown cryptfs subcommand", false); - return 0; - } - - // Always report that the command succeeded and return the error code. - // The caller will check the return value to see what the error was. - char msg[255]; - snprintf(msg, sizeof(msg), "%d", rc); - cli->sendMsg(ResponseCode::CommandOkay, msg, false); - - return 0; -} diff --git a/CryptCommandListener.h b/CryptCommandListener.h deleted file mode 100644 index 478ac02..0000000 --- a/CryptCommandListener.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _CRYPTCOMMANDLISTENER_H__ -#define _CRYPTCOMMANDLISTENER_H__ - -#include -#include -#include "VoldCommand.h" - -class CryptCommandListener : public FrameworkListener { -public: - CryptCommandListener(); - virtual ~CryptCommandListener() {} - -private: - static void dumpArgs(int argc, char **argv, int argObscure); - static int sendGenericOkFailOnBool(SocketClient *cli, bool success); - - class CryptfsCmd : public VoldCommand { - public: - CryptfsCmd(); - virtual ~CryptfsCmd() {} - int runCommand(SocketClient *c, int argc, char ** argv); - }; - int getSocket(); -}; - -#endif diff --git a/Devmapper.cpp b/Devmapper.cpp index c945e9f..ed498a3 100644 --- a/Devmapper.cpp +++ b/Devmapper.cpp @@ -34,7 +34,6 @@ #include #include -#include #include "Devmapper.h" @@ -44,82 +43,6 @@ using android::base::StringPrintf; static const char* kVoldPrefix = "vold:"; -int Devmapper::dumpState(SocketClient *c) { - - char *buffer = (char *) malloc(1024 * 64); - if (!buffer) { - SLOGE("Error allocating memory (%s)", strerror(errno)); - return -1; - } - memset(buffer, 0, (1024 * 64)); - - char *buffer2 = (char *) malloc(DEVMAPPER_BUFFER_SIZE); - if (!buffer2) { - SLOGE("Error allocating memory (%s)", strerror(errno)); - free(buffer); - return -1; - } - - int fd; - if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) { - SLOGE("Error opening devmapper (%s)", strerror(errno)); - free(buffer); - free(buffer2); - return -1; - } - - struct dm_ioctl *io = (struct dm_ioctl *) buffer; - ioctlInit(io, (1024 * 64), NULL, 0); - - if (ioctl(fd, DM_LIST_DEVICES, io)) { - SLOGE("DM_LIST_DEVICES ioctl failed (%s)", strerror(errno)); - free(buffer); - free(buffer2); - close(fd); - return -1; - } - - struct dm_name_list *n = (struct dm_name_list *) (((char *) buffer) + io->data_start); - if (!n->dev) { - free(buffer); - free(buffer2); - close(fd); - return 0; - } - - unsigned nxt = 0; - do { - n = (struct dm_name_list *) (((char *) n) + nxt); - - memset(buffer2, 0, DEVMAPPER_BUFFER_SIZE); - struct dm_ioctl *io2 = (struct dm_ioctl *) buffer2; - ioctlInit(io2, DEVMAPPER_BUFFER_SIZE, n->name, 0); - if (ioctl(fd, DM_DEV_STATUS, io2)) { - if (errno != ENXIO) { - SLOGE("DM_DEV_STATUS ioctl failed (%s)", strerror(errno)); - } - io2 = NULL; - } - - char *tmp; - if (!io2) { - asprintf(&tmp, "%s %llu:%llu (no status available)", n->name, MAJOR(n->dev), MINOR(n->dev)); - } else { - asprintf(&tmp, "%s %llu:%llu %d %d 0x%.8x %llu:%llu", n->name, MAJOR(n->dev), - MINOR(n->dev), io2->target_count, io2->open_count, io2->flags, MAJOR(io2->dev), - MINOR(io2->dev)); - } - c->sendMsg(0, tmp, false); - free(tmp); - nxt = n->next; - } while (nxt); - - free(buffer); - free(buffer2); - close(fd); - return 0; -} - void Devmapper::ioctlInit(struct dm_ioctl *io, size_t dataSize, const char *name, unsigned flags) { memset(io, 0, dataSize); diff --git a/Devmapper.h b/Devmapper.h index dcc39d8..086ad78 100644 --- a/Devmapper.h +++ b/Devmapper.h @@ -20,8 +20,6 @@ #include #include -class SocketClient; - class Devmapper { public: static int create(const char *name, const char *loopFile, const char *key, @@ -29,7 +27,6 @@ public: static int destroy(const char *name); static int destroyAll(); static int lookupActive(const char *name, char *buffer, size_t len); - static int dumpState(SocketClient *c); private: static void *_align(void *ptr, unsigned int a); diff --git a/Loop.cpp b/Loop.cpp index 325b0d3..fc3909b 100644 --- a/Loop.cpp +++ b/Loop.cpp @@ -36,9 +36,7 @@ #include #include -#include #include "Loop.h" -#include "Asec.h" #include "VoldUtil.h" #include "sehandle.h" @@ -47,48 +45,6 @@ using android::base::unique_fd; static const char* kVoldPrefix = "vold:"; -int Loop::dumpState(SocketClient *c) { - int i; - int fd; - char filename[256]; - - for (i = 0; i < LOOP_MAX; i++) { - struct loop_info64 li; - int rc; - - snprintf(filename, sizeof(filename), "/dev/block/loop%d", i); - - if ((fd = open(filename, O_RDWR | O_CLOEXEC)) < 0) { - if (errno != ENOENT) { - SLOGE("Unable to open %s (%s)", filename, strerror(errno)); - } else { - continue; - } - return -1; - } - - rc = ioctl(fd, LOOP_GET_STATUS64, &li); - close(fd); - if (rc < 0 && errno == ENXIO) { - continue; - } - - if (rc < 0) { - SLOGE("Unable to get loop status for %s (%s)", filename, - strerror(errno)); - return -1; - } - char *tmp = NULL; - asprintf(&tmp, "%s %d %lld:%lld %llu %lld:%lld %lld 0x%x {%s} {%s}", filename, li.lo_number, - MAJOR(li.lo_device), MINOR(li.lo_device), li.lo_inode, MAJOR(li.lo_rdevice), - MINOR(li.lo_rdevice), li.lo_offset, li.lo_flags, li.lo_crypt_name, - li.lo_file_name); - c->sendMsg(0, tmp, false); - free(tmp); - } - return 0; -} - int Loop::lookupActive(const char *id_raw, char *buffer, size_t len) { auto id_string = StringPrintf("%s%s", kVoldPrefix, id_raw); const char* id = id_string.c_str(); @@ -380,46 +336,3 @@ int Loop::resizeImageFile(const char *file, unsigned long numSectors) { close(fd); return 0; } - -int Loop::lookupInfo(const char *loopDevice, struct asec_superblock *sb, unsigned long *nr_sec) { - int fd; - struct asec_superblock buffer; - - if ((fd = open(loopDevice, O_RDONLY | O_CLOEXEC)) < 0) { - SLOGE("Failed to open loopdevice (%s)", strerror(errno)); - destroyByDevice(loopDevice); - return -1; - } - - get_blkdev_size(fd, nr_sec); - if (*nr_sec == 0) { - SLOGE("Failed to get loop size (%s)", strerror(errno)); - destroyByDevice(loopDevice); - close(fd); - return -1; - } - - /* - * Try to read superblock. - */ - memset(&buffer, 0, sizeof(struct asec_superblock)); - if (lseek(fd, ((*nr_sec - 1) * 512), SEEK_SET) < 0) { - SLOGE("lseek failed (%s)", strerror(errno)); - close(fd); - destroyByDevice(loopDevice); - return -1; - } - if (read(fd, &buffer, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) { - SLOGE("superblock read failed (%s)", strerror(errno)); - close(fd); - destroyByDevice(loopDevice); - return -1; - } - close(fd); - - /* - * Superblock successfully read. Copy to caller's struct. - */ - memcpy(sb, &buffer, sizeof(struct asec_superblock)); - return 0; -} diff --git a/Loop.h b/Loop.h index e3ad239..654b8ad 100644 --- a/Loop.h +++ b/Loop.h @@ -21,22 +21,17 @@ #include #include -class SocketClient; - class Loop { public: static const int LOOP_MAX = 4096; public: static int lookupActive(const char *id, char *buffer, size_t len); - static int lookupInfo(const char *loopDevice, struct asec_superblock *sb, unsigned long *nr_sec); static int create(const char *id, const char *loopFile, char *loopDeviceBuffer, size_t len); static int create(const std::string& file, std::string& out_device); static int destroyByDevice(const char *loopDevice); static int destroyAll(); static int createImageFile(const char *file, unsigned long numSectors); static int resizeImageFile(const char *file, unsigned long numSectors); - - static int dumpState(SocketClient *c); }; #endif diff --git a/MoveTask.cpp b/MoveTask.cpp index 8c0efac..4268ed4 100644 --- a/MoveTask.cpp +++ b/MoveTask.cpp @@ -17,7 +17,6 @@ #include "MoveTask.h" #include "Utils.h" #include "VolumeManager.h" -#include "ResponseCode.h" #include #include diff --git a/ResponseCode.cpp b/ResponseCode.cpp deleted file mode 100644 index d7e778d..0000000 --- a/ResponseCode.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -#define LOG_TAG "Vold" - -#include - -#include "ResponseCode.h" - -int ResponseCode::convertFromErrno() { - if (errno == ENODEV) { - return(ResponseCode::OpFailedNoMedia); - } else if (errno == ENODATA) { - return(ResponseCode::OpFailedMediaBlank); - } else if (errno == EIO) { - return(ResponseCode::OpFailedMediaCorrupt); - } else if (errno == EBUSY) { - return(ResponseCode::OpFailedStorageBusy); - } else if (errno == ENOENT) { - return(ResponseCode::OpFailedStorageNotFound); - } - - SLOGW("Returning OperationFailed - no handler for errno %d", errno); - return(ResponseCode::OperationFailed); -} diff --git a/ResponseCode.h b/ResponseCode.h deleted file mode 100644 index f2c533e..0000000 --- a/ResponseCode.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _RESPONSECODE_H -#define _RESPONSECODE_H - -class ResponseCode { -public: - // 100 series - Requestion action was initiated; expect another reply - // before proceeding with a new command. - static const int ActionInitiated = 100; - - static const int VolumeListResult = 110; - static const int AsecListResult = 111; - static const int StorageUsersListResult = 112; - static const int CryptfsGetfieldResult = 113; - - // 200 series - Requested action has been successfully completed - static const int CommandOkay = 200; - static const int ShareStatusResult = 210; - static const int AsecPathResult = 211; - static const int ShareEnabledResult = 212; - static const int PasswordTypeResult = 213; - - // 400 series - The command was accepted but the requested action - // did not take place. - static const int OperationFailed = 400; - static const int OpFailedNoMedia = 401; - static const int OpFailedMediaBlank = 402; - static const int OpFailedMediaCorrupt = 403; - static const int OpFailedVolNotMounted = 404; - static const int OpFailedStorageBusy = 405; - static const int OpFailedStorageNotFound = 406; - - // 500 series - The command was not accepted and the requested - // action did not take place. - static const int CommandSyntaxError = 500; - static const int CommandParameterError = 501; - static const int CommandNoPermission = 502; - - // 600 series - Unsolicited broadcasts - static const int UnsolicitedInformational = 600; - static const int VolumeStateChange = 605; - static const int VolumeMountFailedBlank = 610; - static const int VolumeMountFailedDamaged = 611; - static const int VolumeMountFailedNoMedia = 612; - static const int VolumeUuidChange = 613; - static const int VolumeUserLabelChange = 614; - - static const int ShareAvailabilityChange = 620; - - static const int VolumeDiskInserted = 630; - static const int VolumeDiskRemoved = 631; - static const int VolumeBadRemoval = 632; - - static const int DiskCreated = 640; - static const int DiskSizeChanged = 641; - static const int DiskLabelChanged = 642; - static const int DiskScanned = 643; - static const int DiskSysPathChanged = 644; - static const int DiskDestroyed = 649; - - static const int VolumeCreated = 650; - static const int VolumeStateChanged = 651; - static const int VolumeFsTypeChanged = 652; - static const int VolumeFsUuidChanged = 653; - static const int VolumeFsLabelChanged = 654; - static const int VolumePathChanged = 655; - static const int VolumeInternalPathChanged = 656; - static const int VolumeDestroyed = 659; - - static const int MoveStatus = 660; - static const int BenchmarkResult = 661; - static const int TrimResult = 662; - - static int convertFromErrno(); -}; -#endif diff --git a/TrimTask.cpp b/TrimTask.cpp index d37ec20..fafb345 100644 --- a/TrimTask.cpp +++ b/TrimTask.cpp @@ -17,7 +17,6 @@ #include "TrimTask.h" #include "Utils.h" #include "VolumeManager.h" -#include "ResponseCode.h" #include #include diff --git a/Utils.h b/Utils.h index 153c320..4e2be96 100644 --- a/Utils.h +++ b/Utils.h @@ -29,8 +29,6 @@ struct DIR; -#define ENABLE_BINDER 1 - namespace android { namespace vold { diff --git a/VoldCommand.cpp b/VoldCommand.cpp deleted file mode 100644 index 3c0d58d..0000000 --- a/VoldCommand.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "VoldCommand.h" - -VoldCommand::VoldCommand(const char *cmd) : - FrameworkCommand(cmd) { -} diff --git a/VoldCommand.h b/VoldCommand.h deleted file mode 100644 index e435159..0000000 --- a/VoldCommand.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _VOLD_COMMAND_H -#define _VOLD_COMMAND_H - -#include - -class VoldCommand : public FrameworkCommand { -public: - explicit VoldCommand(const char *cmd); - virtual ~VoldCommand() {} -}; - -#endif diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp index 6c25674..310610c 100644 --- a/VoldNativeService.cpp +++ b/VoldNativeService.cpp @@ -211,6 +211,20 @@ binder::Status VoldNativeService::setListener( return ok(); } +binder::Status VoldNativeService::monitor() { + ENFORCE_UID(AID_SYSTEM); + + // Simply acquire/release each lock for watchdog + { + ACQUIRE_LOCK; + } + { + ACQUIRE_CRYPT_LOCK; + } + + return ok(); +} + binder::Status VoldNativeService::reset() { ENFORCE_UID(AID_SYSTEM); ACQUIRE_LOCK; diff --git a/VoldNativeService.h b/VoldNativeService.h index a00010b..dd2b854 100644 --- a/VoldNativeService.h +++ b/VoldNativeService.h @@ -33,6 +33,7 @@ public: binder::Status setListener(const android::sp& listener); + binder::Status monitor(); binder::Status reset(); binder::Status shutdown(); binder::Status mountAll(); diff --git a/VolumeManager.cpp b/VolumeManager.cpp index 3150997..70f71f9 100644 --- a/VolumeManager.cpp +++ b/VolumeManager.cpp @@ -51,45 +51,18 @@ #include "model/ObbVolume.h" #include "VolumeManager.h" #include "NetlinkManager.h" -#include "ResponseCode.h" #include "Loop.h" #include "fs/Ext4.h" #include "fs/Vfat.h" #include "Utils.h" #include "Devmapper.h" #include "Process.h" -#include "Asec.h" #include "VoldUtil.h" #include "cryptfs.h" -#define MASS_STORAGE_FILE_PATH "/sys/class/android_usb/android0/f_mass_storage/lun/file" - -#define ROUND_UP_POWER_OF_2(number, po2) (((!!((number) & ((1U << (po2)) - 1))) << (po2))\ - + ((number) & (~((1U << (po2)) - 1)))) - using android::base::StringPrintf; using android::base::unique_fd; -/* - * Path to external storage where *only* root can access ASEC image files - */ -const char *VolumeManager::SEC_ASECDIR_EXT = "/mnt/secure/asec"; - -/* - * Path to internal storage where *only* root can access ASEC image files - */ -const char *VolumeManager::SEC_ASECDIR_INT = "/data/app-asec"; - -/* - * Path to where secure containers are mounted - */ -const char *VolumeManager::ASECDIR = "/mnt/asec"; - -/* - * Path to where OBBs are mounted - */ -const char *VolumeManager::LOOPDIR = "/mnt/obb"; - bool VolumeManager::shutting_down = false; static const char* kPathUserMount = "/mnt/user"; @@ -104,107 +77,6 @@ static const unsigned int kMajorBlockMmc = 179; static const unsigned int kMajorBlockExperimentalMin = 240; static const unsigned int kMajorBlockExperimentalMax = 254; -/* writes superblock at end of file or device given by name */ -static int writeSuperBlock(const char* name, struct asec_superblock *sb, unsigned int numImgSectors) { - int sbfd = open(name, O_RDWR | O_CLOEXEC); - if (sbfd < 0) { - SLOGE("Failed to open %s for superblock write (%s)", name, strerror(errno)); - return -1; - } - - if (lseek(sbfd, (numImgSectors * 512), SEEK_SET) < 0) { - SLOGE("Failed to lseek for superblock (%s)", strerror(errno)); - close(sbfd); - return -1; - } - - if (write(sbfd, sb, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) { - SLOGE("Failed to write superblock (%s)", strerror(errno)); - close(sbfd); - return -1; - } - close(sbfd); - return 0; -} - -static unsigned long adjustSectorNumExt4(unsigned long numSectors) { - // Ext4 started to reserve 2% or 4096 clusters, whichever is smaller for - // preventing costly operations or unexpected ENOSPC error. - // Ext4::format() uses default block size without clustering. - unsigned long clusterSectors = 4096 / 512; - unsigned long reservedSectors = (numSectors * 2)/100 + (numSectors % 50 > 0); - numSectors += reservedSectors > (4096 * clusterSectors) ? (4096 * clusterSectors) : reservedSectors; - return ROUND_UP_POWER_OF_2(numSectors, 3); -} - -static unsigned long adjustSectorNumFAT(unsigned long numSectors) { - /* - * Add some headroom - */ - unsigned long fatSize = (((numSectors * 4) / 512) + 1) * 2; - numSectors += fatSize + 2; - /* - * FAT is aligned to 32 kb with 512b sectors. - */ - return ROUND_UP_POWER_OF_2(numSectors, 6); -} - -static int setupLoopDevice(char* buffer, size_t len, const char* asecFileName, const char* idHash, bool debug) { - if (Loop::lookupActive(idHash, buffer, len)) { - if (Loop::create(idHash, asecFileName, buffer, len)) { - SLOGE("ASEC loop device creation failed for %s (%s)", asecFileName, strerror(errno)); - return -1; - } - if (debug) { - SLOGD("New loop device created at %s", buffer); - } - } else { - if (debug) { - SLOGD("Found active loopback for %s at %s", asecFileName, buffer); - } - } - return 0; -} - -static int setupDevMapperDevice(char* buffer, size_t len, const char* loopDevice, const char* asecFileName, const char* key, const char* idHash , unsigned long numImgSectors, bool* createdDMDevice, bool debug) { - if (strcmp(key, "none")) { - if (Devmapper::lookupActive(idHash, buffer, len)) { - if (Devmapper::create(idHash, loopDevice, key, numImgSectors, - buffer, len)) { - SLOGE("ASEC device mapping failed for %s (%s)", asecFileName, strerror(errno)); - return -1; - } - if (debug) { - SLOGD("New devmapper instance created at %s", buffer); - } - } else { - if (debug) { - SLOGD("Found active devmapper for %s at %s", asecFileName, buffer); - } - } - *createdDMDevice = true; - } else { - strlcpy(buffer, loopDevice, len); - *createdDMDevice = false; - } - return 0; -} - -static void waitForDevMapper(const char *dmDevice) { - /* - * Wait for the device mapper node to be created. Sometimes it takes a - * while. Wait for up to 1 second. We could also inspect incoming uevents, - * but that would take more effort. - */ - int tries = 25; - while (tries--) { - if (!access(dmDevice, F_OK) || errno != ENOENT) { - break; - } - usleep(40 * 1000); - } -} - VolumeManager *VolumeManager::sInstance = NULL; VolumeManager *VolumeManager::Instance() { @@ -215,49 +87,10 @@ VolumeManager *VolumeManager::Instance() { VolumeManager::VolumeManager() { mDebug = false; - mActiveContainers = new AsecIdCollection(); - mBroadcaster = NULL; - mUmsSharingCount = 0; - mSavedDirtyRatio = -1; - // set dirty ratio to 0 when UMS is active - mUmsDirtyRatio = 0; mNextObbId = 0; } VolumeManager::~VolumeManager() { - delete mActiveContainers; -} - -char *VolumeManager::asecHash(const char *id, char *buffer, size_t len) { - static const char* digits = "0123456789abcdef"; - - unsigned char sig[MD5_DIGEST_LENGTH]; - - if (buffer == NULL) { - SLOGE("Destination buffer is NULL"); - errno = ESPIPE; - return NULL; - } else if (id == NULL) { - SLOGE("Source buffer is NULL"); - errno = ESPIPE; - return NULL; - } else if (len < MD5_ASCII_LENGTH_PLUS_NULL) { - SLOGE("Target hash buffer size < %d bytes (%zu)", - MD5_ASCII_LENGTH_PLUS_NULL, len); - errno = ESPIPE; - return NULL; - } - - MD5(reinterpret_cast(id), strlen(id), sig); - - char *p = buffer; - for (int i = 0; i < MD5_DIGEST_LENGTH; i++) { - *p++ = digits[sig[i] >> 4]; - *p++ = digits[sig[i] & 0x0F]; - } - *p = '\0'; - - return buffer; } int VolumeManager::updateVirtualDisk() { @@ -752,1197 +585,11 @@ int VolumeManager::unmountAll() { return 0; } -int VolumeManager::getObbMountPath(const char *sourceFile, char *mountPath, int mountPathLen) { - char idHash[33]; - if (!asecHash(sourceFile, idHash, sizeof(idHash))) { - SLOGE("Hash of '%s' failed (%s)", sourceFile, strerror(errno)); - return -1; - } - - memset(mountPath, 0, mountPathLen); - int written = snprintf(mountPath, mountPathLen, "%s/%s", VolumeManager::LOOPDIR, idHash); - if ((written < 0) || (written >= mountPathLen)) { - errno = EINVAL; - return -1; - } - - if (access(mountPath, F_OK)) { - errno = ENOENT; - return -1; - } - - return 0; -} - -int VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) { - char asecFileName[255]; - - if (!isLegalAsecId(id)) { - SLOGE("getAsecMountPath: Invalid asec id \"%s\"", id); - errno = EINVAL; - return -1; - } - - if (findAsec(id, asecFileName, sizeof(asecFileName))) { - SLOGE("Couldn't find ASEC %s", id); - return -1; - } - - memset(buffer, 0, maxlen); - if (access(asecFileName, F_OK)) { - errno = ENOENT; - return -1; - } - - int written = snprintf(buffer, maxlen, "%s/%s", VolumeManager::ASECDIR, id); - if ((written < 0) || (written >= maxlen)) { - SLOGE("getAsecMountPath failed for %s: couldn't construct path in buffer", id); - errno = EINVAL; - return -1; - } - - return 0; -} - -int VolumeManager::getAsecFilesystemPath(const char *id, char *buffer, int maxlen) { - char asecFileName[255]; - - if (!isLegalAsecId(id)) { - SLOGE("getAsecFilesystemPath: Invalid asec id \"%s\"", id); - errno = EINVAL; - return -1; - } - - if (findAsec(id, asecFileName, sizeof(asecFileName))) { - SLOGE("Couldn't find ASEC %s", id); - return -1; - } - - memset(buffer, 0, maxlen); - if (access(asecFileName, F_OK)) { - errno = ENOENT; - return -1; - } - - int written = snprintf(buffer, maxlen, "%s", asecFileName); - if ((written < 0) || (written >= maxlen)) { - errno = EINVAL; - return -1; - } - - return 0; -} - -int VolumeManager::createAsec(const char *id, unsigned long numSectors, const char *fstype, - const char *key, const int ownerUid, bool isExternal) { - struct asec_superblock sb; - memset(&sb, 0, sizeof(sb)); - - if (!isLegalAsecId(id)) { - SLOGE("createAsec: Invalid asec id \"%s\"", id); - errno = EINVAL; - return -1; - } - - const bool wantFilesystem = strcmp(fstype, "none"); - bool usingExt4 = false; - if (wantFilesystem) { - usingExt4 = !strcmp(fstype, "ext4"); - if (usingExt4) { - sb.c_opts |= ASEC_SB_C_OPTS_EXT4; - } else if (strcmp(fstype, "fat")) { - SLOGE("Invalid filesystem type %s", fstype); - errno = EINVAL; - return -1; - } - } - - sb.magic = ASEC_SB_MAGIC; - sb.ver = ASEC_SB_VER; - - if (numSectors < ((1024*1024)/512)) { - SLOGE("Invalid container size specified (%lu sectors)", numSectors); - errno = EINVAL; - return -1; - } - - char asecFileName[255]; - - if (!findAsec(id, asecFileName, sizeof(asecFileName))) { - SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)", - asecFileName, strerror(errno)); - errno = EADDRINUSE; - return -1; - } - - const char *asecDir = isExternal ? VolumeManager::SEC_ASECDIR_EXT : VolumeManager::SEC_ASECDIR_INT; - - int written = snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", asecDir, id); - if ((written < 0) || (size_t(written) >= sizeof(asecFileName))) { - errno = EINVAL; - return -1; - } - - if (!access(asecFileName, F_OK)) { - SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)", - asecFileName, strerror(errno)); - errno = EADDRINUSE; - return -1; - } - - unsigned long numImgSectors; - if (usingExt4) - numImgSectors = adjustSectorNumExt4(numSectors); - else - numImgSectors = adjustSectorNumFAT(numSectors); - - // Add +1 for our superblock which is at the end - if (Loop::createImageFile(asecFileName, numImgSectors + 1)) { - SLOGE("ASEC image file creation failed (%s)", strerror(errno)); - return -1; - } - - char idHash[33]; - if (!asecHash(id, idHash, sizeof(idHash))) { - SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); - unlink(asecFileName); - return -1; - } - - char loopDevice[255]; - if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) { - SLOGE("ASEC loop device creation failed (%s)", strerror(errno)); - unlink(asecFileName); - return -1; - } - - char dmDevice[255]; - bool cleanupDm = false; - - if (strcmp(key, "none")) { - // XXX: This is all we support for now - sb.c_cipher = ASEC_SB_C_CIPHER_TWOFISH; - if (Devmapper::create(idHash, loopDevice, key, numImgSectors, dmDevice, - sizeof(dmDevice))) { - SLOGE("ASEC device mapping failed (%s)", strerror(errno)); - Loop::destroyByDevice(loopDevice); - unlink(asecFileName); - return -1; - } - cleanupDm = true; - } else { - sb.c_cipher = ASEC_SB_C_CIPHER_NONE; - strlcpy(dmDevice, loopDevice, sizeof(dmDevice)); - } - - /* - * Drop down the superblock at the end of the file - */ - if (writeSuperBlock(loopDevice, &sb, numImgSectors)) { - if (cleanupDm) { - Devmapper::destroy(idHash); - } - Loop::destroyByDevice(loopDevice); - unlink(asecFileName); - return -1; - } - - if (wantFilesystem) { - int formatStatus; - char mountPoint[255]; - - int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id); - if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { - SLOGE("ASEC fs format failed: couldn't construct mountPoint"); - if (cleanupDm) { - Devmapper::destroy(idHash); - } - Loop::destroyByDevice(loopDevice); - unlink(asecFileName); - return -1; - } - - if (usingExt4) { - formatStatus = android::vold::ext4::Format(dmDevice, numImgSectors, mountPoint); - } else { - formatStatus = android::vold::vfat::Format(dmDevice, numImgSectors); - } - - if (formatStatus < 0) { - SLOGE("ASEC fs format failed (%s)", strerror(errno)); - if (cleanupDm) { - Devmapper::destroy(idHash); - } - Loop::destroyByDevice(loopDevice); - unlink(asecFileName); - return -1; - } - - if (mkdir(mountPoint, 0000)) { - if (errno != EEXIST) { - SLOGE("Mountpoint creation failed (%s)", strerror(errno)); - if (cleanupDm) { - Devmapper::destroy(idHash); - } - Loop::destroyByDevice(loopDevice); - unlink(asecFileName); - return -1; - } - } - - int mountStatus; - if (usingExt4) { - mountStatus = android::vold::ext4::Mount(dmDevice, mountPoint, - false, false, false); - } else { - mountStatus = android::vold::vfat::Mount(dmDevice, mountPoint, - false, false, false, ownerUid, 0, 0000, false); - } - - if (mountStatus) { - SLOGE("ASEC FAT mount failed (%s)", strerror(errno)); - if (cleanupDm) { - Devmapper::destroy(idHash); - } - Loop::destroyByDevice(loopDevice); - unlink(asecFileName); - return -1; - } - - if (usingExt4) { - int dirfd = open(mountPoint, O_DIRECTORY | O_CLOEXEC); - if (dirfd >= 0) { - if (fchown(dirfd, ownerUid, AID_SYSTEM) - || fchmod(dirfd, S_IRUSR | S_IWUSR | S_IXUSR | S_ISGID | S_IRGRP | S_IXGRP)) { - SLOGI("Cannot chown/chmod new ASEC mount point %s", mountPoint); - } - close(dirfd); - } - } - } else { - SLOGI("Created raw secure container %s (no filesystem)", id); - } - - mActiveContainers->push_back(new ContainerData(strdup(id), ASEC)); - return 0; -} - -int VolumeManager::resizeAsec(const char *id, unsigned long numSectors, const char *key) { - char asecFileName[255]; - char mountPoint[255]; - bool cleanupDm = false; - - if (!isLegalAsecId(id)) { - SLOGE("resizeAsec: Invalid asec id \"%s\"", id); - errno = EINVAL; - return -1; - } - - if (findAsec(id, asecFileName, sizeof(asecFileName))) { - SLOGE("Couldn't find ASEC %s", id); - return -1; - } - - int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id); - if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { - SLOGE("ASEC resize failed for %s: couldn't construct mountpoint", id); - return -1; - } - - if (isMountpointMounted(mountPoint)) { - SLOGE("ASEC %s mounted. Unmount before resizing", id); - errno = EBUSY; - return -1; - } - - struct asec_superblock sb; - int fd; - unsigned long oldNumSec = 0; - - if ((fd = open(asecFileName, O_RDONLY | O_CLOEXEC)) < 0) { - SLOGE("Failed to open ASEC file (%s)", strerror(errno)); - return -1; - } - - struct stat info; - if (fstat(fd, &info) < 0) { - SLOGE("Failed to get file size (%s)", strerror(errno)); - close(fd); - return -1; - } - - oldNumSec = info.st_size / 512; - - /* - * Try to read superblock. - */ - memset(&sb, 0, sizeof(struct asec_superblock)); - if (lseek(fd, ((oldNumSec - 1) * 512), SEEK_SET) < 0) { - SLOGE("lseek failed (%s)", strerror(errno)); - close(fd); - return -1; - } - if (read(fd, &sb, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) { - SLOGE("superblock read failed (%s)", strerror(errno)); - close(fd); - return -1; - } - close(fd); - - if (mDebug) { - SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver); - } - if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) { - SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver); - errno = EMEDIUMTYPE; - return -1; - } - - unsigned long numImgSectors; - if (!(sb.c_opts & ASEC_SB_C_OPTS_EXT4)) { - SLOGE("Only ext4 partitions are supported for resize"); - errno = EINVAL; - return -1; - } else { - numImgSectors = adjustSectorNumExt4(numSectors); - } - - /* - * add one block for the superblock - */ - SLOGD("Resizing from %lu sectors to %lu sectors", oldNumSec, numImgSectors + 1); - if (oldNumSec == numImgSectors + 1) { - SLOGW("Size unchanged; ignoring resize request"); - return 0; - } else if (oldNumSec > numImgSectors + 1) { - SLOGE("Only growing is currently supported."); - close(fd); - return -1; - } - - if (Loop::resizeImageFile(asecFileName, numImgSectors + 1)) { - SLOGE("Resize of ASEC image file failed. Could not resize %s", id); - return -1; - } - - /* - * Drop down a copy of the superblock at the end of the file - */ - if (writeSuperBlock(asecFileName, &sb, numImgSectors)) - goto fail; - - char idHash[33]; - if (!asecHash(id, idHash, sizeof(idHash))) { - SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); - goto fail; - } - - char loopDevice[255]; - if (setupLoopDevice(loopDevice, sizeof(loopDevice), asecFileName, idHash, mDebug)) - goto fail; - - char dmDevice[255]; - - if (setupDevMapperDevice(dmDevice, sizeof(dmDevice), loopDevice, asecFileName, key, idHash, numImgSectors, &cleanupDm, mDebug)) { - Loop::destroyByDevice(loopDevice); - goto fail; - } - - /* - * Wait for the device mapper node to be created. - */ - waitForDevMapper(dmDevice); - - if (android::vold::ext4::Resize(dmDevice, numImgSectors)) { - SLOGE("Unable to resize %s (%s)", id, strerror(errno)); - if (cleanupDm) { - Devmapper::destroy(idHash); - } - Loop::destroyByDevice(loopDevice); - goto fail; - } - - return 0; -fail: - Loop::resizeImageFile(asecFileName, oldNumSec); - return -1; -} - -int VolumeManager::finalizeAsec(const char *id) { - char asecFileName[255]; - char loopDevice[255]; - char mountPoint[255]; - - if (!isLegalAsecId(id)) { - SLOGE("finalizeAsec: Invalid asec id \"%s\"", id); - errno = EINVAL; - return -1; - } - - if (findAsec(id, asecFileName, sizeof(asecFileName))) { - SLOGE("Couldn't find ASEC %s", id); - return -1; - } - - char idHash[33]; - if (!asecHash(id, idHash, sizeof(idHash))) { - SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); - return -1; - } - - if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) { - SLOGE("Unable to finalize %s (%s)", id, strerror(errno)); - return -1; - } - - unsigned long nr_sec = 0; - struct asec_superblock sb; - - if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) { - return -1; - } - - int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id); - if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { - SLOGE("ASEC finalize failed: couldn't construct mountPoint"); - return -1; - } - - int result = 0; - if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) { - result = android::vold::ext4::Mount(loopDevice, mountPoint, - true, true, true); - } else { - result = android::vold::vfat::Mount(loopDevice, mountPoint, - true, true, true, 0, 0, 0227, false); - } - - if (result) { - SLOGE("ASEC finalize mount failed (%s)", strerror(errno)); - return -1; - } - - if (mDebug) { - SLOGD("ASEC %s finalized", id); - } - return 0; -} - -int VolumeManager::fixupAsecPermissions(const char *id, gid_t gid, const char* filename) { - char asecFileName[255]; - char loopDevice[255]; - char mountPoint[255]; - - if (gid < AID_APP) { - SLOGE("Group ID is not in application range"); - return -1; - } - - if (!isLegalAsecId(id)) { - SLOGE("fixupAsecPermissions: Invalid asec id \"%s\"", id); - errno = EINVAL; - return -1; - } - - if (findAsec(id, asecFileName, sizeof(asecFileName))) { - SLOGE("Couldn't find ASEC %s", id); - return -1; - } - - char idHash[33]; - if (!asecHash(id, idHash, sizeof(idHash))) { - SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); - return -1; - } - - if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) { - SLOGE("Unable fix permissions during lookup on %s (%s)", id, strerror(errno)); - return -1; - } - - unsigned long nr_sec = 0; - struct asec_superblock sb; - - if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) { - return -1; - } - - int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id); - if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { - SLOGE("Unable remount to fix permissions for %s: couldn't construct mountpoint", id); - return -1; - } - - int result = 0; - if ((sb.c_opts & ASEC_SB_C_OPTS_EXT4) == 0) { - return 0; - } - - int ret = android::vold::ext4::Mount(loopDevice, mountPoint, - false /* read-only */, - true /* remount */, - false /* executable */); - if (ret) { - SLOGE("Unable remount to fix permissions for %s (%s)", id, strerror(errno)); - return -1; - } - - char *paths[] = { mountPoint, NULL }; - - FTS *fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL); - if (fts) { - // Traverse the entire hierarchy and chown to system UID. - for (FTSENT *ftsent = fts_read(fts); ftsent != NULL; ftsent = fts_read(fts)) { - // We don't care about the lost+found directory. - if (!strcmp(ftsent->fts_name, "lost+found")) { - continue; - } - - /* - * There can only be one file marked as private right now. - * This should be more robust, but it satisfies the requirements - * we have for right now. - */ - const bool privateFile = !strcmp(ftsent->fts_name, filename); - - int fd = open(ftsent->fts_accpath, O_NOFOLLOW | O_CLOEXEC); - if (fd < 0) { - SLOGE("Couldn't open file %s: %s", ftsent->fts_accpath, strerror(errno)); - result = -1; - continue; - } - - result |= fchown(fd, AID_SYSTEM, privateFile? gid : AID_SYSTEM); - - if (ftsent->fts_info & FTS_D) { - result |= fchmod(fd, 0755); - } else if (ftsent->fts_info & FTS_F) { - result |= fchmod(fd, privateFile ? 0640 : 0644); - } - - if (selinux_android_restorecon(ftsent->fts_path, 0) < 0) { - SLOGE("restorecon failed for %s: %s\n", ftsent->fts_path, strerror(errno)); - result |= -1; - } - - close(fd); - } - fts_close(fts); - - // Finally make the directory readable by everyone. - int dirfd = open(mountPoint, O_DIRECTORY | O_CLOEXEC); - if (dirfd < 0 || fchmod(dirfd, 0755)) { - SLOGE("Couldn't change owner of existing directory %s: %s", mountPoint, strerror(errno)); - result |= -1; - } - close(dirfd); - } else { - result |= -1; - } - - result |= android::vold::ext4::Mount(loopDevice, mountPoint, - true /* read-only */, - true /* remount */, - true /* execute */); - - if (result) { - SLOGE("ASEC fix permissions failed (%s)", strerror(errno)); - return -1; - } - - if (mDebug) { - SLOGD("ASEC %s permissions fixed", id); - } - return 0; -} - -int VolumeManager::renameAsec(const char *id1, const char *id2) { - char asecFilename1[255]; - char *asecFilename2; - char mountPoint[255]; - - const char *dir; - - if (!isLegalAsecId(id1)) { - SLOGE("renameAsec: Invalid asec id1 \"%s\"", id1); - errno = EINVAL; - return -1; - } - - if (!isLegalAsecId(id2)) { - SLOGE("renameAsec: Invalid asec id2 \"%s\"", id2); - errno = EINVAL; - return -1; - } - - if (findAsec(id1, asecFilename1, sizeof(asecFilename1), &dir)) { - SLOGE("Couldn't find ASEC %s", id1); - return -1; - } - - asprintf(&asecFilename2, "%s/%s.asec", dir, id2); - - int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id1); - if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { - SLOGE("Rename failed: couldn't construct mountpoint"); - goto out_err; - } - - if (isMountpointMounted(mountPoint)) { - SLOGW("Rename attempt when src mounted"); - errno = EBUSY; - goto out_err; - } - - written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id2); - if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { - SLOGE("Rename failed: couldn't construct mountpoint2"); - goto out_err; - } - - if (isMountpointMounted(mountPoint)) { - SLOGW("Rename attempt when dst mounted"); - errno = EBUSY; - goto out_err; - } - - if (!access(asecFilename2, F_OK)) { - SLOGE("Rename attempt when dst exists"); - errno = EADDRINUSE; - goto out_err; - } - - if (rename(asecFilename1, asecFilename2)) { - SLOGE("Rename of '%s' to '%s' failed (%s)", asecFilename1, asecFilename2, strerror(errno)); - goto out_err; - } - - free(asecFilename2); - return 0; - -out_err: - free(asecFilename2); - return -1; -} - -#define UNMOUNT_RETRIES 5 -#define UNMOUNT_SLEEP_BETWEEN_RETRY_MS (1000 * 1000) -int VolumeManager::unmountAsec(const char *id, bool force) { - char asecFileName[255]; - char mountPoint[255]; - - if (!isLegalAsecId(id)) { - SLOGE("unmountAsec: Invalid asec id \"%s\"", id); - errno = EINVAL; - return -1; - } - - if (findAsec(id, asecFileName, sizeof(asecFileName))) { - SLOGE("Couldn't find ASEC %s", id); - return -1; - } - - int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id); - if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { - SLOGE("ASEC unmount failed for %s: couldn't construct mountpoint", id); - return -1; - } - - char idHash[33]; - if (!asecHash(id, idHash, sizeof(idHash))) { - SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); - return -1; - } - - return unmountLoopImage(id, idHash, asecFileName, mountPoint, force); -} - -int VolumeManager::unmountObb(const char *fileName, bool force) { - char mountPoint[255]; - - char idHash[33]; - if (!asecHash(fileName, idHash, sizeof(idHash))) { - SLOGE("Hash of '%s' failed (%s)", fileName, strerror(errno)); - return -1; - } - - int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::LOOPDIR, idHash); - if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { - SLOGE("OBB unmount failed for %s: couldn't construct mountpoint", fileName); - return -1; - } - - return unmountLoopImage(fileName, idHash, fileName, mountPoint, force); -} - -int VolumeManager::unmountLoopImage(const char *id, const char *idHash, - const char *fileName, const char *mountPoint, bool force) { - if (!isMountpointMounted(mountPoint)) { - SLOGE("Unmount request for %s when not mounted", id); - errno = ENOENT; - return -1; - } - - int i, rc; - for (i = 1; i <= UNMOUNT_RETRIES; i++) { - rc = umount(mountPoint); - if (!rc) { - break; - } - if (rc && (errno == EINVAL || errno == ENOENT)) { - SLOGI("Container %s unmounted OK", id); - rc = 0; - break; - } - SLOGW("%s unmount attempt %d failed (%s)", - id, i, strerror(errno)); - - int signal = 0; // default is to just complain - - if (force) { - if (i > (UNMOUNT_RETRIES - 2)) - signal = SIGKILL; - else if (i > (UNMOUNT_RETRIES - 3)) - signal = SIGTERM; - } - - Process::killProcessesWithOpenFiles(mountPoint, signal); - usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS); - } - - if (rc) { - errno = EBUSY; - SLOGE("Failed to unmount container %s (%s)", id, strerror(errno)); - return -1; - } - - int retries = 10; - - while(retries--) { - if (!rmdir(mountPoint)) { - break; - } - - SLOGW("Failed to rmdir %s (%s)", mountPoint, strerror(errno)); - usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS); - } - - if (!retries) { - SLOGE("Timed out trying to rmdir %s (%s)", mountPoint, strerror(errno)); - } - - for (i=1; i <= UNMOUNT_RETRIES; i++) { - if (Devmapper::destroy(idHash) && errno != ENXIO) { - SLOGE("Failed to destroy devmapper instance (%s)", strerror(errno)); - usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS); - continue; - } else { - break; - } - } - - char loopDevice[255]; - if (!Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) { - Loop::destroyByDevice(loopDevice); - } else { - SLOGW("Failed to find loop device for {%s} (%s)", fileName, strerror(errno)); - } - - AsecIdCollection::iterator it; - for (it = mActiveContainers->begin(); it != mActiveContainers->end(); ++it) { - ContainerData* cd = *it; - if (!strcmp(cd->id, id)) { - free(*it); - mActiveContainers->erase(it); - break; - } - } - if (it == mActiveContainers->end()) { - SLOGW("mActiveContainers is inconsistent!"); - } - return 0; -} - -int VolumeManager::destroyAsec(const char *id, bool force) { - char asecFileName[255]; - char mountPoint[255]; - - if (!isLegalAsecId(id)) { - SLOGE("destroyAsec: Invalid asec id \"%s\"", id); - errno = EINVAL; - return -1; - } - - if (findAsec(id, asecFileName, sizeof(asecFileName))) { - SLOGE("Couldn't find ASEC %s", id); - return -1; - } - - int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id); - if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { - SLOGE("ASEC destroy failed for %s: couldn't construct mountpoint", id); - return -1; - } - - if (isMountpointMounted(mountPoint)) { - if (mDebug) { - SLOGD("Unmounting container before destroy"); - } - if (unmountAsec(id, force)) { - SLOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno)); - return -1; - } - } - - if (unlink(asecFileName)) { - SLOGE("Failed to unlink asec '%s' (%s)", asecFileName, strerror(errno)); - return -1; - } - - if (mDebug) { - SLOGD("ASEC %s destroyed", id); - } - return 0; -} - -/* - * Legal ASEC ids consist of alphanumeric characters, '-', - * '_', or '.'. ".." is not allowed. The first or last character - * of the ASEC id cannot be '.' (dot). - */ -bool VolumeManager::isLegalAsecId(const char *id) const { - size_t i; - size_t len = strlen(id); - - if (len == 0) { - return false; - } - if ((id[0] == '.') || (id[len - 1] == '.')) { - return false; - } - - for (i = 0; i < len; i++) { - if (id[i] == '.') { - // i=0 is guaranteed never to have a dot. See above. - if (id[i-1] == '.') return false; - continue; - } - if (id[i] == '_' || id[i] == '-') continue; - if (id[i] >= 'a' && id[i] <= 'z') continue; - if (id[i] >= 'A' && id[i] <= 'Z') continue; - if (id[i] >= '0' && id[i] <= '9') continue; - return false; - } - - return true; -} - -bool VolumeManager::isAsecInDirectory(const char *dir, const char *asecName) const { - int dirfd = open(dir, O_DIRECTORY | O_CLOEXEC); - if (dirfd < 0) { - SLOGE("Couldn't open internal ASEC dir (%s)", strerror(errno)); - return false; - } - - struct stat sb; - bool ret = (fstatat(dirfd, asecName, &sb, AT_SYMLINK_NOFOLLOW) == 0) - && S_ISREG(sb.st_mode); - - close(dirfd); - - return ret; -} - -int VolumeManager::findAsec(const char *id, char *asecPath, size_t asecPathLen, - const char **directory) const { - char *asecName; - - if (!isLegalAsecId(id)) { - SLOGE("findAsec: Invalid asec id \"%s\"", id); - errno = EINVAL; - return -1; - } - - if (asprintf(&asecName, "%s.asec", id) < 0) { - SLOGE("Couldn't allocate string to write ASEC name"); - return -1; - } - - const char *dir; - if (isAsecInDirectory(VolumeManager::SEC_ASECDIR_INT, asecName)) { - dir = VolumeManager::SEC_ASECDIR_INT; - } else if (isAsecInDirectory(VolumeManager::SEC_ASECDIR_EXT, asecName)) { - dir = VolumeManager::SEC_ASECDIR_EXT; - } else { - free(asecName); - return -1; - } - - if (directory != NULL) { - *directory = dir; - } - - if (asecPath != NULL) { - int written = snprintf(asecPath, asecPathLen, "%s/%s", dir, asecName); - if ((written < 0) || (size_t(written) >= asecPathLen)) { - SLOGE("findAsec failed for %s: couldn't construct ASEC path", id); - free(asecName); - return -1; - } - } - - free(asecName); - return 0; -} - -int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid, bool readOnly) { - char asecFileName[255]; - char mountPoint[255]; - - if (!isLegalAsecId(id)) { - SLOGE("mountAsec: Invalid asec id \"%s\"", id); - errno = EINVAL; - return -1; - } - - if (findAsec(id, asecFileName, sizeof(asecFileName))) { - SLOGE("Couldn't find ASEC %s", id); - return -1; - } - - int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::ASECDIR, id); - if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { - SLOGE("ASEC mount failed for %s: couldn't construct mountpoint", id); - return -1; - } - - if (isMountpointMounted(mountPoint)) { - SLOGE("ASEC %s already mounted", id); - errno = EBUSY; - return -1; - } - - char idHash[33]; - if (!asecHash(id, idHash, sizeof(idHash))) { - SLOGE("Hash of '%s' failed (%s)", id, strerror(errno)); - return -1; - } - - char loopDevice[255]; - if (setupLoopDevice(loopDevice, sizeof(loopDevice), asecFileName, idHash, mDebug)) - return -1; - - char dmDevice[255]; - bool cleanupDm = false; - - unsigned long nr_sec = 0; - struct asec_superblock sb; - - if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) { - return -1; - } - - if (mDebug) { - SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver); - } - if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) { - SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver); - Loop::destroyByDevice(loopDevice); - errno = EMEDIUMTYPE; - return -1; - } - nr_sec--; // We don't want the devmapping to extend onto our superblock - - if (setupDevMapperDevice(dmDevice, sizeof(dmDevice), loopDevice, asecFileName, key, idHash , nr_sec, &cleanupDm, mDebug)) { - Loop::destroyByDevice(loopDevice); - return -1; - } - - if (mkdir(mountPoint, 0000)) { - if (errno != EEXIST) { - SLOGE("Mountpoint creation failed (%s)", strerror(errno)); - if (cleanupDm) { - Devmapper::destroy(idHash); - } - Loop::destroyByDevice(loopDevice); - return -1; - } - } - - /* - * Wait for the device mapper node to be created. - */ - waitForDevMapper(dmDevice); - - int result; - if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) { - result = android::vold::ext4::Mount(dmDevice, mountPoint, - readOnly, false, readOnly); - } else { - result = android::vold::vfat::Mount(dmDevice, mountPoint, - readOnly, false, readOnly, ownerUid, 0, 0222, false); - } - - if (result) { - SLOGE("ASEC mount failed (%s)", strerror(errno)); - if (cleanupDm) { - Devmapper::destroy(idHash); - } - Loop::destroyByDevice(loopDevice); - return -1; - } - - mActiveContainers->push_back(new ContainerData(strdup(id), ASEC)); - if (mDebug) { - SLOGD("ASEC %s mounted", id); - } - return 0; -} - -/** - * Mounts an image file img. - */ -int VolumeManager::mountObb(const char *img, const char *key, int ownerGid) { - char mountPoint[255]; - - char idHash[33]; - if (!asecHash(img, idHash, sizeof(idHash))) { - SLOGE("Hash of '%s' failed (%s)", img, strerror(errno)); - return -1; - } - - int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", VolumeManager::LOOPDIR, idHash); - if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) { - SLOGE("OBB mount failed for %s: couldn't construct mountpoint", img); - return -1; - } - - if (isMountpointMounted(mountPoint)) { - SLOGE("Image %s already mounted", img); - errno = EBUSY; - return -1; - } - - char loopDevice[255]; - if (setupLoopDevice(loopDevice, sizeof(loopDevice), img, idHash, mDebug)) - return -1; - - char dmDevice[255]; - bool cleanupDm = false; - int fd; - unsigned long nr_sec = 0; - - if ((fd = open(loopDevice, O_RDWR | O_CLOEXEC)) < 0) { - SLOGE("Failed to open loopdevice (%s)", strerror(errno)); - Loop::destroyByDevice(loopDevice); - return -1; - } - - get_blkdev_size(fd, &nr_sec); - if (nr_sec == 0) { - SLOGE("Failed to get loop size (%s)", strerror(errno)); - Loop::destroyByDevice(loopDevice); - close(fd); - return -1; - } - - close(fd); - - if (setupDevMapperDevice(dmDevice, sizeof(loopDevice), loopDevice, img,key, idHash, nr_sec, &cleanupDm, mDebug)) { - Loop::destroyByDevice(loopDevice); - return -1; - } - - if (mkdir(mountPoint, 0755)) { - if (errno != EEXIST) { - SLOGE("Mountpoint creation failed (%s)", strerror(errno)); - if (cleanupDm) { - Devmapper::destroy(idHash); - } - Loop::destroyByDevice(loopDevice); - return -1; - } - } - - /* - * Wait for the device mapper node to be created. - */ - waitForDevMapper(dmDevice); - - if (android::vold::vfat::Mount(dmDevice, mountPoint, - true, false, true, 0, ownerGid, 0227, false)) { - SLOGE("Image mount failed (%s)", strerror(errno)); - if (cleanupDm) { - Devmapper::destroy(idHash); - } - Loop::destroyByDevice(loopDevice); - return -1; - } - - mActiveContainers->push_back(new ContainerData(strdup(img), OBB)); - if (mDebug) { - SLOGD("Image %s mounted", img); - } - return 0; -} - -int VolumeManager::listMountedObbs(SocketClient* cli) { - FILE *fp = setmntent("/proc/mounts", "r"); - if (fp == NULL) { - SLOGE("Error opening /proc/mounts (%s)", strerror(errno)); - return -1; - } - - // Create a string to compare against that has a trailing slash - int loopDirLen = strlen(VolumeManager::LOOPDIR); - char loopDir[loopDirLen + 2]; - strlcpy(loopDir, VolumeManager::LOOPDIR, sizeof(loopDir)); - loopDir[loopDirLen++] = '/'; - loopDir[loopDirLen] = '\0'; - - mntent* mentry; - while ((mentry = getmntent(fp)) != NULL) { - if (!strncmp(mentry->mnt_dir, loopDir, loopDirLen)) { - int fd = open(mentry->mnt_fsname, O_RDONLY | O_CLOEXEC); - if (fd >= 0) { - struct loop_info64 li; - if (ioctl(fd, LOOP_GET_STATUS64, &li) >= 0) { - cli->sendMsg(ResponseCode::AsecListResult, - (const char*) li.lo_file_name, false); - } - close(fd); - } - } - } - endmntent(fp); - return 0; -} - extern "C" int vold_unmountAll(void) { VolumeManager *vm = VolumeManager::Instance(); return vm->unmountAll(); } -bool VolumeManager::isMountpointMounted(const char *mp) -{ - FILE *fp = setmntent("/proc/mounts", "r"); - if (fp == NULL) { - SLOGE("Error opening /proc/mounts (%s)", strerror(errno)); - return false; - } - - bool found_mp = false; - mntent* mentry; - while ((mentry = getmntent(fp)) != NULL) { - if (strcmp(mentry->mnt_dir, mp) == 0) { - found_mp = true; - break; - } - } - endmntent(fp); - return found_mp; -} - int VolumeManager::mkdirs(const char* path) { // Only offer to create directories for paths managed by vold if (strncmp(path, "/storage/", 9) == 0) { diff --git a/VolumeManager.h b/VolumeManager.h index a00520e..dcfbdad 100644 --- a/VolumeManager.h +++ b/VolumeManager.h @@ -33,7 +33,6 @@ #include #include #include -#include #include #include "android/os/IVoldListener.h" @@ -41,56 +40,18 @@ #include "model/Disk.h" #include "model/VolumeBase.h" -/* The length of an MD5 hash when encoded into ASCII hex characters */ -#define MD5_ASCII_LENGTH_PLUS_NULL ((MD5_DIGEST_LENGTH*2)+1) - #define DEBUG_APPFUSE 0 -typedef enum { ASEC, OBB } container_type_t; - -class ContainerData { -public: - ContainerData(char* _id, container_type_t _type) - : id(_id) - , type(_type) - {} - - ~ContainerData() { - if (id != NULL) { - free(id); - id = NULL; - } - } - - char *id; - container_type_t type; -}; - -typedef android::List AsecIdCollection; - class VolumeManager { public: - static const char *SEC_ASECDIR_EXT; - static const char *SEC_ASECDIR_INT; - static const char *ASECDIR; - static const char *LOOPDIR; - //TODO remove this with better solution, b/64143519 static bool shutting_down; private: static VolumeManager *sInstance; - SocketListener *mBroadcaster; - - AsecIdCollection *mActiveContainers; bool mDebug; - // for adjusting /proc/sys/vm/dirty_ratio when UMS is active - int mUmsSharingCount; - int mSavedDirtyRatio; - int mUmsDirtyRatio; - public: virtual ~VolumeManager(); @@ -150,52 +111,11 @@ public: /* Unmount all volumes, usually for encryption */ int unmountAll(); - /* ASEC */ - int findAsec(const char *id, char *asecPath = NULL, size_t asecPathLen = 0, - const char **directory = NULL) const; - int createAsec(const char *id, unsigned long numSectors, const char *fstype, - const char *key, const int ownerUid, bool isExternal); - int resizeAsec(const char *id, unsigned long numSectors, const char *key); - int finalizeAsec(const char *id); - - /** - * Fixes ASEC permissions on a filesystem that has owners and permissions. - * This currently means EXT4-based ASEC containers. - * - * There is a single file that can be marked as "private" and will not have - * world-readable permission. The group for that file will be set to the gid - * supplied. - * - * Returns 0 on success. - */ - int fixupAsecPermissions(const char *id, gid_t gid, const char* privateFilename); - int destroyAsec(const char *id, bool force); - int mountAsec(const char *id, const char *key, int ownerUid, bool readOnly); - int unmountAsec(const char *id, bool force); - int renameAsec(const char *id1, const char *id2); - int getAsecMountPath(const char *id, char *buffer, int maxlen); - int getAsecFilesystemPath(const char *id, char *buffer, int maxlen); - - /* Loopback images */ - int listMountedObbs(SocketClient* cli); - int mountObb(const char *fileName, const char *key, int ownerUid); - int unmountObb(const char *fileName, bool force); - int getObbMountPath(const char *id, char *buffer, int maxlen); - - /* Shared between ASEC and Loopback images */ - int unmountLoopImage(const char *containerId, const char *loopId, - const char *fileName, const char *mountPoint, bool force); - int updateVirtualDisk(); int setDebug(bool enable); - void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; } - SocketListener *getBroadcaster() { return mBroadcaster; } - static VolumeManager *Instance(); - static char *asecHash(const char *id, char *buffer, size_t len); - /* * Ensure that all directories along given path exist, creating parent * directories as needed. Validates that given path is absolute and that @@ -215,9 +135,6 @@ public: private: VolumeManager(); void readInitialState(); - bool isMountpointMounted(const char *mp); - bool isAsecInDirectory(const char *dir, const char *asec) const; - bool isLegalAsecId(const char *id) const; int linkPrimary(userid_t userId); diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl index 1736829..d47f113 100644 --- a/binder/android/os/IVold.aidl +++ b/binder/android/os/IVold.aidl @@ -23,6 +23,7 @@ import android.os.IVoldTaskListener; interface IVold { void setListener(IVoldListener listener); + void monitor(); void reset(); void shutdown(); void mountAll(); diff --git a/main.cpp b/main.cpp index 8175dc5..37d02e7 100644 --- a/main.cpp +++ b/main.cpp @@ -16,8 +16,6 @@ #include "model/Disk.h" #include "VolumeManager.h" -#include "CommandListener.h" -#include "CryptCommandListener.h" #include "NetlinkManager.h" #include "VoldNativeService.h" #include "cryptfs.h" @@ -27,7 +25,6 @@ #include #include #include -#include #include #include @@ -62,8 +59,6 @@ int main(int argc, char** argv) { << (android::vold::IsFilesystemSupported("vfat") ? " vfat" : ""); VolumeManager *vm; - CommandListener *cl; - CryptCommandListener *ccl; NetlinkManager *nm; parse_args(argc, argv); @@ -73,10 +68,6 @@ int main(int argc, char** argv) { selinux_android_set_sehandle(sehandle); } - // Quickly throw a CLOEXEC on the socket we just inherited from init - fcntl(android_get_control_socket("vold"), F_SETFD, FD_CLOEXEC); - fcntl(android_get_control_socket("cryptd"), F_SETFD, FD_CLOEXEC); - mkdir("/dev/block/vold", 0755); /* For when cryptfs checks and mounts an encrypted filesystem */ @@ -97,11 +88,6 @@ int main(int argc, char** argv) { vm->setDebug(true); } - cl = new CommandListener(); - ccl = new CryptCommandListener(); - vm->setBroadcaster((SocketListener *) cl); - nm->setBroadcaster((SocketListener *) cl); - if (vm->start()) { PLOG(ERROR) << "Unable to start VolumeManager"; exit(1); @@ -124,19 +110,6 @@ int main(int argc, char** argv) { exit(1); } - /* - * Now that we're up, we can respond to commands - */ - if (cl->startListener()) { - PLOG(ERROR) << "Unable to start CommandListener"; - exit(1); - } - - if (ccl->startListener()) { - PLOG(ERROR) << "Unable to start CryptCommandListener"; - exit(1); - } - // This call should go after listeners are started to avoid // a deadlock between vold and init (see b/34278978 for details) property_set("vold.has_adoptable", has_adoptable ? "1" : "0"); diff --git a/model/Disk.cpp b/model/Disk.cpp index 151937f..f9799ad 100644 --- a/model/Disk.cpp +++ b/model/Disk.cpp @@ -20,7 +20,6 @@ #include "Utils.h" #include "VolumeBase.h" #include "VolumeManager.h" -#include "ResponseCode.h" #include "Ext4Crypt.h" #include @@ -151,12 +150,10 @@ void Disk::listVolumes(VolumeBase::Type type, std::list& list) { status_t Disk::create() { CHECK(!mCreated); mCreated = true; -#if ENABLE_BINDER + auto listener = VolumeManager::Instance()->getListener(); if (listener) listener->onDiskCreated(getId(), mFlags); -#else - notifyEvent(ResponseCode::DiskCreated, StringPrintf("%d", mFlags)); -#endif + readMetadata(); readPartitions(); return OK; @@ -166,12 +163,10 @@ status_t Disk::destroy() { CHECK(mCreated); destroyAllVolumes(); mCreated = false; -#if ENABLE_BINDER + auto listener = VolumeManager::Instance()->getListener(); if (listener) listener->onDiskDestroyed(getId()); -#else - notifyEvent(ResponseCode::DiskDestroyed); -#endif + return OK; } @@ -291,15 +286,10 @@ status_t Disk::readMetadata() { } } -#if ENABLE_BINDER auto listener = VolumeManager::Instance()->getListener(); if (listener) listener->onDiskMetadataChanged(getId(), mSize, mLabel, mSysPath); -#else - notifyEvent(ResponseCode::DiskSizeChanged, StringPrintf("%" PRIu64, mSize)); - notifyEvent(ResponseCode::DiskLabelChanged, mLabel); - notifyEvent(ResponseCode::DiskSysPathChanged, mSysPath); -#endif + return OK; } @@ -322,12 +312,10 @@ status_t Disk::readPartitions() { status_t res = ForkExecvp(cmd, output); if (res != OK) { LOG(WARNING) << "sgdisk failed to scan " << mDevPath; -#if ENABLE_BINDER + auto listener = VolumeManager::Instance()->getListener(); if (listener) listener->onDiskScanned(getId()); -#else - notifyEvent(ResponseCode::DiskScanned); -#endif + mJustPartitioned = false; return res; } @@ -393,12 +381,9 @@ status_t Disk::readPartitions() { } } -#if ENABLE_BINDER auto listener = VolumeManager::Instance()->getListener(); if (listener) listener->onDiskScanned(getId()); -#else - notifyEvent(ResponseCode::DiskScanned); -#endif + mJustPartitioned = false; return OK; } @@ -560,16 +545,6 @@ status_t Disk::partitionMixed(int8_t ratio) { return OK; } -void Disk::notifyEvent(int event) { - VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event, - getId().c_str(), false); -} - -void Disk::notifyEvent(int event, const std::string& value) { - VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event, - StringPrintf("%s %s", getId().c_str(), value.c_str()).c_str(), false); -} - int Disk::getMaxMinors() { // Figure out maximum partition devices supported unsigned int majorId = major(mDevice); diff --git a/model/Disk.h b/model/Disk.h index 77ec7df..63acf6a 100644 --- a/model/Disk.h +++ b/model/Disk.h @@ -79,9 +79,6 @@ public: status_t partitionPrivate(); status_t partitionMixed(int8_t ratio); - void notifyEvent(int msg); - void notifyEvent(int msg, const std::string& value); - private: /* ID that uniquely references this disk */ std::string mId; diff --git a/model/PrivateVolume.cpp b/model/PrivateVolume.cpp index 9a96082..3152313 100644 --- a/model/PrivateVolume.cpp +++ b/model/PrivateVolume.cpp @@ -20,7 +20,6 @@ #include "EmulatedVolume.h" #include "Utils.h" #include "VolumeManager.h" -#include "ResponseCode.h" #include "cryptfs.h" #include @@ -55,14 +54,10 @@ PrivateVolume::~PrivateVolume() { status_t PrivateVolume::readMetadata() { status_t res = ReadMetadata(mDmDevPath, mFsType, mFsUuid, mFsLabel); -#if ENABLE_BINDER + auto listener = getListener(); if (listener) listener->onVolumeMetadataChanged(getId(), mFsType, mFsUuid, mFsLabel); -#else - notifyEvent(ResponseCode::VolumeFsTypeChanged, mFsType); - notifyEvent(ResponseCode::VolumeFsUuidChanged, mFsUuid); - notifyEvent(ResponseCode::VolumeFsLabelChanged, mFsLabel); -#endif + return res; } diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp index 04bafed..569203c 100644 --- a/model/PublicVolume.cpp +++ b/model/PublicVolume.cpp @@ -18,7 +18,6 @@ #include "PublicVolume.h" #include "Utils.h" #include "VolumeManager.h" -#include "ResponseCode.h" #include #include @@ -53,14 +52,10 @@ PublicVolume::~PublicVolume() { status_t PublicVolume::readMetadata() { status_t res = ReadMetadataUntrusted(mDevPath, mFsType, mFsUuid, mFsLabel); -#if ENABLE_BINDER + auto listener = getListener(); if (listener) listener->onVolumeMetadataChanged(getId(), mFsType, mFsUuid, mFsLabel); -#else - notifyEvent(ResponseCode::VolumeFsTypeChanged, mFsType); - notifyEvent(ResponseCode::VolumeFsUuidChanged, mFsUuid); - notifyEvent(ResponseCode::VolumeFsLabelChanged, mFsLabel); -#endif + return res; } diff --git a/model/VolumeBase.cpp b/model/VolumeBase.cpp index b2eff3b..429f134 100644 --- a/model/VolumeBase.cpp +++ b/model/VolumeBase.cpp @@ -17,7 +17,6 @@ #include "Utils.h" #include "VolumeBase.h" #include "VolumeManager.h" -#include "ResponseCode.h" #include #include @@ -44,12 +43,9 @@ VolumeBase::~VolumeBase() { void VolumeBase::setState(State state) { mState = state; -#if ENABLE_BINDER + auto listener = getListener(); if (listener) listener->onVolumeStateChanged(getId(), static_cast(mState)); -#else - notifyEvent(ResponseCode::VolumeStateChanged, StringPrintf("%d", mState)); -#endif } status_t VolumeBase::setDiskId(const std::string& diskId) { @@ -119,12 +115,10 @@ status_t VolumeBase::setPath(const std::string& path) { } mPath = path; -#if ENABLE_BINDER + auto listener = getListener(); if (listener) listener->onVolumePathChanged(getId(), mPath); -#else - notifyEvent(ResponseCode::VolumePathChanged, mPath); -#endif + return OK; } @@ -135,25 +129,11 @@ status_t VolumeBase::setInternalPath(const std::string& internalPath) { } mInternalPath = internalPath; -#if ENABLE_BINDER + auto listener = getListener(); if (listener) listener->onVolumeInternalPathChanged(getId(), mInternalPath); -#else - notifyEvent(ResponseCode::VolumeInternalPathChanged, mInternalPath); -#endif - return OK; -} -void VolumeBase::notifyEvent(int event) { - if (mSilent) return; - VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event, - getId().c_str(), false); -} - -void VolumeBase::notifyEvent(int event, const std::string& value) { - if (mSilent) return; - VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event, - StringPrintf("%s %s", getId().c_str(), value.c_str()).c_str(), false); + return OK; } android::sp VolumeBase::getListener() { @@ -186,14 +166,11 @@ status_t VolumeBase::create() { mCreated = true; status_t res = doCreate(); -#if ENABLE_BINDER + auto listener = getListener(); if (listener) listener->onVolumeCreated(getId(), static_cast(mType), mDiskId, mPartGuid); -#else - notifyEvent(ResponseCode::VolumeCreated, - StringPrintf("%d \"%s\" \"%s\"", mType, mDiskId.c_str(), mPartGuid.c_str())); -#endif + setState(State::kUnmounted); return res; } @@ -212,12 +189,10 @@ status_t VolumeBase::destroy() { setState(State::kRemoved); } -#if ENABLE_BINDER + auto listener = getListener(); if (listener) listener->onVolumeDestroyed(getId()); -#else - notifyEvent(ResponseCode::VolumeDestroyed); -#endif + status_t res = doDestroy(); mCreated = false; return res; diff --git a/model/VolumeBase.h b/model/VolumeBase.h index ac111c2..4aa8b02 100644 --- a/model/VolumeBase.h +++ b/model/VolumeBase.h @@ -115,9 +115,6 @@ protected: status_t setPath(const std::string& path); status_t setInternalPath(const std::string& internalPath); - void notifyEvent(int msg); - void notifyEvent(int msg, const std::string& value); - android::sp getListener(); private: diff --git a/tests/VolumeManager_test.cpp b/tests/VolumeManager_test.cpp index c0c1fa5..f661d49 100644 --- a/tests/VolumeManager_test.cpp +++ b/tests/VolumeManager_test.cpp @@ -34,31 +34,4 @@ protected: } }; -TEST_F(VolumeManagerTest, AsecHashTests) { - char buffer[MD5_ASCII_LENGTH_PLUS_NULL]; - char* dst = reinterpret_cast(&buffer); - - const char* src1 = ""; - const char* exp1 = "d41d8cd98f00b204e9800998ecf8427e"; - - EXPECT_TRUE(VolumeManager::asecHash(exp1, (char*)NULL, sizeof(buffer)) == NULL && errno == ESPIPE) - << "Should return NULL and set errno to ESPIPE when destination buffer is NULL"; - EXPECT_TRUE(VolumeManager::asecHash(exp1, dst, 0) == NULL && errno == ESPIPE) - << "Should return NULL and set errno to ESPIPE when destination buffer length is 0"; - EXPECT_TRUE(VolumeManager::asecHash((const char*)NULL, dst, sizeof(buffer)) == NULL && errno == ESPIPE) - << "Should return NULL and set errno to ESPIPE when source buffer is NULL"; - - EXPECT_FALSE(VolumeManager::asecHash(src1, dst, sizeof(buffer)) == NULL) - << "Should not return NULL on valid source, destination, and destination size"; - EXPECT_STREQ(exp1, dst) - << "MD5 summed output should match"; - - const char* src2 = "android"; - const char* exp2 = "c31b32364ce19ca8fcd150a417ecce58"; - EXPECT_FALSE(VolumeManager::asecHash(src2, dst, sizeof(buffer)) == NULL) - << "Should not return NULL on valid source, destination, and destination size"; - EXPECT_STREQ(exp2, dst) - << "MD5 summed output should match"; -} - } diff --git a/vdc.cpp b/vdc.cpp index 3a38641..b249987 100644 --- a/vdc.cpp +++ b/vdc.cpp @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -36,23 +35,13 @@ #include #include -#include #include -#define ENABLE_BINDER 1 - static void usage(char *progname); -#if !ENABLE_BINDER -static int do_monitor(int sock, int stop_after_cmd); -static int do_cmd(int sock, int argc, char **argv); -#endif - -static constexpr int kCommandTimeoutMs = 20 * 1000; - int main(int argc, char **argv) { int sock; - int wait_for_socket; + int wait; char *progname; progname = argv[0]; @@ -64,8 +53,8 @@ int main(int argc, char **argv) { android::base::InitLogging(argv, &android::base::StderrLogger); } - wait_for_socket = argc > 1 && strcmp(argv[1], "--wait") == 0; - if (wait_for_socket) { + wait = argc > 1 && strcmp(argv[1], "--wait") == 0; + if (wait) { argv++; argc--; } @@ -75,7 +64,6 @@ int main(int argc, char **argv) { exit(5); } -#if ENABLE_BINDER std::string arg1 = argv[1]; std::string arg2 = argv[2]; @@ -102,118 +90,7 @@ int main(int argc, char **argv) { LOG(ERROR) << "Raw commands are no longer supported"; exit(EINVAL); } -#else - const char* sockname = "vold"; - if (!strcmp(argv[1], "cryptfs")) { - sockname = "cryptd"; - } - - while ((sock = socket_local_client(sockname, - ANDROID_SOCKET_NAMESPACE_RESERVED, - SOCK_STREAM)) < 0) { - if (!wait_for_socket) { - PLOG(ERROR) << "Error connecting to " << sockname; - exit(4); - } else { - usleep(10000); - } - } - - if (!strcmp(argv[1], "monitor")) { - exit(do_monitor(sock, 0)); - } else { - exit(do_cmd(sock, argc, argv)); - } -#endif -} - -#if !ENABLE_BINDER -static int do_cmd(int sock, int argc, char **argv) { - int seq = getpid(); - - std::string cmd(android::base::StringPrintf("%d ", seq)); - for (int i = 1; i < argc; i++) { - if (!strchr(argv[i], ' ')) { - cmd.append(argv[i]); - } else { - cmd.push_back('\"'); - cmd.append(argv[i]); - cmd.push_back('\"'); - } - - if (i < argc - 1) { - cmd.push_back(' '); - } - } - - if (TEMP_FAILURE_RETRY(write(sock, cmd.c_str(), cmd.length() + 1)) < 0) { - PLOG(ERROR) << "Failed to write command"; - return errno; - } - - return do_monitor(sock, seq); -} - -static int do_monitor(int sock, int stop_after_seq) { - char buffer[4096]; - int timeout = kCommandTimeoutMs; - - if (stop_after_seq == 0) { - LOG(INFO) << "Connected to vold"; - timeout = -1; - } - - while (1) { - struct pollfd poll_sock = { sock, POLLIN, 0 }; - int rc = TEMP_FAILURE_RETRY(poll(&poll_sock, 1, timeout)); - if (rc == 0) { - LOG(ERROR) << "Timeout waiting for " << stop_after_seq; - return ETIMEDOUT; - } else if (rc < 0) { - PLOG(ERROR) << "Failed during poll"; - return errno; - } - - if (!(poll_sock.revents & POLLIN)) { - LOG(INFO) << "No data; trying again"; - continue; - } - - memset(buffer, 0, sizeof(buffer)); - rc = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer))); - if (rc == 0) { - LOG(ERROR) << "Lost connection, did vold crash?"; - return ECONNRESET; - } else if (rc < 0) { - PLOG(ERROR) << "Error reading data"; - return errno; - } - - int offset = 0; - for (int i = 0; i < rc; i++) { - if (buffer[i] == '\0') { - char* res = buffer + offset; - fprintf(stdout, "%s\n", res); - - int code = atoi(strtok(res, " ")); - if (code >= 200 && code < 600) { - int seq = atoi(strtok(nullptr, " ")); - if (seq == stop_after_seq) { - if (code == 200) { - return 0; - } else { - return code; - } - } - } - - offset = i + 1; - } - } - } - return EIO; } -#endif static void usage(char *progname) { LOG(INFO) << "Usage: " << progname << " [--wait] | [arg1] [arg2...]"; diff --git a/vold.rc b/vold.rc index 87e2fd8..c27aeda 100644 --- a/vold.rc +++ b/vold.rc @@ -2,9 +2,6 @@ service vold /system/bin/vold \ --blkid_context=u:r:blkid:s0 --blkid_untrusted_context=u:r:blkid_untrusted:s0 \ --fsck_context=u:r:fsck:s0 --fsck_untrusted_context=u:r:fsck_untrusted:s0 class core - socket vold stream 0660 root mount - socket cryptd stream 0660 root mount ioprio be 2 writepid /dev/cpuset/foreground/tasks shutdown critical -