Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a084fcdc authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Fix external cache and secondary user bugs.

External cache files now have their own GID range, so measure using
those quotas.  Fix secondary user code measurement, since it always
lives under user 0.  Fix secondary user data measurement in manual
mode; we need to match based on appId instead of pure UID.

Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.StorageHostTest
Bug: 35812899, 35844919, 37193650
Change-Id: Ic3b153798164c33ea10e8a4dabc65edff26c56ca
parent c4ced4f0
Loading
Loading
Loading
Loading
+90 −68
Original line number Diff line number Diff line
@@ -1122,6 +1122,7 @@ static void collectQuotaStats(const std::string& device, int32_t userId,

    struct dqblk dq;

    if (stats != nullptr) {
        uid_t uid = multiuser_get_uid(userId, appId);
        if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
                reinterpret_cast<char*>(&dq)) != 0) {
@@ -1150,9 +1151,23 @@ static void collectQuotaStats(const std::string& device, int32_t userId,
            }
        }

#if HACK_FOR_37193650
    extStats->dataSize = extStats->dataSize;
#else
        int sharedGid = multiuser_get_shared_gid(0, appId);
        if (sharedGid != -1) {
            if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), sharedGid,
                    reinterpret_cast<char*>(&dq)) != 0) {
                if (errno != ESRCH) {
                    PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << sharedGid;
                }
            } else {
#if MEASURE_DEBUG
                LOG(DEBUG) << "quotactl() for GID " << sharedGid << " " << dq.dqb_curspace;
#endif
                stats->codeSize += dq.dqb_curspace;
            }
        }
    }

    if (extStats != nullptr) {
        int extGid = multiuser_get_ext_gid(userId, appId);
        if (extGid != -1) {
            if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), extGid,
@@ -1167,20 +1182,21 @@ static void collectQuotaStats(const std::string& device, int32_t userId,
                extStats->dataSize += dq.dqb_curspace;
            }
        }
