Home | History | Annotate | Download | only in installd
      1 /*
      2 ** Copyright 2008, The Android Open Source Project
      3 **
      4 ** Licensed under the Apache License, Version 2.0 (the "License");
      5 ** you may not use this file except in compliance with the License.
      6 ** You may obtain a copy of the License at
      7 **
      8 **     http://www.apache.org/licenses/LICENSE-2.0
      9 **
     10 ** Unless required by applicable law or agreed to in writing, software
     11 ** distributed under the License is distributed on an "AS IS" BASIS,
     12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 ** See the License for the specific language governing permissions and
     14 ** limitations under the License.
     15 */
     16 
     17 #include "InstalldNativeService.h"
     18 
     19 #define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
     20 
     21 #include <errno.h>
     22 #include <inttypes.h>
     23 #include <fstream>
     24 #include <fts.h>
     25 #include <regex>
     26 #include <stdlib.h>
     27 #include <string.h>
     28 #include <sys/capability.h>
     29 #include <sys/file.h>
     30 #include <sys/resource.h>
     31 #include <sys/quota.h>
     32 #include <sys/stat.h>
     33 #include <sys/statvfs.h>
     34 #include <sys/types.h>
     35 #include <sys/wait.h>
     36 #include <sys/xattr.h>
     37 #include <unistd.h>
     38 
     39 #include <android-base/logging.h>
     40 #include <android-base/stringprintf.h>
     41 #include <android-base/strings.h>
     42 #include <android-base/unique_fd.h>
     43 #include <cutils/fs.h>
     44 #include <cutils/properties.h>
     45 #include <cutils/sched_policy.h>
     46 #include <log/log.h>               // TODO: Move everything to base/logging.
     47 #include <logwrap/logwrap.h>
     48 #include <private/android_filesystem_config.h>
     49 #include <selinux/android.h>
     50 #include <system/thread_defs.h>
     51 #include <utils/Trace.h>
     52 
     53 #include "dexopt.h"
     54 #include "globals.h"
     55 #include "installd_deps.h"
     56 #include "otapreopt_utils.h"
     57 #include "utils.h"
     58 
     59 #include "CacheTracker.h"
     60 #include "MatchExtensionGen.h"
     61 
     62 #ifndef LOG_TAG
     63 #define LOG_TAG "installd"
     64 #endif
     65 
     66 using android::base::StringPrintf;
     67 using std::endl;
     68 
     69 namespace android {
     70 namespace installd {
     71 
     72 static constexpr const char* kCpPath = "/system/bin/cp";
     73 static constexpr const char* kXattrDefault = "user.default";
     74 
     75 static constexpr const int MIN_RESTRICTED_HOME_SDK_VERSION = 24; // > M
     76 
     77 static constexpr const char* PKG_LIB_POSTFIX = "/lib";
     78 static constexpr const char* CACHE_DIR_POSTFIX = "/cache";
     79 static constexpr const char* CODE_CACHE_DIR_POSTFIX = "/code_cache";
     80 
     81 static constexpr const char *kIdMapPath = "/system/bin/idmap";
     82 static constexpr const char* IDMAP_PREFIX = "/data/resource-cache/";
     83 static constexpr const char* IDMAP_SUFFIX = "@idmap";
     84 
     85 // NOTE: keep in sync with Installer
     86 static constexpr int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
     87 static constexpr int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9;
     88 static constexpr int FLAG_USE_QUOTA = 1 << 12;
     89 static constexpr int FLAG_FREE_CACHE_V2 = 1 << 13;
     90 static constexpr int FLAG_FREE_CACHE_V2_DEFY_QUOTA = 1 << 14;
     91 static constexpr int FLAG_FREE_CACHE_NOOP = 1 << 15;
     92 static constexpr int FLAG_FORCE = 1 << 16;
     93 
     94 namespace {
     95 
     96 constexpr const char* kDump = "android.permission.DUMP";
     97 
     98 static binder::Status ok() {
     99     return binder::Status::ok();
    100 }
    101 
    102 static binder::Status exception(uint32_t code, const std::string& msg) {
    103     return binder::Status::fromExceptionCode(code, String8(msg.c_str()));
    104 }
    105 
    106 static binder::Status error() {
    107     return binder::Status::fromServiceSpecificError(errno);
    108 }
    109 
    110 static binder::Status error(const std::string& msg) {
    111     PLOG(ERROR) << msg;
    112     return binder::Status::fromServiceSpecificError(errno, String8(msg.c_str()));
    113 }
    114 
    115 static binder::Status error(uint32_t code, const std::string& msg) {
    116     LOG(ERROR) << msg << " (" << code << ")";
    117     return binder::Status::fromServiceSpecificError(code, String8(msg.c_str()));
    118 }
    119 
    120 binder::Status checkPermission(const char* permission) {
    121     pid_t pid;
    122     uid_t uid;
    123 
    124     if (checkCallingPermission(String16(permission), reinterpret_cast<int32_t*>(&pid),
    125             reinterpret_cast<int32_t*>(&uid))) {
    126         return ok();
    127     } else {
    128         return exception(binder::Status::EX_SECURITY,
    129                 StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, permission));
    130     }
    131 }
    132 
    133 binder::Status checkUid(uid_t expectedUid) {
    134     uid_t uid = IPCThreadState::self()->getCallingUid();
    135     if (uid == expectedUid || uid == AID_ROOT) {
    136         return ok();
    137     } else {
    138         return exception(binder::Status::EX_SECURITY,
    139                 StringPrintf("UID %d is not expected UID %d", uid, expectedUid));
    140     }
    141 }
    142 
    143 binder::Status checkArgumentUuid(const std::unique_ptr<std::string>& uuid) {
    144     if (!uuid || is_valid_filename(*uuid)) {
    145         return ok();
    146     } else {
    147         return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
    148                 StringPrintf("UUID %s is malformed", uuid->c_str()));
    149     }
    150 }
    151 
    152 binder::Status checkArgumentPackageName(const std::string& packageName) {
    153     if (is_valid_package_name(packageName.c_str())) {
    154         return ok();
    155     } else {
    156         return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
    157                 StringPrintf("Package name %s is malformed", packageName.c_str()));
    158     }
    159 }
    160 
    161 #define ENFORCE_UID(uid) {                                  \
    162     binder::Status status = checkUid((uid));                \
    163     if (!status.isOk()) {                                   \
    164         return status;                                      \
    165     }                                                       \
    166 }
    167 
    168 #define CHECK_ARGUMENT_UUID(uuid) {                         \
    169     binder::Status status = checkArgumentUuid((uuid));      \
    170     if (!status.isOk()) {                                   \
    171         return status;                                      \
    172     }                                                       \
    173 }
    174 
    175 #define CHECK_ARGUMENT_PACKAGE_NAME(packageName) {          \
    176     binder::Status status =                                 \
    177             checkArgumentPackageName((packageName));        \
    178     if (!status.isOk()) {                                   \
    179         return status;                                      \
    180     }                                                       \
    181 }
    182 
    183 }  // namespace
    184 
    185 status_t InstalldNativeService::start() {
    186     IPCThreadState::self()->disableBackgroundScheduling(true);
    187     status_t ret = BinderService<InstalldNativeService>::publish();
    188     if (ret != android::OK) {
    189         return ret;
    190     }
    191     sp<ProcessState> ps(ProcessState::self());
    192     ps->startThreadPool();
    193     ps->giveThreadPoolName();
    194     return android::OK;
    195 }
    196 
    197 status_t InstalldNativeService::dump(int fd, const Vector<String16> & /* args */) {
    198     auto out = std::fstream(StringPrintf("/proc/self/fd/%d", fd));
    199     const binder::Status dump_permission = checkPermission(kDump);
    200     if (!dump_permission.isOk()) {
    201         out << dump_permission.toString8() << endl;
    202         return PERMISSION_DENIED;
    203     }
    204     std::lock_guard<std::recursive_mutex> lock(mLock);
    205 
    206     out << "installd is happy!" << endl;
    207 
    208     {
    209         std::lock_guard<std::recursive_mutex> lock(mMountsLock);
    210         out << endl << "Storage mounts:" << endl;
    211         for (const auto& n : mStorageMounts) {
    212             out << "    " << n.first << " = " << n.second << endl;
    213         }
    214 
    215         out << endl << "Quota reverse mounts:" << endl;
    216         for (const auto& n : mQuotaReverseMounts) {
    217             out << "    " << n.first << " = " << n.second << endl;
    218         }
    219     }
    220 
    221     {
    222         std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
    223         out << endl << "Per-UID cache quotas:" << endl;
    224         for (const auto& n : mCacheQuotas) {
    225             out << "    " << n.first << " = " << n.second << endl;
    226         }
    227     }
    228 
    229     out << endl;
    230     out.flush();
    231 
    232     return NO_ERROR;
    233 }
    234 
    235 /**
    236  * Perform restorecon of the given path, but only perform recursive restorecon
    237  * if the label of that top-level file actually changed.  This can save us
    238  * significant time by avoiding no-op traversals of large filesystem trees.
    239  */
    240 static int restorecon_app_data_lazy(const std::string& path, const std::string& seInfo, uid_t uid,
    241         bool existing) {
    242     int res = 0;
    243     char* before = nullptr;
    244     char* after = nullptr;
    245 
    246     // Note that SELINUX_ANDROID_RESTORECON_DATADATA flag is set by
    247     // libselinux. Not needed here.
    248 
    249     if (lgetfilecon(path.c_str(), &before) < 0) {
    250         PLOG(ERROR) << "Failed before getfilecon for " << path;
    251         goto fail;
    252     }
    253     if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid, 0) < 0) {
    254         PLOG(ERROR) << "Failed top-level restorecon for " << path;
    255         goto fail;
    256     }
    257     if (lgetfilecon(path.c_str(), &after) < 0) {
    258         PLOG(ERROR) << "Failed after getfilecon for " << path;
    259         goto fail;
    260     }
    261 
    262     // If the initial top-level restorecon above changed the label, then go
    263     // back and restorecon everything recursively
    264     if (strcmp(before, after)) {
    265         if (existing) {
    266             LOG(DEBUG) << "Detected label change from " << before << " to " << after << " at "
    267                     << path << "; running recursive restorecon";
    268         }
    269         if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid,
    270                 SELINUX_ANDROID_RESTORECON_RECURSE) < 0) {
    271             PLOG(ERROR) << "Failed recursive restorecon for " << path;
    272             goto fail;
    273         }
    274     }
    275 
    276     goto done;
    277 fail:
    278     res = -1;
    279 done:
    280     free(before);
    281     free(after);
    282     return res;
    283 }
    284 
    285 static int restorecon_app_data_lazy(const std::string& parent, const char* name,
    286         const std::string& seInfo, uid_t uid, bool existing) {
    287     return restorecon_app_data_lazy(StringPrintf("%s/%s", parent.c_str(), name), seInfo, uid,
    288             existing);
    289 }
    290 
    291 static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid) {
    292     if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) {
    293         PLOG(ERROR) << "Failed to prepare " << path;
    294         return -1;
    295     }
    296     return 0;
    297 }
    298 
    299 /**
    300  * Ensure that we have a hard-limit quota to protect against abusive apps;
    301  * they should never use more than 90% of blocks or 50% of inodes.
    302  */
    303 static int prepare_app_quota(const std::unique_ptr<std::string>& uuid, const std::string& device,
    304         uid_t uid) {
    305     if (device.empty()) return 0;
    306 
    307     struct dqblk dq;
    308     if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
    309             reinterpret_cast<char*>(&dq)) != 0) {
    310         PLOG(WARNING) << "Failed to find quota for " << uid;
    311         return -1;
    312     }
    313 
    314 #if APPLY_HARD_QUOTAS
    315     if ((dq.dqb_bhardlimit == 0) || (dq.dqb_ihardlimit == 0)) {
    316         auto path = create_data_path(uuid ? uuid->c_str() : nullptr);
    317         struct statvfs stat;
    318         if (statvfs(path.c_str(), &stat) != 0) {
    319             PLOG(WARNING) << "Failed to statvfs " << path;
    320             return -1;
    321         }
    322 
    323         dq.dqb_valid = QIF_LIMITS;
    324         dq.dqb_bhardlimit =
    325             (((static_cast<uint64_t>(stat.f_blocks) * stat.f_frsize) / 10) * 9) / QIF_DQBLKSIZE;
    326         dq.dqb_ihardlimit = (stat.f_files / 2);
    327         if (quotactl(QCMD(Q_SETQUOTA, USRQUOTA), device.c_str(), uid,
    328                 reinterpret_cast<char*>(&dq)) != 0) {
    329             PLOG(WARNING) << "Failed to set hard quota for " << uid;
    330             return -1;
    331         } else {
    332             LOG(DEBUG) << "Applied hard quotas for " << uid;
    333             return 0;
    334         }
    335     } else {
    336         // Hard quota already set; assume it's reasonable
    337         return 0;
    338     }
    339 #else
    340     // Hard quotas disabled
    341     return 0;
    342 #endif
    343 }
    344 
    345 binder::Status InstalldNativeService::createAppData(const std::unique_ptr<std::string>& uuid,
    346         const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
    347         const std::string& seInfo, int32_t targetSdkVersion, int64_t* _aidl_return) {
    348     ENFORCE_UID(AID_SYSTEM);
    349     CHECK_ARGUMENT_UUID(uuid);
    350     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
    351     std::lock_guard<std::recursive_mutex> lock(mLock);
    352 
    353     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
    354     const char* pkgname = packageName.c_str();
    355 
    356     // Assume invalid inode unless filled in below
    357     if (_aidl_return != nullptr) *_aidl_return = -1;
    358 
    359     int32_t uid = multiuser_get_uid(userId, appId);
    360     int32_t cacheGid = multiuser_get_cache_gid(userId, appId);
    361     mode_t targetMode = targetSdkVersion >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
    362 
    363     // If UID doesn't have a specific cache GID, use UID value
    364     if (cacheGid == -1) {
    365         cacheGid = uid;
    366     }
    367 
    368     if (flags & FLAG_STORAGE_CE) {
    369         auto path = create_data_user_ce_package_path(uuid_, userId, pkgname);
    370         bool existing = (access(path.c_str(), F_OK) == 0);
    371 
    372         if (prepare_app_dir(path, targetMode, uid) ||
    373                 prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid) ||
    374                 prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid)) {
    375             return error("Failed to prepare " + path);
    376         }
    377 
    378         // Consider restorecon over contents if label changed
    379         if (restorecon_app_data_lazy(path, seInfo, uid, existing) ||
    380                 restorecon_app_data_lazy(path, "cache", seInfo, uid, existing) ||
    381                 restorecon_app_data_lazy(path, "code_cache", seInfo, uid, existing)) {
    382             return error("Failed to restorecon " + path);
    383         }
    384 
    385         // Remember inode numbers of cache directories so that we can clear
    386         // contents while CE storage is locked
    387         if (write_path_inode(path, "cache", kXattrInodeCache) ||
    388                 write_path_inode(path, "code_cache", kXattrInodeCodeCache)) {
    389             return error("Failed to write_path_inode for " + path);
    390         }
    391 
    392         // And return the CE inode of the top-level data directory so we can
    393         // clear contents while CE storage is locked
    394         if ((_aidl_return != nullptr)
    395                 && get_path_inode(path, reinterpret_cast<ino_t*>(_aidl_return)) != 0) {
    396             return error("Failed to get_path_inode for " + path);
    397         }
    398     }
    399     if (flags & FLAG_STORAGE_DE) {
    400         auto path = create_data_user_de_package_path(uuid_, userId, pkgname);
    401         bool existing = (access(path.c_str(), F_OK) == 0);
    402 
    403         if (prepare_app_dir(path, targetMode, uid) ||
    404                 prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid) ||
    405                 prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid)) {
    406             return error("Failed to prepare " + path);
    407         }
    408 
    409         // Consider restorecon over contents if label changed
    410         if (restorecon_app_data_lazy(path, seInfo, uid, existing) ||
    411                 restorecon_app_data_lazy(path, "cache", seInfo, uid, existing) ||
    412                 restorecon_app_data_lazy(path, "code_cache", seInfo, uid, existing)) {
    413             return error("Failed to restorecon " + path);
    414         }
    415 
    416         if (prepare_app_quota(uuid, findQuotaDeviceForUuid(uuid), uid)) {
    417             return error("Failed to set hard quota " + path);
    418         }
    419 
    420         if (property_get_bool("dalvik.vm.usejitprofiles", false)) {
    421             const std::string profile_dir =
    422                     create_primary_current_profile_package_dir_path(userId, pkgname);
    423             // read-write-execute only for the app user.
    424             if (fs_prepare_dir_strict(profile_dir.c_str(), 0700, uid, uid) != 0) {
    425                 return error("Failed to prepare " + profile_dir);
    426             }
    427             const std::string profile_file = create_current_profile_path(userId, pkgname,
    428                     /*is_secondary_dex*/false);
    429             // read-write only for the app user.
    430             if (fs_prepare_file_strict(profile_file.c_str(), 0600, uid, uid) != 0) {
    431                 return error("Failed to prepare " + profile_file);
    432             }
    433             const std::string ref_profile_path =
    434                     create_primary_reference_profile_package_dir_path(pkgname);
    435             // dex2oat/profman runs under the shared app gid and it needs to read/write reference
    436             // profiles.
    437             int shared_app_gid = multiuser_get_shared_gid(0, appId);
    438             if ((shared_app_gid != -1) && fs_prepare_dir_strict(
    439                     ref_profile_path.c_str(), 0700, shared_app_gid, shared_app_gid) != 0) {
    440                 return error("Failed to prepare " + ref_profile_path);
    441             }
    442         }
    443     }
    444     return ok();
    445 }
    446 
    447 binder::Status InstalldNativeService::migrateAppData(const std::unique_ptr<std::string>& uuid,
    448         const std::string& packageName, int32_t userId, int32_t flags) {
    449     ENFORCE_UID(AID_SYSTEM);
    450     CHECK_ARGUMENT_UUID(uuid);
    451     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
    452     std::lock_guard<std::recursive_mutex> lock(mLock);
    453 
    454     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
    455     const char* pkgname = packageName.c_str();
    456 
    457     // This method only exists to upgrade system apps that have requested
    458     // forceDeviceEncrypted, so their default storage always lives in a
    459     // consistent location.  This only works on non-FBE devices, since we
    460     // never want to risk exposing data on a device with real CE/DE storage.
    461 
    462     auto ce_path = create_data_user_ce_package_path(uuid_, userId, pkgname);
    463     auto de_path = create_data_user_de_package_path(uuid_, userId, pkgname);
    464 
    465     // If neither directory is marked as default, assume CE is default
    466     if (getxattr(ce_path.c_str(), kXattrDefault, nullptr, 0) == -1
    467             && getxattr(de_path.c_str(), kXattrDefault, nullptr, 0) == -1) {
    468         if (setxattr(ce_path.c_str(), kXattrDefault, nullptr, 0, 0) != 0) {
    469             return error("Failed to mark default storage " + ce_path);
    470         }
    471     }
    472 
    473     // Migrate default data location if needed
    474     auto target = (flags & FLAG_STORAGE_DE) ? de_path : ce_path;
    475     auto source = (flags & FLAG_STORAGE_DE) ? ce_path : de_path;
    476 
    477     if (getxattr(target.c_str(), kXattrDefault, nullptr, 0) == -1) {
    478         LOG(WARNING) << "Requested default storage " << target
    479                 << " is not active; migrating from " << source;
    480         if (delete_dir_contents_and_dir(target) != 0) {
    481             return error("Failed to delete " + target);
    482         }
    483         if (rename(source.c_str(), target.c_str()) != 0) {
    484             return error("Failed to rename " + source + " to " + target);
    485         }
    486     }
    487 
    488     return ok();
    489 }
    490 
    491 
    492 binder::Status InstalldNativeService::clearAppProfiles(const std::string& packageName) {
    493     ENFORCE_UID(AID_SYSTEM);
    494     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
    495     std::lock_guard<std::recursive_mutex> lock(mLock);
    496 
    497     binder::Status res = ok();
    498     if (!clear_primary_reference_profile(packageName)) {
    499         res = error("Failed to clear reference profile for " + packageName);
    500     }
    501     if (!clear_primary_current_profiles(packageName)) {
    502         res = error("Failed to clear current profiles for " + packageName);
    503     }
    504     return res;
    505 }
    506 
    507 binder::Status InstalldNativeService::clearAppData(const std::unique_ptr<std::string>& uuid,
    508         const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode) {
    509     ENFORCE_UID(AID_SYSTEM);
    510     CHECK_ARGUMENT_UUID(uuid);
    511     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
    512     std::lock_guard<std::recursive_mutex> lock(mLock);
    513 
    514     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
    515     const char* pkgname = packageName.c_str();
    516 
    517     binder::Status res = ok();
    518     if (flags & FLAG_STORAGE_CE) {
    519         auto path = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInode);
    520         if (flags & FLAG_CLEAR_CACHE_ONLY) {
    521             path = read_path_inode(path, "cache", kXattrInodeCache);
    522         } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
    523             path = read_path_inode(path, "code_cache", kXattrInodeCodeCache);
    524         }
    525         if (access(path.c_str(), F_OK) == 0) {
    526             if (delete_dir_contents(path) != 0) {
    527                 res = error("Failed to delete contents of " + path);
    528             }
    529         }
    530     }
    531     if (flags & FLAG_STORAGE_DE) {
    532         std::string suffix = "";
    533         bool only_cache = false;
    534         if (flags & FLAG_CLEAR_CACHE_ONLY) {
    535             suffix = CACHE_DIR_POSTFIX;
    536             only_cache = true;
    537         } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
    538             suffix = CODE_CACHE_DIR_POSTFIX;
    539             only_cache = true;
    540         }
    541 
    542         auto path = create_data_user_de_package_path(uuid_, userId, pkgname) + suffix;
    543         if (access(path.c_str(), F_OK) == 0) {
    544             if (delete_dir_contents(path) != 0) {
    545                 res = error("Failed to delete contents of " + path);
    546             }
    547         }
    548         if (!only_cache) {
    549             if (!clear_primary_current_profile(packageName, userId)) {
    550                 res = error("Failed to clear current profile for " + packageName);
    551             }
    552         }
    553     }
    554     return res;
    555 }
    556 
    557 static int destroy_app_reference_profile(const std::string& pkgname) {
    558     return delete_dir_contents_and_dir(
    559         create_primary_reference_profile_package_dir_path(pkgname),
    560         /*ignore_if_missing*/ true);
    561 }
    562 
    563 static int destroy_app_current_profiles(const std::string& pkgname, userid_t userid) {
    564     return delete_dir_contents_and_dir(
    565         create_primary_current_profile_package_dir_path(userid, pkgname),
    566         /*ignore_if_missing*/ true);
    567 }
    568 
    569 binder::Status InstalldNativeService::destroyAppProfiles(const std::string& packageName) {
    570     ENFORCE_UID(AID_SYSTEM);
    571     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
    572     std::lock_guard<std::recursive_mutex> lock(mLock);
    573 
    574     binder::Status res = ok();
    575     std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
    576     for (auto user : users) {
    577         if (destroy_app_current_profiles(packageName, user) != 0) {
    578             res = error("Failed to destroy current profiles for " + packageName);
    579         }
    580     }
    581     if (destroy_app_reference_profile(packageName) != 0) {
    582         res = error("Failed to destroy reference profile for " + packageName);
    583     }
    584     return res;
    585 }
    586 
    587 binder::Status InstalldNativeService::destroyAppData(const std::unique_ptr<std::string>& uuid,
    588         const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode) {
    589     ENFORCE_UID(AID_SYSTEM);
    590     CHECK_ARGUMENT_UUID(uuid);
    591     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
    592     std::lock_guard<std::recursive_mutex> lock(mLock);
    593 
    594     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
    595     const char* pkgname = packageName.c_str();
    596 
    597     binder::Status res = ok();
    598     if (flags & FLAG_STORAGE_CE) {
    599         auto path = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInode);
    600         if (delete_dir_contents_and_dir(path) != 0) {
    601             res = error("Failed to delete " + path);
    602         }
    603     }
    604     if (flags & FLAG_STORAGE_DE) {
    605         auto path = create_data_user_de_package_path(uuid_, userId, pkgname);
    606         if (delete_dir_contents_and_dir(path) != 0) {
    607             res = error("Failed to delete " + path);
    608         }
    609         destroy_app_current_profiles(packageName, userId);
    610         // TODO(calin): If the package is still installed by other users it's probably
    611         // beneficial to keep the reference profile around.
    612         // Verify if it's ok to do that.
    613         destroy_app_reference_profile(packageName);
    614     }
    615     return res;
    616 }
    617 
    618 static gid_t get_cache_gid(uid_t uid) {
    619     int32_t gid = multiuser_get_cache_gid(multiuser_get_user_id(uid), multiuser_get_app_id(uid));
    620     return (gid != -1) ? gid : uid;
    621 }
    622 
    623 binder::Status InstalldNativeService::fixupAppData(const std::unique_ptr<std::string>& uuid,
    624         int32_t flags) {
    625     ENFORCE_UID(AID_SYSTEM);
    626     CHECK_ARGUMENT_UUID(uuid);
    627     std::lock_guard<std::recursive_mutex> lock(mLock);
    628 
    629     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
    630     for (auto user : get_known_users(uuid_)) {
    631         ATRACE_BEGIN("fixup user");
    632         FTS* fts;
    633         FTSENT* p;
    634         auto ce_path = create_data_user_ce_path(uuid_, user);
    635         auto de_path = create_data_user_de_path(uuid_, user);
    636         char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(), nullptr };
    637         if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
    638             return error("Failed to fts_open");
    639         }
    640         while ((p = fts_read(fts)) != nullptr) {
    641             if (p->fts_info == FTS_D && p->fts_level == 1) {
    642                 // Track down inodes of cache directories
    643                 uint64_t raw = 0;
    644                 ino_t inode_cache = 0;
    645                 ino_t inode_code_cache = 0;
    646                 if (getxattr(p->fts_path, kXattrInodeCache, &raw, sizeof(raw)) == sizeof(raw)) {
    647                     inode_cache = raw;
    648                 }
    649                 if (getxattr(p->fts_path, kXattrInodeCodeCache, &raw, sizeof(raw)) == sizeof(raw)) {
    650                     inode_code_cache = raw;
    651                 }
    652 
    653                 // Figure out expected GID of each child
    654                 FTSENT* child = fts_children(fts, 0);
    655                 while (child != nullptr) {
    656                     if ((child->fts_statp->st_ino == inode_cache)
    657                             || (child->fts_statp->st_ino == inode_code_cache)
    658                             || !strcmp(child->fts_name, "cache")
    659                             || !strcmp(child->fts_name, "code_cache")) {
    660                         child->fts_number = get_cache_gid(p->fts_statp->st_uid);
    661                     } else {
    662                         child->fts_number = p->fts_statp->st_uid;
    663                     }
    664                     child = child->fts_link;
    665                 }
    666             } else if (p->fts_level >= 2) {
    667                 if (p->fts_level > 2) {
    668                     // Inherit GID from parent once we're deeper into tree
    669                     p->fts_number = p->fts_parent->fts_number;
    670                 }
    671 
    672                 uid_t uid = p->fts_parent->fts_statp->st_uid;
    673                 gid_t cache_gid = get_cache_gid(uid);
    674                 gid_t expected = p->fts_number;
    675                 gid_t actual = p->fts_statp->st_gid;
    676                 if (actual == expected) {
    677 #if FIXUP_DEBUG
    678                     LOG(DEBUG) << "Ignoring " << p->fts_path << " with expected GID " << expected;
    679 #endif
    680                     if (!(flags & FLAG_FORCE)) {
    681                         fts_set(fts, p, FTS_SKIP);
    682                     }
    683                 } else if ((actual == uid) || (actual == cache_gid)) {
    684                     // Only consider fixing up when current GID belongs to app
    685                     if (p->fts_info != FTS_D) {
    686                         LOG(INFO) << "Fixing " << p->fts_path << " with unexpected GID " << actual
    687                                 << " instead of " << expected;
    688                     }
    689                     switch (p->fts_info) {
    690                     case FTS_DP:
    691                         // If we're moving towards cache GID, we need to set S_ISGID
    692                         if (expected == cache_gid) {
    693                             if (chmod(p->fts_path, 02771) != 0) {
    694                                 PLOG(WARNING) << "Failed to chmod " << p->fts_path;
    695                             }
    696                         }
    697                         // Intentional fall through to also set GID
    698                     case FTS_F:
    699                         if (chown(p->fts_path, -1, expected) != 0) {
    700                             PLOG(WARNING) << "Failed to chown " << p->fts_path;
    701                         }
    702                         break;
    703                     case FTS_SL:
    704                     case FTS_SLNONE:
    705                         if (lchown(p->fts_path, -1, expected) != 0) {
    706                             PLOG(WARNING) << "Failed to chown " << p->fts_path;
    707                         }
    708                         break;
    709                     }
    710                 } else {
    711                     // Ignore all other GID transitions, since they're kinda shady
    712                     LOG(WARNING) << "Ignoring " << p->fts_path << " with unexpected GID " << actual
    713                             << " instead of " << expected;
    714                 }
    715             }
    716         }
    717         fts_close(fts);
    718         ATRACE_END();
    719     }
    720     return ok();
    721 }
    722 
    723 binder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std::string>& fromUuid,
    724         const std::unique_ptr<std::string>& toUuid, const std::string& packageName,
    725         const std::string& dataAppName, int32_t appId, const std::string& seInfo,
    726         int32_t targetSdkVersion) {
    727     ENFORCE_UID(AID_SYSTEM);
    728     CHECK_ARGUMENT_UUID(fromUuid);
    729     CHECK_ARGUMENT_UUID(toUuid);
    730     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
    731     std::lock_guard<std::recursive_mutex> lock(mLock);
    732 
    733     const char* from_uuid = fromUuid ? fromUuid->c_str() : nullptr;
    734     const char* to_uuid = toUuid ? toUuid->c_str() : nullptr;
    735     const char* package_name = packageName.c_str();
    736     const char* data_app_name = dataAppName.c_str();
    737 
    738     binder::Status res = ok();
    739     std::vector<userid_t> users = get_known_users(from_uuid);
    740 
    741     // Copy app
    742     {
    743         auto from = create_data_app_package_path(from_uuid, data_app_name);
    744         auto to = create_data_app_package_path(to_uuid, data_app_name);
    745         auto to_parent = create_data_app_path(to_uuid);
    746 
    747         char *argv[] = {
    748             (char*) kCpPath,
    749             (char*) "-F", /* delete any existing destination file first (--remove-destination) */
    750             (char*) "-p", /* preserve timestamps, ownership, and permissions */
    751             (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */
    752             (char*) "-P", /* Do not follow symlinks [default] */
    753             (char*) "-d", /* don't dereference symlinks */
    754             (char*) from.c_str(),
    755             (char*) to_parent.c_str()
    756         };
    757 
    758         LOG(DEBUG) << "Copying " << from << " to " << to;
    759         int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true);
    760         if (rc != 0) {
    761             res = error(rc, "Failed copying " + from + " to " + to);
    762             goto fail;
    763         }
    764 
    765         if (selinux_android_restorecon(to.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE) != 0) {
    766             res = error("Failed to restorecon " + to);
    767             goto fail;
    768         }
    769     }
    770 
    771     // Copy private data for all known users
    772     for (auto user : users) {
    773 
    774         // Data source may not exist for all users; that's okay
    775         auto from_ce = create_data_user_ce_package_path(from_uuid, user, package_name);
    776         if (access(from_ce.c_str(), F_OK) != 0) {
    777             LOG(INFO) << "Missing source " << from_ce;
    778             continue;
    779         }
    780 
    781         if (!createAppData(toUuid, packageName, user, FLAG_STORAGE_CE | FLAG_STORAGE_DE, appId,
    782                 seInfo, targetSdkVersion, nullptr).isOk()) {
    783             res = error("Failed to create package target");
    784             goto fail;
    785         }
    786 
    787         char *argv[] = {
    788             (char*) kCpPath,
    789             (char*) "-F", /* delete any existing destination file first (--remove-destination) */
    790             (char*) "-p", /* preserve timestamps, ownership, and permissions */
    791             (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */
    792             (char*) "-P", /* Do not follow symlinks [default] */
    793             (char*) "-d", /* don't dereference symlinks */
    794             nullptr,
    795             nullptr
    796         };
    797 
    798         {
    799             auto from = create_data_user_de_package_path(from_uuid, user, package_name);
    800             auto to = create_data_user_de_path(to_uuid, user);
    801             argv[6] = (char*) from.c_str();
    802             argv[7] = (char*) to.c_str();
    803 
    804             LOG(DEBUG) << "Copying " << from << " to " << to;
    805             int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true);
    806             if (rc != 0) {
    807                 res = error(rc, "Failed copying " + from + " to " + to);
    808                 goto fail;
    809             }
    810         }
    811         {
    812             auto from = create_data_user_ce_package_path(from_uuid, user, package_name);
    813             auto to = create_data_user_ce_path(to_uuid, user);
    814             argv[6] = (char*) from.c_str();
    815             argv[7] = (char*) to.c_str();
    816 
    817             LOG(DEBUG) << "Copying " << from << " to " << to;
    818             int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true);
    819             if (rc != 0) {
    820                 res = error(rc, "Failed copying " + from + " to " + to);
    821                 goto fail;
    822             }
    823         }
    824 
    825         if (!restoreconAppData(toUuid, packageName, user, FLAG_STORAGE_CE | FLAG_STORAGE_DE,
    826                 appId, seInfo).isOk()) {
    827             res = error("Failed to restorecon");
    828             goto fail;
    829         }
    830     }
    831 
    832     // We let the framework scan the new location and persist that before
    833     // deleting the data in the old location; this ordering ensures that
    834     // we can recover from things like battery pulls.
    835     return ok();
    836 
    837 fail:
    838     // Nuke everything we might have already copied
    839     {
    840         auto to = create_data_app_package_path(to_uuid, data_app_name);
    841         if (delete_dir_contents(to.c_str(), 1, NULL) != 0) {
    842             LOG(WARNING) << "Failed to rollback " << to;
    843         }
    844     }
    845     for (auto user : users) {
    846         {
    847             auto to = create_data_user_de_package_path(to_uuid, user, package_name);
    848             if (delete_dir_contents(to.c_str(), 1, NULL) != 0) {
    849                 LOG(WARNING) << "Failed to rollback " << to;
    850             }
    851         }
    852         {
    853             auto to = create_data_user_ce_package_path(to_uuid, user, package_name);
    854             if (delete_dir_contents(to.c_str(), 1, NULL) != 0) {
    855                 LOG(WARNING) << "Failed to rollback " << to;
    856             }
    857         }
    858     }
    859     return res;
    860 }
    861 
    862 binder::Status InstalldNativeService::createUserData(const std::unique_ptr<std::string>& uuid,
    863         int32_t userId, int32_t userSerial ATTRIBUTE_UNUSED, int32_t flags) {
    864     ENFORCE_UID(AID_SYSTEM);
    865     CHECK_ARGUMENT_UUID(uuid);
    866     std::lock_guard<std::recursive_mutex> lock(mLock);
    867 
    868     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
    869     if (flags & FLAG_STORAGE_DE) {
    870         if (uuid_ == nullptr) {
    871             if (ensure_config_user_dirs(userId) != 0) {
    872                 return error(StringPrintf("Failed to ensure dirs for %d", userId));
    873             }
    874         }
    875     }
    876 
    877     // Data under /data/media doesn't have an app, but we still want
    878     // to limit it to prevent abuse.
    879     if (prepare_app_quota(uuid, findQuotaDeviceForUuid(uuid),
    880             multiuser_get_uid(userId, AID_MEDIA_RW))) {
    881         return error("Failed to set hard quota for media_rw");
    882     }
    883 
    884     return ok();
    885 }
    886 
    887 binder::Status InstalldNativeService::destroyUserData(const std::unique_ptr<std::string>& uuid,
    888         int32_t userId, int32_t flags) {
    889     ENFORCE_UID(AID_SYSTEM);
    890     CHECK_ARGUMENT_UUID(uuid);
    891     std::lock_guard<std::recursive_mutex> lock(mLock);
    892 
    893     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
    894     binder::Status res = ok();
    895     if (flags & FLAG_STORAGE_DE) {
    896         auto path = create_data_user_de_path(uuid_, userId);
    897         if (delete_dir_contents_and_dir(path, true) != 0) {
    898             res = error("Failed to delete " + path);
    899         }
    900         if (uuid_ == nullptr) {
    901             path = create_data_misc_legacy_path(userId);
    902             if (delete_dir_contents_and_dir(path, true) != 0) {
    903                 res = error("Failed to delete " + path);
    904             }
    905             path = create_primary_cur_profile_dir_path(userId);
    906             if (delete_dir_contents_and_dir(path, true) != 0) {
    907                 res = error("Failed to delete " + path);
    908             }
    909         }
    910     }
    911     if (flags & FLAG_STORAGE_CE) {
    912         auto path = create_data_user_ce_path(uuid_, userId);
    913         if (delete_dir_contents_and_dir(path, true) != 0) {
    914             res = error("Failed to delete " + path);
    915         }
    916         path = findDataMediaPath(uuid, userId);
    917         if (delete_dir_contents_and_dir(path, true) != 0) {
    918             res = error("Failed to delete " + path);
    919         }
    920     }
    921     return res;
    922 }
    923 
    924 binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::string>& uuid,
    925         int64_t targetFreeBytes, int64_t cacheReservedBytes, int32_t flags) {
    926     ENFORCE_UID(AID_SYSTEM);
    927     CHECK_ARGUMENT_UUID(uuid);
    928     std::lock_guard<std::recursive_mutex> lock(mLock);
    929 
    930     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
    931     auto data_path = create_data_path(uuid_);
    932     auto device = findQuotaDeviceForUuid(uuid);
    933     auto noop = (flags & FLAG_FREE_CACHE_NOOP);
    934 
    935     int64_t free = data_disk_free(data_path);
    936     if (free < 0) {
    937         return error("Failed to determine free space for " + data_path);
    938     }
    939 
    940     int64_t cleared = 0;
    941     int64_t needed = targetFreeBytes - free;
    942     LOG(DEBUG) << "Device " << data_path << " has " << free << " free; requested "
    943             << targetFreeBytes << "; needed " << needed;
    944 
    945     if (free >= targetFreeBytes) {
    946         return ok();
    947     }
    948 
    949     if (flags & FLAG_FREE_CACHE_V2) {
    950         // This new cache strategy fairly removes files from UIDs by deleting
    951         // files from the UIDs which are most over their allocated quota
    952 
    953         // 1. Create trackers for every known UID
    954         ATRACE_BEGIN("create");
    955         std::unordered_map<uid_t, std::shared_ptr<CacheTracker>> trackers;
    956         for (auto user : get_known_users(uuid_)) {
    957             FTS *fts;
    958             FTSENT *p;
    959             auto ce_path = create_data_user_ce_path(uuid_, user);
    960             auto de_path = create_data_user_de_path(uuid_, user);
    961             auto media_path = findDataMediaPath(uuid, user) + "/Android/data/";
    962             char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(),
    963                     (char*) media_path.c_str(), nullptr };
    964             if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
    965                 return error("Failed to fts_open");
    966             }
    967             while ((p = fts_read(fts)) != NULL) {
    968                 if (p->fts_info == FTS_D && p->fts_level == 1) {
    969                     uid_t uid = p->fts_statp->st_uid;
    970                     if (multiuser_get_app_id(uid) == AID_MEDIA_RW) {
    971                         uid = (multiuser_get_app_id(p->fts_statp->st_gid) - AID_EXT_GID_START)
    972                                 + AID_APP_START;
    973                     }
    974                     auto search = trackers.find(uid);
    975                     if (search != trackers.end()) {
    976                         search->second->addDataPath(p->fts_path);
    977                     } else {
    978                         auto tracker = std::shared_ptr<CacheTracker>(new CacheTracker(
    979                                 multiuser_get_user_id(uid), multiuser_get_app_id(uid), device));
    980                         tracker->addDataPath(p->fts_path);
    981                         {
    982                             std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
    983                             tracker->cacheQuota = mCacheQuotas[uid];
    984                         }
    985                         if (tracker->cacheQuota == 0) {
    986 #if MEASURE_DEBUG
    987                             LOG(WARNING) << "UID " << uid << " has no cache quota; assuming 64MB";
    988 #endif
    989                             tracker->cacheQuota = 67108864;
    990                         }
    991                         trackers[uid] = tracker;
    992                     }
    993                     fts_set(fts, p, FTS_SKIP);
    994                 }
    995             }
    996             fts_close(fts);
    997         }
    998         ATRACE_END();
    999 
   1000         // 2. Populate tracker stats and insert into priority queue
   1001         ATRACE_BEGIN("populate");
   1002         int64_t cacheTotal = 0;
   1003         auto cmp = [](std::shared_ptr<CacheTracker> left, std::shared_ptr<CacheTracker> right) {
   1004             return (left->getCacheRatio() < right->getCacheRatio());
   1005         };
   1006         std::priority_queue<std::shared_ptr<CacheTracker>,
   1007                 std::vector<std::shared_ptr<CacheTracker>>, decltype(cmp)> queue(cmp);
   1008         for (const auto& it : trackers) {
   1009             it.second->loadStats();
   1010             queue.push(it.second);
   1011             cacheTotal += it.second->cacheUsed;
   1012         }
   1013         ATRACE_END();
   1014 
   1015         // 3. Bounce across the queue, freeing items from whichever tracker is
   1016         // the most over their assigned quota
   1017         ATRACE_BEGIN("bounce");
   1018         std::shared_ptr<CacheTracker> active;
   1019         while (active || !queue.empty()) {
   1020             // Only look at apps under quota when explicitly requested
   1021             if (active && (active->getCacheRatio() < 10000)
   1022                     && !(flags & FLAG_FREE_CACHE_V2_DEFY_QUOTA)) {
   1023                 LOG(DEBUG) << "Active ratio " << active->getCacheRatio()
   1024                         << " isn't over quota, and defy not requested";
   1025                 break;
   1026             }
   1027 
   1028             // Only keep clearing when we haven't pushed into reserved area
   1029             if (cacheReservedBytes > 0 && cleared >= (cacheTotal - cacheReservedBytes)) {
   1030                 LOG(DEBUG) << "Refusing to clear cached data in reserved space";
   1031                 break;
   1032             }
   1033 
   1034             // Find the best tracker to work with; this might involve swapping
   1035             // if the active tracker is no longer the most over quota
   1036             bool nextBetter = active && !queue.empty()
   1037                     && active->getCacheRatio() < queue.top()->getCacheRatio();
   1038             if (!active || nextBetter) {
   1039                 if (active) {
   1040                     // Current tracker still has items, so we'll consider it
   1041                     // again later once it bubbles up to surface
   1042                     queue.push(active);
   1043                 }
   1044                 active = queue.top(); queue.pop();
   1045                 active->ensureItems();
   1046                 continue;
   1047             }
   1048 
   1049             // If no items remain, go find another tracker
   1050             if (active->items.empty()) {
   1051                 active = nullptr;
   1052                 continue;
   1053             } else {
   1054                 auto item = active->items.back();
   1055                 active->items.pop_back();
   1056 
   1057                 LOG(DEBUG) << "Purging " << item->toString() << " from " << active->toString();
   1058                 if (!noop) {
   1059                     item->purge();
   1060                 }
   1061                 active->cacheUsed -= item->size;
   1062                 needed -= item->size;
   1063                 cleared += item->size;
   1064             }
   1065 
   1066             // Verify that we're actually done before bailing, since sneaky
   1067             // apps might be using hardlinks
   1068             if (needed <= 0) {
   1069                 free = data_disk_free(data_path);
   1070                 needed = targetFreeBytes - free;
   1071                 if (needed <= 0) {
   1072                     break;
   1073                 } else {
   1074                     LOG(WARNING) << "Expected to be done but still need " << needed;
   1075                 }
   1076             }
   1077         }
   1078         ATRACE_END();
   1079 
   1080     } else {
   1081         return error("Legacy cache logic no longer supported");
   1082     }
   1083 
   1084     free = data_disk_free(data_path);
   1085     if (free >= targetFreeBytes) {
   1086         return ok();
   1087     } else {
   1088         return error(StringPrintf("Failed to free up %" PRId64 " on %s; final free space %" PRId64,
   1089                 targetFreeBytes, data_path.c_str(), free));
   1090     }
   1091 }
   1092 
   1093 binder::Status InstalldNativeService::rmdex(const std::string& codePath,
   1094         const std::string& instructionSet) {
   1095     ENFORCE_UID(AID_SYSTEM);
   1096     std::lock_guard<std::recursive_mutex> lock(mLock);
   1097 
   1098     char dex_path[PKG_PATH_MAX];
   1099 
   1100     const char* path = codePath.c_str();
   1101     const char* instruction_set = instructionSet.c_str();
   1102 
   1103     if (validate_apk_path(path) && validate_system_app_path(path)) {
   1104         return error("Invalid path " + codePath);
   1105     }
   1106 
   1107     if (!create_cache_path(dex_path, path, instruction_set)) {
   1108         return error("Failed to create cache path for " + codePath);
   1109     }
   1110 
   1111     ALOGV("unlink %s\n", dex_path);
   1112     if (unlink(dex_path) < 0) {
   1113         // It's ok if we don't have a dalvik cache path. Report error only when the path exists
   1114         // but could not be unlinked.
   1115         if (errno != ENOENT) {
   1116             return error(StringPrintf("Failed to unlink %s", dex_path));
   1117         }
   1118     }
   1119     return ok();
   1120 }
   1121 
   1122 struct stats {
   1123     int64_t codeSize;
   1124     int64_t dataSize;
   1125     int64_t cacheSize;
   1126 };
   1127 
   1128 #if MEASURE_DEBUG
   1129 static std::string toString(std::vector<int64_t> values) {
   1130     std::stringstream res;
   1131     res << "[";
   1132     for (size_t i = 0; i < values.size(); i++) {
   1133         res << values[i];
   1134         if (i < values.size() - 1) {
   1135             res << ",";
   1136         }
   1137     }
   1138     res << "]";
   1139     return res.str();
   1140 }
   1141 #endif
   1142 
   1143 static void collectQuotaStats(const std::string& device, int32_t userId,
   1144         int32_t appId, struct stats* stats, struct stats* extStats) {
   1145     if (device.empty()) return;
   1146 
   1147     struct dqblk dq;
   1148 
   1149     if (stats != nullptr) {
   1150         uid_t uid = multiuser_get_uid(userId, appId);
   1151         if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
   1152                 reinterpret_cast<char*>(&dq)) != 0) {
   1153             if (errno != ESRCH) {
   1154                 PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
   1155             }
   1156         } else {
   1157 #if MEASURE_DEBUG
   1158             LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
   1159 #endif
   1160             stats->dataSize += dq.dqb_curspace;
   1161         }
   1162 
   1163         int cacheGid = multiuser_get_cache_gid(userId, appId);
   1164         if (cacheGid != -1) {
   1165             if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), cacheGid,
   1166                     reinterpret_cast<char*>(&dq)) != 0) {
   1167                 if (errno != ESRCH) {
   1168                     PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << cacheGid;
   1169                 }
   1170             } else {
   1171 #if MEASURE_DEBUG
   1172                 LOG(DEBUG) << "quotactl() for GID " << cacheGid << " " << dq.dqb_curspace;
   1173 #endif
   1174                 stats->cacheSize += dq.dqb_curspace;
   1175             }
   1176         }
   1177 
   1178         int sharedGid = multiuser_get_shared_gid(0, appId);
   1179         if (sharedGid != -1) {
   1180             if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), sharedGid,
   1181                     reinterpret_cast<char*>(&dq)) != 0) {
   1182                 if (errno != ESRCH) {
   1183                     PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << sharedGid;
   1184                 }
   1185             } else {
   1186 #if MEASURE_DEBUG
   1187                 LOG(DEBUG) << "quotactl() for GID " << sharedGid << " " << dq.dqb_curspace;
   1188 #endif
   1189                 stats->codeSize += dq.dqb_curspace;
   1190             }
   1191         }
   1192     }
   1193 
   1194     if (extStats != nullptr) {
   1195         int extGid = multiuser_get_ext_gid(userId, appId);
   1196         if (extGid != -1) {
   1197             if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), extGid,
   1198                     reinterpret_cast<char*>(&dq)) != 0) {
   1199                 if (errno != ESRCH) {
   1200                     PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << extGid;
   1201                 }
   1202             } else {
   1203 #if MEASURE_DEBUG
   1204                 LOG(DEBUG) << "quotactl() for GID " << extGid << " " << dq.dqb_curspace;
   1205 #endif
   1206                 extStats->dataSize += dq.dqb_curspace;
   1207             }
   1208         }
   1209 
   1210         int extCacheGid = multiuser_get_ext_cache_gid(userId, appId);
   1211         if (extCacheGid != -1) {
   1212             if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), extCacheGid,
   1213                     reinterpret_cast<char*>(&dq)) != 0) {
   1214                 if (errno != ESRCH) {
   1215                     PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << extCacheGid;
   1216                 }
   1217             } else {
   1218 #if MEASURE_DEBUG
   1219                 LOG(DEBUG) << "quotactl() for GID " << extCacheGid << " " << dq.dqb_curspace;
   1220 #endif
   1221                 extStats->dataSize += dq.dqb_curspace;
   1222                 extStats->cacheSize += dq.dqb_curspace;
   1223             }
   1224         }
   1225     }
   1226 }
   1227 
   1228 static void collectManualStats(const std::string& path, struct stats* stats) {
   1229     DIR *d;
   1230     int dfd;
   1231     struct dirent *de;
   1232     struct stat s;
   1233 
   1234     d = opendir(path.c_str());
   1235     if (d == nullptr) {
   1236         if (errno != ENOENT) {
   1237             PLOG(WARNING) << "Failed to open " << path;
   1238         }
   1239         return;
   1240     }
   1241     dfd = dirfd(d);
   1242     while ((de = readdir(d))) {
   1243         const char *name = de->d_name;
   1244 
   1245         int64_t size = 0;
   1246         if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
   1247             size = s.st_blocks * 512;
   1248         }
   1249 
   1250         if (de->d_type == DT_DIR) {
   1251             if (!strcmp(name, ".")) {
   1252                 // Don't recurse, but still count node size
   1253             } else if (!strcmp(name, "..")) {
   1254                 // Don't recurse or count node size
   1255                 continue;
   1256             } else {
   1257                 // Measure all children nodes
   1258                 size = 0;
   1259                 calculate_tree_size(StringPrintf("%s/%s", path.c_str(), name), &size);
   1260             }
   1261 
   1262             if (!strcmp(name, "cache") || !strcmp(name, "code_cache")) {
   1263                 stats->cacheSize += size;
   1264             }
   1265         }
   1266 
   1267         // Legacy symlink isn't owned by app
   1268         if (de->d_type == DT_LNK && !strcmp(name, "lib")) {
   1269             continue;
   1270         }
   1271 
   1272         // Everything found inside is considered data
   1273         stats->dataSize += size;
   1274     }
   1275     closedir(d);
   1276 }
   1277 
   1278 static void collectManualStatsForUser(const std::string& path, struct stats* stats,
   1279         bool exclude_apps = false) {
   1280     DIR *d;
   1281     int dfd;
   1282     struct dirent *de;
   1283     struct stat s;
   1284 
   1285     d = opendir(path.c_str());
   1286     if (d == nullptr) {
   1287         if (errno != ENOENT) {
   1288             PLOG(WARNING) << "Failed to open " << path;
   1289         }
   1290         return;
   1291     }
   1292     dfd = dirfd(d);
   1293     while ((de = readdir(d))) {
   1294         if (de->d_type == DT_DIR) {
   1295             const char *name = de->d_name;
   1296             if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) != 0) {
   1297                 continue;
   1298             }
   1299             int32_t user_uid = multiuser_get_app_id(s.st_uid);
   1300             if (!strcmp(name, ".") || !strcmp(name, "..")) {
   1301                 continue;
   1302             } else if (exclude_apps && (user_uid >= AID_APP_START && user_uid <= AID_APP_END)) {
   1303                 continue;
   1304             } else {
   1305                 collectManualStats(StringPrintf("%s/%s", path.c_str(), name), stats);
   1306             }
   1307         }
   1308     }
   1309     closedir(d);
   1310 }
   1311 
   1312 static void collectManualExternalStatsForUser(const std::string& path, struct stats* stats) {
   1313     FTS *fts;
   1314     FTSENT *p;
   1315     char *argv[] = { (char*) path.c_str(), nullptr };
   1316     if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
   1317         PLOG(ERROR) << "Failed to fts_open " << path;
   1318         return;
   1319     }
   1320     while ((p = fts_read(fts)) != NULL) {
   1321         p->fts_number = p->fts_parent->fts_number;
   1322         switch (p->fts_info) {
   1323         case FTS_D:
   1324             if (p->fts_level == 4
   1325                     && !strcmp(p->fts_name, "cache")
   1326                     && !strcmp(p->fts_parent->fts_parent->fts_name, "data")
   1327                     && !strcmp(p->fts_parent->fts_parent->fts_parent->fts_name, "Android")) {
   1328                 p->fts_number = 1;
   1329             }
   1330             // Fall through to count the directory
   1331         case FTS_DEFAULT:
   1332         case FTS_F:
   1333         case FTS_SL:
   1334         case FTS_SLNONE:
   1335             int64_t size = (p->fts_statp->st_blocks * 512);
   1336             if (p->fts_number == 1) {
   1337                 stats->cacheSize += size;
   1338             }
   1339             stats->dataSize += size;
   1340             break;
   1341         }
   1342     }
   1343     fts_close(fts);
   1344 }
   1345 
   1346 binder::Status InstalldNativeService::getAppSize(const std::unique_ptr<std::string>& uuid,
   1347         const std::vector<std::string>& packageNames, int32_t userId, int32_t flags,
   1348         int32_t appId, const std::vector<int64_t>& ceDataInodes,
   1349         const std::vector<std::string>& codePaths, std::vector<int64_t>* _aidl_return) {
   1350     ENFORCE_UID(AID_SYSTEM);
   1351     CHECK_ARGUMENT_UUID(uuid);
   1352     for (auto packageName : packageNames) {
   1353         CHECK_ARGUMENT_PACKAGE_NAME(packageName);
   1354     }
   1355     // NOTE: Locking is relaxed on this method, since it's limited to
   1356     // read-only measurements without mutation.
   1357 
   1358     // When modifying this logic, always verify using tests:
   1359     // runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetAppSize
   1360 
   1361 #if MEASURE_DEBUG
   1362     LOG(INFO) << "Measuring user " << userId << " app " << appId;
   1363 #endif
   1364 
   1365     // Here's a summary of the common storage locations across the platform,
   1366     // and how they're each tagged:
   1367     //
   1368     // /data/app/com.example                           UID system
   1369     // /data/app/com.example/oat                       UID system
   1370     // /data/user/0/com.example                        UID u0_a10      GID u0_a10
   1371     // /data/user/0/com.example/cache                  UID u0_a10      GID u0_a10_cache
   1372     // /data/media/0/foo.txt                           UID u0_media_rw
   1373     // /data/media/0/bar.jpg                           UID u0_media_rw GID u0_media_image
   1374     // /data/media/0/Android/data/com.example          UID u0_media_rw GID u0_a10_ext
   1375     // /data/media/0/Android/data/com.example/cache    UID u0_media_rw GID u0_a10_ext_cache
   1376     // /data/media/obb/com.example                     UID system
   1377 
   1378     struct stats stats;
   1379     struct stats extStats;
   1380     memset(&stats, 0, sizeof(stats));
   1381     memset(&extStats, 0, sizeof(extStats));
   1382 
   1383     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
   1384 
   1385     auto device = findQuotaDeviceForUuid(uuid);
   1386     if (device.empty()) {
   1387         flags &= ~FLAG_USE_QUOTA;
   1388     }
   1389 
   1390     ATRACE_BEGIN("obb");
   1391     for (auto packageName : packageNames) {
   1392         auto obbCodePath = create_data_media_obb_path(uuid_, packageName.c_str());
   1393         calculate_tree_size(obbCodePath, &extStats.codeSize);
   1394     }
   1395     ATRACE_END();
   1396 
   1397     if (flags & FLAG_USE_QUOTA && appId >= AID_APP_START) {
   1398         ATRACE_BEGIN("code");
   1399         for (auto codePath : codePaths) {
   1400             calculate_tree_size(codePath, &stats.codeSize, -1,
   1401                     multiuser_get_shared_gid(0, appId));
   1402         }
   1403         ATRACE_END();
   1404 
   1405         ATRACE_BEGIN("quota");
   1406         collectQuotaStats(device, userId, appId, &stats, &extStats);
   1407         ATRACE_END();
   1408     } else {
   1409         ATRACE_BEGIN("code");
   1410         for (auto codePath : codePaths) {
   1411             calculate_tree_size(codePath, &stats.codeSize);
   1412         }
   1413         ATRACE_END();
   1414 
   1415         for (size_t i = 0; i < packageNames.size(); i++) {
   1416             const char* pkgname = packageNames[i].c_str();
   1417 
   1418             ATRACE_BEGIN("data");
   1419             auto cePath = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInodes[i]);
   1420             collectManualStats(cePath, &stats);
   1421             auto dePath = create_data_user_de_package_path(uuid_, userId, pkgname);
   1422             collectManualStats(dePath, &stats);
   1423             ATRACE_END();
   1424 
   1425             if (!uuid) {
   1426                 ATRACE_BEGIN("profiles");
   1427                 calculate_tree_size(
   1428                         create_primary_current_profile_package_dir_path(userId, pkgname),
   1429                         &stats.dataSize);
   1430                 calculate_tree_size(
   1431                         create_primary_reference_profile_package_dir_path(pkgname),
   1432                         &stats.codeSize);
   1433                 ATRACE_END();
   1434             }
   1435 
   1436             ATRACE_BEGIN("external");
   1437             auto extPath = create_data_media_package_path(uuid_, userId, "data", pkgname);
   1438             collectManualStats(extPath, &extStats);
   1439             auto mediaPath = create_data_media_package_path(uuid_, userId, "media", pkgname);
   1440             calculate_tree_size(mediaPath, &extStats.dataSize);
   1441             ATRACE_END();
   1442         }
   1443 
   1444         if (!uuid) {
   1445             ATRACE_BEGIN("dalvik");
   1446             int32_t sharedGid = multiuser_get_shared_gid(0, appId);
   1447             if (sharedGid != -1) {
   1448                 calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
   1449                         sharedGid, -1);
   1450             }
   1451             ATRACE_END();
   1452         }
   1453     }
   1454 
   1455     std::vector<int64_t> ret;
   1456     ret.push_back(stats.codeSize);
   1457     ret.push_back(stats.dataSize);
   1458     ret.push_back(stats.cacheSize);
   1459     ret.push_back(extStats.codeSize);
   1460     ret.push_back(extStats.dataSize);
   1461     ret.push_back(extStats.cacheSize);
   1462 #if MEASURE_DEBUG
   1463     LOG(DEBUG) << "Final result " << toString(ret);
   1464 #endif
   1465     *_aidl_return = ret;
   1466     return ok();
   1467 }
   1468 
   1469 binder::Status InstalldNativeService::getUserSize(const std::unique_ptr<std::string>& uuid,
   1470         int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
   1471         std::vector<int64_t>* _aidl_return) {
   1472     ENFORCE_UID(AID_SYSTEM);
   1473     CHECK_ARGUMENT_UUID(uuid);
   1474     // NOTE: Locking is relaxed on this method, since it's limited to
   1475     // read-only measurements without mutation.
   1476 
   1477     // When modifying this logic, always verify using tests:
   1478     // runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetUserSize
   1479 
   1480 #if MEASURE_DEBUG
   1481     LOG(INFO) << "Measuring user " << userId;
   1482 #endif
   1483 
   1484     struct stats stats;
   1485     struct stats extStats;
   1486     memset(&stats, 0, sizeof(stats));
   1487     memset(&extStats, 0, sizeof(extStats));
   1488 
   1489     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
   1490 
   1491     auto device = findQuotaDeviceForUuid(uuid);
   1492     if (device.empty()) {
   1493         flags &= ~FLAG_USE_QUOTA;
   1494     }
   1495 
   1496     if (flags & FLAG_USE_QUOTA) {
   1497         struct dqblk dq;
   1498 
   1499         ATRACE_BEGIN("obb");
   1500         if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), AID_MEDIA_OBB,
   1501                 reinterpret_cast<char*>(&dq)) != 0) {
   1502             if (errno != ESRCH) {
   1503                 PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << AID_MEDIA_OBB;
   1504             }
   1505         } else {
   1506 #if MEASURE_DEBUG
   1507             LOG(DEBUG) << "quotactl() for GID " << AID_MEDIA_OBB << " " << dq.dqb_curspace;
   1508 #endif
   1509             extStats.codeSize += dq.dqb_curspace;
   1510         }
   1511         ATRACE_END();
   1512 
   1513         ATRACE_BEGIN("code");
   1514         calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize, -1, -1, true);
   1515         ATRACE_END();
   1516 
   1517         ATRACE_BEGIN("data");
   1518         auto cePath = create_data_user_ce_path(uuid_, userId);
   1519         collectManualStatsForUser(cePath, &stats, true);
   1520         auto dePath = create_data_user_de_path(uuid_, userId);
   1521         collectManualStatsForUser(dePath, &stats, true);
   1522         ATRACE_END();
   1523 
   1524         if (!uuid) {
   1525             ATRACE_BEGIN("profile");
   1526             auto userProfilePath = create_primary_cur_profile_dir_path(userId);
   1527             calculate_tree_size(userProfilePath, &stats.dataSize, -1, -1, true);
   1528             auto refProfilePath = create_primary_ref_profile_dir_path();
   1529             calculate_tree_size(refProfilePath, &stats.codeSize, -1, -1, true);
   1530             ATRACE_END();
   1531         }
   1532 
   1533         ATRACE_BEGIN("external");
   1534         uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
   1535         if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
   1536                 reinterpret_cast<char*>(&dq)) != 0) {
   1537             if (errno != ESRCH) {
   1538                 PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
   1539             }
   1540         } else {
   1541 #if MEASURE_DEBUG
   1542             LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
   1543 #endif
   1544             extStats.dataSize += dq.dqb_curspace;
   1545         }
   1546         ATRACE_END();
   1547 
   1548         if (!uuid) {
   1549             ATRACE_BEGIN("dalvik");
   1550             calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
   1551                     -1, -1, true);
   1552             calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize,
   1553                     -1, -1, true);
   1554             ATRACE_END();
   1555         }
   1556 
   1557         ATRACE_BEGIN("quota");
   1558         int64_t dataSize = extStats.dataSize;
   1559         for (auto appId : appIds) {
   1560             if (appId >= AID_APP_START) {
   1561                 collectQuotaStats(device, userId, appId, &stats, &extStats);
   1562 
   1563 #if MEASURE_DEBUG
   1564                 // Sleep to make sure we don't lose logs
   1565                 usleep(1);
   1566 #endif
   1567             }
   1568         }
   1569         extStats.dataSize = dataSize;
   1570         ATRACE_END();
   1571     } else {
   1572         ATRACE_BEGIN("obb");
   1573         auto obbPath = create_data_path(uuid_) + "/media/obb";
   1574         calculate_tree_size(obbPath, &extStats.codeSize);
   1575         ATRACE_END();
   1576 
   1577         ATRACE_BEGIN("code");
   1578         calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize);
   1579         ATRACE_END();
   1580 
   1581         ATRACE_BEGIN("data");
   1582         auto cePath = create_data_user_ce_path(uuid_, userId);
   1583         collectManualStatsForUser(cePath, &stats);
   1584         auto dePath = create_data_user_de_path(uuid_, userId);
   1585         collectManualStatsForUser(dePath, &stats);
   1586         ATRACE_END();
   1587 
   1588         if (!uuid) {
   1589             ATRACE_BEGIN("profile");
   1590             auto userProfilePath = create_primary_cur_profile_dir_path(userId);
   1591             calculate_tree_size(userProfilePath, &stats.dataSize);
   1592             auto refProfilePath = create_primary_ref_profile_dir_path();
   1593             calculate_tree_size(refProfilePath, &stats.codeSize);
   1594             ATRACE_END();
   1595         }
   1596 
   1597         ATRACE_BEGIN("external");
   1598         auto dataMediaPath = create_data_media_path(uuid_, userId);
   1599         collectManualExternalStatsForUser(dataMediaPath, &extStats);
   1600 #if MEASURE_DEBUG
   1601         LOG(DEBUG) << "Measured external data " << extStats.dataSize << " cache "
   1602                 << extStats.cacheSize;
   1603 #endif
   1604         ATRACE_END();
   1605 
   1606         if (!uuid) {
   1607             ATRACE_BEGIN("dalvik");
   1608             calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize);
   1609             calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize);
   1610             ATRACE_END();
   1611         }
   1612     }
   1613 
   1614     std::vector<int64_t> ret;
   1615     ret.push_back(stats.codeSize);
   1616     ret.push_back(stats.dataSize);
   1617     ret.push_back(stats.cacheSize);
   1618     ret.push_back(extStats.codeSize);
   1619     ret.push_back(extStats.dataSize);
   1620     ret.push_back(extStats.cacheSize);
   1621 #if MEASURE_DEBUG
   1622     LOG(DEBUG) << "Final result " << toString(ret);
   1623 #endif
   1624     *_aidl_return = ret;
   1625     return ok();
   1626 }
   1627 
   1628 binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std::string>& uuid,
   1629         int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
   1630         std::vector<int64_t>* _aidl_return) {
   1631     ENFORCE_UID(AID_SYSTEM);
   1632     CHECK_ARGUMENT_UUID(uuid);
   1633     // NOTE: Locking is relaxed on this method, since it's limited to
   1634     // read-only measurements without mutation.
   1635 
   1636     // When modifying this logic, always verify using tests:
   1637     // runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetExternalSize
   1638 
   1639 #if MEASURE_DEBUG
   1640     LOG(INFO) << "Measuring external " << userId;
   1641 #endif
   1642 
   1643     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
   1644 
   1645     int64_t totalSize = 0;
   1646     int64_t audioSize = 0;
   1647     int64_t videoSize = 0;
   1648     int64_t imageSize = 0;
   1649     int64_t appSize = 0;
   1650     int64_t obbSize = 0;
   1651 
   1652     auto device = findQuotaDeviceForUuid(uuid);
   1653     if (device.empty()) {
   1654         flags &= ~FLAG_USE_QUOTA;
   1655     }
   1656 
   1657     if (flags & FLAG_USE_QUOTA) {
   1658         struct dqblk dq;
   1659 
   1660         ATRACE_BEGIN("quota");
   1661         uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
   1662         if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
   1663                 reinterpret_cast<char*>(&dq)) != 0) {
   1664             if (errno != ESRCH) {
   1665                 PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
   1666             }
   1667         } else {
   1668 #if MEASURE_DEBUG
   1669             LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
   1670 #endif
   1671             totalSize = dq.dqb_curspace;
   1672         }
   1673 
   1674         gid_t audioGid = multiuser_get_uid(userId, AID_MEDIA_AUDIO);
   1675         if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), audioGid,
   1676                 reinterpret_cast<char*>(&dq)) == 0) {
   1677 #if MEASURE_DEBUG
   1678             LOG(DEBUG) << "quotactl() for GID " << audioGid << " " << dq.dqb_curspace;
   1679 #endif
   1680             audioSize = dq.dqb_curspace;
   1681         }
   1682         gid_t videoGid = multiuser_get_uid(userId, AID_MEDIA_VIDEO);
   1683         if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), videoGid,
   1684                 reinterpret_cast<char*>(&dq)) == 0) {
   1685 #if MEASURE_DEBUG
   1686             LOG(DEBUG) << "quotactl() for GID " << videoGid << " " << dq.dqb_curspace;
   1687 #endif
   1688             videoSize = dq.dqb_curspace;
   1689         }
   1690         gid_t imageGid = multiuser_get_uid(userId, AID_MEDIA_IMAGE);
   1691         if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), imageGid,
   1692                 reinterpret_cast<char*>(&dq)) == 0) {
   1693 #if MEASURE_DEBUG
   1694             LOG(DEBUG) << "quotactl() for GID " << imageGid << " " << dq.dqb_curspace;
   1695 #endif
   1696             imageSize = dq.dqb_curspace;
   1697         }
   1698         if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), AID_MEDIA_OBB,
   1699                 reinterpret_cast<char*>(&dq)) == 0) {
   1700 #if MEASURE_DEBUG
   1701             LOG(DEBUG) << "quotactl() for GID " << AID_MEDIA_OBB << " " << dq.dqb_curspace;
   1702 #endif
   1703             obbSize = dq.dqb_curspace;
   1704         }
   1705         ATRACE_END();
   1706 
   1707         ATRACE_BEGIN("apps");
   1708         struct stats extStats;
   1709         memset(&extStats, 0, sizeof(extStats));
   1710         for (auto appId : appIds) {
   1711             if (appId >= AID_APP_START) {
   1712                 collectQuotaStats(device, userId, appId, nullptr, &extStats);
   1713             }
   1714         }
   1715         appSize = extStats.dataSize;
   1716         ATRACE_END();
   1717     } else {
   1718         ATRACE_BEGIN("manual");
   1719         FTS *fts;
   1720         FTSENT *p;
   1721         auto path = create_data_media_path(uuid_, userId);
   1722         char *argv[] = { (char*) path.c_str(), nullptr };
   1723         if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
   1724             return error("Failed to fts_open " + path);
   1725         }
   1726         while ((p = fts_read(fts)) != NULL) {
   1727             char* ext;
   1728             int64_t size = (p->fts_statp->st_blocks * 512);
   1729             switch (p->fts_info) {
   1730             case FTS_F:
   1731                 // Only categorize files not belonging to apps
   1732                 if (p->fts_parent->fts_number == 0) {
   1733                     ext = strrchr(p->fts_name, '.');
   1734                     if (ext != nullptr) {
   1735                         switch (MatchExtension(++ext)) {
   1736                         case AID_MEDIA_AUDIO: audioSize += size; break;
   1737                         case AID_MEDIA_VIDEO: videoSize += size; break;
   1738                         case AID_MEDIA_IMAGE: imageSize += size; break;
   1739                         }
   1740                     }
   1741                 }
   1742                 // Fall through to always count against total
   1743             case FTS_D:
   1744                 // Ignore data belonging to specific apps
   1745                 p->fts_number = p->fts_parent->fts_number;
   1746                 if (p->fts_level == 1 && !strcmp(p->fts_name, "Android")) {
   1747                     p->fts_number = 1;
   1748                 }
   1749             case FTS_DEFAULT:
   1750             case FTS_SL:
   1751             case FTS_SLNONE:
   1752                 if (p->fts_parent->fts_number == 1) {
   1753                     appSize += size;
   1754                 }
   1755                 totalSize += size;
   1756                 break;
   1757             }
   1758         }
   1759         fts_close(fts);
   1760         ATRACE_END();
   1761 
   1762         ATRACE_BEGIN("obb");
   1763         auto obbPath = create_data_media_obb_path(uuid_, "");
   1764         calculate_tree_size(obbPath, &obbSize);
   1765         ATRACE_END();
   1766     }
   1767 
   1768     std::vector<int64_t> ret;
   1769     ret.push_back(totalSize);
   1770     ret.push_back(audioSize);
   1771     ret.push_back(videoSize);
   1772     ret.push_back(imageSize);
   1773     ret.push_back(appSize);
   1774     ret.push_back(obbSize);
   1775 #if MEASURE_DEBUG
   1776     LOG(DEBUG) << "Final result " << toString(ret);
   1777 #endif
   1778     *_aidl_return = ret;
   1779     return ok();
   1780 }
   1781 
   1782 binder::Status InstalldNativeService::setAppQuota(const std::unique_ptr<std::string>& uuid,
   1783         int32_t userId, int32_t appId, int64_t cacheQuota) {
   1784     ENFORCE_UID(AID_SYSTEM);
   1785     CHECK_ARGUMENT_UUID(uuid);
   1786     std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
   1787 
   1788     int32_t uid = multiuser_get_uid(userId, appId);
   1789     mCacheQuotas[uid] = cacheQuota;
   1790 
   1791     return ok();
   1792 }
   1793 
   1794 // Dumps the contents of a profile file, using pkgname's dex files for pretty
   1795 // printing the result.
   1796 binder::Status InstalldNativeService::dumpProfiles(int32_t uid, const std::string& packageName,
   1797         const std::string& codePaths, bool* _aidl_return) {
   1798     ENFORCE_UID(AID_SYSTEM);
   1799     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
   1800     std::lock_guard<std::recursive_mutex> lock(mLock);
   1801 
   1802     const char* pkgname = packageName.c_str();
   1803     const char* code_paths = codePaths.c_str();
   1804 
   1805     *_aidl_return = dump_profiles(uid, pkgname, code_paths);
   1806     return ok();
   1807 }
   1808 
   1809 // Copy the contents of a system profile over the data profile.
   1810 binder::Status InstalldNativeService::copySystemProfile(const std::string& systemProfile,
   1811         int32_t packageUid, const std::string& packageName, bool* _aidl_return) {
   1812     ENFORCE_UID(AID_SYSTEM);
   1813     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
   1814     std::lock_guard<std::recursive_mutex> lock(mLock);
   1815     *_aidl_return = copy_system_profile(systemProfile, packageUid, packageName);
   1816     return ok();
   1817 }
   1818 
   1819 // TODO: Consider returning error codes.
   1820 binder::Status InstalldNativeService::mergeProfiles(int32_t uid, const std::string& packageName,
   1821         bool* _aidl_return) {
   1822     ENFORCE_UID(AID_SYSTEM);
   1823     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
   1824     std::lock_guard<std::recursive_mutex> lock(mLock);
   1825 
   1826     *_aidl_return = analyze_primary_profiles(uid, packageName);
   1827     return ok();
   1828 }
   1829 
   1830 binder::Status InstalldNativeService::dexopt(const std::string& apkPath, int32_t uid,
   1831         const std::unique_ptr<std::string>& packageName, const std::string& instructionSet,
   1832         int32_t dexoptNeeded, const std::unique_ptr<std::string>& outputPath, int32_t dexFlags,
   1833         const std::string& compilerFilter, const std::unique_ptr<std::string>& uuid,
   1834         const std::unique_ptr<std::string>& classLoaderContext,
   1835         const std::unique_ptr<std::string>& seInfo, bool downgrade) {
   1836     ENFORCE_UID(AID_SYSTEM);
   1837     CHECK_ARGUMENT_UUID(uuid);
   1838     if (packageName && *packageName != "*") {
   1839         CHECK_ARGUMENT_PACKAGE_NAME(*packageName);
   1840     }
   1841     std::lock_guard<std::recursive_mutex> lock(mLock);
   1842 
   1843     const char* apk_path = apkPath.c_str();
   1844     const char* pkgname = packageName ? packageName->c_str() : "*";
   1845     const char* instruction_set = instructionSet.c_str();
   1846     const char* oat_dir = outputPath ? outputPath->c_str() : nullptr;
   1847     const char* compiler_filter = compilerFilter.c_str();
   1848     const char* volume_uuid = uuid ? uuid->c_str() : nullptr;
   1849     const char* class_loader_context = classLoaderContext ? classLoaderContext->c_str() : nullptr;
   1850     const char* se_info = seInfo ? seInfo->c_str() : nullptr;
   1851     int res = android::installd::dexopt(apk_path, uid, pkgname, instruction_set, dexoptNeeded,
   1852             oat_dir, dexFlags, compiler_filter, volume_uuid, class_loader_context, se_info,
   1853             downgrade);
   1854     return res ? error(res, "Failed to dexopt") : ok();
   1855 }
   1856 
   1857 binder::Status InstalldNativeService::markBootComplete(const std::string& instructionSet) {
   1858     ENFORCE_UID(AID_SYSTEM);
   1859     std::lock_guard<std::recursive_mutex> lock(mLock);
   1860 
   1861     const char* instruction_set = instructionSet.c_str();
   1862 
   1863     char boot_marker_path[PKG_PATH_MAX];
   1864     sprintf(boot_marker_path,
   1865           "%s/%s/%s/.booting",
   1866           android_data_dir.path,
   1867           DALVIK_CACHE,
   1868           instruction_set);
   1869 
   1870     ALOGV("mark_boot_complete : %s", boot_marker_path);
   1871     if (unlink(boot_marker_path) != 0) {
   1872         return error(StringPrintf("Failed to unlink %s", boot_marker_path));
   1873     }
   1874     return ok();
   1875 }
   1876 
   1877 void mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid,
   1878         struct stat* statbuf)
   1879 {
   1880     while (path[basepos] != 0) {
   1881         if (path[basepos] == '/') {
   1882             path[basepos] = 0;
   1883             if (lstat(path, statbuf) < 0) {
   1884                 ALOGV("Making directory: %s\n", path);
   1885                 if (mkdir(path, mode) == 0) {
   1886                     chown(path, uid, gid);
   1887                 } else {
   1888                     ALOGW("Unable to make directory %s: %s\n", path, strerror(errno));
   1889                 }
   1890             }
   1891             path[basepos] = '/';
   1892             basepos++;
   1893         }
   1894         basepos++;
   1895     }
   1896 }
   1897 
   1898 binder::Status InstalldNativeService::linkNativeLibraryDirectory(
   1899         const std::unique_ptr<std::string>& uuid, const std::string& packageName,
   1900         const std::string& nativeLibPath32, int32_t userId) {
   1901     ENFORCE_UID(AID_SYSTEM);
   1902     CHECK_ARGUMENT_UUID(uuid);
   1903     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
   1904     std::lock_guard<std::recursive_mutex> lock(mLock);
   1905 
   1906     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
   1907     const char* pkgname = packageName.c_str();
   1908     const char* asecLibDir = nativeLibPath32.c_str();
   1909     struct stat s, libStat;
   1910     binder::Status res = ok();
   1911 
   1912     auto _pkgdir = create_data_user_ce_package_path(uuid_, userId, pkgname);
   1913     auto _libsymlink = _pkgdir + PKG_LIB_POSTFIX;
   1914 
   1915     const char* pkgdir = _pkgdir.c_str();
   1916     const char* libsymlink = _libsymlink.c_str();
   1917 
   1918     if (stat(pkgdir, &s) < 0) {
   1919         return error("Failed to stat " + _pkgdir);
   1920     }
   1921 
   1922     if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) {
   1923         return error("Failed to chown " + _pkgdir);
   1924     }
   1925 
   1926     if (chmod(pkgdir, 0700) < 0) {
   1927         res = error("Failed to chmod " + _pkgdir);
   1928         goto out;
   1929     }
   1930 
   1931     if (lstat(libsymlink, &libStat) < 0) {
   1932         if (errno != ENOENT) {
   1933             res = error("Failed to stat " + _libsymlink);
   1934             goto out;
   1935         }
   1936     } else {
   1937         if (S_ISDIR(libStat.st_mode)) {
   1938             if (delete_dir_contents(libsymlink, 1, NULL) < 0) {
   1939                 res = error("Failed to delete " + _libsymlink);
   1940                 goto out;
   1941             }
   1942         } else if (S_ISLNK(libStat.st_mode)) {
   1943             if (unlink(libsymlink) < 0) {
   1944                 res = error("Failed to unlink " + _libsymlink);
   1945                 goto out;
   1946             }
   1947         }
   1948     }
   1949 
   1950     if (symlink(asecLibDir, libsymlink) < 0) {
   1951         res = error("Failed to symlink " + _libsymlink + " to " + nativeLibPath32);
   1952         goto out;
   1953     }
   1954 
   1955 out:
   1956     if (chmod(pkgdir, s.st_mode) < 0) {
   1957         auto msg = "Failed to cleanup chmod " + _pkgdir;
   1958         if (res.isOk()) {
   1959             res = error(msg);
   1960         } else {
   1961             PLOG(ERROR) << msg;
   1962         }
   1963     }
   1964 
   1965     if (chown(pkgdir, s.st_uid, s.st_gid) < 0) {
   1966         auto msg = "Failed to cleanup chown " + _pkgdir;
   1967         if (res.isOk()) {
   1968             res = error(msg);
   1969         } else {
   1970             PLOG(ERROR) << msg;
   1971         }
   1972     }
   1973 
   1974     return res;
   1975 }
   1976 
   1977 static void run_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd)
   1978 {
   1979     execl(kIdMapPath, kIdMapPath, "--fd", target_apk, overlay_apk,
   1980             StringPrintf("%d", idmap_fd).c_str(), (char*)NULL);
   1981     PLOG(ERROR) << "execl (" << kIdMapPath << ") failed";
   1982 }
   1983 
   1984 static void run_verify_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd)
   1985 {
   1986     execl(kIdMapPath, kIdMapPath, "--verify", target_apk, overlay_apk,
   1987             StringPrintf("%d", idmap_fd).c_str(), (char*)NULL);
   1988     PLOG(ERROR) << "execl (" << kIdMapPath << ") failed";
   1989 }
   1990 
   1991 static bool delete_stale_idmap(const char* target_apk, const char* overlay_apk,
   1992         const char* idmap_path, int32_t uid) {
   1993     int idmap_fd = open(idmap_path, O_RDWR);
   1994     if (idmap_fd < 0) {
   1995         PLOG(ERROR) << "idmap open failed: " << idmap_path;
   1996         unlink(idmap_path);
   1997         return true;
   1998     }
   1999 
   2000     pid_t pid;
   2001     pid = fork();
   2002     if (pid == 0) {
   2003         /* child -- drop privileges before continuing */
   2004         if (setgid(uid) != 0) {
   2005             LOG(ERROR) << "setgid(" << uid << ") failed during idmap";
   2006             exit(1);
   2007         }
   2008         if (setuid(uid) != 0) {
   2009             LOG(ERROR) << "setuid(" << uid << ") failed during idmap";
   2010             exit(1);
   2011         }
   2012         if (flock(idmap_fd, LOCK_EX | LOCK_NB) != 0) {
   2013             PLOG(ERROR) << "flock(" << idmap_path << ") failed during idmap";
   2014             exit(1);
   2015         }
   2016 
   2017         run_verify_idmap(target_apk, overlay_apk, idmap_fd);
   2018         exit(1); /* only if exec call to deleting stale idmap failed */
   2019     } else {
   2020         int status = wait_child(pid);
   2021         close(idmap_fd);
   2022 
   2023         if (status != 0) {
   2024             // Failed on verifying if idmap is made from target_apk and overlay_apk.
   2025             LOG(DEBUG) << "delete stale idmap: " << idmap_path;
   2026             unlink(idmap_path);
   2027             return true;
   2028         }
   2029     }
   2030     return false;
   2031 }
   2032 
   2033 // Transform string /a/b/c.apk to (prefix)/a@b (at) c.apk@(suffix)
   2034 // eg /a/b/c.apk to /data/resource-cache/a@b (at) c.apk@idmap
   2035 static int flatten_path(const char *prefix, const char *suffix,
   2036         const char *overlay_path, char *idmap_path, size_t N)
   2037 {
   2038     if (overlay_path == NULL || idmap_path == NULL) {
   2039         return -1;
   2040     }
   2041     const size_t len_overlay_path = strlen(overlay_path);
   2042     // will access overlay_path + 1 further below; requires absolute path
   2043     if (len_overlay_path < 2 || *overlay_path != '/') {
   2044         return -1;
   2045     }
   2046     const size_t len_idmap_root = strlen(prefix);
   2047     const size_t len_suffix = strlen(suffix);
   2048     if (SIZE_MAX - len_idmap_root < len_overlay_path ||
   2049             SIZE_MAX - (len_idmap_root + len_overlay_path) < len_suffix) {
   2050         // additions below would cause overflow
   2051         return -1;
   2052     }
   2053     if (N < len_idmap_root + len_overlay_path + len_suffix) {
   2054         return -1;
   2055     }
   2056     memset(idmap_path, 0, N);
   2057     snprintf(idmap_path, N, "%s%s%s", prefix, overlay_path + 1, suffix);
   2058     char *ch = idmap_path + len_idmap_root;
   2059     while (*ch != '\0') {
   2060         if (*ch == '/') {
   2061             *ch = '@';
   2062         }
   2063         ++ch;
   2064     }
   2065     return 0;
   2066 }
   2067 
   2068 binder::Status InstalldNativeService::idmap(const std::string& targetApkPath,
   2069         const std::string& overlayApkPath, int32_t uid) {
   2070     ENFORCE_UID(AID_SYSTEM);
   2071     std::lock_guard<std::recursive_mutex> lock(mLock);
   2072 
   2073     const char* target_apk = targetApkPath.c_str();
   2074     const char* overlay_apk = overlayApkPath.c_str();
   2075     ALOGV("idmap target_apk=%s overlay_apk=%s uid=%d\n", target_apk, overlay_apk, uid);
   2076 
   2077     int idmap_fd = -1;
   2078     char idmap_path[PATH_MAX];
   2079     struct stat idmap_stat;
   2080     bool outdated = false;
   2081 
   2082     if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk,
   2083                 idmap_path, sizeof(idmap_path)) == -1) {
   2084         ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk);
   2085         goto fail;
   2086     }
   2087 
   2088     if (stat(idmap_path, &idmap_stat) < 0) {
   2089         outdated = true;
   2090     } else {
   2091         outdated = delete_stale_idmap(target_apk, overlay_apk, idmap_path, uid);
   2092     }
   2093 
   2094     if (outdated) {
   2095         idmap_fd = open(idmap_path, O_RDWR | O_CREAT | O_EXCL, 0644);
   2096     } else {
   2097         idmap_fd = open(idmap_path, O_RDWR);
   2098     }
   2099 
   2100     if (idmap_fd < 0) {
   2101         ALOGE("idmap cannot open '%s' for output: %s\n", idmap_path, strerror(errno));
   2102         goto fail;
   2103     }
   2104     if (fchown(idmap_fd, AID_SYSTEM, uid) < 0) {
   2105         ALOGE("idmap cannot chown '%s'\n", idmap_path);
   2106         goto fail;
   2107     }
   2108     if (fchmod(idmap_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) {
   2109         ALOGE("idmap cannot chmod '%s'\n", idmap_path);
   2110         goto fail;
   2111     }
   2112 
   2113     if (!outdated) {
   2114         close(idmap_fd);
   2115         return ok();
   2116     }
   2117 
   2118     pid_t pid;
   2119     pid = fork();
   2120     if (pid == 0) {
   2121         /* child -- drop privileges before continuing */
   2122         if (setgid(uid) != 0) {
   2123             ALOGE("setgid(%d) failed during idmap\n", uid);
   2124             exit(1);
   2125         }
   2126         if (setuid(uid) != 0) {
   2127             ALOGE("setuid(%d) failed during idmap\n", uid);
   2128             exit(1);
   2129         }
   2130         if (flock(idmap_fd, LOCK_EX | LOCK_NB) != 0) {
   2131             ALOGE("flock(%s) failed during idmap: %s\n", idmap_path, strerror(errno));
   2132             exit(1);
   2133         }
   2134 
   2135         run_idmap(target_apk, overlay_apk, idmap_fd);
   2136         exit(1); /* only if exec call to idmap failed */
   2137     } else {
   2138         int status = wait_child(pid);
   2139         if (status != 0) {
   2140             ALOGE("idmap failed, status=0x%04x\n", status);
   2141             goto fail;
   2142         }
   2143     }
   2144 
   2145     close(idmap_fd);
   2146     return ok();
   2147 fail:
   2148     if (idmap_fd >= 0) {
   2149         close(idmap_fd);
   2150         unlink(idmap_path);
   2151     }
   2152     return error();
   2153 }
   2154 
   2155 binder::Status InstalldNativeService::removeIdmap(const std::string& overlayApkPath) {
   2156     const char* overlay_apk = overlayApkPath.c_str();
   2157     char idmap_path[PATH_MAX];
   2158 
   2159     if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk,
   2160                 idmap_path, sizeof(idmap_path)) == -1) {
   2161         ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk);
   2162         return error();
   2163     }
   2164     if (unlink(idmap_path) < 0) {
   2165         ALOGE("couldn't unlink idmap file %s\n", idmap_path);
   2166         return error();
   2167     }
   2168     return ok();
   2169 }
   2170 
   2171 binder::Status InstalldNativeService::restoreconAppData(const std::unique_ptr<std::string>& uuid,
   2172         const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
   2173         const std::string& seInfo) {
   2174     ENFORCE_UID(AID_SYSTEM);
   2175     CHECK_ARGUMENT_UUID(uuid);
   2176     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
   2177     std::lock_guard<std::recursive_mutex> lock(mLock);
   2178 
   2179     binder::Status res = ok();
   2180 
   2181     // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here.
   2182     unsigned int seflags = SELINUX_ANDROID_RESTORECON_RECURSE;
   2183     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
   2184     const char* pkgName = packageName.c_str();
   2185     const char* seinfo = seInfo.c_str();
   2186 
   2187     uid_t uid = multiuser_get_uid(userId, appId);
   2188     if (flags & FLAG_STORAGE_CE) {
   2189         auto path = create_data_user_ce_package_path(uuid_, userId, pkgName);
   2190         if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, seflags) < 0) {
   2191             res = error("restorecon failed for " + path);
   2192         }
   2193     }
   2194     if (flags & FLAG_STORAGE_DE) {
   2195         auto path = create_data_user_de_package_path(uuid_, userId, pkgName);
   2196         if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, seflags) < 0) {
   2197             res = error("restorecon failed for " + path);
   2198         }
   2199     }
   2200     return res;
   2201 }
   2202 
   2203 binder::Status InstalldNativeService::createOatDir(const std::string& oatDir,
   2204         const std::string& instructionSet) {
   2205     ENFORCE_UID(AID_SYSTEM);
   2206     std::lock_guard<std::recursive_mutex> lock(mLock);
   2207 
   2208     const char* oat_dir = oatDir.c_str();
   2209     const char* instruction_set = instructionSet.c_str();
   2210     char oat_instr_dir[PKG_PATH_MAX];
   2211 
   2212     if (validate_apk_path(oat_dir)) {
   2213         return error("Invalid path " + oatDir);
   2214     }
   2215     if (fs_prepare_dir(oat_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) {
   2216         return error("Failed to prepare " + oatDir);
   2217     }
   2218     if (selinux_android_restorecon(oat_dir, 0)) {
   2219         return error("Failed to restorecon " + oatDir);
   2220     }
   2221     snprintf(oat_instr_dir, PKG_PATH_MAX, "%s/%s", oat_dir, instruction_set);
   2222     if (fs_prepare_dir(oat_instr_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) {
   2223         return error(StringPrintf("Failed to prepare %s", oat_instr_dir));
   2224     }
   2225     return ok();
   2226 }
   2227 
   2228 binder::Status InstalldNativeService::rmPackageDir(const std::string& packageDir) {
   2229     ENFORCE_UID(AID_SYSTEM);
   2230     std::lock_guard<std::recursive_mutex> lock(mLock);
   2231 
   2232     if (validate_apk_path(packageDir.c_str())) {
   2233         return error("Invalid path " + packageDir);
   2234     }
   2235     if (delete_dir_contents_and_dir(packageDir) != 0) {
   2236         return error("Failed to delete " + packageDir);
   2237     }
   2238     return ok();
   2239 }
   2240 
   2241 binder::Status InstalldNativeService::linkFile(const std::string& relativePath,
   2242         const std::string& fromBase, const std::string& toBase) {
   2243     ENFORCE_UID(AID_SYSTEM);
   2244     std::lock_guard<std::recursive_mutex> lock(mLock);
   2245 
   2246     const char* relative_path = relativePath.c_str();
   2247     const char* from_base = fromBase.c_str();
   2248     const char* to_base = toBase.c_str();
   2249     char from_path[PKG_PATH_MAX];
   2250     char to_path[PKG_PATH_MAX];
   2251     snprintf(from_path, PKG_PATH_MAX, "%s/%s", from_base, relative_path);
   2252     snprintf(to_path, PKG_PATH_MAX, "%s/%s", to_base, relative_path);
   2253 
   2254     if (validate_apk_path_subdirs(from_path)) {
   2255         return error(StringPrintf("Invalid from path %s", from_path));
   2256     }
   2257 
   2258     if (validate_apk_path_subdirs(to_path)) {
   2259         return error(StringPrintf("Invalid to path %s", to_path));
   2260     }
   2261 
   2262     if (link(from_path, to_path) < 0) {
   2263         return error(StringPrintf("Failed to link from %s to %s", from_path, to_path));
   2264     }
   2265 
   2266     return ok();
   2267 }
   2268 
   2269 binder::Status InstalldNativeService::moveAb(const std::string& apkPath,
   2270         const std::string& instructionSet, const std::string& outputPath) {
   2271     ENFORCE_UID(AID_SYSTEM);
   2272     std::lock_guard<std::recursive_mutex> lock(mLock);
   2273 
   2274     const char* apk_path = apkPath.c_str();
   2275     const char* instruction_set = instructionSet.c_str();
   2276     const char* oat_dir = outputPath.c_str();
   2277 
   2278     bool success = move_ab(apk_path, instruction_set, oat_dir);
   2279     return success ? ok() : error();
   2280 }
   2281 
   2282 binder::Status InstalldNativeService::deleteOdex(const std::string& apkPath,
   2283         const std::string& instructionSet, const std::unique_ptr<std::string>& outputPath) {
   2284     ENFORCE_UID(AID_SYSTEM);
   2285     std::lock_guard<std::recursive_mutex> lock(mLock);
   2286 
   2287     const char* apk_path = apkPath.c_str();
   2288     const char* instruction_set = instructionSet.c_str();
   2289     const char* oat_dir = outputPath ? outputPath->c_str() : nullptr;
   2290 
   2291     bool res = delete_odex(apk_path, instruction_set, oat_dir);
   2292     return res ? ok() : error();
   2293 }
   2294 
   2295 binder::Status InstalldNativeService::reconcileSecondaryDexFile(
   2296         const std::string& dexPath, const std::string& packageName, int32_t uid,
   2297         const std::vector<std::string>& isas, const std::unique_ptr<std::string>& volumeUuid,
   2298         int32_t storage_flag, bool* _aidl_return) {
   2299     ENFORCE_UID(AID_SYSTEM);
   2300     CHECK_ARGUMENT_UUID(volumeUuid);
   2301     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
   2302 
   2303     std::lock_guard<std::recursive_mutex> lock(mLock);
   2304     bool result = android::installd::reconcile_secondary_dex_file(
   2305             dexPath, packageName, uid, isas, volumeUuid, storage_flag, _aidl_return);
   2306     return result ? ok() : error();
   2307 }
   2308 
   2309 binder::Status InstalldNativeService::invalidateMounts() {
   2310     ENFORCE_UID(AID_SYSTEM);
   2311     std::lock_guard<std::recursive_mutex> lock(mMountsLock);
   2312 
   2313     mStorageMounts.clear();
   2314     mQuotaReverseMounts.clear();
   2315 
   2316     std::ifstream in("/proc/mounts");
   2317     if (!in.is_open()) {
   2318         return error("Failed to read mounts");
   2319     }
   2320 
   2321     std::string source;
   2322     std::string target;
   2323     std::string ignored;
   2324     while (!in.eof()) {
   2325         std::getline(in, source, ' ');
   2326         std::getline(in, target, ' ');
   2327         std::getline(in, ignored);
   2328 
   2329 #if !BYPASS_SDCARDFS
   2330         if (target.compare(0, 21, "/mnt/runtime/default/") == 0) {
   2331             LOG(DEBUG) << "Found storage mount " << source << " at " << target;
   2332             mStorageMounts[source] = target;
   2333         }
   2334 #endif
   2335 
   2336 #if !BYPASS_QUOTA
   2337         if (source.compare(0, 11, "/dev/block/") == 0) {
   2338             struct dqblk dq;
   2339             if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0,
   2340                     reinterpret_cast<char*>(&dq)) == 0) {
   2341                 LOG(DEBUG) << "Found quota mount " << source << " at " << target;
   2342                 mQuotaReverseMounts[target] = source;
   2343 
   2344                 // ext4 only enables DQUOT_USAGE_ENABLED by default, so we
   2345                 // need to kick it again to enable DQUOT_LIMITS_ENABLED.
   2346                 if (quotactl(QCMD(Q_QUOTAON, USRQUOTA), source.c_str(), QFMT_VFS_V1, nullptr) != 0
   2347                         && errno != EBUSY) {
   2348                     PLOG(ERROR) << "Failed to enable USRQUOTA on " << source;
   2349                 }
   2350                 if (quotactl(QCMD(Q_QUOTAON, GRPQUOTA), source.c_str(), QFMT_VFS_V1, nullptr) != 0
   2351                         && errno != EBUSY) {
   2352                     PLOG(ERROR) << "Failed to enable GRPQUOTA on " << source;
   2353                 }
   2354             }
   2355         }
   2356 #endif
   2357     }
   2358     return ok();
   2359 }
   2360 
   2361 std::string InstalldNativeService::findDataMediaPath(
   2362         const std::unique_ptr<std::string>& uuid, userid_t userid) {
   2363     std::lock_guard<std::recursive_mutex> lock(mMountsLock);
   2364     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
   2365     auto path = StringPrintf("%s/media", create_data_path(uuid_).c_str());
   2366     auto resolved = mStorageMounts[path];
   2367     if (resolved.empty()) {
   2368         LOG(WARNING) << "Failed to find storage mount for " << path;
   2369         resolved = path;
   2370     }
   2371     return StringPrintf("%s/%u", resolved.c_str(), userid);
   2372 }
   2373 
   2374 std::string InstalldNativeService::findQuotaDeviceForUuid(
   2375         const std::unique_ptr<std::string>& uuid) {
   2376     std::lock_guard<std::recursive_mutex> lock(mMountsLock);
   2377     auto path = create_data_path(uuid ? uuid->c_str() : nullptr);
   2378     return mQuotaReverseMounts[path];
   2379 }
   2380 
   2381 binder::Status InstalldNativeService::isQuotaSupported(
   2382         const std::unique_ptr<std::string>& volumeUuid, bool* _aidl_return) {
   2383     *_aidl_return = !findQuotaDeviceForUuid(volumeUuid).empty();
   2384     return ok();
   2385 }
   2386 
   2387 }  // namespace installd
   2388 }  // namespace android
   2389