Clear cached files on external storage.
When clearing cached files belonging to an app, include any cached
files on external storage. Since we need to keep sdcardfs in the
loop about any file deletions, we always mutate by going through the
sdcardfs layer instead of behind its back.
Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.StorageHostTest
Bug: 37486230, 37566983, 37913442, 37914374
Change-Id: If174bf7eaf682da83cf0ab1b4938fe9a5956d464
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 49a3b23..19dfb87 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -205,15 +205,20 @@
out << "installd is happy!" << endl;
{
- std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock);
- out << endl << "Devices with quota support:" << endl;
- for (const auto& n : mQuotaDevices) {
+ std::lock_guard<std::recursive_mutex> lock(mMountsLock);
+ out << endl << "Storage mounts:" << endl;
+ for (const auto& n : mStorageMounts) {
+ out << " " << n.first << " = " << n.second << endl;
+ }
+
+ out << endl << "Quota reverse mounts:" << endl;
+ for (const auto& n : mQuotaReverseMounts) {
out << " " << n.first << " = " << n.second << endl;
}
}
{
- std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock);
+ std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
out << endl << "Per-UID cache quotas:" << endl;
for (const auto& n : mCacheQuotas) {
out << " " << n.first << " = " << n.second << endl;
@@ -901,7 +906,7 @@
if (delete_dir_contents_and_dir(path, true) != 0) {
res = error("Failed to delete " + path);
}
- path = create_data_media_path(uuid_, userId);
+ path = findDataMediaPath(uuid, userId);
if (delete_dir_contents_and_dir(path, true) != 0) {
res = error("Failed to delete " + path);
}
@@ -952,13 +957,19 @@
FTSENT *p;
auto ce_path = create_data_user_ce_path(uuid_, user);
auto de_path = create_data_user_de_path(uuid_, user);
- char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(), nullptr };
+ auto media_path = findDataMediaPath(uuid, user) + "/Android/data/";
+ char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(),
+ (char*) media_path.c_str(), nullptr };
if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
return error("Failed to fts_open");
}
while ((p = fts_read(fts)) != NULL) {
if (p->fts_info == FTS_D && p->fts_level == 1) {
uid_t uid = p->fts_statp->st_uid;
+ if (multiuser_get_app_id(uid) == AID_MEDIA_RW) {
+ uid = (multiuser_get_app_id(p->fts_statp->st_gid) - AID_EXT_GID_START)
+ + AID_APP_START;
+ }
auto search = trackers.find(uid);
if (search != trackers.end()) {
search->second->addDataPath(p->fts_path);
@@ -967,7 +978,7 @@
multiuser_get_user_id(uid), multiuser_get_app_id(uid), device));
tracker->addDataPath(p->fts_path);
{
- std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock);
+ std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
tracker->cacheQuota = mCacheQuotas[uid];
}
if (tracker->cacheQuota == 0) {
@@ -1745,7 +1756,7 @@
int32_t userId, int32_t appId, int64_t cacheQuota) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
- std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock);
+ std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
int32_t uid = multiuser_get_uid(userId, appId);
mCacheQuotas[uid] = cacheQuota;
@@ -2219,9 +2230,10 @@
binder::Status InstalldNativeService::invalidateMounts() {
ENFORCE_UID(AID_SYSTEM);
- std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock);
+ std::lock_guard<std::recursive_mutex> lock(mMountsLock);
- mQuotaDevices.clear();
+ mStorageMounts.clear();
+ mQuotaReverseMounts.clear();
std::ifstream in("/proc/mounts");
if (!in.is_open()) {
@@ -2231,17 +2243,25 @@
std::string source;
std::string target;
std::string ignored;
- struct dqblk dq;
while (!in.eof()) {
std::getline(in, source, ' ');
std::getline(in, target, ' ');
std::getline(in, ignored);
+#if !BYPASS_SDCARDFS
+ if (target.compare(0, 21, "/mnt/runtime/default/") == 0) {
+ LOG(DEBUG) << "Found storage mount " << source << " at " << target;
+ mStorageMounts[source] = target;
+ }
+#endif
+
+#if !BYPASS_QUOTA
if (source.compare(0, 11, "/dev/block/") == 0) {
+ struct dqblk dq;
if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0,
reinterpret_cast<char*>(&dq)) == 0) {
- LOG(DEBUG) << "Found " << source << " with quota";
- mQuotaDevices[target] = source;
+ LOG(DEBUG) << "Found quota mount " << source << " at " << target;
+ mQuotaReverseMounts[target] = source;
// ext4 only enables DQUOT_USAGE_ENABLED by default, so we
// need to kick it again to enable DQUOT_LIMITS_ENABLED.
@@ -2255,15 +2275,29 @@
}
}
}
+#endif
}
return ok();
}
+std::string InstalldNativeService::findDataMediaPath(
+ const std::unique_ptr<std::string>& uuid, userid_t userid) {
+ std::lock_guard<std::recursive_mutex> lock(mMountsLock);
+ const char* uuid_ = uuid ? uuid->c_str() : nullptr;
+ auto path = StringPrintf("%s/media", create_data_path(uuid_).c_str());
+ auto resolved = mStorageMounts[path];
+ if (resolved.empty()) {
+ LOG(WARNING) << "Failed to find storage mount for " << path;
+ resolved = path;
+ }
+ return StringPrintf("%s/%u", resolved.c_str(), userid);
+}
+
std::string InstalldNativeService::findQuotaDeviceForUuid(
const std::unique_ptr<std::string>& uuid) {
- std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock);
+ std::lock_guard<std::recursive_mutex> lock(mMountsLock);
auto path = create_data_path(uuid ? uuid->c_str() : nullptr);
- return mQuotaDevices[path];
+ return mQuotaReverseMounts[path];
}
binder::Status InstalldNativeService::isQuotaSupported(