Add support for more expressive SD card permissions
We now run an sdcard fuse daemon on top of a physical SD card. Add support for that. Bug: 10330128 Change-Id: I6a291f861ccb0f2911c07cc8f659e2cec4e6d76c
This commit is contained in:
parent
71ebe154a5
commit
ba6ae8db13
7 changed files with 127 additions and 219 deletions
|
@ -33,11 +33,8 @@
|
|||
|
||||
// #define PARTITION_DEBUG
|
||||
|
||||
DirectVolume::DirectVolume(VolumeManager *vm, const char *label,
|
||||
const char *mount_point, int partIdx) :
|
||||
Volume(vm, label, mount_point) {
|
||||
mPartIdx = partIdx;
|
||||
|
||||
DirectVolume::DirectVolume(VolumeManager *vm, const fstab_rec* rec, int flags) :
|
||||
Volume(vm, rec, flags) {
|
||||
mPaths = new PathCollection();
|
||||
for (int i = 0; i < MAX_PARTITIONS; i++)
|
||||
mPartMinors[i] = -1;
|
||||
|
@ -46,6 +43,18 @@ DirectVolume::DirectVolume(VolumeManager *vm, const char *label,
|
|||
mDiskMinor = -1;
|
||||
mDiskNumParts = 0;
|
||||
|
||||
if (strcmp(rec->mount_point, "auto") != 0) {
|
||||
ALOGE("Vold managed volumes must have auto mount point; ignoring %s",
|
||||
rec->mount_point);
|
||||
}
|
||||
|
||||
char mount[PATH_MAX];
|
||||
|
||||
snprintf(mount, PATH_MAX, "%s/%s", Volume::MEDIA_DIR, rec->label);
|
||||
mMountpoint = strdup(mount);
|
||||
snprintf(mount, PATH_MAX, "%s/%s", Volume::FUSE_DIR, rec->label);
|
||||
mFuseMountpoint = strdup(mount);
|
||||
|
||||
setState(Volume::State_NoMedia);
|
||||
}
|
||||
|
||||
|
@ -62,10 +71,6 @@ int DirectVolume::addPath(const char *path) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void DirectVolume::setFlags(int flags) {
|
||||
mFlags = flags;
|
||||
}
|
||||
|
||||
dev_t DirectVolume::getDiskDevice() {
|
||||
return MKDEV(mDiskMajor, mDiskMinor);
|
||||
}
|
||||
|
@ -119,7 +124,7 @@ int DirectVolume::handleBlockEvent(NetlinkEvent *evt) {
|
|||
|
||||
snprintf(msg, sizeof(msg),
|
||||
"Volume %s %s disk inserted (%d:%d)", getLabel(),
|
||||
getMountpoint(), mDiskMajor, mDiskMinor);
|
||||
getFuseMountpoint(), mDiskMajor, mDiskMinor);
|
||||
mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted,
|
||||
msg, false);
|
||||
}
|
||||
|
@ -286,7 +291,7 @@ void DirectVolume::handleDiskRemoved(const char *devpath, NetlinkEvent *evt) {
|
|||
|
||||
SLOGD("Volume %s %s disk %d:%d removed\n", getLabel(), getMountpoint(), major, minor);
|
||||
snprintf(msg, sizeof(msg), "Volume %s %s disk removed (%d:%d)",
|
||||
getLabel(), getMountpoint(), major, minor);
|
||||
getLabel(), getFuseMountpoint(), major, minor);
|
||||
mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskRemoved,
|
||||
msg, false);
|
||||
setState(Volume::State_NoMedia);
|
||||
|
@ -317,7 +322,7 @@ void DirectVolume::handlePartitionRemoved(const char *devpath, NetlinkEvent *evt
|
|||
*/
|
||||
|
||||
snprintf(msg, sizeof(msg), "Volume %s %s bad removal (%d:%d)",
|
||||
getLabel(), getMountpoint(), major, minor);
|
||||
getLabel(), getFuseMountpoint(), major, minor);
|
||||
mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval,
|
||||
msg, false);
|
||||
|
||||
|
@ -452,7 +457,7 @@ int DirectVolume::getVolInfo(struct volume_info *v)
|
|||
{
|
||||
strcpy(v->label, mLabel);
|
||||
strcpy(v->mnt_point, mMountpoint);
|
||||
v->flags=mFlags;
|
||||
v->flags = getFlags();
|
||||
/* Other fields of struct volume_info are filled in by the caller or cryptfs.c */
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -29,6 +29,9 @@ class DirectVolume : public Volume {
|
|||
public:
|
||||
static const int MAX_PARTITIONS = 32;
|
||||
protected:
|
||||
const char* mMountpoint;
|
||||
const char* mFuseMountpoint;
|
||||
|
||||
PathCollection *mPaths;
|
||||
int mDiskMajor;
|
||||
int mDiskMinor;
|
||||
|
@ -42,18 +45,20 @@ protected:
|
|||
int mFlags;
|
||||
|
||||
public:
|
||||
DirectVolume(VolumeManager *vm, const char *label, const char *mount_point, int partIdx);
|
||||
DirectVolume(VolumeManager *vm, const fstab_rec* rec, int flags);
|
||||
virtual ~DirectVolume();
|
||||
|
||||
int addPath(const char *path);
|
||||
|
||||
const char *getMountpoint() { return mMountpoint; }
|
||||
const char *getFuseMountpoint() { return mFuseMountpoint; }
|
||||
|
||||
int handleBlockEvent(NetlinkEvent *evt);
|
||||
dev_t getDiskDevice();
|
||||
dev_t getShareDevice();
|
||||
void handleVolumeShared();
|
||||
void handleVolumeUnshared();
|
||||
int getVolInfo(struct volume_info *v);
|
||||
void setFlags(int flags);
|
||||
|
||||
protected:
|
||||
int getDeviceNodes(dev_t *devs, int max);
|
||||
|
|
249
Volume.cpp
249
Volume.cpp
|
@ -37,6 +37,7 @@
|
|||
|
||||
#define LOG_TAG "Vold"
|
||||
|
||||
#include <cutils/fs.h>
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include "Volume.h"
|
||||
|
@ -51,21 +52,14 @@ extern "C" void dos_partition_enc(void *pp, struct dos_partition *d);
|
|||
|
||||
|
||||
/*
|
||||
* Secure directory - stuff that only root can see
|
||||
* Media directory - stuff that only media_rw user can see
|
||||
*/
|
||||
const char *Volume::SECDIR = "/mnt/secure";
|
||||
const char *Volume::MEDIA_DIR = "/mnt/media_rw";
|
||||
|
||||
/*
|
||||
* Secure staging directory - where media is mounted for preparation
|
||||
* Fuse directory - location where fuse wrapped filesystems go
|
||||
*/
|
||||
const char *Volume::SEC_STGDIR = "/mnt/secure/staging";
|
||||
|
||||
/*
|
||||
* Path to the directory on the media which contains publicly accessable
|
||||
* asec imagefiles. This path will be obscured before the mount is
|
||||
* exposed to non priviledged users.
|
||||
*/
|
||||
const char *Volume::SEC_STG_SECIMGDIR = "/mnt/secure/staging/.android_secure";
|
||||
const char *Volume::FUSE_DIR = "/storage";
|
||||
|
||||
/*
|
||||
* Path to external storage where *only* root can access ASEC image files
|
||||
|
@ -111,26 +105,25 @@ static const char *stateToStr(int state) {
|
|||
return "Unknown-Error";
|
||||
}
|
||||
|
||||
Volume::Volume(VolumeManager *vm, const char *label, const char *mount_point) {
|
||||
Volume::Volume(VolumeManager *vm, const fstab_rec* rec, int flags) {
|
||||
mVm = vm;
|
||||
mDebug = false;
|
||||
mLabel = strdup(label);
|
||||
mMountpoint = strdup(mount_point);
|
||||
mLabel = strdup(rec->label);
|
||||
mState = Volume::State_Init;
|
||||
mFlags = flags;
|
||||
mCurrentlyMountedKdev = -1;
|
||||
mPartIdx = -1;
|
||||
mPartIdx = rec->partnum;
|
||||
mRetryMount = false;
|
||||
}
|
||||
|
||||
Volume::~Volume() {
|
||||
free(mLabel);
|
||||
free(mMountpoint);
|
||||
}
|
||||
|
||||
void Volume::protectFromAutorunStupidity() {
|
||||
char filename[255];
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s/autorun.inf", SEC_STGDIR);
|
||||
snprintf(filename, sizeof(filename), "%s/autorun.inf", getMountpoint());
|
||||
if (!access(filename, F_OK)) {
|
||||
SLOGW("Volume contains an autorun.inf! - removing");
|
||||
/*
|
||||
|
@ -188,7 +181,7 @@ void Volume::setState(int state) {
|
|||
oldState, stateToStr(oldState), mState, stateToStr(mState));
|
||||
snprintf(msg, sizeof(msg),
|
||||
"Volume %s %s state changed from %d (%s) to %d (%s)", getLabel(),
|
||||
getMountpoint(), oldState, stateToStr(oldState), mState,
|
||||
getFuseMountpoint(), oldState, stateToStr(oldState), mState,
|
||||
stateToStr(mState));
|
||||
|
||||
mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange,
|
||||
|
@ -292,12 +285,15 @@ int Volume::mountVol() {
|
|||
dev_t deviceNodes[4];
|
||||
int n, i, rc = 0;
|
||||
char errmsg[255];
|
||||
const char* externalStorage = getenv("EXTERNAL_STORAGE");
|
||||
bool primaryStorage = externalStorage && !strcmp(getMountpoint(), externalStorage);
|
||||
|
||||
int flags = getFlags();
|
||||
bool providesAsec = (flags & VOL_PROVIDES_ASEC) != 0;
|
||||
|
||||
// TODO: handle "bind" style mounts, for emulated storage
|
||||
|
||||
char decrypt_state[PROPERTY_VALUE_MAX];
|
||||
char crypto_state[PROPERTY_VALUE_MAX];
|
||||
char encrypt_progress[PROPERTY_VALUE_MAX];
|
||||
int flags;
|
||||
|
||||
property_get("vold.decrypt", decrypt_state, "");
|
||||
property_get("vold.encrypt_progress", encrypt_progress, "");
|
||||
|
@ -306,10 +302,10 @@ int Volume::mountVol() {
|
|||
* or are in the process of encrypting.
|
||||
*/
|
||||
if ((getState() == Volume::State_NoMedia) ||
|
||||
((!strcmp(decrypt_state, "1") || encrypt_progress[0]) && primaryStorage)) {
|
||||
((!strcmp(decrypt_state, "1") || encrypt_progress[0]) && providesAsec)) {
|
||||
snprintf(errmsg, sizeof(errmsg),
|
||||
"Volume %s %s mount failed - no media",
|
||||
getLabel(), getMountpoint());
|
||||
getLabel(), getFuseMountpoint());
|
||||
mVm->getBroadcaster()->sendBroadcast(
|
||||
ResponseCode::VolumeMountFailedNoMedia,
|
||||
errmsg, false);
|
||||
|
@ -337,13 +333,12 @@ int Volume::mountVol() {
|
|||
}
|
||||
|
||||
/* If we're running encrypted, and the volume is marked as encryptable and nonremovable,
|
||||
* and vold is asking to mount the primaryStorage device, then we need to decrypt
|
||||
* and also marked as providing Asec storage, then we need to decrypt
|
||||
* that partition, and update the volume object to point to it's new decrypted
|
||||
* block device
|
||||
*/
|
||||
property_get("ro.crypto.state", crypto_state, "");
|
||||
flags = getFlags();
|
||||
if (primaryStorage &&
|
||||
if (providesAsec &&
|
||||
((flags & (VOL_NONREMOVABLE | VOL_ENCRYPTABLE))==(VOL_NONREMOVABLE | VOL_ENCRYPTABLE)) &&
|
||||
!strcmp(crypto_state, "encrypted") && !isDecrypted()) {
|
||||
char new_sys_path[MAXPATHLEN];
|
||||
|
@ -409,49 +404,28 @@ int Volume::mountVol() {
|
|||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mount the device on our internal staging mountpoint so we can
|
||||
* muck with it before exposing it to non priviledged users.
|
||||
*/
|
||||
errno = 0;
|
||||
int gid;
|
||||
|
||||
if (primaryStorage) {
|
||||
// Special case the primary SD card.
|
||||
// For this we grant write access to the SDCARD_RW group.
|
||||
gid = AID_SDCARD_RW;
|
||||
} else {
|
||||
// For secondary external storage we keep things locked up.
|
||||
gid = AID_MEDIA_RW;
|
||||
}
|
||||
if (Fat::doMount(devicePath, "/mnt/secure/staging", false, false, false,
|
||||
AID_SYSTEM, gid, 0702, true)) {
|
||||
if (Fat::doMount(devicePath, getMountpoint(), false, false, false,
|
||||
AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) {
|
||||
SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
SLOGI("Device %s, target %s mounted @ /mnt/secure/staging", devicePath, getMountpoint());
|
||||
|
||||
protectFromAutorunStupidity();
|
||||
|
||||
// only create android_secure on primary storage
|
||||
if (primaryStorage && createBindMounts()) {
|
||||
SLOGE("Failed to create bindmounts (%s)", strerror(errno));
|
||||
umount("/mnt/secure/staging");
|
||||
if (providesAsec && mountAsecExternal() != 0) {
|
||||
SLOGE("Failed to mount secure area (%s)", strerror(errno));
|
||||
umount(getMountpoint());
|
||||
setState(Volume::State_Idle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that the bindmount trickery is done, atomically move the
|
||||
* whole subtree to expose it to non priviledged users.
|
||||
*/
|
||||
if (doMoveMount("/mnt/secure/staging", getMountpoint(), false)) {
|
||||
SLOGE("Failed to move mount (%s)", strerror(errno));
|
||||
umount("/mnt/secure/staging");
|
||||
setState(Volume::State_Idle);
|
||||
return -1;
|
||||
}
|
||||
char service[64];
|
||||
snprintf(service, 64, "fuse_%s", getLabel());
|
||||
property_set("ctl.start", service);
|
||||
|
||||
setState(Volume::State_Mounted);
|
||||
mCurrentlyMountedKdev = deviceNodes[i];
|
||||
return 0;
|
||||
|
@ -463,103 +437,33 @@ int Volume::mountVol() {
|
|||
return -1;
|
||||
}
|
||||
|
||||
int Volume::createBindMounts() {
|
||||
unsigned long flags;
|
||||
int Volume::mountAsecExternal() {
|
||||
char legacy_path[PATH_MAX];
|
||||
char secure_path[PATH_MAX];
|
||||
|
||||
/*
|
||||
* Rename old /android_secure -> /.android_secure
|
||||
*/
|
||||
if (!access("/mnt/secure/staging/android_secure", R_OK | X_OK) &&
|
||||
access(SEC_STG_SECIMGDIR, R_OK | X_OK)) {
|
||||
if (rename("/mnt/secure/staging/android_secure", SEC_STG_SECIMGDIR)) {
|
||||
snprintf(legacy_path, PATH_MAX, "%s/android_secure", getMountpoint());
|
||||
snprintf(secure_path, PATH_MAX, "%s/.android_secure", getMountpoint());
|
||||
|
||||
// Recover legacy secure path
|
||||
if (!access(legacy_path, R_OK | X_OK) && access(secure_path, R_OK | X_OK)) {
|
||||
if (rename(legacy_path, secure_path)) {
|
||||
SLOGE("Failed to rename legacy asec dir (%s)", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that /android_secure exists and is a directory
|
||||
*/
|
||||
if (access(SEC_STG_SECIMGDIR, R_OK | X_OK)) {
|
||||
if (errno == ENOENT) {
|
||||
if (mkdir(SEC_STG_SECIMGDIR, 0777)) {
|
||||
SLOGE("Failed to create %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
SLOGE("Failed to access %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
struct stat sbuf;
|
||||
|
||||
if (stat(SEC_STG_SECIMGDIR, &sbuf)) {
|
||||
SLOGE("Failed to stat %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (!S_ISDIR(sbuf.st_mode)) {
|
||||
SLOGE("%s is not a directory", SEC_STG_SECIMGDIR);
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Bind mount /mnt/secure/staging/android_secure -> /mnt/secure/asec so we'll
|
||||
* have a root only accessable mountpoint for it.
|
||||
*/
|
||||
if (mount(SEC_STG_SECIMGDIR, SEC_ASECDIR_EXT, "", MS_BIND, NULL)) {
|
||||
SLOGE("Failed to bind mount points %s -> %s (%s)",
|
||||
SEC_STG_SECIMGDIR, SEC_ASECDIR_EXT, strerror(errno));
|
||||
if (fs_prepare_dir(secure_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mount a read-only, zero-sized tmpfs on <mountpoint>/android_secure to
|
||||
* obscure the underlying directory from everybody - sneaky eh? ;)
|
||||
*/
|
||||
if (mount("tmpfs", SEC_STG_SECIMGDIR, "tmpfs", MS_RDONLY, "size=0,mode=000,uid=0,gid=0")) {
|
||||
SLOGE("Failed to obscure %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
|
||||
umount("/mnt/asec_secure");
|
||||
if (mount(secure_path, SEC_ASECDIR_EXT, "", MS_BIND, NULL)) {
|
||||
SLOGE("Failed to bind mount points %s -> %s (%s)", secure_path,
|
||||
SEC_ASECDIR_EXT, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Volume::doMoveMount(const char *src, const char *dst, bool force) {
|
||||
unsigned int flags = MS_MOVE;
|
||||
int retries = 5;
|
||||
|
||||
while(retries--) {
|
||||
if (!mount(src, dst, "", flags, NULL)) {
|
||||
if (mDebug) {
|
||||
SLOGD("Moved mount %s -> %s sucessfully", src, dst);
|
||||
}
|
||||
return 0;
|
||||
} else if (errno != EBUSY) {
|
||||
SLOGE("Failed to move mount %s -> %s (%s)", src, dst, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
int action = 0;
|
||||
|
||||
if (force) {
|
||||
if (retries == 1) {
|
||||
action = 2; // SIGKILL
|
||||
} else if (retries == 2) {
|
||||
action = 1; // SIGHUP
|
||||
}
|
||||
}
|
||||
SLOGW("Failed to move %s -> %s (%s, retries %d, action %d)",
|
||||
src, dst, strerror(errno), retries, action);
|
||||
Process::killProcessesWithOpenFiles(src, action);
|
||||
usleep(1000*250);
|
||||
}
|
||||
|
||||
errno = EBUSY;
|
||||
SLOGE("Giving up on move %s -> %s (%s)", src, dst, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Volume::doUnmount(const char *path, bool force) {
|
||||
int retries = 10;
|
||||
|
||||
|
@ -597,6 +501,9 @@ int Volume::doUnmount(const char *path, bool force) {
|
|||
int Volume::unmountVol(bool force, bool revert) {
|
||||
int i, rc;
|
||||
|
||||
int flags = getFlags();
|
||||
bool providesAsec = (flags & VOL_PROVIDES_ASEC) != 0;
|
||||
|
||||
if (getState() != Volume::State_Mounted) {
|
||||
SLOGE("Volume %s unmount request when not mounted", getLabel());
|
||||
errno = EINVAL;
|
||||
|
@ -606,35 +513,32 @@ int Volume::unmountVol(bool force, bool revert) {
|
|||
setState(Volume::State_Unmounting);
|
||||
usleep(1000 * 1000); // Give the framework some time to react
|
||||
|
||||
/*
|
||||
* Remove the bindmount we were using to keep a reference to
|
||||
* the previously obscured directory.
|
||||
*/
|
||||
if (doUnmount(Volume::SEC_ASECDIR_EXT, force)) {
|
||||
SLOGE("Failed to remove bindmount on %s (%s)", SEC_ASECDIR_EXT, strerror(errno));
|
||||
goto fail_remount_tmpfs;
|
||||
char service[64];
|
||||
snprintf(service, 64, "fuse_%s", getLabel());
|
||||
property_set("ctl.stop", service);
|
||||
/* Give it a chance to stop. I wish we had a synchronous way to determine this... */
|
||||
sleep(1);
|
||||
|
||||
// TODO: determine failure mode if FUSE times out
|
||||
|
||||
if (providesAsec && doUnmount(Volume::SEC_ASECDIR_EXT, force) != 0) {
|
||||
SLOGE("Failed to unmount secure area on %s (%s)", getMountpoint(), strerror(errno));
|
||||
goto out_mounted;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unmount the tmpfs which was obscuring the asec image directory
|
||||
* from non root users
|
||||
*/
|
||||
char secure_dir[PATH_MAX];
|
||||
snprintf(secure_dir, PATH_MAX, "%s/.android_secure", getMountpoint());
|
||||
if (doUnmount(secure_dir, force)) {
|
||||
SLOGE("Failed to unmount tmpfs on %s (%s)", secure_dir, strerror(errno));
|
||||
goto fail_republish;
|
||||
/* Now that the fuse daemon is dead, unmount it */
|
||||
if (doUnmount(getFuseMountpoint(), force) != 0) {
|
||||
SLOGE("Failed to unmount %s (%s)", getFuseMountpoint(), strerror(errno));
|
||||
goto fail_remount_secure;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, unmount the actual block device from the staging dir
|
||||
*/
|
||||
if (doUnmount(getMountpoint(), force)) {
|
||||
SLOGE("Failed to unmount %s (%s)", SEC_STGDIR, strerror(errno));
|
||||
goto fail_recreate_bindmount;
|
||||
/* Unmount the real sd card */
|
||||
if (doUnmount(getMountpoint(), force) != 0) {
|
||||
SLOGE("Failed to unmount %s (%s)", getMountpoint(), strerror(errno));
|
||||
goto fail_remount_secure;
|
||||
}
|
||||
|
||||
SLOGI("%s unmounted sucessfully", getMountpoint());
|
||||
SLOGI("%s unmounted successfully", getMountpoint());
|
||||
|
||||
/* If this is an encrypted volume, and we've been asked to undo
|
||||
* the crypto mapping, then revert the dm-crypt mapping, and revert
|
||||
|
@ -650,25 +554,13 @@ int Volume::unmountVol(bool force, bool revert) {
|
|||
mCurrentlyMountedKdev = -1;
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Failure handling - try to restore everything back the way it was
|
||||
*/
|
||||
fail_recreate_bindmount:
|
||||
if (mount(SEC_STG_SECIMGDIR, SEC_ASECDIR_EXT, "", MS_BIND, NULL)) {
|
||||
SLOGE("Failed to restore bindmount after failure! - Storage will appear offline!");
|
||||
goto out_nomedia;
|
||||
}
|
||||
fail_remount_tmpfs:
|
||||
if (mount("tmpfs", SEC_STG_SECIMGDIR, "tmpfs", MS_RDONLY, "size=0,mode=0,uid=0,gid=0")) {
|
||||
SLOGE("Failed to restore tmpfs after failure! - Storage will appear offline!");
|
||||
goto out_nomedia;
|
||||
}
|
||||
fail_republish:
|
||||
if (doMoveMount(SEC_STGDIR, getMountpoint(), force)) {
|
||||
SLOGE("Failed to republish mount after failure! - Storage will appear offline!");
|
||||
fail_remount_secure:
|
||||
if (providesAsec && mountAsecExternal() != 0) {
|
||||
SLOGE("Failed to remount secure area (%s)", strerror(errno));
|
||||
goto out_nomedia;
|
||||
}
|
||||
|
||||
out_mounted:
|
||||
setState(Volume::State_Mounted);
|
||||
return -1;
|
||||
|
||||
|
@ -676,6 +568,7 @@ out_nomedia:
|
|||
setState(Volume::State_NoMedia);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Volume::initializeMbr(const char *deviceNode) {
|
||||
struct disk_info dinfo;
|
||||
|
||||
|
|
20
Volume.h
20
Volume.h
|
@ -18,6 +18,7 @@
|
|||
#define _VOLUME_H
|
||||
|
||||
#include <utils/List.h>
|
||||
#include <fs_mgr.h>
|
||||
|
||||
class NetlinkEvent;
|
||||
class VolumeManager;
|
||||
|
@ -25,6 +26,7 @@ class VolumeManager;
|
|||
class Volume {
|
||||
private:
|
||||
int mState;
|
||||
int mFlags;
|
||||
|
||||
public:
|
||||
static const int State_Init = -1;
|
||||
|
@ -38,9 +40,8 @@ public:
|
|||
static const int State_Shared = 7;
|
||||
static const int State_SharedMnt = 8;
|
||||
|
||||
static const char *SECDIR;
|
||||
static const char *SEC_STGDIR;
|
||||
static const char *SEC_STG_SECIMGDIR;
|
||||
static const char *MEDIA_DIR;
|
||||
static const char *FUSE_DIR;
|
||||
static const char *SEC_ASECDIR_EXT;
|
||||
static const char *SEC_ASECDIR_INT;
|
||||
static const char *ASECDIR;
|
||||
|
@ -49,7 +50,6 @@ public:
|
|||
|
||||
protected:
|
||||
char *mLabel;
|
||||
char *mMountpoint;
|
||||
VolumeManager *mVm;
|
||||
bool mDebug;
|
||||
int mPartIdx;
|
||||
|
@ -62,7 +62,7 @@ protected:
|
|||
dev_t mCurrentlyMountedKdev;
|
||||
|
||||
public:
|
||||
Volume(VolumeManager *vm, const char *label, const char *mount_point);
|
||||
Volume(VolumeManager *vm, const fstab_rec* rec, int flags);
|
||||
virtual ~Volume();
|
||||
|
||||
int mountVol();
|
||||
|
@ -70,8 +70,12 @@ public:
|
|||
int formatVol(bool wipe);
|
||||
|
||||
const char *getLabel() { return mLabel; }
|
||||
const char *getMountpoint() { return mMountpoint; }
|
||||
int getState() { return mState; }
|
||||
int getFlags() { return mFlags; };
|
||||
|
||||
/* Mountpoint of the raw volume */
|
||||
virtual const char *getMountpoint() = 0;
|
||||
virtual const char *getFuseMountpoint() = 0;
|
||||
|
||||
virtual int handleBlockEvent(NetlinkEvent *evt);
|
||||
virtual dev_t getDiskDevice();
|
||||
|
@ -89,16 +93,14 @@ protected:
|
|||
virtual int updateDeviceInfo(char *new_path, int new_major, int new_minor) = 0;
|
||||
virtual void revertDeviceInfo(void) = 0;
|
||||
virtual int isDecrypted(void) = 0;
|
||||
virtual int getFlags(void) = 0;
|
||||
|
||||
int createDeviceNode(const char *path, int major, int minor);
|
||||
|
||||
private:
|
||||
int initializeMbr(const char *deviceNode);
|
||||
bool isMountpointMounted(const char *path);
|
||||
int createBindMounts();
|
||||
int mountAsecExternal();
|
||||
int doUnmount(const char *path, bool force);
|
||||
int doMoveMount(const char *src, const char *dst, bool force);
|
||||
void protectFromAutorunStupidity();
|
||||
};
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@ int VolumeManager::listVolumes(SocketClient *cli) {
|
|||
for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
|
||||
char *buffer;
|
||||
asprintf(&buffer, "%s %s %d",
|
||||
(*i)->getLabel(), (*i)->getMountpoint(),
|
||||
(*i)->getLabel(), (*i)->getFuseMountpoint(),
|
||||
(*i)->getState());
|
||||
cli->sendMsg(ResponseCode::VolumeListResult, buffer, false);
|
||||
free(buffer);
|
||||
|
@ -1054,7 +1054,7 @@ Volume* VolumeManager::getVolumeForFile(const char *fileName) {
|
|||
VolumeCollection::iterator i;
|
||||
|
||||
for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
|
||||
const char* mountPoint = (*i)->getMountpoint();
|
||||
const char* mountPoint = (*i)->getFuseMountpoint();
|
||||
if (!strncmp(fileName, mountPoint, strlen(mountPoint))) {
|
||||
return *i;
|
||||
}
|
||||
|
@ -1512,7 +1512,7 @@ Volume *VolumeManager::lookupVolume(const char *label) {
|
|||
|
||||
for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
|
||||
if (label[0] == '/') {
|
||||
if (!strcmp(label, (*i)->getMountpoint()))
|
||||
if (!strcmp(label, (*i)->getFuseMountpoint()))
|
||||
return (*i);
|
||||
} else {
|
||||
if (!strcmp(label, (*i)->getLabel()))
|
||||
|
@ -1570,7 +1570,7 @@ int VolumeManager::cleanupAsec(Volume *v, bool force) {
|
|||
|
||||
for (AsecIdCollection::iterator it = toUnmount.begin(); it != toUnmount.end(); ++it) {
|
||||
ContainerData *cd = *it;
|
||||
SLOGI("Unmounting ASEC %s (dependant on %s)", cd->id, v->getMountpoint());
|
||||
SLOGI("Unmounting ASEC %s (dependant on %s)", cd->id, v->getFuseMountpoint());
|
||||
if (unmountObb(cd->id, force)) {
|
||||
SLOGE("Failed to unmount OBB %s (%s)", cd->id, strerror(errno));
|
||||
rc = -1;
|
||||
|
|
|
@ -127,8 +127,10 @@ struct volume_info {
|
|||
char crypto_blkdev[256];
|
||||
char label[256];
|
||||
};
|
||||
#define VOL_NONREMOVABLE 0x1
|
||||
#define VOL_ENCRYPTABLE 0x2
|
||||
#define VOL_NONREMOVABLE 0x1
|
||||
#define VOL_ENCRYPTABLE 0x2
|
||||
#define VOL_PRIMARY 0x4
|
||||
#define VOL_PROVIDES_ASEC 0x8
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
23
main.cpp
23
main.cpp
|
@ -174,16 +174,6 @@ static int process_config(VolumeManager *vm)
|
|||
DirectVolume *dv = NULL;
|
||||
flags = 0;
|
||||
|
||||
dv = new DirectVolume(vm, fstab->recs[i].label,
|
||||
fstab->recs[i].mount_point,
|
||||
fstab->recs[i].partnum);
|
||||
|
||||
if (dv->addPath(fstab->recs[i].blk_device)) {
|
||||
SLOGE("Failed to add devpath %s to volume %s",
|
||||
fstab->recs[i].blk_device, fstab->recs[i].label);
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
/* Set any flags that might be set for this volume */
|
||||
if (fs_mgr_is_nonremovable(&fstab->recs[i])) {
|
||||
flags |= VOL_NONREMOVABLE;
|
||||
|
@ -191,7 +181,18 @@ static int process_config(VolumeManager *vm)
|
|||
if (fs_mgr_is_encryptable(&fstab->recs[i])) {
|
||||
flags |= VOL_ENCRYPTABLE;
|
||||
}
|
||||
dv->setFlags(flags);
|
||||
/* Only set this flag if there is not an emulated sd card */
|
||||
if (fs_mgr_is_noemulatedsd(&fstab->recs[i]) &&
|
||||
!strcmp(fstab->recs[i].fs_type, "vfat")) {
|
||||
flags |= VOL_PROVIDES_ASEC;
|
||||
}
|
||||
dv = new DirectVolume(vm, &(fstab->recs[i]), flags);
|
||||
|
||||
if (dv->addPath(fstab->recs[i].blk_device)) {
|
||||
SLOGE("Failed to add devpath %s to volume %s",
|
||||
fstab->recs[i].blk_device, fstab->recs[i].label);
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
vm->addVolume(dv);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue