vold: Bugfixes & cleanups
- Fix issue where container-names > 64 bytes were getting truncated in the
kernel. lo_name is only 64 bytes in length, so we now hash the container
id via md5
- Add 'dump' command to dump loop and devicemapper status
- Add 'debug' command to enable more detailed logging at runtime
- Log vold IPC arguments (minus encryption keys)
- Fix premature return from Loop::lookupActive() and friends
Change-Id: I0e833261a445ce9dc1a8187e5501d27daba1ca76
Signed-off-by: San Mehat <san@google.com>
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 8f1cb52..77dad20 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -39,6 +39,7 @@
#include "Devmapper.h"
#include "Process.h"
#include "Asec.h"
+#include "md5.h"
VolumeManager *VolumeManager::sInstance = NULL;
@@ -49,6 +50,7 @@
}
VolumeManager::VolumeManager() {
+ mDebug = false;
mBlockDevices = new BlockDeviceCollection();
mVolumes = new VolumeCollection();
mActiveContainers = new AsecIdCollection();
@@ -62,6 +64,38 @@
delete mActiveContainers;
}
+char *VolumeManager::asecHash(const char *id, char *buffer, size_t len) {
+ MD5_CTX ctx;
+ unsigned char sig[16];
+
+ if (len < 33) {
+ LOGE("Target hash buffer size < 33 bytes (%d)", len);
+ errno = ESPIPE;
+ return NULL;
+ }
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, id, strlen(id));
+ MD5_Final(sig, &ctx);
+
+ memset(buffer, 0, len);
+
+ for (int i = 0; i < 16; i++) {
+ char tmp[3];
+ snprintf(tmp, 3, "%.02x", sig[i]);
+ strcat(buffer, tmp);
+ }
+
+ return buffer;
+}
+
+void VolumeManager::setDebug(bool enable) {
+ mDebug = enable;
+ VolumeCollection::iterator it;
+ for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
+ (*it)->setDebug(enable);
+ }
+}
+
int VolumeManager::start() {
return 0;
}
@@ -213,8 +247,15 @@
return -1;
}
+ char idHash[33];
+ if (!asecHash(id, idHash, sizeof(idHash))) {
+ LOGE("Hash of '%s' failed (%s)", id, strerror(errno));
+ unlink(asecFileName);
+ return -1;
+ }
+
char loopDevice[255];
- if (Loop::create(asecFileName, loopDevice, sizeof(loopDevice))) {
+ if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
LOGE("ASEC loop device creation failed (%s)", strerror(errno));
unlink(asecFileName);
return -1;
@@ -226,7 +267,7 @@
if (strcmp(key, "none")) {
// XXX: This is all we support for now
sb.c_cipher = ASEC_SB_C_CIPHER_TWOFISH;
- if (Devmapper::create(id, loopDevice, key, numImgSectors, dmDevice,
+ if (Devmapper::create(idHash, loopDevice, key, numImgSectors, dmDevice,
sizeof(dmDevice))) {
LOGE("ASEC device mapping failed (%s)", strerror(errno));
Loop::destroyByDevice(loopDevice);
@@ -247,7 +288,7 @@
if (sbfd < 0) {
LOGE("Failed to open new DM device for superblock write (%s)", strerror(errno));
if (cleanupDm) {
- Devmapper::destroy(id);
+ Devmapper::destroy(idHash);
}
Loop::destroyByDevice(loopDevice);
unlink(asecFileName);
@@ -258,7 +299,7 @@
close(sbfd);
LOGE("Failed to lseek for superblock (%s)", strerror(errno));
if (cleanupDm) {
- Devmapper::destroy(id);
+ Devmapper::destroy(idHash);
}
Loop::destroyByDevice(loopDevice);
unlink(asecFileName);
@@ -269,7 +310,7 @@
close(sbfd);
LOGE("Failed to write superblock (%s)", strerror(errno));
if (cleanupDm) {
- Devmapper::destroy(id);
+ Devmapper::destroy(idHash);
}
Loop::destroyByDevice(loopDevice);
unlink(asecFileName);
@@ -285,7 +326,7 @@
if (Fat::format(dmDevice, numImgSectors)) {
LOGE("ASEC FAT format failed (%s)", strerror(errno));
if (cleanupDm) {
- Devmapper::destroy(id);
+ Devmapper::destroy(idHash);
}
Loop::destroyByDevice(loopDevice);
unlink(asecFileName);
@@ -298,7 +339,7 @@
if (errno != EEXIST) {
LOGE("Mountpoint creation failed (%s)", strerror(errno));
if (cleanupDm) {
- Devmapper::destroy(id);
+ Devmapper::destroy(idHash);
}
Loop::destroyByDevice(loopDevice);
unlink(asecFileName);
@@ -310,7 +351,7 @@
0, 0000, false)) {
LOGE("ASEC FAT mount failed (%s)", strerror(errno));
if (cleanupDm) {
- Devmapper::destroy(id);
+ Devmapper::destroy(idHash);
}
Loop::destroyByDevice(loopDevice);
unlink(asecFileName);
@@ -331,7 +372,13 @@
snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
- if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
+ char idHash[33];
+ if (!asecHash(id, idHash, sizeof(idHash))) {
+ LOGE("Hash of '%s' failed (%s)", id, strerror(errno));
+ return -1;
+ }
+
+ if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
LOGE("Unable to finalize %s (%s)", id, strerror(errno));
return -1;
}
@@ -343,7 +390,9 @@
return -1;
}
- LOGD("ASEC %s finalized", id);
+ if (mDebug) {
+ LOGD("ASEC %s finalized", id);
+ }
return 0;
}
@@ -398,6 +447,12 @@
snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
+ char idHash[33];
+ if (!asecHash(id, idHash, sizeof(idHash))) {
+ LOGE("Hash of '%s' failed (%s)", id, strerror(errno));
+ return -1;
+ }
+
if (!isMountpointMounted(mountPoint)) {
LOGE("Unmount request for ASEC %s when not mounted", id);
errno = EINVAL;
@@ -452,13 +507,15 @@
LOGE("Timed out trying to rmdir %s (%s)", mountPoint, strerror(errno));
}
- if (Devmapper::destroy(id) && errno != ENXIO) {
+ if (Devmapper::destroy(idHash) && errno != ENXIO) {
LOGE("Failed to destroy devmapper instance (%s)", strerror(errno));
}
char loopDevice[255];
- if (!Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
+ if (!Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
Loop::destroyByDevice(loopDevice);
+ } else {
+ LOGW("Failed to find loop device for {%s} (%s)", asecFileName, strerror(errno));
}
AsecIdCollection::iterator it;
@@ -483,7 +540,9 @@
snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
if (isMountpointMounted(mountPoint)) {
- LOGD("Unmounting container before destroy");
+ if (mDebug) {
+ LOGD("Unmounting container before destroy");
+ }
if (unmountAsec(id, force)) {
LOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno));
return -1;
@@ -495,7 +554,9 @@
return -1;
}
- LOGD("ASEC %s destroyed", id);
+ if (mDebug) {
+ LOGD("ASEC %s destroyed", id);
+ }
return 0;
}
@@ -512,15 +573,24 @@
return -1;
}
+ char idHash[33];
+ if (!asecHash(id, idHash, sizeof(idHash))) {
+ LOGE("Hash of '%s' failed (%s)", id, strerror(errno));
+ return -1;
+ }
char loopDevice[255];
- if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
- if (Loop::create(asecFileName, loopDevice, sizeof(loopDevice))) {
+ if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
+ if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
LOGE("ASEC loop device creation failed (%s)", strerror(errno));
return -1;
}
- LOGD("New loop device created at %s", loopDevice);
+ if (mDebug) {
+ LOGD("New loop device created at %s", loopDevice);
+ }
} else {
- LOGD("Found active loopback for %s at %s", asecFileName, loopDevice);
+ if (mDebug) {
+ LOGD("Found active loopback for %s at %s", asecFileName, loopDevice);
+ }
}
char dmDevice[255];
@@ -561,7 +631,9 @@
close(fd);
- LOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
+ if (mDebug) {
+ LOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
+ }
if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) {
LOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver);
Loop::destroyByDevice(loopDevice);
@@ -571,16 +643,20 @@
nr_sec--; // We don't want the devmapping to extend onto our superblock
if (strcmp(key, "none")) {
- if (Devmapper::lookupActive(id, dmDevice, sizeof(dmDevice))) {
- if (Devmapper::create(id, loopDevice, key, nr_sec,
+ if (Devmapper::lookupActive(idHash, dmDevice, sizeof(dmDevice))) {
+ if (Devmapper::create(idHash, loopDevice, key, nr_sec,
dmDevice, sizeof(dmDevice))) {
LOGE("ASEC device mapping failed (%s)", strerror(errno));
Loop::destroyByDevice(loopDevice);
return -1;
}
- LOGD("New devmapper instance created at %s", dmDevice);
+ if (mDebug) {
+ LOGD("New devmapper instance created at %s", dmDevice);
+ }
} else {
- LOGD("Found active devmapper for %s at %s", asecFileName, dmDevice);
+ if (mDebug) {
+ LOGD("Found active devmapper for %s at %s", asecFileName, dmDevice);
+ }
}
cleanupDm = true;
} else {
@@ -591,7 +667,7 @@
if (errno != EEXIST) {
LOGE("Mountpoint creation failed (%s)", strerror(errno));
if (cleanupDm) {
- Devmapper::destroy(id);
+ Devmapper::destroy(idHash);
}
Loop::destroyByDevice(loopDevice);
return -1;
@@ -603,14 +679,16 @@
// 0227, false)) {
LOGE("ASEC mount failed (%s)", strerror(errno));
if (cleanupDm) {
- Devmapper::destroy(id);
+ Devmapper::destroy(idHash);
}
Loop::destroyByDevice(loopDevice);
return -1;
}
mActiveContainers->push_back(strdup(id));
- LOGD("ASEC %s mounted", id);
+ if (mDebug) {
+ LOGD("ASEC %s mounted", id);
+ }
return 0;
}