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 -