#endif

    int sharedGid = multiuser_get_shared_gid(userId, appId);
    if (sharedGid != -1) {
        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), sharedGid,
        int extCacheGid = multiuser_get_ext_cache_gid(userId, appId);
        if (extCacheGid != -1) {
            if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), extCacheGid,
                    reinterpret_cast<char*>(&dq)) != 0) {
                if (errno != ESRCH) {
                PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << sharedGid;
                    PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << extCacheGid;
                }
            } else {
#if MEASURE_DEBUG
            LOG(DEBUG) << "quotactl() for GID " << sharedGid << " " << dq.dqb_curspace;
                LOG(DEBUG) << "quotactl() for GID " << extCacheGid << " " << dq.dqb_curspace;
#endif
            stats->codeSize += dq.dqb_curspace;
                extStats->dataSize += dq.dqb_curspace;
                extStats->cacheSize += dq.dqb_curspace;
            }
        }
    }
}
@@ -1256,9 +1272,10 @@ static void collectManualStatsForUser(const std::string& path, struct stats* sta
            if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) != 0) {
                continue;
            }
            int32_t user_uid = multiuser_get_app_id(s.st_uid);
            if (!strcmp(name, ".") || !strcmp(name, "..")) {
                continue;
            } else if (exclude_apps && (s.st_uid >= AID_APP_START && s.st_uid <= AID_APP_END)) {
            } else if (exclude_apps && (user_uid >= AID_APP_START && user_uid <= AID_APP_END)) {
                continue;
            } else {
                collectManualStats(StringPrintf("%s/%s", path.c_str(), name), stats);
@@ -1357,25 +1374,13 @@ binder::Status InstalldNativeService::getAppSize(const std::unique_ptr<std::stri
        ATRACE_BEGIN("code");
        for (auto codePath : codePaths) {
            calculate_tree_size(codePath, &stats.codeSize, -1,
                    multiuser_get_shared_gid(userId, appId));
                    multiuser_get_shared_gid(0, appId));
        }
        ATRACE_END();

        ATRACE_BEGIN("quota");
        collectQuotaStats(device, userId, appId, &stats, &extStats);
        ATRACE_END();

#if HACK_FOR_37193650
        ATRACE_BEGIN("external");
        for (size_t i = 0; i < packageNames.size(); i++) {
            const char* pkgname = packageNames[i].c_str();
            auto extPath = create_data_media_package_path(uuid_, userId, "data", pkgname);
            calculate_tree_size(extPath, &extStats.dataSize);
            auto mediaPath = create_data_media_package_path(uuid_, userId, "media", pkgname);
            calculate_tree_size(mediaPath, &extStats.dataSize);
        }
        ATRACE_END();
#endif
    } else {
        ATRACE_BEGIN("code");
        for (auto codePath : codePaths) {
@@ -1414,7 +1419,7 @@ binder::Status InstalldNativeService::getAppSize(const std::unique_ptr<std::stri

        if (!uuid) {
            ATRACE_BEGIN("dalvik");
            int32_t sharedGid = multiuser_get_shared_gid(userId, appId);
            int32_t sharedGid = multiuser_get_shared_gid(0, appId);
            if (sharedGid != -1) {
                calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
                        sharedGid, -1);
@@ -1464,12 +1469,6 @@ binder::Status InstalldNativeService::getUserSize(const std::unique_ptr<std::str
        flags &= ~FLAG_USE_QUOTA;
    }

#if HACK_FOR_37193650
    if (userId != 0) {
        flags &= ~FLAG_USE_QUOTA;
    }
#endif

    if (flags & FLAG_USE_QUOTA) {
        struct dqblk dq;

@@ -1532,6 +1531,7 @@ binder::Status InstalldNativeService::getUserSize(const std::unique_ptr<std::str
        }

        ATRACE_BEGIN("quota");
        int64_t dataSize = extStats.dataSize;
        for (auto appId : appIds) {
            if (appId >= AID_APP_START) {
                collectQuotaStats(device, userId, appId, &stats, &extStats);
@@ -1542,6 +1542,7 @@ binder::Status InstalldNativeService::getUserSize(const std::unique_ptr<std::str
#endif
            }
        }
        extStats.dataSize = dataSize;
        ATRACE_END();
    } else {
        ATRACE_BEGIN("obb");
@@ -1601,7 +1602,8 @@ binder::Status InstalldNativeService::getUserSize(const std::unique_ptr<std::str
}

binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std::string>& uuid,
        int32_t userId, int32_t flags, std::vector<int64_t>* _aidl_return) {
        int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
        std::vector<int64_t>* _aidl_return) {
    ENFORCE_UID(AID_SYSTEM);
    CHECK_ARGUMENT_UUID(uuid);
    // NOTE: Locking is relaxed on this method, since it's limited to
@@ -1620,6 +1622,7 @@ binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std:
    int64_t audioSize = 0;
    int64_t videoSize = 0;
    int64_t imageSize = 0;
    int64_t appSize = 0;

    auto device = findQuotaDeviceForUuid(uuid);
    if (device.empty()) {
@@ -1629,6 +1632,7 @@ binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std:
    if (flags & FLAG_USE_QUOTA) {
        struct dqblk dq;

        ATRACE_BEGIN("quota");
        uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
        if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
                reinterpret_cast<char*>(&dq)) != 0) {
@@ -1666,7 +1670,20 @@ binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std:
#endif
            imageSize = dq.dqb_curspace;
        }
        ATRACE_END();

        ATRACE_BEGIN("apps");
        struct stats extStats;
        memset(&extStats, 0, sizeof(extStats));
        for (auto appId : appIds) {
            if (appId >= AID_APP_START) {
                collectQuotaStats(device, userId, appId, nullptr, &extStats);
            }
        }
        appSize = extStats.dataSize + extStats.cacheSize;
        ATRACE_END();
    } else {
        ATRACE_BEGIN("manual");
        FTS *fts;
        FTSENT *p;
        auto path = create_data_media_path(uuid_, userId);
@@ -1700,11 +1717,15 @@ binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std:
            case FTS_DEFAULT:
            case FTS_SL:
            case FTS_SLNONE:
                if (p->fts_parent->fts_number == 1) {
                    appSize += size;
                }
                totalSize += size;
                break;
            }
        }
        fts_close(fts);
        ATRACE_END();
    }

    std::vector<int64_t> ret;
@@ -1712,6 +1733,7 @@ binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std:
    ret.push_back(audioSize);
    ret.push_back(videoSize);
    ret.push_back(imageSize);
    ret.push_back(appSize);
#if MEASURE_DEBUG
    LOG(DEBUG) << "Final result " << toString(ret);
#endif
+2 −1
Original line number Diff line number Diff line
@@ -68,7 +68,8 @@ public:
            int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
            std::vector<int64_t>* _aidl_return);
    binder::Status getExternalSize(const std::unique_ptr<std::string>& uuid,
            int32_t userId, int32_t flags, std::vector<int64_t>* _aidl_return);
            int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
            std::vector<int64_t>* _aidl_return);

    binder::Status setAppQuota(const std::unique_ptr<std::string>& uuid,
            int32_t userId, int32_t appId, int64_t cacheQuota);
+1 −1
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ interface IInstalld {
            int userId, int flags, int appId, in long[] ceDataInodes,
            in @utf8InCpp String[] codePaths);
    long[] getUserSize(@nullable @utf8InCpp String uuid, int userId, int flags, in int[] appIds);
    long[] getExternalSize(@nullable @utf8InCpp String uuid, int userId, int flags);
    long[] getExternalSize(@nullable @utf8InCpp String uuid, int userId, int flags, in int[] appIds);

    void setAppQuota(@nullable @utf8InCpp String uuid, int userId, int appId, long cacheQuota);

+0 −1
Original line number Diff line number Diff line
@@ -32,7 +32,6 @@

#define MEASURE_DEBUG 0
#define FIXUP_DEBUG 0
#define HACK_FOR_37193650 1

namespace android {
namespace installd {