Merge "Merge QP1A.190122.001" into q-keystone-qcom-dev
diff --git a/Checkpoint.cpp b/Checkpoint.cpp
index 28855e6..7586a6c 100644
--- a/Checkpoint.cpp
+++ b/Checkpoint.cpp
@@ -229,6 +229,7 @@
uint32_t magic;
uint32_t count;
uint32_t sequence;
+ uint64_t sector0;
struct log_entry entries[];
} __attribute__((packed));
@@ -289,62 +290,119 @@
} // namespace
+static void read(std::fstream& device, std::vector<log_entry> const& logs, sector_t sector,
+ char* buffer) {
+ for (auto l = logs.rbegin(); l != logs.rend(); l++)
+ if (sector >= l->source && (sector - l->source) * kSectorSize < l->size)
+ sector = sector - l->source + l->dest;
+
+ device.seekg(sector * kSectorSize);
+ device.read(buffer, kBlockSize);
+}
+
+static std::vector<char> read(std::fstream& device, std::vector<log_entry> const& logs,
+ bool validating, sector_t sector, uint32_t size) {
+ if (!validating) {
+ std::vector<char> buffer(size);
+ device.seekg(sector * kSectorSize);
+ device.read(&buffer[0], size);
+ return buffer;
+ }
+
+ // Crude approach at first where we do this sector by sector and just scan
+ // the entire logs for remappings each time
+ std::vector<char> buffer(size);
+
+ for (uint32_t i = 0; i < size; i += kBlockSize, sector += kBlockSize / kSectorSize)
+ read(device, logs, sector, &buffer[i]);
+
+ return buffer;
+}
+
Status cp_restoreCheckpoint(const std::string& blockDevice) {
- LOG(INFO) << "Restoring checkpoint on " << blockDevice;
- std::fstream device(blockDevice, std::ios::binary | std::ios::in | std::ios::out);
- if (!device) {
- PLOG(ERROR) << "Cannot open " << blockDevice;
- return Status::fromExceptionCode(errno, ("Cannot open " + blockDevice).c_str());
- }
- alignas(alignof(log_sector)) char ls_buffer[kBlockSize];
- device.read(ls_buffer, kBlockSize);
- log_sector& ls = *reinterpret_cast<log_sector*>(ls_buffer);
- if (ls.magic != kMagic) {
- LOG(ERROR) << "No magic";
- return Status::fromExceptionCode(EINVAL, "No magic");
- }
+ bool validating = true;
+ std::string action = "Validating";
- LOG(INFO) << "Restoring " << ls.sequence << " log sectors";
+ for (;;) {
+ std::vector<log_entry> logs;
+ Status status = Status::ok();
- for (int sequence = ls.sequence; sequence >= 0; sequence--) {
- device.seekg(0);
- device.read(ls_buffer, kBlockSize);
- ls = *reinterpret_cast<log_sector*>(ls_buffer);
+ LOG(INFO) << action << " checkpoint on " << blockDevice;
+ std::fstream device(blockDevice, std::ios::binary | std::ios::in | std::ios::out);
+ if (!device) {
+ PLOG(ERROR) << "Cannot open " << blockDevice;
+ return Status::fromExceptionCode(errno, ("Cannot open " + blockDevice).c_str());
+ }
+ auto buffer = read(device, logs, validating, 0, kBlockSize);
+ log_sector& ls = *reinterpret_cast<log_sector*>(&buffer[0]);
if (ls.magic != kMagic) {
- LOG(ERROR) << "No magic!";
+ LOG(ERROR) << "No magic";
return Status::fromExceptionCode(EINVAL, "No magic");
}
- if ((int)ls.sequence != sequence) {
- LOG(ERROR) << "Expecting log sector " << sequence << " but got " << ls.sequence;
- return Status::fromExceptionCode(
- EINVAL, ("Expecting log sector " + std::to_string(sequence) + " but got " +
- std::to_string(ls.sequence))
- .c_str());
- }
+ LOG(INFO) << action << " " << ls.sequence << " log sectors";
- LOG(INFO) << "Restoring from log sector " << ls.sequence;
-
- for (log_entry* le = &ls.entries[ls.count - 1]; le >= ls.entries; --le) {
- LOG(INFO) << "Restoring " << le->size << " bytes from sector " << le->dest << " to "
- << le->source << " with checksum " << std::hex << le->checksum;
- std::vector<char> buffer(le->size);
- device.seekg(le->dest * kSectorSize);
- device.read(&buffer[0], le->size);
-
- uint32_t checksum = le->source / (kBlockSize / kSectorSize);
- for (size_t i = 0; i < le->size; i += kBlockSize) {
- crc32(&buffer[i], kBlockSize, &checksum);
+ for (int sequence = ls.sequence; sequence >= 0 && status.isOk(); sequence--) {
+ auto buffer = read(device, logs, validating, 0, kBlockSize);
+ log_sector& ls = *reinterpret_cast<log_sector*>(&buffer[0]);
+ if (ls.magic != kMagic) {
+ LOG(ERROR) << "No magic!";
+ status = Status::fromExceptionCode(EINVAL, "No magic");
+ break;
}
- if (le->checksum && checksum != le->checksum) {
- LOG(ERROR) << "Checksums don't match " << std::hex << checksum;
- return Status::fromExceptionCode(EINVAL, "Checksums don't match");
+ if ((int)ls.sequence != sequence) {
+ LOG(ERROR) << "Expecting log sector " << sequence << " but got " << ls.sequence;
+ status = Status::fromExceptionCode(
+ EINVAL, ("Expecting log sector " + std::to_string(sequence) + " but got " +
+ std::to_string(ls.sequence))
+ .c_str());
+ break;
}
- device.seekg(le->source * kSectorSize);
- device.write(&buffer[0], le->size);
+ LOG(INFO) << action << " from log sector " << ls.sequence;
+
+ for (log_entry* le = &ls.entries[ls.count - 1]; le >= ls.entries; --le) {
+ LOG(INFO) << action << " " << le->size << " bytes from sector " << le->dest
+ << " to " << le->source << " with checksum " << std::hex << le->checksum;
+ auto buffer = read(device, logs, validating, le->dest, le->size);
+ uint32_t checksum = le->source / (kBlockSize / kSectorSize);
+ for (size_t i = 0; i < le->size; i += kBlockSize) {
+ crc32(&buffer[i], kBlockSize, &checksum);
+ }
+
+ if (le->checksum && checksum != le->checksum) {
+ LOG(ERROR) << "Checksums don't match " << std::hex << checksum;
+ status = Status::fromExceptionCode(EINVAL, "Checksums don't match");
+ break;
+ }
+
+ logs.push_back(*le);
+
+ if (!validating) {
+ device.seekg(le->source * kSectorSize);
+ device.write(&buffer[0], le->size);
+ }
+ }
}
+
+ if (!status.isOk()) {
+ if (!validating) {
+ LOG(ERROR) << "Checkpoint restore failed even though checkpoint validation passed";
+ return status;
+ }
+
+ LOG(WARNING) << "Checkpoint validation failed - attempting to roll forward";
+ auto buffer = read(device, logs, false, ls.sector0, kBlockSize);
+ device.seekg(0);
+ device.write(&buffer[0], kBlockSize);
+ return Status::ok();
+ }
+
+ if (!validating) break;
+
+ validating = false;
+ action = "Restoring";
}
return Status::ok();
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index f52e32f..9041838 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -176,27 +176,12 @@
auto const current_path = get_ce_key_current_path(directory_path);
if (to_fix != current_path) {
LOG(DEBUG) << "Renaming " << to_fix << " to " << current_path;
- android::base::unique_fd fd(TEMP_FAILURE_RETRY(
- open(to_fix.c_str(), O_RDONLY | O_CLOEXEC)));
- if (fd == -1) {
- PLOG(ERROR) << "Failed to open " << to_fix;
- return;
- }
- if (fsync(fd) == -1) {
- if (errno == EROFS || errno == EINVAL) {
- PLOG(WARNING) << "Skip fsync " << to_fix
- << " on a file system does not support synchronization";
- } else {
- PLOG(ERROR) << "Failed to fsync " << to_fix;
- unlink(to_fix.c_str());
- return;
- }
- }
if (rename(to_fix.c_str(), current_path.c_str()) != 0) {
PLOG(WARNING) << "Unable to rename " << to_fix << " to " << current_path;
return;
}
}
+ android::vold::FsyncDirectory(directory_path);
}
static bool read_and_fixate_user_ce_key(userid_t user_id,
@@ -684,6 +669,7 @@
std::string ce_key_path;
if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false;
if (!android::vold::storeKeyAtomically(ce_key_path, user_key_temp, auth, ce_key)) return false;
+ if (!android::vold::FsyncDirectory(directory_path)) return false;
return true;
}
diff --git a/KeyStorage.cpp b/KeyStorage.cpp
index dffece5..36a7777 100644
--- a/KeyStorage.cpp
+++ b/KeyStorage.cpp
@@ -544,6 +544,7 @@
if (!encryptWithoutKeymaster(appId, key, &encryptedKey)) return false;
}
if (!writeStringToFile(encryptedKey, dir + "/" + kFn_encrypted_key)) return false;
+ if (!FsyncDirectory(dir)) return false;
return true;
}
diff --git a/Utils.cpp b/Utils.cpp
index 4ec2679..341c927 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -753,9 +753,52 @@
return android::base::GetBoolProperty("ro.kernel.qemu", false);
}
-status_t UnmountTree(const std::string& prefix) {
- if (umount2(prefix.c_str(), MNT_DETACH)) {
- PLOG(ERROR) << "Failed to unmount " << prefix;
+static status_t findMountPointsWithPrefix(const std::string& prefix,
+ std::list<std::string>& mountPoints) {
+ // Add a trailing slash if the client didn't provide one so that we don't match /foo/barbaz
+ // when the prefix is /foo/bar
+ std::string prefixWithSlash(prefix);
+ if (prefix.back() != '/') {
+ android::base::StringAppendF(&prefixWithSlash, "/");
+ }
+
+ std::unique_ptr<FILE, int (*)(FILE*)> mnts(setmntent("/proc/mounts", "re"), endmntent);
+ if (!mnts) {
+ PLOG(ERROR) << "Unable to open /proc/mounts";
+ return -errno;
+ }
+
+ // Some volumes can be stacked on each other, so force unmount in
+ // reverse order to give us the best chance of success.
+ struct mntent* mnt; // getmntent returns a thread local, so it's safe.
+ while ((mnt = getmntent(mnts.get())) != nullptr) {
+ auto mountPoint = std::string(mnt->mnt_dir) + "/";
+ if (android::base::StartsWith(mountPoint, prefixWithSlash)) {
+ mountPoints.push_front(mountPoint);
+ }
+ }
+ return OK;
+}
+
+// Unmount all mountpoints that start with prefix. prefix itself doesn't need to be a mountpoint.
+status_t UnmountTreeWithPrefix(const std::string& prefix) {
+ std::list<std::string> toUnmount;
+ status_t result = findMountPointsWithPrefix(prefix, toUnmount);
+ if (result < 0) {
+ return result;
+ }
+ for (const auto& path : toUnmount) {
+ if (umount2(path.c_str(), MNT_DETACH)) {
+ PLOG(ERROR) << "Failed to unmount " << path;
+ result = -errno;
+ }
+ }
+ return result;
+}
+
+status_t UnmountTree(const std::string& mountPoint) {
+ if (umount2(mountPoint.c_str(), MNT_DETACH)) {
+ PLOG(ERROR) << "Failed to unmount " << mountPoint;
return -errno;
}
return OK;
@@ -768,7 +811,7 @@
return -errno;
}
- status_t result;
+ status_t result = OK;
struct dirent* de;
while ((de = readdir(dir))) {
const char* name = de->d_name;
@@ -846,5 +889,23 @@
return -1;
}
+bool FsyncDirectory(const std::string& dirname) {
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(dirname.c_str(), O_RDONLY | O_CLOEXEC)));
+ if (fd == -1) {
+ PLOG(ERROR) << "Failed to open " << dirname;
+ return false;
+ }
+ if (fsync(fd) == -1) {
+ if (errno == EROFS || errno == EINVAL) {
+ PLOG(WARNING) << "Skip fsync " << dirname
+ << " on a file system does not support synchronization";
+ } else {
+ PLOG(ERROR) << "Failed to fsync " << dirname;
+ return false;
+ }
+ }
+ return true;
+}
+
} // namespace vold
} // namespace android
diff --git a/Utils.h b/Utils.h
index 68c82eb..e51ec1e 100644
--- a/Utils.h
+++ b/Utils.h
@@ -127,12 +127,15 @@
/* Checks if Android is running in QEMU */
bool IsRunningInEmulator();
-status_t UnmountTree(const std::string& prefix);
+status_t UnmountTreeWithPrefix(const std::string& prefix);
+status_t UnmountTree(const std::string& mountPoint);
status_t DeleteDirContentsAndDir(const std::string& pathname);
status_t WaitForFile(const char* filename, std::chrono::nanoseconds timeout);
+bool FsyncDirectory(const std::string& dirname);
+
} // namespace vold
} // namespace android
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index d113cf9..f600f64 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -79,6 +79,7 @@
static const char* kPathVirtualDisk = "/data/misc/vold/virtual_disk";
static const char* kIsolatedStorage = "persist.sys.isolated_storage";
+static const char* kIsolatedStorageSnapshot = "sys.isolated_storage_snapshot";
static const char* kPropVirtualDisk = "persist.sys.virtual_disk";
static const std::string kEmptyString("");
@@ -108,6 +109,10 @@
VolumeManager::~VolumeManager() {}
+static bool hasIsolatedStorage() {
+ return GetBoolProperty(kIsolatedStorageSnapshot, GetBoolProperty(kIsolatedStorage, false));
+}
+
int VolumeManager::updateVirtualDisk() {
ATRACE_NAME("VolumeManager::updateVirtualDisk");
if (GetBoolProperty(kPropVirtualDisk, false)) {
@@ -420,8 +425,13 @@
return -1;
}
- struct stat fullWriteSb;
- if (TEMP_FAILURE_RETRY(stat("/mnt/runtime/write", &fullWriteSb)) == -1) {
+ struct stat mntFullSb;
+ struct stat mntWriteSb;
+ if (TEMP_FAILURE_RETRY(stat("/mnt/runtime/full", &mntFullSb)) == -1) {
+ PLOG(ERROR) << "Failed to stat /mnt/runtime/full";
+ return -1;
+ }
+ if (TEMP_FAILURE_RETRY(stat("/mnt/runtime/write", &mntWriteSb)) == -1) {
PLOG(ERROR) << "Failed to stat /mnt/runtime/write";
return -1;
}
@@ -500,7 +510,8 @@
int mountMode;
if (remountMode == -1) {
- mountMode = getMountModeForRunningProc(packagesForUid, userId, fullWriteSb);
+ mountMode =
+ getMountModeForRunningProc(packagesForUid, userId, mntWriteSb, mntFullSb);
if (mountMode == -1) {
_exit(1);
}
@@ -520,6 +531,7 @@
}
}
if (mountMode == VoldNativeService::REMOUNT_MODE_FULL ||
+ mountMode == VoldNativeService::REMOUNT_MODE_LEGACY ||
mountMode == VoldNativeService::REMOUNT_MODE_NONE) {
// These mount modes are not going to change dynamically, so don't bother
// unmounting/remounting dirs.
@@ -573,7 +585,8 @@
}
int VolumeManager::getMountModeForRunningProc(const std::vector<std::string>& packagesForUid,
- userid_t userId, struct stat& mntWriteStat) {
+ userid_t userId, struct stat& mntWriteStat,
+ struct stat& mntFullStat) {
struct stat storageSb;
if (TEMP_FAILURE_RETRY(stat("/storage", &storageSb)) == -1) {
PLOG(ERROR) << "Failed to stat /storage";
@@ -581,9 +594,11 @@
}
// Some packages have access to full external storage, identify processes belonging
- // to those packages by comparing inode no.s of /mnt/runtime/write and /storage
- if (storageSb.st_dev == mntWriteStat.st_dev && storageSb.st_ino == mntWriteStat.st_ino) {
+ // to those packages by comparing inode no.s of /mnt/runtime/full and /storage
+ if (storageSb.st_dev == mntFullStat.st_dev && storageSb.st_ino == mntFullStat.st_ino) {
return VoldNativeService::REMOUNT_MODE_FULL;
+ } else if (storageSb.st_dev == mntWriteStat.st_dev && storageSb.st_ino == mntWriteStat.st_ino) {
+ return VoldNativeService::REMOUNT_MODE_LEGACY;
}
std::string obbMountFile =
@@ -843,7 +858,7 @@
if (mPrimary) {
linkPrimary(userId);
}
- if (GetBoolProperty(kIsolatedStorage, false)) {
+ if (hasIsolatedStorage()) {
std::vector<std::string> visibleVolLabels;
for (auto& volId : mVisibleVolumeIds) {
auto vol = findVolume(volId);
@@ -863,11 +878,11 @@
LOG(VERBOSE) << "onUserStopped: " << userId;
mStartedUsers.erase(userId);
- if (GetBoolProperty(kIsolatedStorage, false)) {
+ if (hasIsolatedStorage()) {
mUserPackages.erase(userId);
std::string mntTargetDir = StringPrintf("/mnt/user/%d", userId);
- if (android::vold::UnmountTree(mntTargetDir) != 0) {
- PLOG(ERROR) << "unmountTree on " << mntTargetDir << " failed";
+ if (android::vold::UnmountTreeWithPrefix(mntTargetDir) < 0) {
+ PLOG(ERROR) << "UnmountTreeWithPrefix on " << mntTargetDir << " failed";
return -errno;
}
if (android::vold::DeleteDirContentsAndDir(mntTargetDir) < 0) {
@@ -897,7 +912,7 @@
int VolumeManager::prepareSandboxForApp(const std::string& packageName, appid_t appId,
const std::string& sandboxId, userid_t userId) {
- if (!GetBoolProperty(kIsolatedStorage, false)) {
+ if (!hasIsolatedStorage()) {
return 0;
} else if (mStartedUsers.find(userId) == mStartedUsers.end()) {
// User not started, no need to do anything now. Required bind mounts for the package will
@@ -923,7 +938,7 @@
int VolumeManager::destroySandboxForApp(const std::string& packageName,
const std::string& sandboxId, userid_t userId) {
- if (!GetBoolProperty(kIsolatedStorage, false)) {
+ if (!hasIsolatedStorage()) {
return 0;
}
LOG(VERBOSE) << "destroySandboxForApp: " << packageName << ", sandboxId=" << sandboxId
@@ -969,8 +984,8 @@
<< ", volLabel=" << volLabel;
std::string pkgSandboxTarget =
StringPrintf("/mnt/user/%d/package/%s", userId, packageName.c_str());
- if (android::vold::UnmountTree(pkgSandboxTarget)) {
- PLOG(ERROR) << "UnmountTree failed on " << pkgSandboxTarget;
+ if (android::vold::UnmountTreeWithPrefix(pkgSandboxTarget) < 0) {
+ PLOG(ERROR) << "UnmountTreeWithPrefix failed on " << pkgSandboxTarget;
}
std::string sandboxDir = StringPrintf("/mnt/runtime/write/%s", volLabel.c_str());
@@ -1001,7 +1016,7 @@
}
int VolumeManager::onVolumeMounted(android::vold::VolumeBase* vol) {
- if (!GetBoolProperty(kIsolatedStorage, false)) {
+ if (!hasIsolatedStorage()) {
return 0;
}
@@ -1036,7 +1051,7 @@
}
int VolumeManager::onVolumeUnmounted(android::vold::VolumeBase* vol) {
- if (!GetBoolProperty(kIsolatedStorage, false)) {
+ if (!hasIsolatedStorage()) {
return 0;
}
@@ -1070,8 +1085,8 @@
for (auto& packageName : packageNames) {
std::string volSandboxRoot = StringPrintf("/mnt/user/%d/package/%s/%s", userId,
packageName.c_str(), vol->getLabel().c_str());
- if (android::vold::UnmountTree(volSandboxRoot) != 0) {
- PLOG(ERROR) << "unmountTree on " << volSandboxRoot << " failed";
+ if (android::vold::UnmountTreeWithPrefix(volSandboxRoot) < 0) {
+ PLOG(ERROR) << "UnmountTreeWithPrefix on " << volSandboxRoot << " failed";
continue;
}
if (android::vold::DeleteDirContentsAndDir(volSandboxRoot) < 0) {
@@ -1084,7 +1099,7 @@
}
int VolumeManager::setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol) {
- if (GetBoolProperty(kIsolatedStorage, false)) {
+ if (hasIsolatedStorage()) {
return 0;
}
mPrimary = vol;
@@ -1095,7 +1110,7 @@
}
int VolumeManager::remountUid(uid_t uid, int32_t mountMode) {
- if (!GetBoolProperty(kIsolatedStorage, false)) {
+ if (!hasIsolatedStorage()) {
return remountUidLegacy(uid, mountMode);
}
@@ -1283,7 +1298,7 @@
mVisibleVolumeIds.clear();
// For unmounting dirs under /mnt/user/<user-id>/package/<package-name>
- android::vold::UnmountTree("/mnt/user/");
+ android::vold::UnmountTreeWithPrefix("/mnt/user/");
return 0;
}
diff --git a/VolumeManager.h b/VolumeManager.h
index 3a7bae4..7d299a1 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -174,7 +174,7 @@
int destroySandboxForAppOnVol(const std::string& packageName, const std::string& sandboxId,
userid_t userId, const std::string& volLabel);
int getMountModeForRunningProc(const std::vector<std::string>& packagesForUid, userid_t userId,
- struct stat& mntWriteStat);
+ struct stat& mntWriteStat, struct stat& mntFullStat);
void handleDiskAdded(const std::shared_ptr<android::vold::Disk>& disk);
void handleDiskChanged(dev_t device);
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index 59e8795..b9181bd 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -152,8 +152,9 @@
const int REMOUNT_MODE_DEFAULT = 1;
const int REMOUNT_MODE_READ = 2;
const int REMOUNT_MODE_WRITE = 3;
- const int REMOUNT_MODE_INSTALLER = 4;
- const int REMOUNT_MODE_FULL = 5;
+ const int REMOUNT_MODE_LEGACY = 4;
+ const int REMOUNT_MODE_INSTALLER = 5;
+ const int REMOUNT_MODE_FULL = 6;
const int VOLUME_STATE_UNMOUNTED = 0;
const int VOLUME_STATE_CHECKING = 1;
diff --git a/cryptfs.cpp b/cryptfs.cpp
index 43eca62..08bcaba 100644
--- a/cryptfs.cpp
+++ b/cryptfs.cpp
@@ -1366,6 +1366,7 @@
char buffer[DM_CRYPT_BUF_SIZE];
struct dm_ioctl* io;
int retval = -1;
+ int err;
if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) {
SLOGE("Cannot open device-mapper\n");
@@ -1375,8 +1376,9 @@
io = (struct dm_ioctl*)buffer;
ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
- if (ioctl(fd, DM_DEV_REMOVE, io)) {
- SLOGE("Cannot remove dm-crypt device\n");
+ err = ioctl(fd, DM_DEV_REMOVE, io);
+ if (err) {
+ SLOGE("Cannot remove dm-crypt device %s: %s\n", name, strerror(errno));
goto errout;
}
diff --git a/model/EmulatedVolume.cpp b/model/EmulatedVolume.cpp
index 8f46191..1d5546c 100644
--- a/model/EmulatedVolume.cpp
+++ b/model/EmulatedVolume.cpp
@@ -66,6 +66,7 @@
mFuseDefault = StringPrintf("/mnt/runtime/default/%s", label.c_str());
mFuseRead = StringPrintf("/mnt/runtime/read/%s", label.c_str());
mFuseWrite = StringPrintf("/mnt/runtime/write/%s", label.c_str());
+ mFuseFull = StringPrintf("/mnt/runtime/full/%s", label.c_str());
setInternalPath(mRawPath);
setPath(StringPrintf("/storage/%s", label.c_str()));
@@ -73,12 +74,13 @@
if (fs_prepare_dir(mFuseDefault.c_str(), 0700, AID_ROOT, AID_ROOT) ||
fs_prepare_dir(mFuseRead.c_str(), 0700, AID_ROOT, AID_ROOT) ||
- fs_prepare_dir(mFuseWrite.c_str(), 0700, AID_ROOT, AID_ROOT)) {
+ fs_prepare_dir(mFuseWrite.c_str(), 0700, AID_ROOT, AID_ROOT) ||
+ fs_prepare_dir(mFuseFull.c_str(), 0700, AID_ROOT, AID_ROOT)) {
PLOG(ERROR) << getId() << " failed to create mount points";
return -errno;
}
- dev_t before = GetDevice(mFuseWrite);
+ dev_t before = GetDevice(mFuseFull);
if (!(mFusePid = fork())) {
// clang-format off
@@ -106,7 +108,7 @@
}
nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
- while (before == GetDevice(mFuseWrite)) {
+ while (before == GetDevice(mFuseFull)) {
LOG(DEBUG) << "Waiting for FUSE to spin up...";
usleep(50000); // 50ms
@@ -132,14 +134,17 @@
ForceUnmount(mFuseDefault);
ForceUnmount(mFuseRead);
ForceUnmount(mFuseWrite);
+ ForceUnmount(mFuseFull);
rmdir(mFuseDefault.c_str());
rmdir(mFuseRead.c_str());
rmdir(mFuseWrite.c_str());
+ rmdir(mFuseFull.c_str());
mFuseDefault.clear();
mFuseRead.clear();
mFuseWrite.clear();
+ mFuseFull.clear();
return OK;
}
diff --git a/model/EmulatedVolume.h b/model/EmulatedVolume.h
index f618c55..fddfe4e 100644
--- a/model/EmulatedVolume.h
+++ b/model/EmulatedVolume.h
@@ -52,6 +52,7 @@
std::string mFuseDefault;
std::string mFuseRead;
std::string mFuseWrite;
+ std::string mFuseFull;
/* PID of FUSE wrapper */
pid_t mFusePid;
diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp
index 77a156c..e751eca 100644
--- a/model/PublicVolume.cpp
+++ b/model/PublicVolume.cpp
@@ -123,6 +123,7 @@
mFuseDefault = StringPrintf("/mnt/runtime/default/%s", stableName.c_str());
mFuseRead = StringPrintf("/mnt/runtime/read/%s", stableName.c_str());
mFuseWrite = StringPrintf("/mnt/runtime/write/%s", stableName.c_str());
+ mFuseFull = StringPrintf("/mnt/runtime/full/%s", stableName.c_str());
setInternalPath(mRawPath);
if (getMountFlags() & MountFlags::kVisible) {
@@ -161,12 +162,13 @@
if (fs_prepare_dir(mFuseDefault.c_str(), 0700, AID_ROOT, AID_ROOT) ||
fs_prepare_dir(mFuseRead.c_str(), 0700, AID_ROOT, AID_ROOT) ||
- fs_prepare_dir(mFuseWrite.c_str(), 0700, AID_ROOT, AID_ROOT)) {
+ fs_prepare_dir(mFuseWrite.c_str(), 0700, AID_ROOT, AID_ROOT) ||
+ fs_prepare_dir(mFuseFull.c_str(), 0700, AID_ROOT, AID_ROOT)) {
PLOG(ERROR) << getId() << " failed to create FUSE mount points";
return -errno;
}
- dev_t before = GetDevice(mFuseWrite);
+ dev_t before = GetDevice(mFuseFull);
if (!(mFusePid = fork())) {
if (getMountFlags() & MountFlags::kPrimary) {
@@ -183,36 +185,16 @@
PLOG(ERROR) << "Failed to exec";
}
} else {
- // In Pre-Q, apps have full read access to secondary storage devices but only
- // write access for their package specific directories. In Q, they only have access
- // to their own sandboxes and they can write anywhere inside the sandbox. Instead of
- // updating sdcardfs to allow packages writing into their own sandboxes, we could
- // just allow them to write anywhere by passing "-w".
// clang-format off
- if (GetBoolProperty(kIsolatedStorage, false)) {
- if (execl(kFusePath, kFusePath,
- "-u", "1023", // AID_MEDIA_RW
- "-g", "1023", // AID_MEDIA_RW
- "-U", std::to_string(getMountUserId()).c_str(),
- "-w",
- mRawPath.c_str(),
- stableName.c_str(),
- NULL)) {
- // clang-format on
- PLOG(ERROR) << "Failed to exec";
- }
- } else {
- // clang-format off
- if (execl(kFusePath, kFusePath,
- "-u", "1023", // AID_MEDIA_RW
- "-g", "1023", // AID_MEDIA_RW
- "-U", std::to_string(getMountUserId()).c_str(),
- mRawPath.c_str(),
- stableName.c_str(),
- NULL)) {
- // clang-format on
- PLOG(ERROR) << "Failed to exec";
- }
+ if (execl(kFusePath, kFusePath,
+ "-u", "1023", // AID_MEDIA_RW
+ "-g", "1023", // AID_MEDIA_RW
+ "-U", std::to_string(getMountUserId()).c_str(),
+ mRawPath.c_str(),
+ stableName.c_str(),
+ NULL)) {
+ // clang-format on
+ PLOG(ERROR) << "Failed to exec";
}
}
@@ -226,7 +208,7 @@
}
nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
- while (before == GetDevice(mFuseWrite)) {
+ while (before == GetDevice(mFuseFull)) {
LOG(DEBUG) << "Waiting for FUSE to spin up...";
usleep(50000); // 50ms
@@ -255,16 +237,19 @@
ForceUnmount(mFuseDefault);
ForceUnmount(mFuseRead);
ForceUnmount(mFuseWrite);
+ ForceUnmount(mFuseFull);
ForceUnmount(mRawPath);
rmdir(mFuseDefault.c_str());
rmdir(mFuseRead.c_str());
rmdir(mFuseWrite.c_str());
+ rmdir(mFuseFull.c_str());
rmdir(mRawPath.c_str());
mFuseDefault.clear();
mFuseRead.clear();
mFuseWrite.clear();
+ mFuseFull.clear();
mRawPath.clear();
return OK;
diff --git a/model/PublicVolume.h b/model/PublicVolume.h
index c918f52..2feccca 100644
--- a/model/PublicVolume.h
+++ b/model/PublicVolume.h
@@ -63,6 +63,7 @@
std::string mFuseDefault;
std::string mFuseRead;
std::string mFuseWrite;
+ std::string mFuseFull;
/* PID of FUSE wrapper */
pid_t mFusePid;
diff --git a/vold_prepare_subdirs.cpp b/vold_prepare_subdirs.cpp
index b8e5cb6..1dd5e85 100644
--- a/vold_prepare_subdirs.cpp
+++ b/vold_prepare_subdirs.cpp
@@ -128,6 +128,7 @@
auto misc_de_path = android::vold::BuildDataMiscDePath(user_id);
if (!prepare_dir(sehandle, 0700, 0, 0, misc_de_path + "/vold")) return false;
if (!prepare_dir(sehandle, 0700, 0, 0, misc_de_path + "/storaged")) return false;
+ if (!prepare_dir(sehandle, 0700, 0, 0, misc_de_path + "/rollback")) return false;
auto vendor_de_path = android::vold::BuildDataVendorDePath(user_id);
if (!prepare_dir(sehandle, 0700, AID_SYSTEM, AID_SYSTEM, vendor_de_path + "/fpdata")) {
@@ -142,6 +143,16 @@
auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id);
if (!prepare_dir(sehandle, 0700, 0, 0, misc_ce_path + "/vold")) return false;
if (!prepare_dir(sehandle, 0700, 0, 0, misc_ce_path + "/storaged")) return false;
+ if (!prepare_dir(sehandle, 0700, 0, 0, misc_ce_path + "/rollback")) return false;
+
+ auto system_ce_path = android::vold::BuildDataSystemCePath(user_id);
+ if (!prepare_dir(sehandle, 0700, AID_SYSTEM, AID_SYSTEM, system_ce_path + "/backup")) {
+ return false;
+ }
+ if (!prepare_dir(sehandle, 0700, AID_SYSTEM, AID_SYSTEM,
+ system_ce_path + "/backup_stage")) {
+ return false;
+ }
}
}
return true;