summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jeff Sharkey <jsharkey@android.com> 2017-05-03 11:36:42 -0600
committer Jeff Sharkey <jsharkey@android.com> 2017-05-05 14:57:29 -0600
commitd712f0ccc120357e1267a04ac6de9dd732b27e76 (patch)
tree7c022021ac8547cd4c061772552c5cfe9ca34d88
parent8bba03d323684abb4e209398019c2540b053b827 (diff)
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
-rw-r--r--cmds/installd/CacheItem.cpp33
-rw-r--r--cmds/installd/CacheTracker.cpp50
-rw-r--r--cmds/installd/CacheTracker.h1
-rw-r--r--cmds/installd/InstalldNativeService.cpp64
-rw-r--r--cmds/installd/InstalldNativeService.h12
-rw-r--r--cmds/installd/utils.h3
6 files changed, 122 insertions, 41 deletions
diff --git a/cmds/installd/CacheItem.cpp b/cmds/installd/CacheItem.cpp
index 17eb7ff0e1..515f915b8b 100644
--- a/cmds/installd/CacheItem.cpp
+++ b/cmds/installd/CacheItem.cpp
@@ -67,6 +67,7 @@ std::string CacheItem::buildPath() {
}
int CacheItem::purge() {
+ int res = 0;
auto path = buildPath();
if (directory) {
FTS *fts;
@@ -88,29 +89,47 @@ int CacheItem::purge() {
break;
case FTS_F:
if (p->fts_parent->fts_number) {
- truncate(p->fts_path, 0);
+ if (truncate(p->fts_path, 0) != 0) {
+ PLOG(WARNING) << "Failed to truncate " << p->fts_path;
+ res = -1;
+ }
} else {
- unlink(p->fts_path);
+ if (unlink(p->fts_path) != 0) {
+ PLOG(WARNING) << "Failed to unlink " << p->fts_path;
+ res = -1;
+ }
}
break;
case FTS_DEFAULT:
case FTS_SL:
case FTS_SLNONE:
- unlink(p->fts_path);
+ if (unlink(p->fts_path) != 0) {
+ PLOG(WARNING) << "Failed to unlink " << p->fts_path;
+ res = -1;
+ }
break;
case FTS_DP:
- rmdir(p->fts_path);
+ if (rmdir(p->fts_path) != 0) {
+ PLOG(WARNING) << "Failed to rmdir " << p->fts_path;
+ res = -1;
+ }
break;
}
}
- return 0;
} else {
if (tombstone) {
- return truncate(path.c_str(), 0);
+ if (truncate(path.c_str(), 0) != 0) {
+ PLOG(WARNING) << "Failed to truncate " << path;
+ res = -1;
+ }
} else {
- return unlink(path.c_str());
+ if (unlink(path.c_str()) != 0) {
+ PLOG(WARNING) << "Failed to unlink " << path;
+ res = -1;
+ }
}
}
+ return res;
}
} // namespace installd
diff --git a/cmds/installd/CacheTracker.cpp b/cmds/installd/CacheTracker.cpp
index 4bfc834d86..e293948caa 100644
--- a/cmds/installd/CacheTracker.cpp
+++ b/cmds/installd/CacheTracker.cpp
@@ -51,22 +51,12 @@ void CacheTracker::addDataPath(const std::string& dataPath) {
}
void CacheTracker::loadStats() {
- int cacheGid = multiuser_get_cache_gid(mUserId, mAppId);
- if (cacheGid != -1 && !mQuotaDevice.empty()) {
- ATRACE_BEGIN("loadStats quota");
- struct dqblk dq;
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), cacheGid,
- reinterpret_cast<char*>(&dq)) != 0) {
- ATRACE_END();
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid;
- }
- } else {
- cacheUsed = dq.dqb_curspace;
- ATRACE_END();
- return;
- }
+ ATRACE_BEGIN("loadStats quota");
+ cacheUsed = 0;
+ if (loadQuotaStats()) {
+ return;
}
+ ATRACE_END();
ATRACE_BEGIN("loadStats tree");
cacheUsed = 0;
@@ -79,6 +69,36 @@ void CacheTracker::loadStats() {
ATRACE_END();
}
+bool CacheTracker::loadQuotaStats() {
+ int cacheGid = multiuser_get_cache_gid(mUserId, mAppId);
+ int extCacheGid = multiuser_get_ext_cache_gid(mUserId, mAppId);
+ if (!mQuotaDevice.empty() && cacheGid != -1 && extCacheGid != -1) {
+ struct dqblk dq;
+ if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), cacheGid,
+ reinterpret_cast<char*>(&dq)) != 0) {
+ if (errno != ESRCH) {
+ PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid;
+ }
+ return false;
+ } else {
+ cacheUsed += dq.dqb_curspace;
+ }
+
+ if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), extCacheGid,
+ reinterpret_cast<char*>(&dq)) != 0) {
+ if (errno != ESRCH) {
+ PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid;
+ }
+ return false;
+ } else {
+ cacheUsed += dq.dqb_curspace;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
void CacheTracker::loadItemsFrom(const std::string& path) {
FTS *fts;
FTSENT *p;
diff --git a/cmds/installd/CacheTracker.h b/cmds/installd/CacheTracker.h
index 91692d7469..44359b4970 100644
--- a/cmds/installd/CacheTracker.h
+++ b/cmds/installd/CacheTracker.h
@@ -66,6 +66,7 @@ private:
std::vector<std::string> mDataPaths;
+ bool loadQuotaStats();
void loadItemsFrom(const std::string& path);
DISALLOW_COPY_AND_ASSIGN(CacheTracker);
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 49a3b23b52..19dfb8789d 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -205,15 +205,20 @@ status_t InstalldNativeService::dump(int fd, const Vector<String16> & /* args */
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 @@ binder::Status InstalldNativeService::destroyUserData(const std::unique_ptr<std:
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 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin
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 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin
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 @@ binder::Status InstalldNativeService::setAppQuota(const std::unique_ptr<std::str
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::reconcileSecondaryDexFile(
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 @@ binder::Status InstalldNativeService::invalidateMounts() {
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 @@ binder::Status InstalldNativeService::invalidateMounts() {
}
}
}
+#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(
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 7f73c2ae15..200fc77341 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -121,14 +121,18 @@ public:
private:
std::recursive_mutex mLock;
- std::recursive_mutex mQuotaDevicesLock;
- std::recursive_mutex mCacheQuotasLock;
+ std::recursive_mutex mMountsLock;
+ std::recursive_mutex mQuotasLock;
+
+ /* Map of all storage mounts from source to target */
+ std::unordered_map<std::string, std::string> mStorageMounts;
+ /* Map of all quota mounts from target to source */
+ std::unordered_map<std::string, std::string> mQuotaReverseMounts;
- /* Map from mount point to underlying device node */
- std::unordered_map<std::string, std::string> mQuotaDevices;
/* Map from UID to cache quota size */
std::unordered_map<uid_t, int64_t> mCacheQuotas;
+ std::string findDataMediaPath(const std::unique_ptr<std::string>& uuid, userid_t userid);
std::string findQuotaDeviceForUuid(const std::unique_ptr<std::string>& uuid);
};
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index dd94da9e31..070da84c9e 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -33,6 +33,9 @@
#define MEASURE_DEBUG 0
#define FIXUP_DEBUG 0
+#define BYPASS_QUOTA 0
+#define BYPASS_SDCARDFS 0
+
namespace android {
namespace installd {