diff options
-rw-r--r-- | Android.mk | 1 | ||||
-rw-r--r-- | Disk.cpp | 125 | ||||
-rw-r--r-- | Disk.h | 4 | ||||
-rw-r--r-- | EmulatedVolume.cpp | 6 | ||||
-rw-r--r-- | Ext4.cpp | 112 | ||||
-rw-r--r-- | Ext4.h | 1 | ||||
-rw-r--r-- | PrivateVolume.cpp | 145 | ||||
-rw-r--r-- | PrivateVolume.h | 78 | ||||
-rw-r--r-- | PublicVolume.cpp | 73 | ||||
-rw-r--r-- | PublicVolume.h | 2 | ||||
-rw-r--r-- | Utils.cpp | 143 | ||||
-rw-r--r-- | Utils.h | 13 | ||||
-rw-r--r-- | Volume.cpp | 12 | ||||
-rw-r--r-- | VolumeBase.cpp | 13 | ||||
-rw-r--r-- | VolumeBase.h | 3 | ||||
-rw-r--r-- | VolumeManager.cpp | 102 | ||||
-rw-r--r-- | VolumeManager.h | 7 | ||||
-rw-r--r-- | cryptfs.c | 143 | ||||
-rw-r--r-- | cryptfs.h | 8 |
19 files changed, 719 insertions, 272 deletions
@@ -21,6 +21,7 @@ common_src_files := \ Disk.cpp \ VolumeBase.cpp \ PublicVolume.cpp \ + PrivateVolume.cpp \ EmulatedVolume.cpp \ Utils.cpp \ @@ -16,6 +16,7 @@ #include "Disk.h" #include "PublicVolume.h" +#include "PrivateVolume.h" #include "Utils.h" #include "VolumeBase.h" #include "VolumeManager.h" @@ -26,6 +27,7 @@ #include <base/logging.h> #include <diskconfig/diskconfig.h> +#include <vector> #include <fcntl.h> #include <inttypes.h> #include <stdio.h> @@ -35,6 +37,7 @@ #include <sys/mount.h> using android::base::ReadFileToString; +using android::base::WriteStringToFile; using android::base::StringPrintf; namespace android { @@ -52,6 +55,8 @@ static const char* kGptBasicData = "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"; static const char* kGptAndroidMeta = "19A710A2-B3CA-11E4-B026-10604B889DCF"; static const char* kGptAndroidExt = "193D1EA4-B3CA-11E4-B075-10604B889DCF"; +static const char* kKeyPath = "/data/misc/vold"; + enum class Table { kUnknown, kMbr, @@ -105,18 +110,44 @@ status_t Disk::destroy() { return OK; } +static std::string BuildKeyPath(const std::string& partGuid) { + return StringPrintf("%s/ext_%s.key", kKeyPath, partGuid.c_str()); +} + void Disk::createPublicVolume(dev_t device) { - auto vol = new PublicVolume(device); + auto vol = std::shared_ptr<VolumeBase>(new PublicVolume(device)); vol->create(); - mVolumes.push_back(std::shared_ptr<VolumeBase>(vol)); + mVolumes.push_back(vol); VolumeManager::Instance()->getBroadcaster()->sendBroadcast( ResponseCode::DiskVolumeCreated, StringPrintf("%s %s", getId().c_str(), vol->getId().c_str()).c_str(), false); } -void Disk::createPrivateVolume(dev_t device) { - // TODO: create and add +void Disk::createPrivateVolume(dev_t device, const std::string& partGuid) { + std::string tmp; + std::string normalizedGuid; + if (HexToStr(partGuid, tmp)) { + LOG(WARNING) << "Invalid GUID " << partGuid; + return; + } + StrToHex(tmp, normalizedGuid); + + std::string keyRaw; + if (!ReadFileToString(BuildKeyPath(normalizedGuid), &keyRaw)) { + PLOG(ERROR) << "Failed to load key for GUID " << normalizedGuid; + return; + } + + LOG(DEBUG) << "Found key for GUID " << normalizedGuid; + + auto vol = std::shared_ptr<VolumeBase>(new PrivateVolume(device, keyRaw)); + vol->create(); + + mVolumes.push_back(vol); + VolumeManager::Instance()->getBroadcaster()->sendBroadcast( + ResponseCode::DiskVolumeCreated, + StringPrintf("%s %s", getId().c_str(), vol->getId().c_str()).c_str(), false); } void Disk::destroyAllVolumes() { @@ -246,7 +277,7 @@ status_t Disk::readPartitions() { if (!strcasecmp(typeGuid, kGptBasicData)) { createPublicVolume(partDevice); } else if (!strcasecmp(typeGuid, kGptAndroidExt)) { - createPrivateVolume(partDevice); + createPrivateVolume(partDevice, partGuid); } } } @@ -262,6 +293,13 @@ status_t Disk::readPartitions() { return OK; } +status_t Disk::unmountAll() { + for (auto vol : mVolumes) { + vol->unmount(); + } + return OK; +} + status_t Disk::partitionPublic() { // TODO: improve this code destroyAllVolumes(); @@ -304,13 +342,84 @@ out: } status_t Disk::partitionPrivate() { - destroyAllVolumes(); - return -ENOTSUP; + return partitionMixed(0); } status_t Disk::partitionMixed(int8_t ratio) { + int status = 0; + destroyAllVolumes(); - return -ENOTSUP; + + // First nuke any existing partition table + std::vector<std::string> cmd; + cmd.push_back(kSgdiskPath); + cmd.push_back("--zap-all"); + cmd.push_back(mDevPath); + + if (ForkExecvp(cmd, &status, false, true)) { + LOG(ERROR) << "Failed to zap; status " << status; + return -EIO; + } + + // We've had some success above, so generate both the private partition + // GUID and encryption key and persist them. + std::string partGuidRaw; + std::string keyRaw; + if (ReadRandomBytes(16, partGuidRaw) || ReadRandomBytes(16, keyRaw)) { + LOG(ERROR) << "Failed to generate GUID or key"; + return -EIO; + } + + std::string partGuid; + StrToHex(partGuidRaw, partGuid); + + if (!WriteStringToFile(keyRaw, BuildKeyPath(partGuid))) { + LOG(ERROR) << "Failed to persist key"; + return -EIO; + } else { + LOG(DEBUG) << "Persisted key for GUID " << partGuid; + } + + // Now let's build the new GPT table. We heavily rely on sgdisk to + // force optimal alignment on the created partitions. + cmd.clear(); + cmd.push_back(kSgdiskPath); + + // If requested, create a public partition first. Mixed-mode partitioning + // like this is an experimental feature. + if (ratio > 0) { + if (ratio < 10 || ratio > 90) { + LOG(ERROR) << "Mixed partition ratio must be between 10-90%"; + return -EINVAL; + } + + uint64_t splitMb = ((mSize / 100) * ratio) / 1024 / 1024; + cmd.push_back(StringPrintf("--new=0:0:+%" PRId64 "M", splitMb)); + cmd.push_back(StringPrintf("--typecode=0:%s", kGptBasicData)); + cmd.push_back("--change-name=0:shared"); + } + + // Define a metadata partition which is designed for future use; there + // should only be one of these per physical device, even if there are + // multiple private volumes. + cmd.push_back("--new=0:0:+16M"); + cmd.push_back(StringPrintf("--typecode=0:%s", kGptAndroidMeta)); + cmd.push_back("--change-name=0:android_meta"); + + // Define a single private partition filling the rest of disk. + cmd.push_back("--new=0:0:-0"); + cmd.push_back(StringPrintf("--typecode=0:%s", kGptAndroidExt)); + cmd.push_back(StringPrintf("--partition-guid=0:%s", partGuid.c_str())); + cmd.push_back("--change-name=0:android_ext"); + + cmd.push_back(mDevPath); + + if (ForkExecvp(cmd, &status, false, true)) { + LOG(ERROR) << "Failed to partition; status " << status; + return -EIO; + } + + return OK; } int Disk::getMaxMinors() { @@ -68,6 +68,8 @@ public: status_t readMetadata(); status_t readPartitions(); + status_t unmountAll(); + status_t partitionPublic(); status_t partitionPrivate(); status_t partitionMixed(int8_t ratio); @@ -97,7 +99,7 @@ private: bool mCreated; void createPublicVolume(dev_t device); - void createPrivateVolume(dev_t device); + void createPrivateVolume(dev_t device, const std::string& partGuid); void destroyAllVolumes(); diff --git a/EmulatedVolume.cpp b/EmulatedVolume.cpp index 0a1418b..5dcab72 100644 --- a/EmulatedVolume.cpp +++ b/EmulatedVolume.cpp @@ -53,7 +53,7 @@ EmulatedVolume::~EmulatedVolume() { status_t EmulatedVolume::doMount() { if (fs_prepare_dir(mFusePath.c_str(), 0700, AID_ROOT, AID_ROOT)) { - PLOG(ERROR) << "Failed to create mount point " << mFusePath; + PLOG(ERROR) << getId() << " failed to create mount point " << mFusePath; return -errno; } @@ -75,7 +75,7 @@ status_t EmulatedVolume::doMount() { } if (mFusePid == -1) { - PLOG(ERROR) << "Failed to fork"; + PLOG(ERROR) << getId() << " failed to fork"; return -errno; } @@ -93,7 +93,7 @@ status_t EmulatedVolume::doUnmount() { ForceUnmount(mRawPath); if (TEMP_FAILURE_RETRY(rmdir(mFusePath.c_str()))) { - PLOG(ERROR) << "Failed to rmdir mount point " << mFusePath; + PLOG(ERROR) << getId() << " failed to rmdir mount point " << mFusePath; return -errno; } @@ -23,6 +23,8 @@ #include <dirent.h> #include <errno.h> #include <fcntl.h> +#include <vector> +#include <string> #include <sys/types.h> #include <sys/stat.h> @@ -35,17 +37,92 @@ #define LOG_TAG "Vold" +#include <base/stringprintf.h> #include <cutils/log.h> #include <cutils/properties.h> - #include <logwrap/logwrap.h> #include "Ext4.h" +#include "Utils.h" #include "VoldUtil.h" -#define MKEXT4FS_PATH "/system/bin/make_ext4fs" #define RESIZE2FS_PATH "/system/bin/resize2fs" +using android::base::StringPrintf; + +static const char* kMkfsPath = "/system/bin/make_ext4fs"; + +static const char* kFsckPath = "/system/bin/e2fsck"; +static const char* kFsckLogFile = "/dev/fscklogs/log"; + +int Ext4::check(const char *fsPath, const char *mountPoint) { + // The following is shamelessly borrowed from fs_mgr.c, so it should be + // kept in sync with any changes over there. + + char* blk_device = (char*) fsPath; + char* target = (char*) mountPoint; + + int status; + int ret; + long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID; + char *tmpmnt_opts = (char*) "nomblk_io_submit,errors=remount-ro"; + char *e2fsck_argv[] = { + (char*) kFsckPath, + (char*) "-y", + blk_device + }; + + /* + * First try to mount and unmount the filesystem. We do this because + * the kernel is more efficient than e2fsck in running the journal and + * processing orphaned inodes, and on at least one device with a + * performance issue in the emmc firmware, it can take e2fsck 2.5 minutes + * to do what the kernel does in about a second. + * + * After mounting and unmounting the filesystem, run e2fsck, and if an + * error is recorded in the filesystem superblock, e2fsck will do a full + * check. Otherwise, it does nothing. If the kernel cannot mount the + * filesytsem due to an error, e2fsck is still run to do a full check + * fix the filesystem. + */ + ret = mount(blk_device, target, "ext4", tmpmnt_flags, tmpmnt_opts); + if (!ret) { + int i; + for (i = 0; i < 5; i++) { + // Try to umount 5 times before continuing on. + // Should we try rebooting if all attempts fail? + int result = umount(target); + if (result == 0) { + break; + } + ALOGW("%s(): umount(%s)=%d: %s\n", __func__, target, result, strerror(errno)); + sleep(1); + } + } + + /* + * Some system images do not have e2fsck for licensing reasons + * (e.g. recent SDK system images). Detect these and skip the check. + */ + if (access(kFsckPath, X_OK)) { + ALOGD("Not running %s on %s (executable not in system image)\n", + kFsckPath, blk_device); + } else { + ALOGD("Running %s on %s\n", kFsckPath, blk_device); + + ret = android_fork_execvp(ARRAY_SIZE(e2fsck_argv), e2fsck_argv, + &status, false, true); + + if (ret < 0) { + /* No need to check for error in fork, we can't really handle it now */ + ALOGW("Failed trying to run %s\n", kFsckPath); + return -1; + } + } + + return 0; +} + int Ext4::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount, bool executable) { int rc; @@ -112,28 +189,23 @@ int Ext4::resize(const char *fspath, unsigned int numSectors) { } int Ext4::format(const char *fsPath, unsigned int numSectors, const char *mountpoint) { - const char *args[7]; - int rc; int status; - args[0] = MKEXT4FS_PATH; - args[1] = "-J"; - args[2] = "-a"; - args[3] = mountpoint; + std::vector<std::string> cmd; + cmd.push_back(kMkfsPath); + cmd.push_back("-J"); + + cmd.push_back("-a"); + cmd.push_back(mountpoint); + if (numSectors) { - char tmp[32]; - snprintf(tmp, sizeof(tmp), "%u", numSectors * 512); - const char *size = tmp; - args[4] = "-l"; - args[5] = size; - args[6] = fsPath; - rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, true); - } else { - args[4] = fsPath; - rc = android_fork_execvp(5, (char **)args, &status, false, true); + cmd.push_back("-l"); + cmd.push_back(StringPrintf("%u", numSectors * 512)); } - rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, - true); + + cmd.push_back(fsPath); + + int rc = android::vold::ForkExecvp(cmd, &status, false, true); if (rc != 0) { SLOGE("Filesystem (ext4) format failed due to logwrap error"); errno = EIO; @@ -21,6 +21,7 @@ class Ext4 { public: + static int check(const char *fsPath, const char *mountPoint); static int doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount, bool executable); static int format(const char *fsPath, unsigned int numSectors, const char *mountpoint); diff --git a/PrivateVolume.cpp b/PrivateVolume.cpp new file mode 100644 index 0000000..42eea64 --- /dev/null +++ b/PrivateVolume.cpp @@ -0,0 +1,145 @@ +/* + * 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 "Ext4.h" +#include "PrivateVolume.h" +#include "Utils.h" +#include "VolumeManager.h" +#include "ResponseCode.h" +#include "cryptfs.h" + +#include <base/stringprintf.h> +#include <base/logging.h> +#include <cutils/fs.h> +#include <private/android_filesystem_config.h> + +#include <fcntl.h> +#include <stdlib.h> +#include <sys/mount.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/param.h> + +using android::base::StringPrintf; + +namespace android { +namespace vold { + +PrivateVolume::PrivateVolume(dev_t device, const std::string& keyRaw) : + VolumeBase(Type::kPrivate), mRawDevice(device), mKeyRaw(keyRaw) { + setId(StringPrintf("private:%u,%u", major(device), minor(device))); + mRawDevPath = StringPrintf("/dev/block/vold/%s", getId().c_str()); + mPath = StringPrintf("/mnt/secure/%s", getId().c_str()); +} + +PrivateVolume::~PrivateVolume() { +} + +status_t PrivateVolume::readMetadata() { + status_t res = ReadMetadata(mDmDevPath, mFsType, mFsUuid, mFsLabel); + + VolumeManager::Instance()->getBroadcaster()->sendBroadcast( + ResponseCode::VolumeFsTypeChanged, + StringPrintf("%s %s", getId().c_str(), mFsType.c_str()).c_str(), false); + VolumeManager::Instance()->getBroadcaster()->sendBroadcast( + ResponseCode::VolumeFsUuidChanged, + StringPrintf("%s %s", getId().c_str(), mFsUuid.c_str()).c_str(), false); + VolumeManager::Instance()->getBroadcaster()->sendBroadcast( + ResponseCode::VolumeFsLabelChanged, + StringPrintf("%s %s", getId().c_str(), mFsLabel.c_str()).c_str(), false); + + return res; +} + +status_t PrivateVolume::doCreate() { + if (CreateDeviceNode(mRawDevPath, mRawDevice)) { + return -EIO; + } + + // Recover from stale vold by tearing down any old mappings + cryptfs_revert_ext_volume(getId().c_str()); + + // TODO: figure out better SELinux labels for private volumes + + unsigned char* key = (unsigned char*) mKeyRaw.data(); + char crypto_blkdev[MAXPATHLEN]; + int res = cryptfs_setup_ext_volume(getId().c_str(), mRawDevPath.c_str(), + key, mKeyRaw.size(), crypto_blkdev); + mDmDevPath = crypto_blkdev; + if (res != 0) { + PLOG(ERROR) << getId() << " failed to setup cryptfs"; + return -EIO; + } + + return OK; +} + +status_t PrivateVolume::doDestroy() { + if (cryptfs_revert_ext_volume(getId().c_str())) { + LOG(ERROR) << getId() << " failed to revert cryptfs"; + } + return DestroyDeviceNode(mRawDevPath); +} + +status_t PrivateVolume::doMount() { + if (readMetadata()) { + LOG(ERROR) << getId() << " failed to read metadata"; + return -EIO; + } + + if (Ext4::check(mDmDevPath.c_str(), mPath.c_str())) { + PLOG(ERROR) << getId() << " failed filesystem check"; + return -EIO; + } + + setPath(mPath); + + if (fs_prepare_dir(mPath.c_str(), 0700, AID_ROOT, AID_ROOT)) { + PLOG(ERROR) << getId() << " failed to create mount point " << mPath; + return -errno; + } + + if (Ext4::doMount(mDmDevPath.c_str(), mPath.c_str(), false, false, true)) { + PLOG(ERROR) << getId() << " failed to mount"; + return -EIO; + } + + return OK; +} + +status_t PrivateVolume::doUnmount() { + ForceUnmount(mPath); + + if (TEMP_FAILURE_RETRY(rmdir(mPath.c_str()))) { + PLOG(ERROR) << getId() << " failed to rmdir mount point " << mPath; + } + + return OK; +} + +status_t PrivateVolume::doFormat() { + // TODO: change mountpoint once we have selinux labels + if (Ext4::format(mDmDevPath.c_str(), 0, "/data")) { + PLOG(ERROR) << getId() << " failed to format"; + return -EIO; + } + + return OK; +} + +} // namespace vold +} // namespace android diff --git a/PrivateVolume.h b/PrivateVolume.h new file mode 100644 index 0000000..bd464e6 --- /dev/null +++ b/PrivateVolume.h @@ -0,0 +1,78 @@ +/* + * 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 ANDROID_VOLD_PRIVATE_VOLUME_H +#define ANDROID_VOLD_PRIVATE_VOLUME_H + +#include "VolumeBase.h" + +#include <cutils/multiuser.h> + +namespace android { +namespace vold { + +/* + * Private storage provided by an encrypted partition. + * + * Given a raw block device, it knows how to wrap it in dm-crypt and + * format as ext4/f2fs. EmulatedVolume can be stacked above it. + * + * This volume is designed to behave much like the internal /data + * partition, both in layout and function. For example, apps and + * private app data can be safely stored on this volume because the + * keys are tightly tied to this device. + */ +class PrivateVolume : public VolumeBase { +public: + PrivateVolume(dev_t device, const std::string& keyRaw); + virtual ~PrivateVolume(); + +protected: + status_t doCreate() override; + status_t doDestroy() override; + status_t doMount() override; + status_t doUnmount() override; + status_t doFormat() override; + + status_t readMetadata(); + +private: + /* Kernel device of raw, encrypted partition */ + dev_t mRawDevice; + /* Path to raw, encrypted block device */ + std::string mRawDevPath; + /* Path to decrypted block device */ + std::string mDmDevPath; + /* Path where decrypted device is mounted */ + std::string mPath; + + /* Encryption key as raw bytes */ + std::string mKeyRaw; + + /* Filesystem type */ + std::string mFsType; + /* Filesystem UUID */ + std::string mFsUuid; + /* User-visible filesystem label */ + std::string mFsLabel; + + DISALLOW_COPY_AND_ASSIGN(PrivateVolume); +}; + +} // namespace vold +} // namespace android + +#endif diff --git a/PublicVolume.cpp b/PublicVolume.cpp index e4ed9c1..f3bd905 100644 --- a/PublicVolume.cpp +++ b/PublicVolume.cpp @@ -37,7 +37,6 @@ using android::base::StringPrintf; namespace android { namespace vold { -static const char* kBlkidPath = "/system/bin/blkid"; static const char* kFusePath = "/system/bin/sdcard"; static const char* kAsecPath = "/mnt/secure/asec"; @@ -46,51 +45,13 @@ PublicVolume::PublicVolume(dev_t device) : VolumeBase(Type::kPublic), mDevice(device), mFusePid(0) { setId(StringPrintf("public:%u,%u", major(device), minor(device))); mDevPath = StringPrintf("/dev/block/vold/%s", getId().c_str()); - CreateDeviceNode(mDevPath, mDevice); } PublicVolume::~PublicVolume() { - DestroyDeviceNode(mDevPath); } status_t PublicVolume::readMetadata() { - mFsType.clear(); - mFsUuid.clear(); - mFsLabel.clear(); - - std::string path(StringPrintf("%s -c /dev/null %s", kBlkidPath, mDevPath.c_str())); - FILE* fp = popen(path.c_str(), "r"); - if (!fp) { - PLOG(ERROR) << "Failed to run " << path; - return -errno; - } - - status_t res = OK; - char line[1024]; - char value[128]; - if (fgets(line, sizeof(line), fp) != nullptr) { - LOG(DEBUG) << "blkid identified as " << line; - - char* start = strstr(line, "TYPE="); - if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) { - mFsType = value; - } - - start = strstr(line, "UUID="); - if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) { - mFsUuid = value; - } - - start = strstr(line, "LABEL="); - if (start != nullptr && sscanf(start + 6, "\"%127[^\"]\"", value) == 1) { - mFsLabel = value; - } - } else { - LOG(WARNING) << "blkid failed to identify " << mDevPath; - res = -ENODATA; - } - - pclose(fp); + status_t res = ReadMetadata(mDevPath, mFsType, mFsUuid, mFsLabel); VolumeManager::Instance()->getBroadcaster()->sendBroadcast( ResponseCode::VolumeFsTypeChanged, @@ -113,13 +74,13 @@ status_t PublicVolume::initAsecStage() { if (!access(legacyPath.c_str(), R_OK | X_OK) && access(securePath.c_str(), R_OK | X_OK)) { if (rename(legacyPath.c_str(), securePath.c_str())) { - PLOG(WARNING) << "Failed to rename legacy ASEC dir"; + PLOG(WARNING) << getId() << " failed to rename legacy ASEC dir"; } } if (TEMP_FAILURE_RETRY(mkdir(securePath.c_str(), 0700))) { if (errno != EEXIST) { - PLOG(WARNING) << "Creating ASEC stage failed"; + PLOG(WARNING) << getId() << " creating ASEC stage failed"; return -errno; } } @@ -129,15 +90,23 @@ status_t PublicVolume::initAsecStage() { return OK; } +status_t PublicVolume::doCreate() { + return CreateDeviceNode(mDevPath, mDevice); +} + +status_t PublicVolume::doDestroy() { + return DestroyDeviceNode(mDevPath); +} + status_t PublicVolume::doMount() { // TODO: expand to support mounting other filesystems + readMetadata(); + if (Fat::check(mDevPath.c_str())) { - LOG(ERROR) << "Failed filesystem check; not mounting"; + LOG(ERROR) << getId() << " failed filesystem check"; return -EIO; } - readMetadata(); - // Use UUID as stable name, if available std::string stableName = getId(); if (!mFsUuid.empty()) { @@ -149,17 +118,17 @@ status_t PublicVolume::doMount() { setPath(mFusePath); if (fs_prepare_dir(mRawPath.c_str(), 0700, AID_ROOT, AID_ROOT)) { - PLOG(ERROR) << "Failed to create mount point " << mRawPath; + PLOG(ERROR) << getId() << " failed to create mount point " << mRawPath; return -errno; } if (fs_prepare_dir(mFusePath.c_str(), 0700, AID_ROOT, AID_ROOT)) { - PLOG(ERROR) << "Failed to create mount point " << mFusePath; + PLOG(ERROR) << getId() << " failed to create mount point " << mFusePath; return -errno; } if (Fat::doMount(mDevPath.c_str(), mRawPath.c_str(), false, false, false, AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) { - PLOG(ERROR) << "Failed to mount " << mDevPath; + PLOG(ERROR) << getId() << " failed to mount " << mDevPath; return -EIO; } @@ -202,7 +171,7 @@ status_t PublicVolume::doMount() { } if (mFusePid == -1) { - PLOG(ERROR) << "Failed to fork"; + PLOG(ERROR) << getId() << " failed to fork"; return -errno; } @@ -220,10 +189,10 @@ status_t PublicVolume::doUnmount() { ForceUnmount(mRawPath); if (TEMP_FAILURE_RETRY(rmdir(mRawPath.c_str()))) { - PLOG(ERROR) << "Failed to rmdir mount point " << mRawPath; + PLOG(ERROR) << getId() << " failed to rmdir mount point " << mRawPath; } if (TEMP_FAILURE_RETRY(rmdir(mFusePath.c_str()))) { - PLOG(ERROR) << "Failed to rmdir mount point " << mFusePath; + PLOG(ERROR) << getId() << " failed to rmdir mount point " << mFusePath; } mFusePath.clear(); @@ -234,7 +203,7 @@ status_t PublicVolume::doUnmount() { status_t PublicVolume::doFormat() { if (Fat::format(mDevPath.c_str(), 0, true)) { - LOG(ERROR) << "Failed to format"; + LOG(ERROR) << getId() << " failed to format"; return -errno; } return OK; diff --git a/PublicVolume.h b/PublicVolume.h index 2d2ec6b..45313ec 100644 --- a/PublicVolume.h +++ b/PublicVolume.h @@ -43,6 +43,8 @@ public: virtual ~PublicVolume(); protected: + status_t doCreate() override; + status_t doDestroy() override; status_t doMount() override; status_t doUnmount() override; status_t doFormat() override; @@ -19,8 +19,10 @@ #include "Process.h" #include <base/logging.h> +#include <base/stringprintf.h> #include <cutils/fs.h> #include <private/android_filesystem_config.h> +#include <logwrap/logwrap.h> #include <fcntl.h> #include <linux/fs.h> @@ -34,9 +36,13 @@ #define UMOUNT_NOFOLLOW 0x00000008 /* Don't follow symlink on umount */ #endif +using android::base::StringPrintf; + namespace android { namespace vold { +static const char* kBlkidPath = "/system/bin/blkid"; + status_t CreateDeviceNode(const std::string& path, dev_t dev) { const char* cpath = path.c_str(); status_t res = 0; @@ -81,14 +87,14 @@ status_t ForceUnmount(const std::string& path) { } PLOG(WARNING) << "Failed to unmount " << path << "; sending SIGTERM"; Process::killProcessesWithOpenFiles(cpath, SIGTERM); - sleep(1); + sleep(5); if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) { return OK; } PLOG(WARNING) << "Failed to unmount " << path << "; sending SIGKILL"; Process::killProcessesWithOpenFiles(cpath, SIGKILL); - sleep(1); + sleep(5); if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) { return OK; @@ -105,5 +111,138 @@ status_t BindMount(const std::string& source, const std::string& target) { return OK; } +status_t ReadMetadata(const std::string& path, std::string& fsType, + std::string& fsUuid, std::string& fsLabel) { + fsType.clear(); + fsUuid.clear(); + fsLabel.clear(); + + std::string cmd(StringPrintf("%s -c /dev/null %s", kBlkidPath, path.c_str())); + FILE* fp = popen(cmd.c_str(), "r"); + if (!fp) { + PLOG(ERROR) << "Failed to run " << cmd; + return -errno; + } + + status_t res = OK; + char line[1024]; + char value[128]; + if (fgets(line, sizeof(line), fp) != nullptr) { + LOG(DEBUG) << "blkid identified " << path << " as " << line; + + // Extract values from blkid output, if defined + char* start = strstr(line, "TYPE="); + if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) { + fsType = value; + } + + start = strstr(line, "UUID="); + if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) { + fsUuid = value; + } + + start = strstr(line, "LABEL="); + if (start != nullptr && sscanf(start + 6, "\"%127[^\"]\"", value) == 1) { + fsLabel = value; + } + } else { + LOG(WARNING) << "blkid failed to identify " << path; + res = -ENODATA; + } + + pclose(fp); + return res; +} + +status_t ForkExecvp(const std::vector<std::string>& args, int* status, + bool ignore_int_quit, bool logwrap) { + int argc = args.size(); + char** argv = (char**) calloc(argc, sizeof(char*)); + for (int i = 0; i < argc; i++) { + argv[i] = (char*) args[i].c_str(); + if (i == 0) { + LOG(VERBOSE) << args[i]; + } else { + LOG(VERBOSE) << " " << args[i]; + } + } + int res = android_fork_execvp(argc, argv, status, ignore_int_quit, logwrap); + free(argv); + return res; +} + +status_t ReadRandomBytes(size_t bytes, std::string& out) { + out.clear(); + + int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOFOLLOW)); + if (fd == -1) { + return -errno; + } + + char buf[BUFSIZ]; + size_t n; + while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], std::min(sizeof(buf), bytes)))) > 0) { + out.append(buf, n); + bytes -= n; + } + TEMP_FAILURE_RETRY(close(fd)); + + if (bytes == 0) { + return OK; + } else { + return -EIO; + } +} + +status_t HexToStr(const std::string& hex, std::string& str) { + str.clear(); + bool even = true; + char cur = 0; + for (size_t i = 0; i < hex.size(); i++) { + int val = 0; + switch (hex[i]) { + case ' ': case '-': case ':': continue; + case 'f': case 'F': val = 15; break; + case 'e': case 'E': val = 14; break; + case 'd': case 'D': val = 13; break; + case 'c': case 'C': val = 12; break; + case 'b': case 'B': val = 11; break; + case 'a': case 'A': val = 10; break; + case '9': val = 9; break; + case '8': val = 8; break; + case '7': val = 7; break; + case '6': val = 6; break; + case '5': val = 5; break; + case '4': val = 4; break; + case '3': val = 3; break; + case '2': val = 2; break; + case '1': val = 1; break; + case '0': val = 0; break; + default: return -EINVAL; + } + + if (even) { + cur = val << 4; + } else { + cur += val; + str.push_back(cur); + cur = 0; + } + even = !even; + } + return even ? OK : -EINVAL; +} + +static const char* kLookup = "0123456789abcdef"; + +status_t StrToHex(const std::string& str, std::string& hex) { + hex.clear(); + for (size_t i = 0; i < str.size(); i++) { + hex.push_back(kLookup[str[i] >> 4]); + hex.push_back(kLookup[str[i] & 0x0F]); + } + return OK; +} + } // namespace vold } // namespace android @@ -19,6 +19,7 @@ #include <utils/Errors.h> +#include <vector> #include <string> // DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions. It goes in the private: @@ -41,6 +42,18 @@ status_t ForceUnmount(const std::string& path); /* Creates bind mount from source to target */ status_t BindMount(const std::string& source, const std::string& target); +/* Reads filesystem metadata from device at path */ +status_t ReadMetadata(const std::string& path, std::string& fsType, + std::string& fsUuid, std::string& fsLabel); + +status_t ForkExecvp(const std::vector<std::string>& args, int* status, + bool ignore_int_quit, bool logwrap); + +status_t ReadRandomBytes(size_t bytes, std::string& out); + +status_t HexToStr(const std::string& hex, std::string& str); +status_t StrToHex(const std::string& str, std::string& hex); + } // namespace vold } // namespace android @@ -395,12 +395,12 @@ int Volume::mountVol() { return -1; } - if (cryptfs_setup_volume(getLabel(), MAJOR(deviceNodes[0]), MINOR(deviceNodes[0]), - new_sys_path, sizeof(new_sys_path), - &new_major, &new_minor)) { +// if (cryptfs_setup_volume(getLabel(), MAJOR(deviceNodes[0]), MINOR(deviceNodes[0]), +// new_sys_path, sizeof(new_sys_path), +// &new_major, &new_minor)) { SLOGE("Cannot setup encryption mapping for %s\n", getMountpoint()); return -1; - } +// } /* We now have the new sysfs path for the decrypted block device, and the * majore and minor numbers for it. So, create the device, update the * path to the new sysfs path, and continue. @@ -587,8 +587,8 @@ int Volume::unmountVol(bool force, bool revert) { * the device info to the original values. */ if (revert && isDecrypted()) { - cryptfs_revert_volume(getLabel()); - revertDeviceInfo(); +// cryptfs_revert_volume(getLabel()); +// revertDeviceInfo(); SLOGI("Encrypted volume %s reverted successfully", getMountpoint()); } diff --git a/VolumeBase.cpp b/VolumeBase.cpp index 8d160ae..292a4cd 100644 --- a/VolumeBase.cpp +++ b/VolumeBase.cpp @@ -113,10 +113,16 @@ std::shared_ptr<VolumeBase> VolumeBase::findVolume(const std::string& id) { status_t VolumeBase::create() { CHECK(!mCreated); + mCreated = true; + status_t res = doCreate(); VolumeManager::Instance()->getBroadcaster()->sendBroadcast( ResponseCode::VolumeCreated, StringPrintf("%s %d", getId().c_str(), mType).c_str(), false); + return res; +} + +status_t VolumeBase::doCreate() { return OK; } @@ -127,9 +133,14 @@ status_t VolumeBase::destroy() { unmount(); } - mCreated = false; VolumeManager::Instance()->getBroadcaster()->sendBroadcast( ResponseCode::VolumeDestroyed, getId().c_str(), false); + status_t res = doDestroy(); + mCreated = false; + return res; +} + +status_t VolumeBase::doDestroy() { return OK; } diff --git a/VolumeBase.h b/VolumeBase.h index e7be8fb..e3d91ff 100644 --- a/VolumeBase.h +++ b/VolumeBase.h @@ -87,7 +87,6 @@ public: status_t create(); status_t destroy(); - status_t mount(); status_t unmount(); status_t format(); @@ -95,6 +94,8 @@ public: protected: explicit VolumeBase(Type type); + virtual status_t doCreate(); + virtual status_t doDestroy(); virtual status_t doMount() = 0; virtual status_t doUnmount() = 0; virtual status_t doFormat(); diff --git a/VolumeManager.cpp b/VolumeManager.cpp index 0404ce7..5296114 100644 --- a/VolumeManager.cpp +++ b/VolumeManager.cpp @@ -243,30 +243,7 @@ void VolumeManager::setDebug(bool enable) { int VolumeManager::start() { // Always start from a clean slate by unmounting everything in // directories that we own, in case we crashed. - FILE* fp = setmntent("/proc/mounts", "r"); - if (fp == NULL) { - SLOGE("Error opening /proc/mounts: %s", strerror(errno)); - return -errno; - } - - // Some volumes can be stacked on each other, so force unmount in - // reverse order to give us the best chance of success. - std::list<std::string> toUnmount; - mntent* mentry; - while ((mentry = getmntent(fp)) != NULL) { - if (strncmp(mentry->mnt_dir, "/mnt/", 5) == 0 - || strncmp(mentry->mnt_dir, "/storage/", 9) == 0) { - toUnmount.push_front(std::string(mentry->mnt_dir)); - } - } - endmntent(fp); - - for (auto path : toUnmount) { - SLOGW("Tearing down stale mount %s", path.c_str()); - android::vold::ForceUnmount(path); - } - - // TODO: nuke all files under mnt and storage tmpfs too? + unmountAll(); // Assume that we always have an emulated volume on internal // storage; the framework will decide if it should be mounted. @@ -440,6 +417,7 @@ int VolumeManager::reset() { } int VolumeManager::shutdown() { + mInternalEmulated->destroy(); for (auto disk : mDisks) { disk->destroy(); } @@ -447,6 +425,43 @@ int VolumeManager::shutdown() { return 0; } +int VolumeManager::unmountAll() { + // First, try gracefully unmounting all known devices + if (mInternalEmulated != nullptr) { + mInternalEmulated->unmount(); + } + for (auto disk : mDisks) { + disk->unmountAll(); + } + + // Worst case we might have some stale mounts lurking around, so + // force unmount those just to be safe. + FILE* fp = setmntent("/proc/mounts", "r"); + if (fp == NULL) { + SLOGE("Error opening /proc/mounts: %s", strerror(errno)); + return -errno; + } + + // Some volumes can be stacked on each other, so force unmount in + // reverse order to give us the best chance of success. + std::list<std::string> toUnmount; + mntent* mentry; + while ((mentry = getmntent(fp)) != NULL) { + if (strncmp(mentry->mnt_dir, "/mnt/", 5) == 0 + || strncmp(mentry->mnt_dir, "/storage/", 9) == 0) { + toUnmount.push_front(std::string(mentry->mnt_dir)); + } + } + endmntent(fp); + + for (auto path : toUnmount) { + SLOGW("Tearing down stale mount %s", path.c_str()); + android::vold::ForceUnmount(path); + } + + return 0; +} + int VolumeManager::listVolumes(SocketClient *cli, bool broadcast) { VolumeCollection::iterator i; char msg[256]; @@ -1831,35 +1846,6 @@ int VolumeManager::unshareVolume(const char *label, const char *method) { return 0; } -extern "C" int vold_disableVol(const char *label) { - VolumeManager *vm = VolumeManager::Instance(); - vm->disableVolumeManager(); - vm->unshareVolume(label, "ums"); - return vm->unmountVolume(label, true, false); -} - -extern "C" int vold_getNumDirectVolumes(void) { - VolumeManager *vm = VolumeManager::Instance(); - return vm->getNumDirectVolumes(); -} - -int VolumeManager::getNumDirectVolumes(void) { - VolumeCollection::iterator i; - int n=0; - - for (i = mVolumes->begin(); i != mVolumes->end(); ++i) { - if ((*i)->getShareDevice() != (dev_t)0) { - n++; - } - } - return n; -} - -extern "C" int vold_getDirectVolumeList(struct volume_info *vol_list) { - VolumeManager *vm = VolumeManager::Instance(); - return vm->getDirectVolumeList(vol_list); -} - int VolumeManager::getDirectVolumeList(struct volume_info *vol_list) { VolumeCollection::iterator i; int n=0; @@ -1902,15 +1888,9 @@ int VolumeManager::unmountVolume(const char *label, bool force, bool revert) { return v->unmountVol(force, revert); } -extern "C" int vold_unmountAllAsecs(void) { - int rc; - +extern "C" int vold_unmountAll(void) { VolumeManager *vm = VolumeManager::Instance(); - rc = vm->unmountAllAsecsInDir(Volume::SEC_ASECDIR_EXT); - if (vm->unmountAllAsecsInDir(Volume::SEC_ASECDIR_INT)) { - rc = -1; - } - return rc; + return vm->unmountAll(); } #define ID_BUF_LEN 256 diff --git a/VolumeManager.h b/VolumeManager.h index 5b3fbf6..f36561c 100644 --- a/VolumeManager.h +++ b/VolumeManager.h @@ -118,6 +118,8 @@ public: int reset(); /* Prepare for device shutdown, safely unmounting all devices */ int shutdown(); + /* Unmount all volumes, usually for encryption */ + int unmountAll(); int listVolumes(SocketClient *cli, bool broadcast); int mountVolume(const char *label); @@ -213,10 +215,7 @@ private: extern "C" { #endif /* __cplusplus */ #define UNMOUNT_NOT_MOUNTED_ERR -2 - int vold_disableVol(const char *label); - int vold_getNumDirectVolumes(void); - int vold_getDirectVolumeList(struct volume_info *v); - int vold_unmountAllAsecs(void); + int vold_unmountAll(void); #ifdef __cplusplus } #endif @@ -945,9 +945,8 @@ static unsigned char* convert_hex_ascii_to_key(const char* master_key_ascii, /* Convert a binary key of specified length into an ascii hex string equivalent, * without the leading 0x and with null termination */ -static void convert_key_to_hex_ascii(unsigned char *master_key, unsigned int keysize, - char *master_key_ascii) -{ +static void convert_key_to_hex_ascii(const unsigned char *master_key, + unsigned int keysize, char *master_key_ascii) { unsigned int i, a; unsigned char nibble; @@ -965,10 +964,9 @@ static void convert_key_to_hex_ascii(unsigned char *master_key, unsigned int key } -static int load_crypto_mapping_table(struct crypt_mnt_ftr *crypt_ftr, unsigned char *master_key, - char *real_blk_name, const char *name, int fd, - char *extra_params) -{ +static int load_crypto_mapping_table(struct crypt_mnt_ftr *crypt_ftr, + const unsigned char *master_key, const char *real_blk_name, + const char *name, int fd, const char *extra_params) { _Alignas(struct dm_ioctl) char buffer[DM_CRYPT_BUF_SIZE]; struct dm_ioctl *io; struct dm_target_spec *tgt; @@ -1057,9 +1055,9 @@ static int get_dm_crypt_version(int fd, const char *name, int *version) return -1; } -static int create_crypto_blk_dev(struct crypt_mnt_ftr *crypt_ftr, unsigned char *master_key, - char *real_blk_name, char *crypto_blk_name, const char *name) -{ +static int create_crypto_blk_dev(struct crypt_mnt_ftr *crypt_ftr, + const unsigned char *master_key, const char *real_blk_name, + char *crypto_blk_name, const char *name) { char buffer[DM_CRYPT_BUF_SIZE]; struct dm_ioctl *io; unsigned int minor; @@ -1885,36 +1883,18 @@ static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, return rc; } -/* Called by vold when it wants to undo the crypto mapping of a volume it - * manages. This is usually in response to a factory reset, when we want - * to undo the crypto mapping so the volume is formatted in the clear. - */ -int cryptfs_revert_volume(const char *label) -{ - return delete_crypto_blk_dev((char *)label); -} - /* - * Called by vold when it's asked to mount an encrypted, nonremovable volume. - * Setup a dm-crypt mapping, use the saved master key from - * setting up the /data mapping, and return the new device path. + * Called by vold when it's asked to mount an encrypted external + * storage volume. The incoming partition has no crypto header/footer, + * as any metadata is been stored in a separate, small partition. + * + * out_crypto_blkdev must be MAXPATHLEN. */ -int cryptfs_setup_volume(const char *label, int major, int minor, - char *crypto_sys_path, unsigned int max_path, - int *new_major, int *new_minor) -{ - char real_blkdev[MAXPATHLEN], crypto_blkdev[MAXPATHLEN]; - struct crypt_mnt_ftr sd_crypt_ftr; - struct stat statbuf; - - sprintf(real_blkdev, "/dev/block/vold/%d:%d", major, minor); - - get_crypt_ftr_and_key(&sd_crypt_ftr); - - /* Update the fs_size field to be the size of the volume */ +int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, + const unsigned char* key, int keysize, char* out_crypto_blkdev) { int fd = open(real_blkdev, O_RDONLY); if (fd == -1) { - SLOGE("Cannot open volume %s\n", real_blkdev); + SLOGE("Failed to open %s: %s", real_blkdev, strerror(errno)); return -1; } @@ -1923,25 +1903,26 @@ int cryptfs_setup_volume(const char *label, int major, int minor, close(fd); if (nr_sec == 0) { - SLOGE("Cannot get size of volume %s\n", real_blkdev); + SLOGE("Failed to get size of %s: %s", real_blkdev, strerror(errno)); return -1; } - sd_crypt_ftr.fs_size = nr_sec; - create_crypto_blk_dev(&sd_crypt_ftr, saved_master_key, real_blkdev, - crypto_blkdev, label); - - if (stat(crypto_blkdev, &statbuf) < 0) { - SLOGE("Error get stat for crypto_blkdev %s. err=%d(%s)\n", - crypto_blkdev, errno, strerror(errno)); - } - *new_major = MAJOR(statbuf.st_rdev); - *new_minor = MINOR(statbuf.st_rdev); + struct crypt_mnt_ftr ext_crypt_ftr; + memset(&ext_crypt_ftr, 0, sizeof(ext_crypt_ftr)); + ext_crypt_ftr.fs_size = nr_sec; + ext_crypt_ftr.keysize = keysize; + strcpy((char*) ext_crypt_ftr.crypto_type_name, "aes-cbc-essiv:sha256"); - /* Create path to sys entry for this block device */ - snprintf(crypto_sys_path, max_path, "/devices/virtual/block/%s", strrchr(crypto_blkdev, '/')+1); + return create_crypto_blk_dev(&ext_crypt_ftr, key, real_blkdev, + out_crypto_blkdev, label); +} - return 0; +/* + * Called by vold when it's asked to unmount an encrypted external + * storage volume. + */ +int cryptfs_revert_ext_volume(const char* label) { + return delete_crypto_blk_dev((char*) label); } int cryptfs_crypto_complete(void) @@ -2836,12 +2817,6 @@ static int cryptfs_enable_inplace(char *crypto_blkdev, char *real_blkdev, #define FRAMEWORK_BOOT_WAIT 60 -static inline int should_encrypt(struct volume_info *volume) -{ - return (volume->flags & (VOL_ENCRYPTABLE | VOL_NONREMOVABLE)) == - (VOL_ENCRYPTABLE | VOL_NONREMOVABLE); -} - static int cryptfs_SHA256_fileblock(const char* filename, __le8* buf) { int fd = open(filename, O_RDONLY); @@ -2944,10 +2919,7 @@ int cryptfs_enable_internal(char *howarg, int crypt_type, char *passwd, char encrypted_state[PROPERTY_VALUE_MAX]; char lockid[32] = { 0 }; char key_loc[PROPERTY_VALUE_MAX]; - char fuse_sdcard[PROPERTY_VALUE_MAX]; - char *sd_mnt_point; int num_vols; - struct volume_info *vol_list = 0; off64_t previously_encrypted_upto = 0; if (!strcmp(howarg, "wipe")) { @@ -3022,58 +2994,15 @@ int cryptfs_enable_internal(char *howarg, int crypt_type, char *passwd, snprintf(lockid, sizeof(lockid), "enablecrypto%d", (int) getpid()); acquire_wake_lock(PARTIAL_WAKE_LOCK, lockid); - /* Get the sdcard mount point */ - sd_mnt_point = getenv("EMULATED_STORAGE_SOURCE"); - if (!sd_mnt_point) { - sd_mnt_point = getenv("EXTERNAL_STORAGE"); - } - if (!sd_mnt_point) { - sd_mnt_point = "/mnt/sdcard"; - } - - /* TODO - * Currently do not have test devices with multiple encryptable volumes. - * When we acquire some, re-add support. - */ - num_vols=vold_getNumDirectVolumes(); - vol_list = malloc(sizeof(struct volume_info) * num_vols); - vold_getDirectVolumeList(vol_list); - - for (i=0; i<num_vols; i++) { - if (should_encrypt(&vol_list[i])) { - SLOGE("Cannot encrypt if there are multiple encryptable volumes" - "%s\n", vol_list[i].label); - goto error_unencrypted; - } - } - /* The init files are setup to stop the class main and late start when * vold sets trigger_shutdown_framework. */ property_set("vold.decrypt", "trigger_shutdown_framework"); SLOGD("Just asked init to shut down class main\n"); - if (vold_unmountAllAsecs()) { - /* Just report the error. If any are left mounted, - * umounting /data below will fail and handle the error. - */ - SLOGE("Error unmounting internal asecs"); - } - - property_get("ro.crypto.fuse_sdcard", fuse_sdcard, ""); - if (!strcmp(fuse_sdcard, "true")) { - // STOPSHIP: UNMOUNT ALL STORAGE BEFORE REACHING HERE, SINCE VOLD NOW MANAGES FUSE - // "ro.crypto.fuse_sdcard" is now deprecated - - /* This is a device using the fuse layer to emulate the sdcard semantics - * on top of the userdata partition. vold does not manage it, it is managed - * by the sdcard service. The sdcard service was killed by the property trigger - * above, so just unmount it now. We must do this _AFTER_ killing the framework, - * unlike the case for vold managed devices above. - */ - if (wait_and_unmount(sd_mnt_point, false)) { - goto error_shutting_down; - } + /* Ask vold to unmount all devices that it manages */ + if (vold_unmountAll()) { + SLOGE("Failed to unmount all vold managed devices"); } /* Now unmount the /data partition. */ @@ -3221,8 +3150,6 @@ int cryptfs_enable_internal(char *howarg, int crypt_type, char *passwd, /* Undo the dm-crypt mapping whether we succeed or not */ delete_crypto_blk_dev("userdata"); - free(vol_list); - if (! rc) { /* Success */ crypt_ftr.flags &= ~CRYPT_INCONSISTENT_STATE; @@ -3289,7 +3216,6 @@ int cryptfs_enable_internal(char *howarg, int crypt_type, char *passwd, return rc; error_unencrypted: - free(vol_list); property_set("vold.encrypt_progress", "error_not_encrypted"); if (lockid[0]) { release_wake_lock(lockid); @@ -3306,7 +3232,6 @@ error_shutting_down: /* shouldn't get here */ property_set("vold.encrypt_progress", "error_shutting_down"); - free(vol_list); if (lockid[0]) { release_wake_lock(lockid); } @@ -172,6 +172,7 @@ struct crypt_persist_data { struct crypt_persist_entry persist_entry[0]; }; +// TODO: remove this deprecated struct struct volume_info { unsigned int size; unsigned int flags; @@ -232,10 +233,9 @@ extern "C" { int cryptfs_enable(char *flag, int type, char *passwd, int allow_reboot); int cryptfs_changepw(int type, const char *newpw); int cryptfs_enable_default(char *flag, int allow_reboot); - int cryptfs_setup_volume(const char *label, int major, int minor, - char *crypto_dev_path, unsigned int max_pathlen, - int *new_major, int *new_minor); - int cryptfs_revert_volume(const char *label); + int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, + const unsigned char* key, int keysize, char* out_crypto_blkdev); + int cryptfs_revert_ext_volume(const char* label); int cryptfs_getfield(const char *fieldname, char *value, int len); int cryptfs_setfield(const char *fieldname, const char *value); int cryptfs_mount_default_encrypted(void); |