Merge "Destroy vold socket interface completely."
This commit is contained in:
commit
49672b9351
33 changed files with 40 additions and 3378 deletions
|
@ -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 \
|
||||
|
|
43
Asec.h
43
Asec.h
|
@ -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
|
|
@ -17,7 +17,6 @@
|
|||
#include "BenchmarkTask.h"
|
||||
#include "BenchmarkGen.h"
|
||||
#include "VolumeManager.h"
|
||||
#include "ResponseCode.h"
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
|
|
|
@ -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 <stdlib.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fs_mgr.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define LOG_TAG "VoldCmdListener"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <cutils/fs.h>
|
||||
|
||||
#include <sysutils/SocketClient.h>
|
||||
#include <private/android_filesystem_config.h>
|
||||
|
||||
#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<std::mutex> 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 <mountpoint>", 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 <container-id> <size_mb> <fstype> <key> <ownerUid> "
|
||||
"<isExternal>", 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 <container-id> <size_mb> <key>", 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 <container-id>", 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 <container-id> <gid> <filename>", 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 <container-id> <gid> <filename>", 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 <container-id> [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 <namespace-id> <key> <ownerUid> <ro|rw>", 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 <container-id> [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 <old_id> <new_id>", 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 <container-id>", 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 <container-id>", 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 <filename> <key> <ownerGid>", 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 <source file> [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 <source file>", 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<std::mutex> 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<std::mutex> 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;
|
||||
}
|
|
@ -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 <sysutils/FrameworkListener.h>
|
||||
#include <utils/Errors.h>
|
||||
#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
|
|
@ -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 <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fs_mgr.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
|
||||
#define LOG_TAG "VoldCryptCmdListener"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
|
||||
#include <cutils/fs.h>
|
||||
#include <cutils/log.h>
|
||||
#include <cutils/sockets.h>
|
||||
|
||||
#include <sysutils/SocketClient.h>
|
||||
#include <private/android_filesystem_config.h>
|
||||
|
||||
#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, "<passwd>")) 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 <wipe|inplace> "
|
||||
"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, "<passwd>")) return 0;
|
||||
SLOGD("cryptfs verifypw {}");
|
||||
rc = cryptfs_verify_passwd(argv[2]);
|
||||
} else if (subcommand == "getfield") {
|
||||
if (!check_argc(cli, subcommand, argc, 3, "<fieldname>")) 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, "<fieldname> <value>")) 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, "<user> <serial> <ephemeral>")) 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, "<user>")) 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, "<user> <serial> <token> <secret>")) 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, "<user>")) 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, "<user> <serial> <token> <secret>")) 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, "<user>")) 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, "<uuid> <user> <serial> <flags>")) 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, "<uuid> <user> <flags>")) 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, "<path>")) 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;
|
||||
}
|
|
@ -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 <sysutils/FrameworkListener.h>
|
||||
#include <utils/Errors.h>
|
||||
#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
|
|
@ -34,7 +34,6 @@
|
|||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <sysutils/SocketClient.h>
|
||||
|
||||
#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);
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
#include <unistd.h>
|
||||
#include <linux/dm-ioctl.h>
|
||||
|
||||
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);
|
||||
|
|
87
Loop.cpp
87
Loop.cpp
|
@ -36,9 +36,7 @@
|
|||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
|
||||
#include <sysutils/SocketClient.h>
|
||||
#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;
|
||||
}
|
||||
|
|
5
Loop.h
5
Loop.h
|
@ -21,22 +21,17 @@
|
|||
#include <unistd.h>
|
||||
#include <linux/loop.h>
|
||||
|
||||
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
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "MoveTask.h"
|
||||
#include "Utils.h"
|
||||
#include "VolumeManager.h"
|
||||
#include "ResponseCode.h"
|
||||
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/logging.h>
|
||||
|
|
|
@ -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 <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LOG_TAG "Vold"
|
||||
|
||||
#include <cutils/log.h>
|
||||
|
||||
#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);
|
||||
}
|
|
@ -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
|
|
@ -17,7 +17,6 @@
|
|||
#include "TrimTask.h"
|
||||
#include "Utils.h"
|
||||
#include "VolumeManager.h"
|
||||
#include "ResponseCode.h"
|
||||
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/logging.h>
|
||||
|
|
2
Utils.h
2
Utils.h
|
@ -29,8 +29,6 @@
|
|||
|
||||
struct DIR;
|
||||
|
||||
#define ENABLE_BINDER 1
|
||||
|
||||
namespace android {
|
||||
namespace vold {
|
||||
|
||||
|
|
|
@ -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) {
|
||||
}
|
|
@ -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 <sysutils/FrameworkCommand.h>
|
||||
|
||||
class VoldCommand : public FrameworkCommand {
|
||||
public:
|
||||
explicit VoldCommand(const char *cmd);
|
||||
virtual ~VoldCommand() {}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -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;
|
||||
|
|
|
@ -33,6 +33,7 @@ public:
|
|||
|
||||
binder::Status setListener(const android::sp<android::os::IVoldListener>& listener);
|
||||
|
||||
binder::Status monitor();
|
||||
binder::Status reset();
|
||||
binder::Status shutdown();
|
||||
binder::Status mountAll();
|
||||
|
|
1353
VolumeManager.cpp
1353
VolumeManager.cpp
File diff suppressed because it is too large
Load diff
|
@ -33,7 +33,6 @@
|
|||
#include <cutils/multiuser.h>
|
||||
#include <utils/List.h>
|
||||
#include <utils/Timers.h>
|
||||
#include <sysutils/SocketListener.h>
|
||||
#include <sysutils/NetlinkEvent.h>
|
||||
|
||||
#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<ContainerData*> 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);
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import android.os.IVoldTaskListener;
|
|||
interface IVold {
|
||||
void setListener(IVoldListener listener);
|
||||
|
||||
void monitor();
|
||||
void reset();
|
||||
void shutdown();
|
||||
void mountAll();
|
||||
|
|
27
main.cpp
27
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 <android-base/stringprintf.h>
|
||||
#include <cutils/klog.h>
|
||||
#include <cutils/properties.h>
|
||||
#include <cutils/sockets.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -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");
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "Utils.h"
|
||||
#include "VolumeBase.h"
|
||||
#include "VolumeManager.h"
|
||||
#include "ResponseCode.h"
|
||||
#include "Ext4Crypt.h"
|
||||
|
||||
#include <android-base/file.h>
|
||||
|
@ -151,12 +150,10 @@ void Disk::listVolumes(VolumeBase::Type type, std::list<std::string>& 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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "EmulatedVolume.h"
|
||||
#include "Utils.h"
|
||||
#include "VolumeManager.h"
|
||||
#include "ResponseCode.h"
|
||||
#include "cryptfs.h"
|
||||
|
||||
#include <android-base/stringprintf.h>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "PublicVolume.h"
|
||||
#include "Utils.h"
|
||||
#include "VolumeManager.h"
|
||||
#include "ResponseCode.h"
|
||||
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/logging.h>
|
||||
|
@ -54,14 +53,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "Utils.h"
|
||||
#include "VolumeBase.h"
|
||||
#include "VolumeManager.h"
|
||||
#include "ResponseCode.h"
|
||||
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/logging.h>
|
||||
|
@ -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<int32_t>(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,27 +129,13 @@ 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);
|
||||
}
|
||||
|
||||
android::sp<android::os::IVoldListener> VolumeBase::getListener() {
|
||||
if (mSilent) {
|
||||
return nullptr;
|
||||
|
@ -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<int32_t>(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;
|
||||
|
|
|
@ -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<android::os::IVoldListener> getListener();
|
||||
|
||||
private:
|
||||
|
|
|
@ -34,31 +34,4 @@ protected:
|
|||
}
|
||||
};
|
||||
|
||||
TEST_F(VolumeManagerTest, AsecHashTests) {
|
||||
char buffer[MD5_ASCII_LENGTH_PLUS_NULL];
|
||||
char* dst = reinterpret_cast<char*>(&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";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
129
vdc.cpp
129
vdc.cpp
|
@ -24,7 +24,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -36,23 +35,13 @@
|
|||
#include <android-base/stringprintf.h>
|
||||
#include <binder/IServiceManager.h>
|
||||
|
||||
#include <cutils/sockets.h>
|
||||
#include <private/android_filesystem_config.h>
|
||||
|
||||
#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];
|
||||
|
||||
|
@ -104,119 +92,8 @@ 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] <monitor>|<cmd> [arg1] [arg2...]";
|
||||
}
|
||||
|
|
3
vold.rc
3
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
|
||||
|
||||
|
|
Loading…
Reference in a new issue