InstalldNativeService.cpp revision e12d5964a8d14abe7f2eb6e57469cbe7f7391a19
15778822d86b0337407514b9372562b86edfa91cdAndreas Huber/* 25778822d86b0337407514b9372562b86edfa91cdAndreas Huber** Copyright 2008, The Android Open Source Project 35778822d86b0337407514b9372562b86edfa91cdAndreas Huber** 45778822d86b0337407514b9372562b86edfa91cdAndreas Huber** Licensed under the Apache License, Version 2.0 (the "License"); 55778822d86b0337407514b9372562b86edfa91cdAndreas Huber** you may not use this file except in compliance with the License. 65778822d86b0337407514b9372562b86edfa91cdAndreas Huber** You may obtain a copy of the License at 75778822d86b0337407514b9372562b86edfa91cdAndreas Huber** 85778822d86b0337407514b9372562b86edfa91cdAndreas Huber** http://www.apache.org/licenses/LICENSE-2.0 95778822d86b0337407514b9372562b86edfa91cdAndreas Huber** 105778822d86b0337407514b9372562b86edfa91cdAndreas Huber** Unless required by applicable law or agreed to in writing, software 115778822d86b0337407514b9372562b86edfa91cdAndreas Huber** distributed under the License is distributed on an "AS IS" BASIS, 125778822d86b0337407514b9372562b86edfa91cdAndreas Huber** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135778822d86b0337407514b9372562b86edfa91cdAndreas Huber** See the License for the specific language governing permissions and 145778822d86b0337407514b9372562b86edfa91cdAndreas Huber** limitations under the License. 155778822d86b0337407514b9372562b86edfa91cdAndreas Huber*/ 165778822d86b0337407514b9372562b86edfa91cdAndreas Huber 175778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include "InstalldNativeService.h" 185778822d86b0337407514b9372562b86edfa91cdAndreas Huber 19fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER 205778822d86b0337407514b9372562b86edfa91cdAndreas Huber 212606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include <errno.h> 225778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <inttypes.h> 235778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <fstream> 242606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include <fts.h> 252606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include <regex> 261a2952aee048ca7b1765e2bc09ebe9aeddaeafa3Mathias Agopian#include <stdlib.h> 27ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber#include <string.h> 285778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <sys/capability.h> 295778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <sys/file.h> 305778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <sys/resource.h> 315b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber#include <sys/quota.h> 32ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber#include <sys/stat.h> 335778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <sys/statvfs.h> 347cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden#include <sys/types.h> 352606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include <sys/wait.h> 366f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen#include <sys/xattr.h> 37e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber#include <unistd.h> 385778822d86b0337407514b9372562b86edfa91cdAndreas Huber 395778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <android-base/logging.h> 405778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <android-base/stringprintf.h> 412606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include <android-base/strings.h> 422606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include <android-base/unique_fd.h> 432606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include <cutils/fs.h> 44e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber#include <cutils/properties.h> 455778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <cutils/sched_policy.h> 465778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <log/log.h> // TODO: Move everything to base/logging. 472606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include <logwrap/logwrap.h> 482606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include <private/android_filesystem_config.h> 492606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include <selinux/android.h> 502606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include <system/thread_defs.h> 512606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include <utils/Trace.h> 522606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang 532606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include "dexopt.h" 542606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include "globals.h" 552606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include "installd_deps.h" 562606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include "otapreopt_utils.h" 572606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include "utils.h" 582606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang 592606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include "CacheTracker.h" 602606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#include "MatchExtensionGen.h" 612606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang 622606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#ifndef LOG_TAG 632606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#define LOG_TAG "installd" 642606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang#endif 652606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang 662606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangusing android::base::StringPrintf; 672606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangusing std::endl; 682606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang 692606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangnamespace android { 702606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangnamespace installd { 712606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang 722606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic constexpr const char* kCpPath = "/system/bin/cp"; 732606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic constexpr const char* kXattrDefault = "user.default"; 742606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang 752606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic constexpr const int MIN_RESTRICTED_HOME_SDK_VERSION = 24; // > M 762606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang 772606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic constexpr const char* PKG_LIB_POSTFIX = "/lib"; 782606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic constexpr const char* CACHE_DIR_POSTFIX = "/cache"; 792606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic constexpr const char* CODE_CACHE_DIR_POSTFIX = "/code_cache"; 802606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang 812606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic constexpr const char* IDMAP_PREFIX = "/data/resource-cache/"; 822606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic constexpr const char* IDMAP_SUFFIX = "@idmap"; 832606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang 842606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang// NOTE: keep in sync with Installer 852606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic constexpr int FLAG_CLEAR_CACHE_ONLY = 1 << 8; 862606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic constexpr int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9; 872606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic constexpr int FLAG_USE_QUOTA = 1 << 12; 882606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic constexpr int FLAG_FREE_CACHE_V2 = 1 << 13; 892606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic constexpr int FLAG_FREE_CACHE_V2_DEFY_QUOTA = 1 << 14; 902606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic constexpr int FLAG_FREE_CACHE_NOOP = 1 << 15; 912606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic constexpr int FLAG_FORCE = 1 << 16; 922606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang 932606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangnamespace { 942606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang 952606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangconstexpr const char* kDump = "android.permission.DUMP"; 962606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang 972606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic binder::Status ok() { 982606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang return binder::Status::ok(); 992606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang} 1002606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang 1012606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic binder::Status exception(uint32_t code, const std::string& msg) { 1022606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang return binder::Status::fromExceptionCode(code, String8(msg.c_str())); 1032606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang} 1042606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang 1052606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic binder::Status error() { 1062606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang return binder::Status::fromServiceSpecificError(errno); 1072606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang} 1082606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang 1092606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhangstatic binder::Status error(const std::string& msg) { 1102606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang PLOG(ERROR) << msg; 1112606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang return binder::Status::fromServiceSpecificError(errno, String8(msg.c_str())); 1122606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang} 1132606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang 1145778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatic binder::Status error(uint32_t code, const std::string& msg) { 1155778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(ERROR) << msg << " (" << code << ")"; 116251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung return binder::Status::fromServiceSpecificError(code, String8(msg.c_str())); 1175778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 1185778822d86b0337407514b9372562b86edfa91cdAndreas Huber 119251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hungbinder::Status checkPermission(const char* permission) { 120251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung pid_t pid; 121251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung uid_t uid; 122251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung 123251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung if (checkCallingPermission(String16(permission), reinterpret_cast<int32_t*>(&pid), 1245778822d86b0337407514b9372562b86edfa91cdAndreas Huber reinterpret_cast<int32_t*>(&uid))) { 1255778822d86b0337407514b9372562b86edfa91cdAndreas Huber return ok(); 1265778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 1275778822d86b0337407514b9372562b86edfa91cdAndreas Huber return exception(binder::Status::EX_SECURITY, 128251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, permission)); 1295778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 1305778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 131251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung 132251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hungbinder::Status checkUid(uid_t expectedUid) { 133251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung uid_t uid = IPCThreadState::self()->getCallingUid(); 134251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung if (uid == expectedUid || uid == AID_ROOT) { 135251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung return ok(); 1365778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 1375778822d86b0337407514b9372562b86edfa91cdAndreas Huber return exception(binder::Status::EX_SECURITY, 1385778822d86b0337407514b9372562b86edfa91cdAndreas Huber StringPrintf("UID %d is not expected UID %d", uid, expectedUid)); 1395778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 1405778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 14192cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar 1427cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFaddenbinder::Status checkArgumentUuid(const std::unique_ptr<std::string>& uuid) { 1435778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (!uuid || is_valid_filename(*uuid)) { 144251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung return ok(); 1455778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 1462606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang return exception(binder::Status::EX_ILLEGAL_ARGUMENT, 1472606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang StringPrintf("UUID %s is malformed", uuid->c_str())); 1485778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 1495778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 1505778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1516507d14c6d10f93d390de62b9eed267f9b544985Andy McFaddenbinder::Status checkArgumentPackageName(const std::string& packageName) { 1526507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden if (is_valid_package_name(packageName.c_str())) { 1535778822d86b0337407514b9372562b86edfa91cdAndreas Huber return ok(); 1545778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 1555778822d86b0337407514b9372562b86edfa91cdAndreas Huber return exception(binder::Status::EX_ILLEGAL_ARGUMENT, 1565778822d86b0337407514b9372562b86edfa91cdAndreas Huber StringPrintf("Package name %s is malformed", packageName.c_str())); 1575778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 1585778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 1595778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1605778822d86b0337407514b9372562b86edfa91cdAndreas Huber#define ENFORCE_UID(uid) { \ 1615778822d86b0337407514b9372562b86edfa91cdAndreas Huber binder::Status status = checkUid((uid)); \ 1625778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (!status.isOk()) { \ 1635778822d86b0337407514b9372562b86edfa91cdAndreas Huber return status; \ 1645778822d86b0337407514b9372562b86edfa91cdAndreas Huber } \ 1655778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 1665778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1675778822d86b0337407514b9372562b86edfa91cdAndreas Huber#define CHECK_ARGUMENT_UUID(uuid) { \ 1685778822d86b0337407514b9372562b86edfa91cdAndreas Huber binder::Status status = checkArgumentUuid((uuid)); \ 1695778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (!status.isOk()) { \ 1705778822d86b0337407514b9372562b86edfa91cdAndreas Huber return status; \ 1715778822d86b0337407514b9372562b86edfa91cdAndreas Huber } \ 1725778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 1735778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1745778822d86b0337407514b9372562b86edfa91cdAndreas Huber#define CHECK_ARGUMENT_PACKAGE_NAME(packageName) { \ 175c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang binder::Status status = \ 176c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang checkArgumentPackageName((packageName)); \ 177c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang if (!status.isOk()) { \ 178c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang return status; \ 179c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } \ 180c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang} 181c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 182dc9f58dc23a86d0635fd8601d1cbc8d47bab0303Andy Hung} // namespace 183671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar 184671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnarstatus_t InstalldNativeService::start() { 185671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar IPCThreadState::self()->disableBackgroundScheduling(true); 186671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar status_t ret = BinderService<InstalldNativeService>::publish(); 187671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar if (ret != android::OK) { 1885778822d86b0337407514b9372562b86edfa91cdAndreas Huber return ret; 1895778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 1905778822d86b0337407514b9372562b86edfa91cdAndreas Huber sp<ProcessState> ps(ProcessState::self()); 1915778822d86b0337407514b9372562b86edfa91cdAndreas Huber ps->startThreadPool(); 19292cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar ps->giveThreadPoolName(); 1935778822d86b0337407514b9372562b86edfa91cdAndreas Huber return android::OK; 194dc9f58dc23a86d0635fd8601d1cbc8d47bab0303Andy Hung} 1955778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1966f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissenstatus_t InstalldNativeService::dump(int fd, const Vector<String16> & /* args */) { 1976f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen auto out = std::fstream(StringPrintf("/proc/self/fd/%d", fd)); 1986f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen const binder::Status dump_permission = checkPermission(kDump); 1996f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen if (!dump_permission.isOk()) { 2006f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen out << dump_permission.toString8() << endl; 20160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar return PERMISSION_DENIED; 2026f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen } 2036f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen std::lock_guard<std::recursive_mutex> lock(mLock); 20460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar 20560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar out << "installd is happy!" << endl; 20660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar 20760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar { 20860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock); 20960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar out << endl << "Devices with quota support:" << endl; 21060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar for (const auto& n : mQuotaDevices) { 2116f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen out << " " << n.first << " = " << n.second << endl; 2126f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen } 2136f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen } 2145778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2155778822d86b0337407514b9372562b86edfa91cdAndreas Huber { 2165778822d86b0337407514b9372562b86edfa91cdAndreas Huber std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock); 2175778822d86b0337407514b9372562b86edfa91cdAndreas Huber out << endl << "Per-UID cache quotas:" << endl; 2185778822d86b0337407514b9372562b86edfa91cdAndreas Huber for (const auto& n : mCacheQuotas) { 2195778822d86b0337407514b9372562b86edfa91cdAndreas Huber out << " " << n.first << " = " << n.second << endl; 2205778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2215778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2225778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2235778822d86b0337407514b9372562b86edfa91cdAndreas Huber out << endl; 2245778822d86b0337407514b9372562b86edfa91cdAndreas Huber out.flush(); 2255778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2265778822d86b0337407514b9372562b86edfa91cdAndreas Huber return NO_ERROR; 2275778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 2285778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2295778822d86b0337407514b9372562b86edfa91cdAndreas Huber/** 2305778822d86b0337407514b9372562b86edfa91cdAndreas Huber * Perform restorecon of the given path, but only perform recursive restorecon 2315778822d86b0337407514b9372562b86edfa91cdAndreas Huber * if the label of that top-level file actually changed. This can save us 2325778822d86b0337407514b9372562b86edfa91cdAndreas Huber * significant time by avoiding no-op traversals of large filesystem trees. 2335778822d86b0337407514b9372562b86edfa91cdAndreas Huber */ 2345778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatic int restorecon_app_data_lazy(const std::string& path, const std::string& seInfo, uid_t uid, 2355778822d86b0337407514b9372562b86edfa91cdAndreas Huber bool existing) { 2365778822d86b0337407514b9372562b86edfa91cdAndreas Huber int res = 0; 2375778822d86b0337407514b9372562b86edfa91cdAndreas Huber char* before = nullptr; 2385778822d86b0337407514b9372562b86edfa91cdAndreas Huber char* after = nullptr; 2395778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2405778822d86b0337407514b9372562b86edfa91cdAndreas Huber // Note that SELINUX_ANDROID_RESTORECON_DATADATA flag is set by 2415778822d86b0337407514b9372562b86edfa91cdAndreas Huber // libselinux. Not needed here. 2425778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2435778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (lgetfilecon(path.c_str(), &before) < 0) { 244c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang PLOG(ERROR) << "Failed before getfilecon for " << path; 245c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang goto fail; 246c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 247c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid, 0) < 0) { 248c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang PLOG(ERROR) << "Failed top-level restorecon for " << path; 249c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang goto fail; 250c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 251c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang if (lgetfilecon(path.c_str(), &after) < 0) { 2525778822d86b0337407514b9372562b86edfa91cdAndreas Huber PLOG(ERROR) << "Failed after getfilecon for " << path; 2535778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto fail; 2541a2952aee048ca7b1765e2bc09ebe9aeddaeafa3Mathias Agopian } 2551bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber 2565778822d86b0337407514b9372562b86edfa91cdAndreas Huber // If the initial top-level restorecon above changed the label, then go 2575778822d86b0337407514b9372562b86edfa91cdAndreas Huber // back and restorecon everything recursively 2585778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (strcmp(before, after)) { 2595778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (existing) { 2605778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(DEBUG) << "Detected label change from " << before << " to " << after << " at " 2615778822d86b0337407514b9372562b86edfa91cdAndreas Huber << path << "; running recursive restorecon"; 2625778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2631bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid, 2641bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber SELINUX_ANDROID_RESTORECON_RECURSE) < 0) { 2651bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber PLOG(ERROR) << "Failed recursive restorecon for " << path; 2661bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber goto fail; 2671bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber } 2681bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber } 2691bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber 2705778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto done; 2715778822d86b0337407514b9372562b86edfa91cdAndreas Huberfail: 2725778822d86b0337407514b9372562b86edfa91cdAndreas Huber res = -1; 273f64b36deccd473b545dbed22c2feb11fc49157e5Chong Zhangdone: 274f64b36deccd473b545dbed22c2feb11fc49157e5Chong Zhang free(before); 275f64b36deccd473b545dbed22c2feb11fc49157e5Chong Zhang free(after); 276f64b36deccd473b545dbed22c2feb11fc49157e5Chong Zhang return res; 277f64b36deccd473b545dbed22c2feb11fc49157e5Chong Zhang} 278f64b36deccd473b545dbed22c2feb11fc49157e5Chong Zhang 279f64b36deccd473b545dbed22c2feb11fc49157e5Chong Zhangstatic int restorecon_app_data_lazy(const std::string& parent, const char* name, 280f64b36deccd473b545dbed22c2feb11fc49157e5Chong Zhang const std::string& seInfo, uid_t uid, bool existing) { 281f64b36deccd473b545dbed22c2feb11fc49157e5Chong Zhang return restorecon_app_data_lazy(StringPrintf("%s/%s", parent.c_str(), name), seInfo, uid, 282f64b36deccd473b545dbed22c2feb11fc49157e5Chong Zhang existing); 283f64b36deccd473b545dbed22c2feb11fc49157e5Chong Zhang} 284f64b36deccd473b545dbed22c2feb11fc49157e5Chong Zhang 285f64b36deccd473b545dbed22c2feb11fc49157e5Chong Zhangstatic int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid) { 286f64b36deccd473b545dbed22c2feb11fc49157e5Chong Zhang if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) { 2875778822d86b0337407514b9372562b86edfa91cdAndreas Huber PLOG(ERROR) << "Failed to prepare " << path; 2885778822d86b0337407514b9372562b86edfa91cdAndreas Huber return -1; 2897cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 2907cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden return 0; 2917cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden} 2927cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden 2937cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden/** 2947cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden * Ensure that we have a hard-limit quota to protect against abusive apps; 2957cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden * they should never use more than 90% of blocks or 50% of inodes. 2967cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden */ 2977cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFaddenstatic int prepare_app_quota(const std::unique_ptr<std::string>& uuid, const std::string& device, 2987cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden uid_t uid) { 2997cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden if (device.empty()) return 0; 3007cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden 3017cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden struct dqblk dq; 3027cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid, 3037cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden reinterpret_cast<char*>(&dq)) != 0) { 3047cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden PLOG(WARNING) << "Failed to find quota for " << uid; 3057cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden return -1; 3067cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 3077cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden 3087cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden if ((dq.dqb_bhardlimit == 0) || (dq.dqb_ihardlimit == 0)) { 3095778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto path = create_data_path(uuid ? uuid->c_str() : nullptr); 3105778822d86b0337407514b9372562b86edfa91cdAndreas Huber struct statvfs stat; 3115778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (statvfs(path.c_str(), &stat) != 0) { 3125778822d86b0337407514b9372562b86edfa91cdAndreas Huber PLOG(WARNING) << "Failed to statvfs " << path; 3135778822d86b0337407514b9372562b86edfa91cdAndreas Huber return -1; 3145778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3155778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3165778822d86b0337407514b9372562b86edfa91cdAndreas Huber dq.dqb_valid = QIF_LIMITS; 3175778822d86b0337407514b9372562b86edfa91cdAndreas Huber dq.dqb_bhardlimit = (((stat.f_blocks * stat.f_frsize) / 10) * 9) / QIF_DQBLKSIZE; 3185778822d86b0337407514b9372562b86edfa91cdAndreas Huber dq.dqb_ihardlimit = (stat.f_files / 2); 3195778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (quotactl(QCMD(Q_SETQUOTA, USRQUOTA), device.c_str(), uid, 3205778822d86b0337407514b9372562b86edfa91cdAndreas Huber reinterpret_cast<char*>(&dq)) != 0) { 3215778822d86b0337407514b9372562b86edfa91cdAndreas Huber PLOG(WARNING) << "Failed to set hard quota for " << uid; 3225778822d86b0337407514b9372562b86edfa91cdAndreas Huber return -1; 323c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber } else { 324c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber LOG(DEBUG) << "Applied hard quotas for " << uid; 325c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber return 0; 326c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber } 327c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber } else { 328c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber // Hard quota already set; assume it's reasonable 329c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber return 0; 330671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar } 331671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar} 332671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar 333671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnarbinder::Status InstalldNativeService::createAppData(const std::unique_ptr<std::string>& uuid, 334671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar const std::string& packageName, int32_t userId, int32_t flags, int32_t appId, 335671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar const std::string& seInfo, int32_t targetSdkVersion, int64_t* _aidl_return) { 336671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar ENFORCE_UID(AID_SYSTEM); 337671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar CHECK_ARGUMENT_UUID(uuid); 338671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar CHECK_ARGUMENT_PACKAGE_NAME(packageName); 339671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar std::lock_guard<std::recursive_mutex> lock(mLock); 340671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar 341671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar const char* uuid_ = uuid ? uuid->c_str() : nullptr; 342671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar const char* pkgname = packageName.c_str(); 343671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar 344671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar // Assume invalid inode unless filled in below 345671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar if (_aidl_return != nullptr) *_aidl_return = -1; 346671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar 347671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar int32_t uid = multiuser_get_uid(userId, appId); 348671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar int32_t cacheGid = multiuser_get_cache_gid(userId, appId); 349251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung mode_t targetMode = targetSdkVersion >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751; 350671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar 351671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar // If UID doesn't have a specific cache GID, use UID value 352671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar if (cacheGid == -1) { 353671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar cacheGid = uid; 354671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar } 355671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar 356671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar if (flags & FLAG_STORAGE_CE) { 357671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar auto path = create_data_user_ce_package_path(uuid_, userId, pkgname); 358671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar bool existing = (access(path.c_str(), F_OK) == 0); 359671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar 360dc9f58dc23a86d0635fd8601d1cbc8d47bab0303Andy Hung if (prepare_app_dir(path, targetMode, uid) || 361671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid) || 362671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid)) { 363671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar return error("Failed to prepare " + path); 364671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar } 3655778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3665778822d86b0337407514b9372562b86edfa91cdAndreas Huber // Consider restorecon over contents if label changed 3675778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (restorecon_app_data_lazy(path, seInfo, uid, existing) || 3685778822d86b0337407514b9372562b86edfa91cdAndreas Huber restorecon_app_data_lazy(path, "cache", seInfo, uid, existing) || 3695778822d86b0337407514b9372562b86edfa91cdAndreas Huber restorecon_app_data_lazy(path, "code_cache", seInfo, uid, existing)) { 3705b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber return error("Failed to restorecon " + path); 3715b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber } 3725b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber 3735b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber // Remember inode numbers of cache directories so that we can clear 3745b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber // contents while CE storage is locked 3755b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber if (write_path_inode(path, "cache", kXattrInodeCache) || 3765778822d86b0337407514b9372562b86edfa91cdAndreas Huber write_path_inode(path, "code_cache", kXattrInodeCodeCache)) { 3775778822d86b0337407514b9372562b86edfa91cdAndreas Huber return error("Failed to write_path_inode for " + path); 3785778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3795778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3805778822d86b0337407514b9372562b86edfa91cdAndreas Huber // And return the CE inode of the top-level data directory so we can 3815778822d86b0337407514b9372562b86edfa91cdAndreas Huber // clear contents while CE storage is locked 3825b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber if ((_aidl_return != nullptr) 3835778822d86b0337407514b9372562b86edfa91cdAndreas Huber && get_path_inode(path, reinterpret_cast<ino_t*>(_aidl_return)) != 0) { 3845778822d86b0337407514b9372562b86edfa91cdAndreas Huber return error("Failed to get_path_inode for " + path); 3855778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3865778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3875778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (flags & FLAG_STORAGE_DE) { 3884b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber auto path = create_data_user_de_package_path(uuid_, userId, pkgname); 3894b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber bool existing = (access(path.c_str(), F_OK) == 0); 3904b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber 3914b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber if (prepare_app_dir(path, targetMode, uid) || 3924b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid) || 3934b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid)) { 3944b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber return error("Failed to prepare " + path); 3954b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } 3964b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber 3975b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber // Consider restorecon over contents if label changed 3985b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber if (restorecon_app_data_lazy(path, seInfo, uid, existing)) { 3995b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber return error("Failed to restorecon " + path); 4005b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber } 4015b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber 4025b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber if (prepare_app_quota(uuid, findQuotaDeviceForUuid(uuid), uid)) { 4034b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber return error("Failed to set hard quota " + path); 4044b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } 4054b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber 4064b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber if (property_get_bool("dalvik.vm.usejitprofiles", false)) { 4074b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber const std::string profile_dir = 4084b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber create_primary_current_profile_package_dir_path(userId, pkgname); 4094b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber // read-write-execute only for the app user. 4104b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber if (fs_prepare_dir_strict(profile_dir.c_str(), 0700, uid, uid) != 0) { 4114b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber return error("Failed to prepare " + profile_dir); 4124b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } 4135b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber const std::string profile_file = create_current_profile_path(userId, pkgname, 4144b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber /*is_secondary_dex*/false); 4154b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber // read-write only for the app user. 4165b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber if (fs_prepare_file_strict(profile_file.c_str(), 0600, uid, uid) != 0) { 4175b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber return error("Failed to prepare " + profile_file); 4185b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber } 4194b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber const std::string ref_profile_path = 4204b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber create_primary_reference_profile_package_dir_path(pkgname); 4215778822d86b0337407514b9372562b86edfa91cdAndreas Huber // dex2oat/profman runs under the shared app gid and it needs to read/write reference 4225778822d86b0337407514b9372562b86edfa91cdAndreas Huber // profiles. 4235778822d86b0337407514b9372562b86edfa91cdAndreas Huber int shared_app_gid = multiuser_get_shared_gid(0, appId); 4245778822d86b0337407514b9372562b86edfa91cdAndreas Huber if ((shared_app_gid != -1) && fs_prepare_dir_strict( 4255778822d86b0337407514b9372562b86edfa91cdAndreas Huber ref_profile_path.c_str(), 0700, shared_app_gid, shared_app_gid) != 0) { 4265778822d86b0337407514b9372562b86edfa91cdAndreas Huber return error("Failed to prepare " + ref_profile_path); 4275778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4285778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4295778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4305778822d86b0337407514b9372562b86edfa91cdAndreas Huber return ok(); 4315778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 4325778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4335778822d86b0337407514b9372562b86edfa91cdAndreas Huberbinder::Status InstalldNativeService::migrateAppData(const std::unique_ptr<std::string>& uuid, 4345778822d86b0337407514b9372562b86edfa91cdAndreas Huber const std::string& packageName, int32_t userId, int32_t flags) { 4355778822d86b0337407514b9372562b86edfa91cdAndreas Huber ENFORCE_UID(AID_SYSTEM); 4365778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_ARGUMENT_UUID(uuid); 4375778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_ARGUMENT_PACKAGE_NAME(packageName); 4385778822d86b0337407514b9372562b86edfa91cdAndreas Huber std::lock_guard<std::recursive_mutex> lock(mLock); 4395778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4405778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* uuid_ = uuid ? uuid->c_str() : nullptr; 4415778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* pkgname = packageName.c_str(); 4425778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4435778822d86b0337407514b9372562b86edfa91cdAndreas Huber // This method only exists to upgrade system apps that have requested 4445778822d86b0337407514b9372562b86edfa91cdAndreas Huber // forceDeviceEncrypted, so their default storage always lives in a 4455778822d86b0337407514b9372562b86edfa91cdAndreas Huber // consistent location. This only works on non-FBE devices, since we 4465778822d86b0337407514b9372562b86edfa91cdAndreas Huber // never want to risk exposing data on a device with real CE/DE storage. 4475778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4485778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto ce_path = create_data_user_ce_package_path(uuid_, userId, pkgname); 4495778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto de_path = create_data_user_de_package_path(uuid_, userId, pkgname); 4505778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4515778822d86b0337407514b9372562b86edfa91cdAndreas Huber // If neither directory is marked as default, assume CE is default 4525778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (getxattr(ce_path.c_str(), kXattrDefault, nullptr, 0) == -1 4535778822d86b0337407514b9372562b86edfa91cdAndreas Huber && getxattr(de_path.c_str(), kXattrDefault, nullptr, 0) == -1) { 4545778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (setxattr(ce_path.c_str(), kXattrDefault, nullptr, 0, 0) != 0) { 4555778822d86b0337407514b9372562b86edfa91cdAndreas Huber return error("Failed to mark default storage " + ce_path); 4565778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4575778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4585778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4595778822d86b0337407514b9372562b86edfa91cdAndreas Huber // Migrate default data location if needed 4605778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto target = (flags & FLAG_STORAGE_DE) ? de_path : ce_path; 4615778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto source = (flags & FLAG_STORAGE_DE) ? ce_path : de_path; 4625778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4635778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (getxattr(target.c_str(), kXattrDefault, nullptr, 0) == -1) { 4645778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(WARNING) << "Requested default storage " << target 4655778822d86b0337407514b9372562b86edfa91cdAndreas Huber << " is not active; migrating from " << source; 4665778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (delete_dir_contents_and_dir(target) != 0) { 4675778822d86b0337407514b9372562b86edfa91cdAndreas Huber return error("Failed to delete " + target); 4685778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4695778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (rename(source.c_str(), target.c_str()) != 0) { 470fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar return error("Failed to rename " + source + " to " + target); 471fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar } 472fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar } 473fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar 474fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar return ok(); 475fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar} 476fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar 477fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar 478fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnarbinder::Status InstalldNativeService::clearAppProfiles(const std::string& packageName) { 479fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar ENFORCE_UID(AID_SYSTEM); 4805778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_ARGUMENT_PACKAGE_NAME(packageName); 4815778822d86b0337407514b9372562b86edfa91cdAndreas Huber std::lock_guard<std::recursive_mutex> lock(mLock); 4825778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4835778822d86b0337407514b9372562b86edfa91cdAndreas Huber binder::Status res = ok(); 4845778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (!clear_primary_reference_profile(packageName)) { 4855778822d86b0337407514b9372562b86edfa91cdAndreas Huber res = error("Failed to clear reference profile for " + packageName); 4865778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4875778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (!clear_primary_current_profiles(packageName)) { 4887cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden res = error("Failed to clear current profiles for " + packageName); 4897cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 4907cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden return res; 4917cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden} 4927cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden 4937cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFaddenbinder::Status InstalldNativeService::clearAppData(const std::unique_ptr<std::string>& uuid, 4947cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode) { 4955778822d86b0337407514b9372562b86edfa91cdAndreas Huber ENFORCE_UID(AID_SYSTEM); 4965778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_ARGUMENT_UUID(uuid); 4975778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_ARGUMENT_PACKAGE_NAME(packageName); 4985778822d86b0337407514b9372562b86edfa91cdAndreas Huber std::lock_guard<std::recursive_mutex> lock(mLock); 4995778822d86b0337407514b9372562b86edfa91cdAndreas Huber 5005778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* uuid_ = uuid ? uuid->c_str() : nullptr; 5015778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* pkgname = packageName.c_str(); 5025778822d86b0337407514b9372562b86edfa91cdAndreas Huber 5035778822d86b0337407514b9372562b86edfa91cdAndreas Huber binder::Status res = ok(); 5045778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (flags & FLAG_STORAGE_CE) { 5055778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto path = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInode); 5065778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (flags & FLAG_CLEAR_CACHE_ONLY) { 5075778822d86b0337407514b9372562b86edfa91cdAndreas Huber path = read_path_inode(path, "cache", kXattrInodeCache); 5085778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) { 509e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar path = read_path_inode(path, "code_cache", kXattrInodeCodeCache); 510e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar } 511e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar if (access(path.c_str(), F_OK) == 0) { 512e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar if (delete_dir_contents(path) != 0) { 513e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar res = error("Failed to delete contents of " + path); 514e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar } 515e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar } 516e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar } 517e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar if (flags & FLAG_STORAGE_DE) { 518e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar std::string suffix = ""; 519e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar bool only_cache = false; 520e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar if (flags & FLAG_CLEAR_CACHE_ONLY) { 521e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar suffix = CACHE_DIR_POSTFIX; 522e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar only_cache = true; 523717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) { 524717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo suffix = CODE_CACHE_DIR_POSTFIX; 525717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo only_cache = true; 526717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo } 527717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo 528717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo auto path = create_data_user_de_package_path(uuid_, userId, pkgname) + suffix; 529717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo if (access(path.c_str(), F_OK) == 0) { 530717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo if (delete_dir_contents(path) != 0) { 531717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo res = error("Failed to delete contents of " + path); 532717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo } 533717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo } 534717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo if (!only_cache) { 535717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo if (!clear_primary_current_profile(packageName, userId)) { 536717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo res = error("Failed to clear current profile for " + packageName); 5375778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 5385778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 5395778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 5405778822d86b0337407514b9372562b86edfa91cdAndreas Huber return res; 5415778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 5425778822d86b0337407514b9372562b86edfa91cdAndreas Huber 5435778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatic int destroy_app_reference_profile(const std::string& pkgname) { 5445778822d86b0337407514b9372562b86edfa91cdAndreas Huber return delete_dir_contents_and_dir( 5455778822d86b0337407514b9372562b86edfa91cdAndreas Huber create_primary_reference_profile_package_dir_path(pkgname), 5465778822d86b0337407514b9372562b86edfa91cdAndreas Huber /*ignore_if_missing*/ true); 5475778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 5485778822d86b0337407514b9372562b86edfa91cdAndreas Huber 5495778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatic int destroy_app_current_profiles(const std::string& pkgname, userid_t userid) { 5505778822d86b0337407514b9372562b86edfa91cdAndreas Huber return delete_dir_contents_and_dir( 5515778822d86b0337407514b9372562b86edfa91cdAndreas Huber create_primary_current_profile_package_dir_path(userid, pkgname), 5525778822d86b0337407514b9372562b86edfa91cdAndreas Huber /*ignore_if_missing*/ true); 5535778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 5545778822d86b0337407514b9372562b86edfa91cdAndreas Huber 5557bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnarbinder::Status InstalldNativeService::destroyAppProfiles(const std::string& packageName) { 5567bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar ENFORCE_UID(AID_SYSTEM); 5577bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar CHECK_ARGUMENT_PACKAGE_NAME(packageName); 5587bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar std::lock_guard<std::recursive_mutex> lock(mLock); 5597bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar 5607bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar binder::Status res = ok(); 5617bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr); 5627bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar for (auto user : users) { 5637bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar if (destroy_app_current_profiles(packageName, user) != 0) { 5647bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar res = error("Failed to destroy current profiles for " + packageName); 5657bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar } 5667bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar } 5677bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar if (destroy_app_reference_profile(packageName) != 0) { 5687bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar res = error("Failed to destroy reference profile for " + packageName); 5697bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar } 5700e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar return res; 5710e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar} 5720e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar 5730e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnarbinder::Status InstalldNativeService::destroyAppData(const std::unique_ptr<std::string>& uuid, 5747bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode) { 5757bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar ENFORCE_UID(AID_SYSTEM); 5767bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar CHECK_ARGUMENT_UUID(uuid); 5777bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar CHECK_ARGUMENT_PACKAGE_NAME(packageName); 5787bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar std::lock_guard<std::recursive_mutex> lock(mLock); 5797bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar 5807bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar const char* uuid_ = uuid ? uuid->c_str() : nullptr; 5810e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar const char* pkgname = packageName.c_str(); 5827bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar 5837bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar binder::Status res = ok(); 5847bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar if (flags & FLAG_STORAGE_CE) { 5857bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar auto path = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInode); 5867bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar if (delete_dir_contents_and_dir(path) != 0) { 5877bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar res = error("Failed to delete " + path); 5887bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar } 5897bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar } 5907bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar if (flags & FLAG_STORAGE_DE) { 5917bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar auto path = create_data_user_de_package_path(uuid_, userId, pkgname); 5927bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar if (delete_dir_contents_and_dir(path) != 0) { 5937bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar res = error("Failed to delete " + path); 5947bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar } 5957bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar destroy_app_current_profiles(packageName, userId); 5967bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar // TODO(calin): If the package is still installed by other users it's probably 5977bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar // beneficial to keep the reference profile around. 5987bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar // Verify if it's ok to do that. 5995778822d86b0337407514b9372562b86edfa91cdAndreas Huber destroy_app_reference_profile(packageName); 6005778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6015778822d86b0337407514b9372562b86edfa91cdAndreas Huber return res; 6025778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 6035778822d86b0337407514b9372562b86edfa91cdAndreas Huber 6045778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatic gid_t get_cache_gid(uid_t uid) { 6055778822d86b0337407514b9372562b86edfa91cdAndreas Huber int32_t gid = multiuser_get_cache_gid(multiuser_get_user_id(uid), multiuser_get_app_id(uid)); 606496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber return (gid != -1) ? gid : uid; 607496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber} 608496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber 609496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huberbinder::Status InstalldNativeService::fixupAppData(const std::unique_ptr<std::string>& uuid, 610496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber int32_t flags) { 611496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber ENFORCE_UID(AID_SYSTEM); 612575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber CHECK_ARGUMENT_UUID(uuid); 613575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber std::lock_guard<std::recursive_mutex> lock(mLock); 614575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber 615575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber const char* uuid_ = uuid ? uuid->c_str() : nullptr; 616575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber for (auto user : get_known_users(uuid_)) { 617575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber ATRACE_BEGIN("fixup user"); 6185778822d86b0337407514b9372562b86edfa91cdAndreas Huber FTS* fts; 6195778822d86b0337407514b9372562b86edfa91cdAndreas Huber FTSENT* p; 6205778822d86b0337407514b9372562b86edfa91cdAndreas Huber char *argv[] = { 6215778822d86b0337407514b9372562b86edfa91cdAndreas Huber (char*) create_data_user_ce_path(uuid_, user).c_str(), 622c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang (char*) create_data_user_de_path(uuid_, user).c_str(), 6235778822d86b0337407514b9372562b86edfa91cdAndreas Huber nullptr 6245778822d86b0337407514b9372562b86edfa91cdAndreas Huber }; 6255778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) { 6265778822d86b0337407514b9372562b86edfa91cdAndreas Huber return error("Failed to fts_open"); 6275778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6285778822d86b0337407514b9372562b86edfa91cdAndreas Huber while ((p = fts_read(fts)) != nullptr) { 6295778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (p->fts_info == FTS_D && p->fts_level == 1) { 630c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang // Track down inodes of cache directories 6315778822d86b0337407514b9372562b86edfa91cdAndreas Huber uint64_t raw = 0; 6325778822d86b0337407514b9372562b86edfa91cdAndreas Huber ino_t inode_cache = 0; 6335778822d86b0337407514b9372562b86edfa91cdAndreas Huber ino_t inode_code_cache = 0; 6345778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (getxattr(p->fts_path, kXattrInodeCache, &raw, sizeof(raw)) == sizeof(raw)) { 6355778822d86b0337407514b9372562b86edfa91cdAndreas Huber inode_cache = raw; 6365778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6375778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (getxattr(p->fts_path, kXattrInodeCodeCache, &raw, sizeof(raw)) == sizeof(raw)) { 6385778822d86b0337407514b9372562b86edfa91cdAndreas Huber inode_code_cache = raw; 6390e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar } 6405778822d86b0337407514b9372562b86edfa91cdAndreas Huber 641c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang // Figure out expected GID of each child 6425778822d86b0337407514b9372562b86edfa91cdAndreas Huber FTSENT* child = fts_children(fts, 0); 643251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung while (child != nullptr) { 644251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung if ((child->fts_statp->st_ino == inode_cache) 645251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung || (child->fts_statp->st_ino == inode_code_cache) 6465778822d86b0337407514b9372562b86edfa91cdAndreas Huber || !strcmp(child->fts_name, "cache") 6475778822d86b0337407514b9372562b86edfa91cdAndreas Huber || !strcmp(child->fts_name, "code_cache")) { 6485778822d86b0337407514b9372562b86edfa91cdAndreas Huber child->fts_number = get_cache_gid(p->fts_statp->st_uid); 6495778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 6505778822d86b0337407514b9372562b86edfa91cdAndreas Huber child->fts_number = p->fts_statp->st_uid; 6515778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6525778822d86b0337407514b9372562b86edfa91cdAndreas Huber child = child->fts_link; 6535778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6545778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (p->fts_level >= 2) { 6555778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (p->fts_level > 2) { 6565778822d86b0337407514b9372562b86edfa91cdAndreas Huber // Inherit GID from parent once we're deeper into tree 6575778822d86b0337407514b9372562b86edfa91cdAndreas Huber p->fts_number = p->fts_parent->fts_number; 6585778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6595778822d86b0337407514b9372562b86edfa91cdAndreas Huber 6605778822d86b0337407514b9372562b86edfa91cdAndreas Huber uid_t uid = p->fts_parent->fts_statp->st_uid; 6615778822d86b0337407514b9372562b86edfa91cdAndreas Huber gid_t cache_gid = get_cache_gid(uid); 6625778822d86b0337407514b9372562b86edfa91cdAndreas Huber gid_t expected = p->fts_number; 6635778822d86b0337407514b9372562b86edfa91cdAndreas Huber gid_t actual = p->fts_statp->st_gid; 6645778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (actual == expected) { 6650e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar#if FIXUP_DEBUG 6665778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(DEBUG) << "Ignoring " << p->fts_path << " with expected GID " << expected; 6675778822d86b0337407514b9372562b86edfa91cdAndreas Huber#endif 668251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung if (!(flags & FLAG_FORCE)) { 669251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung fts_set(fts, p, FTS_SKIP); 6705778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6715778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if ((actual == uid) || (actual == cache_gid)) { 6725778822d86b0337407514b9372562b86edfa91cdAndreas Huber // Only consider fixing up when current GID belongs to app 6735778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (p->fts_info != FTS_D) { 6745778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(INFO) << "Fixing " << p->fts_path << " with unexpected GID " << actual 6755778822d86b0337407514b9372562b86edfa91cdAndreas Huber << " instead of " << expected; 6765778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6775778822d86b0337407514b9372562b86edfa91cdAndreas Huber switch (p->fts_info) { 6785778822d86b0337407514b9372562b86edfa91cdAndreas Huber case FTS_DP: 6795778822d86b0337407514b9372562b86edfa91cdAndreas Huber // If we're moving towards cache GID, we need to set S_ISGID 6805778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (expected == cache_gid) { 6815778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (chmod(p->fts_path, 02771) != 0) { 6825778822d86b0337407514b9372562b86edfa91cdAndreas Huber PLOG(WARNING) << "Failed to chmod " << p->fts_path; 6835778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6845778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6855778822d86b0337407514b9372562b86edfa91cdAndreas Huber // Intentional fall through to also set GID 6865778822d86b0337407514b9372562b86edfa91cdAndreas Huber case FTS_F: 6875778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (chown(p->fts_path, -1, expected) != 0) { 6885778822d86b0337407514b9372562b86edfa91cdAndreas Huber PLOG(WARNING) << "Failed to chown " << p->fts_path; 6895778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6905778822d86b0337407514b9372562b86edfa91cdAndreas Huber break; 6915778822d86b0337407514b9372562b86edfa91cdAndreas Huber case FTS_SL: 6925778822d86b0337407514b9372562b86edfa91cdAndreas Huber case FTS_SLNONE: 6935778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (lchown(p->fts_path, -1, expected) != 0) { 6945778822d86b0337407514b9372562b86edfa91cdAndreas Huber PLOG(WARNING) << "Failed to chown " << p->fts_path; 6955778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6965778822d86b0337407514b9372562b86edfa91cdAndreas Huber break; 6975778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 6985778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 6995778822d86b0337407514b9372562b86edfa91cdAndreas Huber // Ignore all other GID transitions, since they're kinda shady 7005778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(WARNING) << "Ignoring " << p->fts_path << " with unexpected GID " << actual 7015778822d86b0337407514b9372562b86edfa91cdAndreas Huber << " instead of " << expected; 7025778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7035778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7045778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7055778822d86b0337407514b9372562b86edfa91cdAndreas Huber fts_close(fts); 7065778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_END(); 7075778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7085778822d86b0337407514b9372562b86edfa91cdAndreas Huber return ok(); 7095778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 7105778822d86b0337407514b9372562b86edfa91cdAndreas Huber 7115778822d86b0337407514b9372562b86edfa91cdAndreas Huberbinder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std::string>& fromUuid, 7125778822d86b0337407514b9372562b86edfa91cdAndreas Huber const std::unique_ptr<std::string>& toUuid, const std::string& packageName, 7135778822d86b0337407514b9372562b86edfa91cdAndreas Huber const std::string& dataAppName, int32_t appId, const std::string& seInfo, 7145778822d86b0337407514b9372562b86edfa91cdAndreas Huber int32_t targetSdkVersion) { 7155778822d86b0337407514b9372562b86edfa91cdAndreas Huber ENFORCE_UID(AID_SYSTEM); 7165778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_ARGUMENT_UUID(fromUuid); 7175778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_ARGUMENT_UUID(toUuid); 7185778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_ARGUMENT_PACKAGE_NAME(packageName); 7195778822d86b0337407514b9372562b86edfa91cdAndreas Huber std::lock_guard<std::recursive_mutex> lock(mLock); 7205778822d86b0337407514b9372562b86edfa91cdAndreas Huber 7215778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* from_uuid = fromUuid ? fromUuid->c_str() : nullptr; 7225778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* to_uuid = toUuid ? toUuid->c_str() : nullptr; 7235778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* package_name = packageName.c_str(); 7245778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* data_app_name = dataAppName.c_str(); 7255778822d86b0337407514b9372562b86edfa91cdAndreas Huber 72692cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar binder::Status res = ok(); 7275778822d86b0337407514b9372562b86edfa91cdAndreas Huber std::vector<userid_t> users = get_known_users(from_uuid); 728251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung 729251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung // Copy app 730251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung { 7315778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto from = create_data_app_package_path(from_uuid, data_app_name); 7329e2b7918eb5621b24bd54c922f630da45339de77Marco Nelissen auto to = create_data_app_package_path(to_uuid, data_app_name); 7339e2b7918eb5621b24bd54c922f630da45339de77Marco Nelissen auto to_parent = create_data_app_path(to_uuid); 734251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung 735aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber char *argv[] = { 736aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber (char*) kCpPath, 737aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber (char*) "-F", /* delete any existing destination file first (--remove-destination) */ 7385530f7a7f9dff5280be84f2675b3be081beb5540Wei Jia (char*) "-p", /* preserve timestamps, ownership, and permissions */ 7395778822d86b0337407514b9372562b86edfa91cdAndreas Huber (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */ 7405778822d86b0337407514b9372562b86edfa91cdAndreas Huber (char*) "-P", /* Do not follow symlinks [default] */ 7415778822d86b0337407514b9372562b86edfa91cdAndreas Huber (char*) "-d", /* don't dereference symlinks */ 7425778822d86b0337407514b9372562b86edfa91cdAndreas Huber (char*) from.c_str(), 7435778822d86b0337407514b9372562b86edfa91cdAndreas Huber (char*) to_parent.c_str() 7445778822d86b0337407514b9372562b86edfa91cdAndreas Huber }; 7455778822d86b0337407514b9372562b86edfa91cdAndreas Huber 7465778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(DEBUG) << "Copying " << from << " to " << to; 7475778822d86b0337407514b9372562b86edfa91cdAndreas Huber int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true); 7485778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (rc != 0) { 749c22c695660ed9edaba0d4cd7c0ab3a794216fe80Wei Jia res = error(rc, "Failed copying " + from + " to " + to); 750c22c695660ed9edaba0d4cd7c0ab3a794216fe80Wei Jia goto fail; 7515778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7525778822d86b0337407514b9372562b86edfa91cdAndreas Huber 7535778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (selinux_android_restorecon(to.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE) != 0) { 7545778822d86b0337407514b9372562b86edfa91cdAndreas Huber res = error("Failed to restorecon " + to); 7555778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto fail; 756c22c695660ed9edaba0d4cd7c0ab3a794216fe80Wei Jia } 757c22c695660ed9edaba0d4cd7c0ab3a794216fe80Wei Jia } 7585778822d86b0337407514b9372562b86edfa91cdAndreas Huber 7595778822d86b0337407514b9372562b86edfa91cdAndreas Huber // Copy private data for all known users 7605778822d86b0337407514b9372562b86edfa91cdAndreas Huber for (auto user : users) { 7615778822d86b0337407514b9372562b86edfa91cdAndreas Huber 762c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber // Data source may not exist for all users; that's okay 7635778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto from_ce = create_data_user_ce_package_path(from_uuid, user, package_name); 7645778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (access(from_ce.c_str(), F_OK) != 0) { 7655778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(INFO) << "Missing source " << from_ce; 7665778822d86b0337407514b9372562b86edfa91cdAndreas Huber continue; 7675530f7a7f9dff5280be84f2675b3be081beb5540Wei Jia } 76803ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber 769aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber if (!createAppData(toUuid, packageName, user, FLAG_STORAGE_CE | FLAG_STORAGE_DE, appId, 77003ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber seInfo, targetSdkVersion, nullptr).isOk()) { 77103ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber res = error("Failed to create package target"); 77203ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber goto fail; 77303ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber } 77403ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber 77503ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber char *argv[] = { 77603ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber (char*) kCpPath, 77703ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber (char*) "-F", /* delete any existing destination file first (--remove-destination) */ 77803ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber (char*) "-p", /* preserve timestamps, ownership, and permissions */ 77903ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */ 78003ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber (char*) "-P", /* Do not follow symlinks [default] */ 7815778822d86b0337407514b9372562b86edfa91cdAndreas Huber (char*) "-d", /* don't dereference symlinks */ 7825778822d86b0337407514b9372562b86edfa91cdAndreas Huber nullptr, 7835778822d86b0337407514b9372562b86edfa91cdAndreas Huber nullptr 7845778822d86b0337407514b9372562b86edfa91cdAndreas Huber }; 7855778822d86b0337407514b9372562b86edfa91cdAndreas Huber 7869e2b7918eb5621b24bd54c922f630da45339de77Marco Nelissen { 7879e2b7918eb5621b24bd54c922f630da45339de77Marco Nelissen auto from = create_data_user_de_package_path(from_uuid, user, package_name); 7889e2b7918eb5621b24bd54c922f630da45339de77Marco Nelissen auto to = create_data_user_de_path(to_uuid, user); 7899e2b7918eb5621b24bd54c922f630da45339de77Marco Nelissen argv[6] = (char*) from.c_str(); 7909e2b7918eb5621b24bd54c922f630da45339de77Marco Nelissen argv[7] = (char*) to.c_str(); 7919e2b7918eb5621b24bd54c922f630da45339de77Marco Nelissen 7925778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(DEBUG) << "Copying " << from << " to " << to; 7935778822d86b0337407514b9372562b86edfa91cdAndreas Huber int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true); 7945778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (rc != 0) { 7950e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar res = error(rc, "Failed copying " + from + " to " + to); 7965778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto fail; 7975778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 7985530f7a7f9dff5280be84f2675b3be081beb5540Wei Jia } 7995778822d86b0337407514b9372562b86edfa91cdAndreas Huber { 800251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung auto from = create_data_user_ce_package_path(from_uuid, user, package_name); 801575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber auto to = create_data_user_ce_path(to_uuid, user); 8025778822d86b0337407514b9372562b86edfa91cdAndreas Huber argv[6] = (char*) from.c_str(); 8035778822d86b0337407514b9372562b86edfa91cdAndreas Huber argv[7] = (char*) to.c_str(); 804c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 805c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang LOG(DEBUG) << "Copying " << from << " to " << to; 806251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true); 807251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung if (rc != 0) { 808251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung res = error(rc, "Failed copying " + from + " to " + to); 809251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung goto fail; 810251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung } 811251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung } 812251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung 813251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung if (!restoreconAppData(toUuid, packageName, user, FLAG_STORAGE_CE | FLAG_STORAGE_DE, 814251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung appId, seInfo).isOk()) { 815251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung res = error("Failed to restorecon"); 816251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung goto fail; 817c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 8185778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 8195778822d86b0337407514b9372562b86edfa91cdAndreas Huber 8205778822d86b0337407514b9372562b86edfa91cdAndreas Huber // We let the framework scan the new location and persist that before 8215778822d86b0337407514b9372562b86edfa91cdAndreas Huber // deleting the data in the old location; this ordering ensures that 8225778822d86b0337407514b9372562b86edfa91cdAndreas Huber // we can recover from things like battery pulls. 8235530f7a7f9dff5280be84f2675b3be081beb5540Wei Jia return ok(); 8245778822d86b0337407514b9372562b86edfa91cdAndreas Huber 825251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hungfail: 826575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber // Nuke everything we might have already copied 827c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang { 828251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung auto to = create_data_app_package_path(to_uuid, data_app_name); 829251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { 830251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung LOG(WARNING) << "Failed to rollback " << to; 831251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung } 832c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 833251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung for (auto user : users) { 834251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung { 835251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung auto to = create_data_user_de_package_path(to_uuid, user, package_name); 836251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { 837251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung LOG(WARNING) << "Failed to rollback " << to; 838251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung } 839251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung } 840251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung { 841251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung auto to = create_data_user_ce_package_path(to_uuid, user, package_name); 842251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { 843251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung LOG(WARNING) << "Failed to rollback " << to; 844c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 8455778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 8465778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 8475778822d86b0337407514b9372562b86edfa91cdAndreas Huber return res; 8485778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 8495530f7a7f9dff5280be84f2675b3be081beb5540Wei Jia 850251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hungbinder::Status InstalldNativeService::createUserData(const std::unique_ptr<std::string>& uuid, 8515778822d86b0337407514b9372562b86edfa91cdAndreas Huber int32_t userId, int32_t userSerial ATTRIBUTE_UNUSED, int32_t flags) { 8525778822d86b0337407514b9372562b86edfa91cdAndreas Huber ENFORCE_UID(AID_SYSTEM); 8535778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_ARGUMENT_UUID(uuid); 8545778822d86b0337407514b9372562b86edfa91cdAndreas Huber std::lock_guard<std::recursive_mutex> lock(mLock); 85592cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar 8565778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* uuid_ = uuid ? uuid->c_str() : nullptr; 8575778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (flags & FLAG_STORAGE_DE) { 8585778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (uuid_ == nullptr) { 8595778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (ensure_config_user_dirs(userId) != 0) { 860717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo return error(StringPrintf("Failed to ensure dirs for %d", userId)); 8615778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 862717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo } 8635778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 8645778822d86b0337407514b9372562b86edfa91cdAndreas Huber 8655778822d86b0337407514b9372562b86edfa91cdAndreas Huber // Data under /data/media doesn't have an app, but we still want 8665778822d86b0337407514b9372562b86edfa91cdAndreas Huber // to limit it to prevent abuse. 8675778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (prepare_app_quota(uuid, findQuotaDeviceForUuid(uuid), 868717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo multiuser_get_uid(userId, AID_MEDIA_RW))) { 8691bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber return error("Failed to set hard quota for media_rw"); 8701bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber } 8711bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber 8721bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber return ok(); 8731bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber} 8745778822d86b0337407514b9372562b86edfa91cdAndreas Huber 8755778822d86b0337407514b9372562b86edfa91cdAndreas Huberbinder::Status InstalldNativeService::destroyUserData(const std::unique_ptr<std::string>& uuid, 8765778822d86b0337407514b9372562b86edfa91cdAndreas Huber int32_t userId, int32_t flags) { 8775778822d86b0337407514b9372562b86edfa91cdAndreas Huber ENFORCE_UID(AID_SYSTEM); 87892cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar CHECK_ARGUMENT_UUID(uuid); 8795778822d86b0337407514b9372562b86edfa91cdAndreas Huber std::lock_guard<std::recursive_mutex> lock(mLock); 8805778822d86b0337407514b9372562b86edfa91cdAndreas Huber 8815778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* uuid_ = uuid ? uuid->c_str() : nullptr; 8826507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden binder::Status res = ok(); 8836507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden if (flags & FLAG_STORAGE_DE) { 8846507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden auto path = create_data_user_de_path(uuid_, userId); 885e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar if (delete_dir_contents_and_dir(path, true) != 0) { 886e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar res = error("Failed to delete " + path); 887e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar } 8882606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang if (uuid_ == nullptr) { 8895778822d86b0337407514b9372562b86edfa91cdAndreas Huber path = create_data_misc_legacy_path(userId); 8905778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (delete_dir_contents_and_dir(path, true) != 0) { 8915778822d86b0337407514b9372562b86edfa91cdAndreas Huber res = error("Failed to delete " + path); 8925778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 89392cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar path = create_primary_cur_profile_dir_path(userId); 8947cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden if (delete_dir_contents_and_dir(path, true) != 0) { 89592cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar res = error("Failed to delete " + path); 8967cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 8977cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 8987cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 8997cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden if (flags & FLAG_STORAGE_CE) { 9007cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden auto path = create_data_user_ce_path(uuid_, userId); 9017cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden if (delete_dir_contents_and_dir(path, true) != 0) { 9027cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden res = error("Failed to delete " + path); 9036507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden } 9047cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden path = create_data_media_path(uuid_, userId); 9057cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden if (delete_dir_contents_and_dir(path, true) != 0) { 9067cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden res = error("Failed to delete " + path); 9077cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 9087cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 9097cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden return res; 9107cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden} 91192cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar 9127cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden/* Try to ensure free_size bytes of storage are available. 91392cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar * Returns 0 on success. 9147cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden * This is rather simple-minded because doing a full LRU would 9157cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden * be potentially memory-intensive, and without atime it would 9167cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden * also require that apps constantly modify file metadata even 9177cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden * when just reading from the cache, which is pretty awful. 9187cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden */ 9197cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFaddenbinder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::string>& uuid, 9207cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden int64_t freeStorageSize, int32_t flags) { 9217cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden ENFORCE_UID(AID_SYSTEM); 9227cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden CHECK_ARGUMENT_UUID(uuid); 9237cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden std::lock_guard<std::recursive_mutex> lock(mLock); 92492cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar 9255778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* uuid_ = uuid ? uuid->c_str() : nullptr; 9267bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar auto data_path = create_data_path(uuid_); 9275778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto device = findQuotaDeviceForUuid(uuid); 9285778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto noop = (flags & FLAG_FREE_CACHE_NOOP); 9295778822d86b0337407514b9372562b86edfa91cdAndreas Huber 9305778822d86b0337407514b9372562b86edfa91cdAndreas Huber int64_t free = data_disk_free(data_path); 9315778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (free < 0) { 9325778822d86b0337407514b9372562b86edfa91cdAndreas Huber return error("Failed to determine free space for " + data_path); 9335778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 9345778822d86b0337407514b9372562b86edfa91cdAndreas Huber 9355778822d86b0337407514b9372562b86edfa91cdAndreas Huber int64_t needed = freeStorageSize - free; 9365778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(DEBUG) << "Device " << data_path << " has " << free << " free; requested " 9375778822d86b0337407514b9372562b86edfa91cdAndreas Huber << freeStorageSize << "; needed " << needed; 9385778822d86b0337407514b9372562b86edfa91cdAndreas Huber 9395778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (free >= freeStorageSize) { 940eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber return ok(); 941eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber } 942eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber 94392cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar if (flags & FLAG_FREE_CACHE_V2) { 94492cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar // This new cache strategy fairly removes files from UIDs by deleting 9455778822d86b0337407514b9372562b86edfa91cdAndreas Huber // files from the UIDs which are most over their allocated quota 946eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber 9475778822d86b0337407514b9372562b86edfa91cdAndreas Huber // 1. Create trackers for every known UID 948eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber ATRACE_BEGIN("create"); 9495778822d86b0337407514b9372562b86edfa91cdAndreas Huber std::unordered_map<uid_t, std::shared_ptr<CacheTracker>> trackers; 950eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber for (auto user : get_known_users(uuid_)) { 9515778822d86b0337407514b9372562b86edfa91cdAndreas Huber FTS *fts; 952eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber FTSENT *p; 9535778822d86b0337407514b9372562b86edfa91cdAndreas Huber char *argv[] = { 9541bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber (char*) create_data_user_ce_path(uuid_, user).c_str(), 955ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber (char*) create_data_user_de_path(uuid_, user).c_str(), 956ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber nullptr 957ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber }; 958ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) { 9595778822d86b0337407514b9372562b86edfa91cdAndreas Huber return error("Failed to fts_open"); 9605778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 9615778822d86b0337407514b9372562b86edfa91cdAndreas Huber while ((p = fts_read(fts)) != NULL) { 9625778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (p->fts_info == FTS_D && p->fts_level == 1) { 9635778822d86b0337407514b9372562b86edfa91cdAndreas Huber uid_t uid = p->fts_statp->st_uid; 9645778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto search = trackers.find(uid); 9655778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (search != trackers.end()) { 9665778822d86b0337407514b9372562b86edfa91cdAndreas Huber search->second->addDataPath(p->fts_path); 9675778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 9685778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto tracker = std::shared_ptr<CacheTracker>(new CacheTracker( 9695778822d86b0337407514b9372562b86edfa91cdAndreas Huber multiuser_get_user_id(uid), multiuser_get_app_id(uid), device)); 9705778822d86b0337407514b9372562b86edfa91cdAndreas Huber tracker->addDataPath(p->fts_path); 971575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber { 9725778822d86b0337407514b9372562b86edfa91cdAndreas Huber std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock); 9735778822d86b0337407514b9372562b86edfa91cdAndreas Huber tracker->cacheQuota = mCacheQuotas[uid]; 9745778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 9755778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (tracker->cacheQuota == 0) { 9765778822d86b0337407514b9372562b86edfa91cdAndreas Huber#if MEASURE_DEBUG 97792cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar LOG(WARNING) << "UID " << uid << " has no cache quota; assuming 64MB"; 9785778822d86b0337407514b9372562b86edfa91cdAndreas Huber#endif 9795778822d86b0337407514b9372562b86edfa91cdAndreas Huber tracker->cacheQuota = 67108864; 9805778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 981475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu trackers[uid] = tracker; 982475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu } 983475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu fts_set(fts, p, FTS_SKIP); 9845778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 9855778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 9865778822d86b0337407514b9372562b86edfa91cdAndreas Huber fts_close(fts); 987475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu } 988475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu ATRACE_END(); 9895778822d86b0337407514b9372562b86edfa91cdAndreas Huber 9905778822d86b0337407514b9372562b86edfa91cdAndreas Huber // 2. Populate tracker stats and insert into priority queue 9915778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_BEGIN("populate"); 9925778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto cmp = [](std::shared_ptr<CacheTracker> left, std::shared_ptr<CacheTracker> right) { 993e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber return (left->getCacheRatio() < right->getCacheRatio()); 994e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber }; 995e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber std::priority_queue<std::shared_ptr<CacheTracker>, 996e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber std::vector<std::shared_ptr<CacheTracker>>, decltype(cmp)> queue(cmp); 997e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber for (const auto& it : trackers) { 998e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber it.second->loadStats(); 999c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang queue.push(it.second); 1000c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 1001e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber ATRACE_END(); 1002e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber 1003e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber // 3. Bounce across the queue, freeing items from whichever tracker is 1004e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber // the most over their assigned quota 10055778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_BEGIN("bounce"); 10065778822d86b0337407514b9372562b86edfa91cdAndreas Huber std::shared_ptr<CacheTracker> active; 10075778822d86b0337407514b9372562b86edfa91cdAndreas Huber while (active || !queue.empty()) { 100892cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar // Only look at apps under quota when explicitly requested 10095778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (active && (active->getCacheRatio() < 10000) 10105778822d86b0337407514b9372562b86edfa91cdAndreas Huber && !(flags & FLAG_FREE_CACHE_V2_DEFY_QUOTA)) { 10115778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(DEBUG) << "Active ratio " << active->getCacheRatio() 1012c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber << " isn't over quota, and defy not requested"; 1013c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber break; 1014c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber } 10155778822d86b0337407514b9372562b86edfa91cdAndreas Huber 10165778822d86b0337407514b9372562b86edfa91cdAndreas Huber // Find the best tracker to work with; this might involve swapping 10175778822d86b0337407514b9372562b86edfa91cdAndreas Huber // if the active tracker is no longer the most over quota 10185778822d86b0337407514b9372562b86edfa91cdAndreas Huber bool nextBetter = active && !queue.empty() 10198ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber && active->getCacheRatio() < queue.top()->getCacheRatio(); 10208ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber if (!active || nextBetter) { 10218ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber if (active) { 10228ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber // Current tracker still has items, so we'll consider it 10238ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber // again later once it bubbles up to surface 10248ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber queue.push(active); 10258ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber } 10268ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber active = queue.top(); queue.pop(); 10278ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber active->ensureItems(); 10288ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber continue; 10298ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber } 10308ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber 10318ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber // If no items remain, go find another tracker 10328ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber if (active->items.empty()) { 10338ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber active = nullptr; 10348ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber continue; 1035251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung } else { 1036575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber auto item = active->items.back(); 1037575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber active->items.pop_back(); 10388ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber 10398ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber LOG(DEBUG) << "Purging " << item->toString() << " from " << active->toString(); 10408ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber if (!noop) { 10418ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber item->purge(); 10428ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber } 1043c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang active->cacheUsed -= item->size; 1044c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang needed -= item->size; 1045c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 10465778822d86b0337407514b9372562b86edfa91cdAndreas Huber 10475778822d86b0337407514b9372562b86edfa91cdAndreas Huber // Verify that we're actually done before bailing, since sneaky 10485778822d86b0337407514b9372562b86edfa91cdAndreas Huber // apps might be using hardlinks 10495778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (needed <= 0) { 10505778822d86b0337407514b9372562b86edfa91cdAndreas Huber free = data_disk_free(data_path); 1051575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber needed = freeStorageSize - free; 1052575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber if (needed <= 0) { 10535778822d86b0337407514b9372562b86edfa91cdAndreas Huber break; 10545778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 10555778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(WARNING) << "Expected to be done but still need " << needed; 10565778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 105792cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar } 10585778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 10595778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_END(); 10605778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1061c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber } else { 1062c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber return error("Legacy cache logic no longer supported"); 1063c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber } 10645778822d86b0337407514b9372562b86edfa91cdAndreas Huber 10655778822d86b0337407514b9372562b86edfa91cdAndreas Huber free = data_disk_free(data_path); 10665778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (free >= freeStorageSize) { 10675778822d86b0337407514b9372562b86edfa91cdAndreas Huber return ok(); 10682d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber } else { 10692d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber return error(StringPrintf("Failed to free up %" PRId64 " on %s; final free space %" PRId64, 10705778822d86b0337407514b9372562b86edfa91cdAndreas Huber freeStorageSize, data_path.c_str(), free)); 10715778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 10725778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 10735778822d86b0337407514b9372562b86edfa91cdAndreas Huber 10745778822d86b0337407514b9372562b86edfa91cdAndreas Huberbinder::Status InstalldNativeService::rmdex(const std::string& codePath, 10755778822d86b0337407514b9372562b86edfa91cdAndreas Huber const std::string& instructionSet) { 1076e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber ENFORCE_UID(AID_SYSTEM); 1077e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber std::lock_guard<std::recursive_mutex> lock(mLock); 1078e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber 1079e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber char dex_path[PKG_PATH_MAX]; 1080e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber 1081e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber const char* path = codePath.c_str(); 1082e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber const char* instruction_set = instructionSet.c_str(); 1083e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber 1084e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber if (validate_apk_path(path) && validate_system_app_path(path)) { 1085e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber return error("Invalid path " + codePath); 1086e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber } 1087e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber 1088e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber if (!create_cache_path(dex_path, path, instruction_set)) { 1089e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber return error("Failed to create cache path for " + codePath); 1090e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber } 1091e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber 1092c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang ALOGV("unlink %s\n", dex_path); 1093c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang if (unlink(dex_path) < 0) { 1094c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang return error(StringPrintf("Failed to unlink %s", dex_path)); 1095c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } else { 1096c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang return ok(); 1097e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber } 1098e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber} 1099c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 1100c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhangstruct stats { 1101c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang int64_t codeSize; 11025778822d86b0337407514b9372562b86edfa91cdAndreas Huber int64_t dataSize; 11035778822d86b0337407514b9372562b86edfa91cdAndreas Huber int64_t cacheSize; 11045778822d86b0337407514b9372562b86edfa91cdAndreas Huber}; 11055778822d86b0337407514b9372562b86edfa91cdAndreas Huber 11065778822d86b0337407514b9372562b86edfa91cdAndreas Huber#if MEASURE_DEBUG 1107575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huberstatic std::string toString(std::vector<int64_t> values) { 1108575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber std::stringstream res; 11095778822d86b0337407514b9372562b86edfa91cdAndreas Huber res << "["; 1110575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber for (size_t i = 0; i < values.size(); i++) { 11115778822d86b0337407514b9372562b86edfa91cdAndreas Huber res << values[i]; 11125778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (i < values.size() - 1) { 11135778822d86b0337407514b9372562b86edfa91cdAndreas Huber res << ","; 111492cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar } 11155778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 11165778822d86b0337407514b9372562b86edfa91cdAndreas Huber res << "]"; 11175778822d86b0337407514b9372562b86edfa91cdAndreas Huber return res.str(); 11185778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 11195778822d86b0337407514b9372562b86edfa91cdAndreas Huber#endif 11205778822d86b0337407514b9372562b86edfa91cdAndreas Huber 112192cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnarstatic void collectQuotaStats(const std::string& device, int32_t userId, 11225778822d86b0337407514b9372562b86edfa91cdAndreas Huber int32_t appId, struct stats* stats, struct stats* extStats) { 1123c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber if (device.empty()) return; 1124c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber 1125c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber struct dqblk dq; 1126c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber 1127c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber uid_t uid = multiuser_get_uid(userId, appId); 1128c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid, 11295778822d86b0337407514b9372562b86edfa91cdAndreas Huber reinterpret_cast<char*>(&dq)) != 0) { 11305778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (errno != ESRCH) { 11315778822d86b0337407514b9372562b86edfa91cdAndreas Huber PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid; 11325778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 11335778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 113492cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar#if MEASURE_DEBUG 11355778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace; 11365530f7a7f9dff5280be84f2675b3be081beb5540Wei Jia#endif 11375530f7a7f9dff5280be84f2675b3be081beb5540Wei Jia stats->dataSize += dq.dqb_curspace; 11385530f7a7f9dff5280be84f2675b3be081beb5540Wei Jia } 11395530f7a7f9dff5280be84f2675b3be081beb5540Wei Jia 11405530f7a7f9dff5280be84f2675b3be081beb5540Wei Jia int cacheGid = multiuser_get_cache_gid(userId, appId); 11415778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (cacheGid != -1) { 11420e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), cacheGid, 11430e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar reinterpret_cast<char*>(&dq)) != 0) { 11440e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar if (errno != ESRCH) { 11450e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << cacheGid; 11460e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar } 11470e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar } else { 11485778822d86b0337407514b9372562b86edfa91cdAndreas Huber#if MEASURE_DEBUG 11495778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(DEBUG) << "quotactl() for GID " << cacheGid << " " << dq.dqb_curspace; 11505778822d86b0337407514b9372562b86edfa91cdAndreas Huber#endif 11515778822d86b0337407514b9372562b86edfa91cdAndreas Huber stats->cacheSize += dq.dqb_curspace; 11525778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 11535778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 11545778822d86b0337407514b9372562b86edfa91cdAndreas Huber 11555778822d86b0337407514b9372562b86edfa91cdAndreas Huber int extGid = multiuser_get_ext_gid(userId, appId); 11565778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (extGid != -1) { 11575778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), extGid, 11585778822d86b0337407514b9372562b86edfa91cdAndreas Huber reinterpret_cast<char*>(&dq)) != 0) { 11595778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (errno != ESRCH) { 11605778822d86b0337407514b9372562b86edfa91cdAndreas Huber PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << extGid; 11615778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 11625778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 11635778822d86b0337407514b9372562b86edfa91cdAndreas Huber#if MEASURE_DEBUG 11645778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(DEBUG) << "quotactl() for GID " << extGid << " " << dq.dqb_curspace; 1165c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang#endif 11665778822d86b0337407514b9372562b86edfa91cdAndreas Huber extStats->dataSize += dq.dqb_curspace; 11675778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 11685778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 11695778822d86b0337407514b9372562b86edfa91cdAndreas Huber 11705778822d86b0337407514b9372562b86edfa91cdAndreas Huber int sharedGid = multiuser_get_shared_gid(userId, appId); 11715778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (sharedGid != -1) { 11725778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), sharedGid, 11735778822d86b0337407514b9372562b86edfa91cdAndreas Huber reinterpret_cast<char*>(&dq)) != 0) { 11745778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (errno != ESRCH) { 11755778822d86b0337407514b9372562b86edfa91cdAndreas Huber PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << sharedGid; 11765778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 11770db280176bd3277e3256252d063f3712b1905ba9Andreas Huber } else { 11780db280176bd3277e3256252d063f3712b1905ba9Andreas Huber#if MEASURE_DEBUG 11795778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(DEBUG) << "quotactl() for GID " << sharedGid << " " << dq.dqb_curspace; 11805778822d86b0337407514b9372562b86edfa91cdAndreas Huber#endif 11815778822d86b0337407514b9372562b86edfa91cdAndreas Huber stats->codeSize += dq.dqb_curspace; 11825778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 11835778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 11845778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 11855778822d86b0337407514b9372562b86edfa91cdAndreas Huber 11865778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatic void collectManualStats(const std::string& path, struct stats* stats) { 11875778822d86b0337407514b9372562b86edfa91cdAndreas Huber DIR *d; 11885778822d86b0337407514b9372562b86edfa91cdAndreas Huber int dfd; 11895778822d86b0337407514b9372562b86edfa91cdAndreas Huber struct dirent *de; 11905778822d86b0337407514b9372562b86edfa91cdAndreas Huber struct stat s; 11915778822d86b0337407514b9372562b86edfa91cdAndreas Huber 11925778822d86b0337407514b9372562b86edfa91cdAndreas Huber d = opendir(path.c_str()); 11935778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (d == nullptr) { 11945778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (errno != ENOENT) { 1195c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang PLOG(WARNING) << "Failed to open " << path; 1196c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 1197c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang return; 1198c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 1199c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang dfd = dirfd(d); 1200c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang while ((de = readdir(d))) { 1201c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang const char *name = de->d_name; 12020e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar 12030e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar int64_t size = 0; 1204c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { 1205c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang size = s.st_blocks * 512; 1206c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 1207c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 1208c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang if (de->d_type == DT_DIR) { 1209c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang if (!strcmp(name, ".")) { 1210c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang // Don't recurse, but still count node size 1211c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } else if (!strcmp(name, "..")) { 1212c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang // Don't recurse or count node size 1213c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang continue; 1214c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } else { 1215c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang // Measure all children nodes 1216c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang size = 0; 1217c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang calculate_tree_size(StringPrintf("%s/%s", path.c_str(), name), &size); 1218c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 1219c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 1220c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang if (!strcmp(name, "cache") || !strcmp(name, "code_cache")) { 1221c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang stats->cacheSize += size; 1222c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 1223c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 1224c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 1225c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang // Legacy symlink isn't owned by app 1226c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang if (de->d_type == DT_LNK && !strcmp(name, "lib")) { 12275778822d86b0337407514b9372562b86edfa91cdAndreas Huber continue; 12285778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 12295778822d86b0337407514b9372562b86edfa91cdAndreas Huber 12305778822d86b0337407514b9372562b86edfa91cdAndreas Huber // Everything found inside is considered data 12315778822d86b0337407514b9372562b86edfa91cdAndreas Huber stats->dataSize += size; 12325778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 1233c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang closedir(d); 12345778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 12355778822d86b0337407514b9372562b86edfa91cdAndreas Huber 12365778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatic void collectManualStatsForUser(const std::string& path, struct stats* stats, 12375778822d86b0337407514b9372562b86edfa91cdAndreas Huber bool exclude_apps = false) { 12385778822d86b0337407514b9372562b86edfa91cdAndreas Huber DIR *d; 12395778822d86b0337407514b9372562b86edfa91cdAndreas Huber int dfd; 12405778822d86b0337407514b9372562b86edfa91cdAndreas Huber struct dirent *de; 12415778822d86b0337407514b9372562b86edfa91cdAndreas Huber struct stat s; 12425778822d86b0337407514b9372562b86edfa91cdAndreas Huber 12435778822d86b0337407514b9372562b86edfa91cdAndreas Huber d = opendir(path.c_str()); 12445778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (d == nullptr) { 12455778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (errno != ENOENT) { 12465778822d86b0337407514b9372562b86edfa91cdAndreas Huber PLOG(WARNING) << "Failed to open " << path; 12471bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber } 12487541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber return; 12497541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber } 12507541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber dfd = dirfd(d); 12517541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber while ((de = readdir(d))) { 12527541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber if (de->d_type == DT_DIR) { 1253c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang const char *name = de->d_name; 12547541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) != 0) { 12551bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber continue; 12561bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber } 12577541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber if (!strcmp(name, ".") || !strcmp(name, "..")) { 12581bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber continue; 12591bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber } else if (exclude_apps && (s.st_uid >= AID_APP_START && s.st_uid <= AID_APP_END)) { 12607541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber continue; 12617541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber } else { 12627541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber collectManualStats(StringPrintf("%s/%s", path.c_str(), name), stats); 12631bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber } 12641bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber } 12651bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber } 12665778822d86b0337407514b9372562b86edfa91cdAndreas Huber closedir(d); 12675778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 12681bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber 12691bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huberstatic void collectManualExternalStatsForUser(const std::string& path, struct stats* stats) { 12705778822d86b0337407514b9372562b86edfa91cdAndreas Huber FTS *fts; 12715778822d86b0337407514b9372562b86edfa91cdAndreas Huber FTSENT *p; 12725778822d86b0337407514b9372562b86edfa91cdAndreas Huber char *argv[] = { (char*) path.c_str(), nullptr }; 12735778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) { 12745778822d86b0337407514b9372562b86edfa91cdAndreas Huber PLOG(ERROR) << "Failed to fts_open " << path; 1275e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber return; 12765778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 12775778822d86b0337407514b9372562b86edfa91cdAndreas Huber while ((p = fts_read(fts)) != NULL) { 12788ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber p->fts_number = p->fts_parent->fts_number; 12798ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber switch (p->fts_info) { 12805778822d86b0337407514b9372562b86edfa91cdAndreas Huber case FTS_D: 12815778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (p->fts_level == 4 12825778822d86b0337407514b9372562b86edfa91cdAndreas Huber && !strcmp(p->fts_name, "cache") 12835778822d86b0337407514b9372562b86edfa91cdAndreas Huber && !strcmp(p->fts_parent->fts_parent->fts_name, "data") 12847cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden && !strcmp(p->fts_parent->fts_parent->fts_parent->fts_name, "Android")) { 12857cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden p->fts_number = 1; 12867cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 12877cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden // Fall through to count the directory 12887cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden case FTS_DEFAULT: 12897cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden case FTS_F: 12907cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden case FTS_SL: 1291c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang case FTS_SLNONE: 12927cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden int64_t size = (p->fts_statp->st_blocks * 512); 12937cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden if (p->fts_number == 1) { 12947cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden stats->cacheSize += size; 12957cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 12967cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden stats->dataSize += size; 12977cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden break; 12987cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 12997cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden } 13005778822d86b0337407514b9372562b86edfa91cdAndreas Huber fts_close(fts); 13015778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 13025778822d86b0337407514b9372562b86edfa91cdAndreas Huber 13035778822d86b0337407514b9372562b86edfa91cdAndreas Huberbinder::Status InstalldNativeService::getAppSize(const std::unique_ptr<std::string>& uuid, 13045778822d86b0337407514b9372562b86edfa91cdAndreas Huber const std::vector<std::string>& packageNames, int32_t userId, int32_t flags, 13050e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar int32_t appId, const std::vector<int64_t>& ceDataInodes, 13060e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar const std::vector<std::string>& codePaths, std::vector<int64_t>* _aidl_return) { 13070e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar ENFORCE_UID(AID_SYSTEM); 13080e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar CHECK_ARGUMENT_UUID(uuid); 1309c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang for (auto packageName : packageNames) { 13105778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_ARGUMENT_PACKAGE_NAME(packageName); 13115778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 13125778822d86b0337407514b9372562b86edfa91cdAndreas Huber // NOTE: Locking is relaxed on this method, since it's limited to 13135778822d86b0337407514b9372562b86edfa91cdAndreas Huber // read-only measurements without mutation. 13145778822d86b0337407514b9372562b86edfa91cdAndreas Huber 13155778822d86b0337407514b9372562b86edfa91cdAndreas Huber // When modifying this logic, always verify using tests: 13165778822d86b0337407514b9372562b86edfa91cdAndreas Huber // runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetAppSize 13175778822d86b0337407514b9372562b86edfa91cdAndreas Huber 13185778822d86b0337407514b9372562b86edfa91cdAndreas Huber#if MEASURE_DEBUG 13195778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(INFO) << "Measuring user " << userId << " app " << appId; 13205778822d86b0337407514b9372562b86edfa91cdAndreas Huber#endif 1321c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber 1322c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber // Here's a summary of the common storage locations across the platform, 1323aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber // and how they're each tagged: 1324aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber // 1325aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber // /data/app/com.example UID system 1326c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber // /data/app/com.example/oat UID system 1327c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber // /data/user/0/com.example UID u0_a10 GID u0_a10 1328c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber // /data/user/0/com.example/cache UID u0_a10 GID u0_a10_cache 1329c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber // /data/media/0/foo.txt UID u0_media_rw 13300e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar // /data/media/0/bar.jpg UID u0_media_rw GID u0_media_image 133103ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber // /data/media/0/Android/data/com.example UID u0_media_rw GID u0_a10_ext 133203ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber // /data/media/0/Android/data/com.example/cache UID u0_media_rw GID u0_a10_ext_cache 133303ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber // /data/media/obb/com.example UID system 133403ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber 133503ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber struct stats stats; 133603ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber struct stats extStats; 1337aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber memset(&stats, 0, sizeof(stats)); 1338c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber memset(&extStats, 0, sizeof(extStats)); 133903ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber 134003ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber const char* uuid_ = uuid ? uuid->c_str() : nullptr; 1341aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber 1342c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber auto device = findQuotaDeviceForUuid(uuid); 1343c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber if (device.empty()) { 1344c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber flags &= ~FLAG_USE_QUOTA; 1345c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber } 1346c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber 1347aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber ATRACE_BEGIN("obb"); 1348aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber for (auto packageName : packageNames) { 1349aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber auto obbCodePath = create_data_media_obb_path(uuid_, packageName.c_str()); 1350aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber calculate_tree_size(obbCodePath, &extStats.codeSize); 1351aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber } 1352aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber ATRACE_END(); 1353aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber 1354aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber if (flags & FLAG_USE_QUOTA && appId >= AID_APP_START) { 1355c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber ATRACE_BEGIN("code"); 1356aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber for (auto codePath : codePaths) { 1357aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber calculate_tree_size(codePath, &stats.codeSize, -1, 1358aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber multiuser_get_shared_gid(userId, appId)); 1359aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber } 1360c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber ATRACE_END(); 13615778822d86b0337407514b9372562b86edfa91cdAndreas Huber 13625778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_BEGIN("quota"); 13635778822d86b0337407514b9372562b86edfa91cdAndreas Huber collectQuotaStats(device, userId, appId, &stats, &extStats); 13645778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_END(); 13655778822d86b0337407514b9372562b86edfa91cdAndreas Huber 13665778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 13675778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_BEGIN("code"); 13685778822d86b0337407514b9372562b86edfa91cdAndreas Huber for (auto codePath : codePaths) { 13695778822d86b0337407514b9372562b86edfa91cdAndreas Huber calculate_tree_size(codePath, &stats.codeSize); 1370c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 1371c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang ATRACE_END(); 1372c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 1373c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang for (size_t i = 0; i < packageNames.size(); i++) { 1374c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang const char* pkgname = packageNames[i].c_str(); 1375c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 13766507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden ATRACE_BEGIN("data"); 13776507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden auto cePath = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInodes[i]); 1378c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang collectManualStats(cePath, &stats); 13796507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden auto dePath = create_data_user_de_package_path(uuid_, userId, pkgname); 13806507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden collectManualStats(dePath, &stats); 13816507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden ATRACE_END(); 13825778822d86b0337407514b9372562b86edfa91cdAndreas Huber 13835778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_BEGIN("profiles"); 13845778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto userProfilePath = create_primary_current_profile_package_dir_path(userId, pkgname); 13855778822d86b0337407514b9372562b86edfa91cdAndreas Huber calculate_tree_size(userProfilePath, &stats.dataSize); 13865778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto refProfilePath = create_primary_reference_profile_package_dir_path(pkgname); 13875778822d86b0337407514b9372562b86edfa91cdAndreas Huber calculate_tree_size(refProfilePath, &stats.codeSize); 13885778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_END(); 13895778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1390c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang ATRACE_BEGIN("external"); 13915778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto extPath = create_data_media_package_path(uuid_, userId, "data", pkgname); 13925778822d86b0337407514b9372562b86edfa91cdAndreas Huber collectManualStats(extPath, &extStats); 13935778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto mediaPath = create_data_media_package_path(uuid_, userId, "media", pkgname); 13945778822d86b0337407514b9372562b86edfa91cdAndreas Huber calculate_tree_size(mediaPath, &extStats.dataSize); 13955778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_END(); 13965778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 13975778822d86b0337407514b9372562b86edfa91cdAndreas Huber 13985778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_BEGIN("dalvik"); 13995778822d86b0337407514b9372562b86edfa91cdAndreas Huber int32_t sharedGid = multiuser_get_shared_gid(userId, appId); 14005778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (sharedGid != -1) { 14015778822d86b0337407514b9372562b86edfa91cdAndreas Huber calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize, 14025778822d86b0337407514b9372562b86edfa91cdAndreas Huber sharedGid, -1); 14035778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 14045778822d86b0337407514b9372562b86edfa91cdAndreas Huber calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize, 14055778822d86b0337407514b9372562b86edfa91cdAndreas Huber multiuser_get_uid(userId, appId), -1); 14065778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_END(); 14075778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 14085778822d86b0337407514b9372562b86edfa91cdAndreas Huber 14095778822d86b0337407514b9372562b86edfa91cdAndreas Huber std::vector<int64_t> ret; 14105778822d86b0337407514b9372562b86edfa91cdAndreas Huber ret.push_back(stats.codeSize); 14115778822d86b0337407514b9372562b86edfa91cdAndreas Huber ret.push_back(stats.dataSize); 14125778822d86b0337407514b9372562b86edfa91cdAndreas Huber ret.push_back(stats.cacheSize); 14135778822d86b0337407514b9372562b86edfa91cdAndreas Huber ret.push_back(extStats.codeSize); 14145778822d86b0337407514b9372562b86edfa91cdAndreas Huber ret.push_back(extStats.dataSize); 14155778822d86b0337407514b9372562b86edfa91cdAndreas Huber ret.push_back(extStats.cacheSize); 14165778822d86b0337407514b9372562b86edfa91cdAndreas Huber#if MEASURE_DEBUG 14175778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(DEBUG) << "Final result " << toString(ret); 14185778822d86b0337407514b9372562b86edfa91cdAndreas Huber#endif 1419c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang *_aidl_return = ret; 14205778822d86b0337407514b9372562b86edfa91cdAndreas Huber return ok(); 14215778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 14225778822d86b0337407514b9372562b86edfa91cdAndreas Huber 14235778822d86b0337407514b9372562b86edfa91cdAndreas Huberbinder::Status InstalldNativeService::getUserSize(const std::unique_ptr<std::string>& uuid, 14245778822d86b0337407514b9372562b86edfa91cdAndreas Huber int32_t userId, int32_t flags, const std::vector<int32_t>& appIds, 14255778822d86b0337407514b9372562b86edfa91cdAndreas Huber std::vector<int64_t>* _aidl_return) { 14265778822d86b0337407514b9372562b86edfa91cdAndreas Huber ENFORCE_UID(AID_SYSTEM); 14275778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_ARGUMENT_UUID(uuid); 14285778822d86b0337407514b9372562b86edfa91cdAndreas Huber // NOTE: Locking is relaxed on this method, since it's limited to 14295778822d86b0337407514b9372562b86edfa91cdAndreas Huber // read-only measurements without mutation. 14305778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1431251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung // When modifying this logic, always verify using tests: 1432c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang // runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetUserSize 14335778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1434251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung#if MEASURE_DEBUG 1435251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung LOG(INFO) << "Measuring user " << userId; 1436251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung#endif 14375778822d86b0337407514b9372562b86edfa91cdAndreas Huber 14385778822d86b0337407514b9372562b86edfa91cdAndreas Huber struct stats stats; 14395778822d86b0337407514b9372562b86edfa91cdAndreas Huber struct stats extStats; 14405778822d86b0337407514b9372562b86edfa91cdAndreas Huber memset(&stats, 0, sizeof(stats)); 1441c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang memset(&extStats, 0, sizeof(extStats)); 14425778822d86b0337407514b9372562b86edfa91cdAndreas Huber 14435778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* uuid_ = uuid ? uuid->c_str() : nullptr; 14445778822d86b0337407514b9372562b86edfa91cdAndreas Huber 14455778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto device = findQuotaDeviceForUuid(uuid); 14465778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (device.empty()) { 14475778822d86b0337407514b9372562b86edfa91cdAndreas Huber flags &= ~FLAG_USE_QUOTA; 14485778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 14495778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1450c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang if (flags & FLAG_USE_QUOTA) { 1451c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang struct dqblk dq; 1452c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 1453c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang ATRACE_BEGIN("obb"); 1454c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), AID_MEDIA_OBB, 1455c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang reinterpret_cast<char*>(&dq)) != 0) { 14565778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (errno != ESRCH) { 14575778822d86b0337407514b9372562b86edfa91cdAndreas Huber PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << AID_MEDIA_OBB; 14585778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 14595778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 14605778822d86b0337407514b9372562b86edfa91cdAndreas Huber#if MEASURE_DEBUG 14615778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(DEBUG) << "quotactl() for GID " << AID_MEDIA_OBB << " " << dq.dqb_curspace; 14625778822d86b0337407514b9372562b86edfa91cdAndreas Huber#endif 14635778822d86b0337407514b9372562b86edfa91cdAndreas Huber extStats.codeSize += dq.dqb_curspace; 1464c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 14655778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_END(); 14665778822d86b0337407514b9372562b86edfa91cdAndreas Huber 14675778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_BEGIN("code"); 14685778822d86b0337407514b9372562b86edfa91cdAndreas Huber calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize, -1, -1, true); 14695778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_END(); 14705778822d86b0337407514b9372562b86edfa91cdAndreas Huber 14715778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_BEGIN("data"); 14725778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto cePath = create_data_user_ce_path(uuid_, userId); 14735778822d86b0337407514b9372562b86edfa91cdAndreas Huber collectManualStatsForUser(cePath, &stats, true); 14745778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto dePath = create_data_user_de_path(uuid_, userId); 14755778822d86b0337407514b9372562b86edfa91cdAndreas Huber collectManualStatsForUser(dePath, &stats, true); 14765778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_END(); 14775778822d86b0337407514b9372562b86edfa91cdAndreas Huber 14785778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_BEGIN("profile"); 14795778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto userProfilePath = create_primary_cur_profile_dir_path(userId); 14805778822d86b0337407514b9372562b86edfa91cdAndreas Huber calculate_tree_size(userProfilePath, &stats.dataSize, -1, -1, true); 14815778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto refProfilePath = create_primary_ref_profile_dir_path(); 14825778822d86b0337407514b9372562b86edfa91cdAndreas Huber calculate_tree_size(refProfilePath, &stats.codeSize, -1, -1, true); 14835778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_END(); 14845778822d86b0337407514b9372562b86edfa91cdAndreas Huber 14855778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_BEGIN("external"); 14865778822d86b0337407514b9372562b86edfa91cdAndreas Huber uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW); 14875778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid, 14885778822d86b0337407514b9372562b86edfa91cdAndreas Huber reinterpret_cast<char*>(&dq)) != 0) { 14895778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (errno != ESRCH) { 14905778822d86b0337407514b9372562b86edfa91cdAndreas Huber PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid; 14915778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 14925778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 1493c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang#if MEASURE_DEBUG 14945778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace; 14955778822d86b0337407514b9372562b86edfa91cdAndreas Huber#endif 14965778822d86b0337407514b9372562b86edfa91cdAndreas Huber extStats.dataSize += dq.dqb_curspace; 14975778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 14985778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_END(); 14995778822d86b0337407514b9372562b86edfa91cdAndreas Huber 15005778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_BEGIN("dalvik"); 15015778822d86b0337407514b9372562b86edfa91cdAndreas Huber calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize, 15025778822d86b0337407514b9372562b86edfa91cdAndreas Huber -1, -1, true); 15035778822d86b0337407514b9372562b86edfa91cdAndreas Huber calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize, 15045778822d86b0337407514b9372562b86edfa91cdAndreas Huber -1, -1, true); 1505251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung ATRACE_END(); 1506c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 15075778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_BEGIN("quota"); 1508251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung for (auto appId : appIds) { 1509251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung if (appId >= AID_APP_START) { 1510251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung collectQuotaStats(device, userId, appId, &stats, &extStats); 15115778822d86b0337407514b9372562b86edfa91cdAndreas Huber#if MEASURE_DEBUG 15125778822d86b0337407514b9372562b86edfa91cdAndreas Huber // Sleep to make sure we don't lose logs 15135778822d86b0337407514b9372562b86edfa91cdAndreas Huber usleep(1); 15145778822d86b0337407514b9372562b86edfa91cdAndreas Huber#endif 1515c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 15165778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 15175778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_END(); 15185778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 15197cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden ATRACE_BEGIN("obb"); 15207cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden auto obbPath = create_data_path(uuid_) + "/media/obb"; 15217cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden calculate_tree_size(obbPath, &extStats.codeSize); 15227cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden ATRACE_END(); 15237cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden 1524251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung ATRACE_BEGIN("code"); 1525c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize); 15267cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden ATRACE_END(); 1527251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung 1528251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung ATRACE_BEGIN("data"); 1529251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung auto cePath = create_data_user_ce_path(uuid_, userId); 15307cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden collectManualStatsForUser(cePath, &stats); 15317cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden auto dePath = create_data_user_de_path(uuid_, userId); 15327cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden collectManualStatsForUser(dePath, &stats); 15337cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden ATRACE_END(); 15347cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden 15357cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden ATRACE_BEGIN("profile"); 15367cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden auto userProfilePath = create_primary_cur_profile_dir_path(userId); 15375778822d86b0337407514b9372562b86edfa91cdAndreas Huber calculate_tree_size(userProfilePath, &stats.dataSize); 15385778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto refProfilePath = create_primary_ref_profile_dir_path(); 15395778822d86b0337407514b9372562b86edfa91cdAndreas Huber calculate_tree_size(refProfilePath, &stats.codeSize); 15405778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_END(); 15415778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1542251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung ATRACE_BEGIN("external"); 1543c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang auto dataMediaPath = create_data_media_path(uuid_, userId); 15445778822d86b0337407514b9372562b86edfa91cdAndreas Huber collectManualExternalStatsForUser(dataMediaPath, &extStats); 1545251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung#if MEASURE_DEBUG 1546251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung LOG(DEBUG) << "Measured external data " << extStats.dataSize << " cache " 1547251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung << extStats.cacheSize; 15485778822d86b0337407514b9372562b86edfa91cdAndreas Huber#endif 15495778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_END(); 15505778822d86b0337407514b9372562b86edfa91cdAndreas Huber 15515778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_BEGIN("dalvik"); 15525778822d86b0337407514b9372562b86edfa91cdAndreas Huber calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize); 15535778822d86b0337407514b9372562b86edfa91cdAndreas Huber calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize); 15545778822d86b0337407514b9372562b86edfa91cdAndreas Huber ATRACE_END(); 15555778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 15565778822d86b0337407514b9372562b86edfa91cdAndreas Huber 15575778822d86b0337407514b9372562b86edfa91cdAndreas Huber std::vector<int64_t> ret; 15585778822d86b0337407514b9372562b86edfa91cdAndreas Huber ret.push_back(stats.codeSize); 15595778822d86b0337407514b9372562b86edfa91cdAndreas Huber ret.push_back(stats.dataSize); 15605778822d86b0337407514b9372562b86edfa91cdAndreas Huber ret.push_back(stats.cacheSize); 15615778822d86b0337407514b9372562b86edfa91cdAndreas Huber ret.push_back(extStats.codeSize); 1562ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber ret.push_back(extStats.dataSize); 15631bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber ret.push_back(extStats.cacheSize); 1564ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber#if MEASURE_DEBUG 15655778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(DEBUG) << "Final result " << toString(ret); 15665778822d86b0337407514b9372562b86edfa91cdAndreas Huber#endif 15675778822d86b0337407514b9372562b86edfa91cdAndreas Huber *_aidl_return = ret; 15685778822d86b0337407514b9372562b86edfa91cdAndreas Huber return ok(); 15695778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 15705778822d86b0337407514b9372562b86edfa91cdAndreas Huber 15715778822d86b0337407514b9372562b86edfa91cdAndreas Huberbinder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std::string>& uuid, 15725778822d86b0337407514b9372562b86edfa91cdAndreas Huber int32_t userId, int32_t flags, std::vector<int64_t>* _aidl_return) { 15735778822d86b0337407514b9372562b86edfa91cdAndreas Huber ENFORCE_UID(AID_SYSTEM); 15745778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_ARGUMENT_UUID(uuid); 15755778822d86b0337407514b9372562b86edfa91cdAndreas Huber // NOTE: Locking is relaxed on this method, since it's limited to 1576251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung // read-only measurements without mutation. 1577c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 15785778822d86b0337407514b9372562b86edfa91cdAndreas Huber // When modifying this logic, always verify using tests: 1579251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung // runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetExternalSize 1580251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung 1581251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung#if MEASURE_DEBUG 15825778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(INFO) << "Measuring external " << userId; 15835778822d86b0337407514b9372562b86edfa91cdAndreas Huber#endif 15845778822d86b0337407514b9372562b86edfa91cdAndreas Huber 15850e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar const char* uuid_ = uuid ? uuid->c_str() : nullptr; 15865778822d86b0337407514b9372562b86edfa91cdAndreas Huber 15875778822d86b0337407514b9372562b86edfa91cdAndreas Huber int64_t totalSize = 0; 15885778822d86b0337407514b9372562b86edfa91cdAndreas Huber int64_t audioSize = 0; 15895778822d86b0337407514b9372562b86edfa91cdAndreas Huber int64_t videoSize = 0; 15905778822d86b0337407514b9372562b86edfa91cdAndreas Huber int64_t imageSize = 0; 15915778822d86b0337407514b9372562b86edfa91cdAndreas Huber 15925778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto device = findQuotaDeviceForUuid(uuid); 1593e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar if (device.empty()) { 15945778822d86b0337407514b9372562b86edfa91cdAndreas Huber flags &= ~FLAG_USE_QUOTA; 15955778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 1596e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar 1597e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar if (flags & FLAG_USE_QUOTA) { 1598e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar struct dqblk dq; 15995778822d86b0337407514b9372562b86edfa91cdAndreas Huber 16005778822d86b0337407514b9372562b86edfa91cdAndreas Huber uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW); 16015778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid, 1602e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar reinterpret_cast<char*>(&dq)) != 0) { 16030e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar if (errno != ESRCH) { 16040e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid; 1605e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar } 1606c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } else { 16075778822d86b0337407514b9372562b86edfa91cdAndreas Huber#if MEASURE_DEBUG 1608251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace; 1609251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung#endif 1610251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung totalSize = dq.dqb_curspace; 16115778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 16125778822d86b0337407514b9372562b86edfa91cdAndreas Huber 16135778822d86b0337407514b9372562b86edfa91cdAndreas Huber gid_t audioGid = multiuser_get_uid(userId, AID_MEDIA_AUDIO); 1614e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), audioGid, 16155778822d86b0337407514b9372562b86edfa91cdAndreas Huber reinterpret_cast<char*>(&dq)) == 0) { 16165778822d86b0337407514b9372562b86edfa91cdAndreas Huber#if MEASURE_DEBUG 16175778822d86b0337407514b9372562b86edfa91cdAndreas Huber LOG(DEBUG) << "quotactl() for GID " << audioGid << " " << dq.dqb_curspace; 16185778822d86b0337407514b9372562b86edfa91cdAndreas Huber#endif 1619496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber audioSize = dq.dqb_curspace; 1620496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber } 1621496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber gid_t videoGid = multiuser_get_uid(userId, AID_MEDIA_VIDEO); 1622496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), videoGid, 1623496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber reinterpret_cast<char*>(&dq)) == 0) { 1624496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber#if MEASURE_DEBUG 1625575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber LOG(DEBUG) << "quotactl() for GID " << videoGid << " " << dq.dqb_curspace; 1626575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber#endif 1627575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber videoSize = dq.dqb_curspace; 1628575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber } 1629575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber gid_t imageGid = multiuser_get_uid(userId, AID_MEDIA_IMAGE); 1630575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), imageGid, 1631575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber reinterpret_cast<char*>(&dq)) == 0) { 1632575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber#if MEASURE_DEBUG 1633575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber LOG(DEBUG) << "quotactl() for GID " << imageGid << " " << dq.dqb_curspace; 1634717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo#endif 1635717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo imageSize = dq.dqb_curspace; 1636717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo } 1637717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo } else { 1638717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo FTS *fts; 1639717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo FTSENT *p; 1640c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang auto path = create_data_media_path(uuid_, userId); 1641717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo char *argv[] = { (char*) path.c_str(), nullptr }; 1642717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) { 1643717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo return error("Failed to fts_open " + path); 1644717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo } 1645717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo while ((p = fts_read(fts)) != NULL) { 1646717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo char* ext; 1647717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo int64_t size = (p->fts_statp->st_blocks * 512); 1648717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo switch (p->fts_info) { 1649717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo case FTS_F: 1650a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber // Only categorize files not belonging to apps 1651a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber if (p->fts_parent->fts_number == 0) { 1652a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber ext = strrchr(p->fts_name, '.'); 1653a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber if (ext != nullptr) { 1654a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber switch (MatchExtension(++ext)) { 1655a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber case AID_MEDIA_AUDIO: audioSize += size; break; 1656a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber case AID_MEDIA_VIDEO: videoSize += size; break; 1657a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber case AID_MEDIA_IMAGE: imageSize += size; break; 1658a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber } 1659a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber } 1660c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 1661a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber // Fall through to always count against total 1662a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber case FTS_D: 1663a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber // Ignore data belonging to specific apps 16645778822d86b0337407514b9372562b86edfa91cdAndreas Huber p->fts_number = p->fts_parent->fts_number; 16655778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (p->fts_level == 1 && !strcmp(p->fts_name, "Android")) { 16665778822d86b0337407514b9372562b86edfa91cdAndreas Huber p->fts_number = 1; 16675778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 16685778822d86b0337407514b9372562b86edfa91cdAndreas Huber case FTS_DEFAULT: 16698ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber case FTS_SL: 16708ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber case FTS_SLNONE: 16718ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber totalSize += size; 16728ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber break; 16738ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber } 16748ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber } 16758ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber fts_close(fts); 16768ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber } 16778ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber 16788ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber std::vector<int64_t> ret; 16798ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber ret.push_back(totalSize); 16808ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber ret.push_back(audioSize); 16818ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber ret.push_back(videoSize); 16828ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber ret.push_back(imageSize); 1683a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#if MEASURE_DEBUG 16848ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber LOG(DEBUG) << "Final result " << toString(ret); 16858ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber#endif 16868ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber *_aidl_return = ret; 16878ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber return ok(); 16888ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber} 16897bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar 16907bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnarbinder::Status InstalldNativeService::setAppQuota(const std::unique_ptr<std::string>& uuid, 16918ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber int32_t userId, int32_t appId, int64_t cacheQuota) { 16928ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber ENFORCE_UID(AID_SYSTEM); 16938ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber CHECK_ARGUMENT_UUID(uuid); 16948ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock); 16958ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber 16968ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber int32_t uid = multiuser_get_uid(userId, appId); 16978ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber mCacheQuotas[uid] = cacheQuota; 16988ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber 16998ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber return ok(); 17008ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber} 17018ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber 17028ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber// Dumps the contents of a profile file, using pkgname's dex files for pretty 17038ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber// printing the result. 17048ee516a515c70a492c395b67ce12e19e7d159804Andreas Huberbinder::Status InstalldNativeService::dumpProfiles(int32_t uid, const std::string& packageName, 17058ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber const std::string& codePaths, bool* _aidl_return) { 17068ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber ENFORCE_UID(AID_SYSTEM); 17078ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber CHECK_ARGUMENT_PACKAGE_NAME(packageName); 17088ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber std::lock_guard<std::recursive_mutex> lock(mLock); 17098ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber 17108ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber const char* pkgname = packageName.c_str(); 17118ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber const char* code_paths = codePaths.c_str(); 17128ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber 17138ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber *_aidl_return = dump_profiles(uid, pkgname, code_paths); 17148ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber return ok(); 17158ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber} 17168ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber 17175778822d86b0337407514b9372562b86edfa91cdAndreas Huber// TODO: Consider returning error codes. 17187541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huberbinder::Status InstalldNativeService::mergeProfiles(int32_t uid, const std::string& packageName, 17195778822d86b0337407514b9372562b86edfa91cdAndreas Huber bool* _aidl_return) { 17205778822d86b0337407514b9372562b86edfa91cdAndreas Huber ENFORCE_UID(AID_SYSTEM); 17215778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_ARGUMENT_PACKAGE_NAME(packageName); 17221bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber std::lock_guard<std::recursive_mutex> lock(mLock); 17237541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber 17245778822d86b0337407514b9372562b86edfa91cdAndreas Huber *_aidl_return = analyze_primary_profiles(uid, packageName); 1725671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar return ok(); 17265778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 17275778822d86b0337407514b9372562b86edfa91cdAndreas Huber 17285778822d86b0337407514b9372562b86edfa91cdAndreas Huberbinder::Status InstalldNativeService::dexopt(const std::string& apkPath, int32_t uid, 17295778822d86b0337407514b9372562b86edfa91cdAndreas Huber const std::unique_ptr<std::string>& packageName, const std::string& instructionSet, 1730e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber int32_t dexoptNeeded, const std::unique_ptr<std::string>& outputPath, int32_t dexFlags, 1731e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber const std::string& compilerFilter, const std::unique_ptr<std::string>& uuid, 1732c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang const std::unique_ptr<std::string>& sharedLibraries) { 1733251d4be8aa5ab80bc915a82a2420233bdc62018eAndy Hung ENFORCE_UID(AID_SYSTEM); 1734575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber CHECK_ARGUMENT_UUID(uuid); 1735575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber if (packageName && *packageName != "*") { 1736c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang CHECK_ARGUMENT_PACKAGE_NAME(*packageName); 17375778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 17385778822d86b0337407514b9372562b86edfa91cdAndreas Huber std::lock_guard<std::recursive_mutex> lock(mLock); 1739717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo 1740671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar const char* apk_path = apkPath.c_str(); 1741671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar const char* pkgname = packageName ? packageName->c_str() : "*"; 1742671160ffe81592efa376dc1ff0fc3f4ddcdebc35Lajos Molnar const char* instruction_set = instructionSet.c_str(); 1743717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo const char* oat_dir = outputPath ? outputPath->c_str() : nullptr; 1744aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber const char* compiler_filter = compilerFilter.c_str(); 1745aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber const char* volume_uuid = uuid ? uuid->c_str() : nullptr; 1746aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber const char* shared_libraries = sharedLibraries ? sharedLibraries->c_str() : nullptr; 1747aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber 1748aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber int res = android::installd::dexopt(apk_path, uid, pkgname, instruction_set, dexoptNeeded, 1749717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo oat_dir, dexFlags, compiler_filter, volume_uuid, shared_libraries); 1750717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo return res ? error(res, "Failed to dexopt") : ok(); 17515778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 17525778822d86b0337407514b9372562b86edfa91cdAndreas Huber 17535778822d86b0337407514b9372562b86edfa91cdAndreas Huberbinder::Status InstalldNativeService::markBootComplete(const std::string& instructionSet) { 17542606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang ENFORCE_UID(AID_SYSTEM); 17552606b10d51c2dceb851a2ea63e803aba4134bf00Chong Zhang std::lock_guard<std::recursive_mutex> lock(mLock); 17565778822d86b0337407514b9372562b86edfa91cdAndreas Huber 17575778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* instruction_set = instructionSet.c_str(); 17585778822d86b0337407514b9372562b86edfa91cdAndreas Huber 17595778822d86b0337407514b9372562b86edfa91cdAndreas Huber char boot_marker_path[PKG_PATH_MAX]; 17605778822d86b0337407514b9372562b86edfa91cdAndreas Huber sprintf(boot_marker_path, 17615778822d86b0337407514b9372562b86edfa91cdAndreas Huber "%s/%s/%s/.booting", 17625778822d86b0337407514b9372562b86edfa91cdAndreas Huber android_data_dir.path, 17635778822d86b0337407514b9372562b86edfa91cdAndreas Huber DALVIK_CACHE, 17645778822d86b0337407514b9372562b86edfa91cdAndreas Huber instruction_set); 17657bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar 17665778822d86b0337407514b9372562b86edfa91cdAndreas Huber ALOGV("mark_boot_complete : %s", boot_marker_path); 17675778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (unlink(boot_marker_path) != 0) { 17685778822d86b0337407514b9372562b86edfa91cdAndreas Huber return error(StringPrintf("Failed to unlink %s", boot_marker_path)); 17695778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 17705778822d86b0337407514b9372562b86edfa91cdAndreas Huber return ok(); 17715778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 17725778822d86b0337407514b9372562b86edfa91cdAndreas Huber 17735778822d86b0337407514b9372562b86edfa91cdAndreas Hubervoid mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid, 17745778822d86b0337407514b9372562b86edfa91cdAndreas Huber struct stat* statbuf) 17755778822d86b0337407514b9372562b86edfa91cdAndreas Huber{ 17765778822d86b0337407514b9372562b86edfa91cdAndreas Huber while (path[basepos] != 0) { 17775778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (path[basepos] == '/') { 17787fa015217e618265ff5a844cf6961ecc316c81a4Lajos Molnar path[basepos] = 0; 17797fa015217e618265ff5a844cf6961ecc316c81a4Lajos Molnar if (lstat(path, statbuf) < 0) { 17805778822d86b0337407514b9372562b86edfa91cdAndreas Huber ALOGV("Making directory: %s\n", path); 17815778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (mkdir(path, mode) == 0) { 17825778822d86b0337407514b9372562b86edfa91cdAndreas Huber chown(path, uid, gid); 17835778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 17845778822d86b0337407514b9372562b86edfa91cdAndreas Huber ALOGW("Unable to make directory %s: %s\n", path, strerror(errno)); 17855778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 17865778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 17875778822d86b0337407514b9372562b86edfa91cdAndreas Huber path[basepos] = '/'; 17885778822d86b0337407514b9372562b86edfa91cdAndreas Huber basepos++; 17895778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 17905778822d86b0337407514b9372562b86edfa91cdAndreas Huber basepos++; 17915778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 1792609b815a3131d22da38b2f452faa9f89daad4039Andy Hung} 1793609b815a3131d22da38b2f452faa9f89daad4039Andy Hung 17945778822d86b0337407514b9372562b86edfa91cdAndreas Huberbinder::Status InstalldNativeService::linkNativeLibraryDirectory( 17955778822d86b0337407514b9372562b86edfa91cdAndreas Huber const std::unique_ptr<std::string>& uuid, const std::string& packageName, 17965778822d86b0337407514b9372562b86edfa91cdAndreas Huber const std::string& nativeLibPath32, int32_t userId) { 17975778822d86b0337407514b9372562b86edfa91cdAndreas Huber ENFORCE_UID(AID_SYSTEM); 17985778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_ARGUMENT_UUID(uuid); 17995778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_ARGUMENT_PACKAGE_NAME(packageName); 18005778822d86b0337407514b9372562b86edfa91cdAndreas Huber std::lock_guard<std::recursive_mutex> lock(mLock); 18015778822d86b0337407514b9372562b86edfa91cdAndreas Huber 18025778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* uuid_ = uuid ? uuid->c_str() : nullptr; 18035778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* pkgname = packageName.c_str(); 1804475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu const char* asecLibDir = nativeLibPath32.c_str(); 1805475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu struct stat s, libStat; 18065778822d86b0337407514b9372562b86edfa91cdAndreas Huber binder::Status res = ok(); 18075778822d86b0337407514b9372562b86edfa91cdAndreas Huber 18085778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto _pkgdir = create_data_user_ce_package_path(uuid_, userId, pkgname); 18095778822d86b0337407514b9372562b86edfa91cdAndreas Huber auto _libsymlink = _pkgdir + PKG_LIB_POSTFIX; 18105778822d86b0337407514b9372562b86edfa91cdAndreas Huber 18115778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* pkgdir = _pkgdir.c_str(); 18125778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* libsymlink = _libsymlink.c_str(); 18135778822d86b0337407514b9372562b86edfa91cdAndreas Huber 18145778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (stat(pkgdir, &s) < 0) { 18155778822d86b0337407514b9372562b86edfa91cdAndreas Huber return error("Failed to stat " + _pkgdir); 18165778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 18175778822d86b0337407514b9372562b86edfa91cdAndreas Huber 18185778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) { 18195778822d86b0337407514b9372562b86edfa91cdAndreas Huber return error("Failed to chown " + _pkgdir); 18205778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 18215778822d86b0337407514b9372562b86edfa91cdAndreas Huber 18225778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (chmod(pkgdir, 0700) < 0) { 18235778822d86b0337407514b9372562b86edfa91cdAndreas Huber res = error("Failed to chmod " + _pkgdir); 18245778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto out; 18255778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 18265778822d86b0337407514b9372562b86edfa91cdAndreas Huber 18275778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (lstat(libsymlink, &libStat) < 0) { 18284b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber if (errno != ENOENT) { 18294b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber res = error("Failed to stat " + _libsymlink); 18304b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber goto out; 18314b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } 18324b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } else { 18334b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber if (S_ISDIR(libStat.st_mode)) { 18344b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber if (delete_dir_contents(libsymlink, 1, NULL) < 0) { 18354b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber res = error("Failed to delete " + _libsymlink); 18364b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber goto out; 18374b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } 18384b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } else if (S_ISLNK(libStat.st_mode)) { 18394b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber if (unlink(libsymlink) < 0) { 18404b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber res = error("Failed to unlink " + _libsymlink); 18414b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber goto out; 18424b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } 18434b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } 18444b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } 18454b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber 18464b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber if (symlink(asecLibDir, libsymlink) < 0) { 18474b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber res = error("Failed to symlink " + _libsymlink + " to " + nativeLibPath32); 18484b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber goto out; 18494b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } 18504b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber 18514b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huberout: 18524b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber if (chmod(pkgdir, s.st_mode) < 0) { 18534b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber auto msg = "Failed to cleanup chmod " + _pkgdir; 18544b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber if (res.isOk()) { 18554b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber res = error(msg); 18564b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } else { 18574b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber PLOG(ERROR) << msg; 18584b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } 18594b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } 18604b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber 18614b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber if (chown(pkgdir, s.st_uid, s.st_gid) < 0) { 18624b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber auto msg = "Failed to cleanup chown " + _pkgdir; 18634b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber if (res.isOk()) { 18644b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber res = error(msg); 18654b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } else { 18664b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber PLOG(ERROR) << msg; 18674b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } 18684b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber } 18694b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber 18705778822d86b0337407514b9372562b86edfa91cdAndreas Huber return res; 18715778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 18725778822d86b0337407514b9372562b86edfa91cdAndreas Huber 18735778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatic void run_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd) 18745778822d86b0337407514b9372562b86edfa91cdAndreas Huber{ 18755778822d86b0337407514b9372562b86edfa91cdAndreas Huber static const char *IDMAP_BIN = "/system/bin/idmap"; 18765778822d86b0337407514b9372562b86edfa91cdAndreas Huber static const size_t MAX_INT_LEN = 32; 18775778822d86b0337407514b9372562b86edfa91cdAndreas Huber char idmap_str[MAX_INT_LEN]; 18785778822d86b0337407514b9372562b86edfa91cdAndreas Huber 18795778822d86b0337407514b9372562b86edfa91cdAndreas Huber snprintf(idmap_str, sizeof(idmap_str), "%d", idmap_fd); 18805778822d86b0337407514b9372562b86edfa91cdAndreas Huber 18815778822d86b0337407514b9372562b86edfa91cdAndreas Huber execl(IDMAP_BIN, IDMAP_BIN, "--fd", target_apk, overlay_apk, idmap_str, (char*)NULL); 18825778822d86b0337407514b9372562b86edfa91cdAndreas Huber ALOGE("execl(%s) failed: %s\n", IDMAP_BIN, strerror(errno)); 18835778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 18845778822d86b0337407514b9372562b86edfa91cdAndreas Huber 18855778822d86b0337407514b9372562b86edfa91cdAndreas Huber// Transform string /a/b/c.apk to (prefix)/a@b@c.apk@(suffix) 18865778822d86b0337407514b9372562b86edfa91cdAndreas Huber// eg /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap 18875778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatic int flatten_path(const char *prefix, const char *suffix, 18885778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char *overlay_path, char *idmap_path, size_t N) 18895778822d86b0337407514b9372562b86edfa91cdAndreas Huber{ 18905778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (overlay_path == NULL || idmap_path == NULL) { 18915778822d86b0337407514b9372562b86edfa91cdAndreas Huber return -1; 18925778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 18935778822d86b0337407514b9372562b86edfa91cdAndreas Huber const size_t len_overlay_path = strlen(overlay_path); 18945778822d86b0337407514b9372562b86edfa91cdAndreas Huber // will access overlay_path + 1 further below; requires absolute path 18955778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (len_overlay_path < 2 || *overlay_path != '/') { 18961bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber return -1; 18971bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber } 18981bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber const size_t len_idmap_root = strlen(prefix); 1899ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber const size_t len_suffix = strlen(suffix); 1900ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber if (SIZE_MAX - len_idmap_root < len_overlay_path || 19015b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber SIZE_MAX - (len_idmap_root + len_overlay_path) < len_suffix) { 19025b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber // additions below would cause overflow 19035b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber return -1; 1904fa2b8f243eb048fb2b8e5a14356190f69eb31a36Edwin Wong } 19051bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber if (N < len_idmap_root + len_overlay_path + len_suffix) { 19061bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber return -1; 19071bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber } 19081bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber memset(idmap_path, 0, N); 19091bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber snprintf(idmap_path, N, "%s%s%s", prefix, overlay_path + 1, suffix); 19104b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber char *ch = idmap_path + len_idmap_root; 19114b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber while (*ch != '\0') { 19125b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber if (*ch == '/') { 19135b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber *ch = '@'; 19141bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber } 1915fa2b8f243eb048fb2b8e5a14356190f69eb31a36Edwin Wong ++ch; 1916fa2b8f243eb048fb2b8e5a14356190f69eb31a36Edwin Wong } 1917ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber return 0; 1918ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber} 1919fa2b8f243eb048fb2b8e5a14356190f69eb31a36Edwin Wong 1920ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huberbinder::Status InstalldNativeService::idmap(const std::string& targetApkPath, 1921ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber const std::string& overlayApkPath, int32_t uid) { 19227bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar ENFORCE_UID(AID_SYSTEM); 19237bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar std::lock_guard<std::recursive_mutex> lock(mLock); 19247bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar 19257bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar const char* target_apk = targetApkPath.c_str(); 19267bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar const char* overlay_apk = overlayApkPath.c_str(); 19272d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber ALOGV("idmap target_apk=%s overlay_apk=%s uid=%d\n", target_apk, overlay_apk, uid); 19285778822d86b0337407514b9372562b86edfa91cdAndreas Huber 19295778822d86b0337407514b9372562b86edfa91cdAndreas Huber int idmap_fd = -1; 19305b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber char idmap_path[PATH_MAX]; 19315b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber 19325778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk, 19335778822d86b0337407514b9372562b86edfa91cdAndreas Huber idmap_path, sizeof(idmap_path)) == -1) { 19345778822d86b0337407514b9372562b86edfa91cdAndreas Huber ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk); 19355778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto fail; 19365778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 19375778822d86b0337407514b9372562b86edfa91cdAndreas Huber 19385778822d86b0337407514b9372562b86edfa91cdAndreas Huber unlink(idmap_path); 19395778822d86b0337407514b9372562b86edfa91cdAndreas Huber idmap_fd = open(idmap_path, O_RDWR | O_CREAT | O_EXCL, 0644); 19405778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (idmap_fd < 0) { 19415778822d86b0337407514b9372562b86edfa91cdAndreas Huber ALOGE("idmap cannot open '%s' for output: %s\n", idmap_path, strerror(errno)); 19425778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto fail; 19435778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 19440e8cfc36044ba97545e7c9e129b0b3e98eec5089Lajos Molnar if (fchown(idmap_fd, AID_SYSTEM, uid) < 0) { 19455778822d86b0337407514b9372562b86edfa91cdAndreas Huber ALOGE("idmap cannot chown '%s'\n", idmap_path); 19465778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto fail; 19475778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 19485778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (fchmod(idmap_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) { 19495778822d86b0337407514b9372562b86edfa91cdAndreas Huber ALOGE("idmap cannot chmod '%s'\n", idmap_path); 19505778822d86b0337407514b9372562b86edfa91cdAndreas Huber goto fail; 19515778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 19525778822d86b0337407514b9372562b86edfa91cdAndreas Huber 19535778822d86b0337407514b9372562b86edfa91cdAndreas Huber pid_t pid; 19545778822d86b0337407514b9372562b86edfa91cdAndreas Huber pid = fork(); 19555778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (pid == 0) { 19565778822d86b0337407514b9372562b86edfa91cdAndreas Huber /* child -- drop privileges before continuing */ 19575778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (setgid(uid) != 0) { 19587bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar ALOGE("setgid(%d) failed during idmap\n", uid); 19597bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar exit(1); 19607bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar } 19617bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar if (setuid(uid) != 0) { 19627bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar ALOGE("setuid(%d) failed during idmap\n", uid); 19637bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar exit(1); 196479ee2399b67c7a11042c5904dc1309712a76f8cbJianzheng Zhou } 19655778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (flock(idmap_fd, LOCK_EX | LOCK_NB) != 0) { 19665778822d86b0337407514b9372562b86edfa91cdAndreas Huber ALOGE("flock(%s) failed during idmap: %s\n", idmap_path, strerror(errno)); 1967fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar exit(1); 1968fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar } 1969fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar 1970fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar run_idmap(target_apk, overlay_apk, idmap_fd); 1971fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar exit(1); /* only if exec call to idmap failed */ 1972fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar } else { 1973fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar int status = wait_child(pid); 1974fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar if (status != 0) { 1975fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar ALOGE("idmap failed, status=0x%04x\n", status); 1976fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar goto fail; 197747aea1f7c58f5302b16822f9e7e1763f2af04ef5Lajos Molnar } 1978fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar } 1979fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar 1980fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar close(idmap_fd); 1981fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar return ok(); 1982fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnarfail: 19835778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (idmap_fd >= 0) { 19845778822d86b0337407514b9372562b86edfa91cdAndreas Huber close(idmap_fd); 1985475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu unlink(idmap_path); 1986475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu } 19875778822d86b0337407514b9372562b86edfa91cdAndreas Huber return error(); 19885778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 19895778822d86b0337407514b9372562b86edfa91cdAndreas Huber 19905778822d86b0337407514b9372562b86edfa91cdAndreas Huberbinder::Status InstalldNativeService::removeIdmap(const std::string& overlayApkPath) { 19915778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char* overlay_apk = overlayApkPath.c_str(); 19925778822d86b0337407514b9372562b86edfa91cdAndreas Huber char idmap_path[PATH_MAX]; 19935778822d86b0337407514b9372562b86edfa91cdAndreas Huber 19945778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk, 19955778822d86b0337407514b9372562b86edfa91cdAndreas Huber idmap_path, sizeof(idmap_path)) == -1) { 19965778822d86b0337407514b9372562b86edfa91cdAndreas Huber ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk); 19975778822d86b0337407514b9372562b86edfa91cdAndreas Huber return error(); 19985778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 19995778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (unlink(idmap_path) < 0) { 20005778822d86b0337407514b9372562b86edfa91cdAndreas Huber ALOGE("couldn't unlink idmap file %s\n", idmap_path); 20015778822d86b0337407514b9372562b86edfa91cdAndreas Huber return error(); 20025778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 20035778822d86b0337407514b9372562b86edfa91cdAndreas Huber return ok(); 20045778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 20055778822d86b0337407514b9372562b86edfa91cdAndreas Huber 20065778822d86b0337407514b9372562b86edfa91cdAndreas Huberbinder::Status InstalldNativeService::restoreconAppData(const std::unique_ptr<std::string>& uuid, 20075778822d86b0337407514b9372562b86edfa91cdAndreas Huber const std::string& packageName, int32_t userId, int32_t flags, int32_t appId, 20085778822d86b0337407514b9372562b86edfa91cdAndreas Huber const std::string& seInfo) { 20095778822d86b0337407514b9372562b86edfa91cdAndreas Huber ENFORCE_UID(AID_SYSTEM); 20107bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar CHECK_ARGUMENT_UUID(uuid); 20117bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar CHECK_ARGUMENT_PACKAGE_NAME(packageName); 20127bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar std::lock_guard<std::recursive_mutex> lock(mLock); 201303c556ae1eb409ad088c49037e185946c54e1d25Lajos Molnar 201403c556ae1eb409ad088c49037e185946c54e1d25Lajos Molnar binder::Status res = ok(); 201503c556ae1eb409ad088c49037e185946c54e1d25Lajos Molnar 201603c556ae1eb409ad088c49037e185946c54e1d25Lajos Molnar // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here. 201703c556ae1eb409ad088c49037e185946c54e1d25Lajos Molnar unsigned int seflags = SELINUX_ANDROID_RESTORECON_RECURSE; 201803c556ae1eb409ad088c49037e185946c54e1d25Lajos Molnar const char* uuid_ = uuid ? uuid->c_str() : nullptr; 201903c556ae1eb409ad088c49037e185946c54e1d25Lajos Molnar const char* pkgName = packageName.c_str(); 202003c556ae1eb409ad088c49037e185946c54e1d25Lajos Molnar const char* seinfo = seInfo.c_str(); 202103c556ae1eb409ad088c49037e185946c54e1d25Lajos Molnar 202203c556ae1eb409ad088c49037e185946c54e1d25Lajos Molnar uid_t uid = multiuser_get_uid(userId, appId); 202303c556ae1eb409ad088c49037e185946c54e1d25Lajos Molnar if (flags & FLAG_STORAGE_CE) { 202403c556ae1eb409ad088c49037e185946c54e1d25Lajos Molnar auto path = create_data_user_ce_package_path(uuid_, userId, pkgName); 20257bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, seflags) < 0) { 20265778822d86b0337407514b9372562b86edfa91cdAndreas Huber res = error("restorecon failed for " + path); 20275778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 20285778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 20295778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (flags & FLAG_STORAGE_DE) { 20307541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber auto path = create_data_user_de_package_path(uuid_, userId, pkgName); 20311a2952aee048ca7b1765e2bc09ebe9aeddaeafa3Mathias Agopian if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, seflags) < 0) { 20327541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber res = error("restorecon failed for " + path); 20337541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber } 20347541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber } 20357541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber return res; 20367541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber} 20377541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber 20387541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huberbinder::Status InstalldNativeService::createOatDir(const std::string& oatDir, 20397541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber const std::string& instructionSet) { 20407541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber ENFORCE_UID(AID_SYSTEM); 20417541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber std::lock_guard<std::recursive_mutex> lock(mLock); 20427541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber 20437541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber const char* oat_dir = oatDir.c_str(); 20447541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber const char* instruction_set = instructionSet.c_str(); 20457541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber char oat_instr_dir[PKG_PATH_MAX]; 20467541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber 20477541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber if (validate_apk_path(oat_dir)) { 20487541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber return error("Invalid path " + oatDir); 20497541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber } 20507541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber if (fs_prepare_dir(oat_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) { 20517541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber return error("Failed to prepare " + oatDir); 20527541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber } 20537541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber if (selinux_android_restorecon(oat_dir, 0)) { 20547541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber return error("Failed to restorecon " + oatDir); 20557541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber } 20567541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber snprintf(oat_instr_dir, PKG_PATH_MAX, "%s/%s", oat_dir, instruction_set); 20577541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber if (fs_prepare_dir(oat_instr_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) { 20587541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber return error(StringPrintf("Failed to prepare %s", oat_instr_dir)); 20597541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber } 20607541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber return ok(); 20617541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber} 20627541ff5d83a3e77cb533841a0326a241550b95d9Andreas Huber 2063c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhangbinder::Status InstalldNativeService::rmPackageDir(const std::string& packageDir) { 2064c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang ENFORCE_UID(AID_SYSTEM); 2065c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang std::lock_guard<std::recursive_mutex> lock(mLock); 2066c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 2067c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang if (validate_apk_path(packageDir.c_str())) { 2068c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang return error("Invalid path " + packageDir); 2069c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 2070c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang if (delete_dir_contents_and_dir(packageDir) != 0) { 2071c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang return error("Failed to delete " + packageDir); 2072c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 2073c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang return ok(); 2074c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang} 2075c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 2076c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhangbinder::Status InstalldNativeService::linkFile(const std::string& relativePath, 2077c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang const std::string& fromBase, const std::string& toBase) { 2078c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang ENFORCE_UID(AID_SYSTEM); 2079c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang std::lock_guard<std::recursive_mutex> lock(mLock); 2080c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 2081c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang const char* relative_path = relativePath.c_str(); 2082c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang const char* from_base = fromBase.c_str(); 2083c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang const char* to_base = toBase.c_str(); 2084c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang char from_path[PKG_PATH_MAX]; 2085c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang char to_path[PKG_PATH_MAX]; 2086c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang snprintf(from_path, PKG_PATH_MAX, "%s/%s", from_base, relative_path); 2087c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang snprintf(to_path, PKG_PATH_MAX, "%s/%s", to_base, relative_path); 2088c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 2089c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang if (validate_apk_path_subdirs(from_path)) { 2090c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang return error(StringPrintf("Invalid from path %s", from_path)); 2091c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 2092c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 2093c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang if (validate_apk_path_subdirs(to_path)) { 2094c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang return error(StringPrintf("Invalid to path %s", to_path)); 2095c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 2096c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 2097c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang if (link(from_path, to_path) < 0) { 2098c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang return error(StringPrintf("Failed to link from %s to %s", from_path, to_path)); 2099c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang } 2100c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 2101c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang return ok(); 2102c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang} 2103c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 2104c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhangbinder::Status InstalldNativeService::moveAb(const std::string& apkPath, 2105c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang const std::string& instructionSet, const std::string& outputPath) { 2106c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang ENFORCE_UID(AID_SYSTEM); 2107c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang std::lock_guard<std::recursive_mutex> lock(mLock); 2108c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 2109749dafad09d85f2aaf6902a7ff16b4087e3bc4c7Chong Zhang const char* apk_path = apkPath.c_str(); 2110c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang const char* instruction_set = instructionSet.c_str(); 2111c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang const char* oat_dir = outputPath.c_str(); 2112c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 2113c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang bool success = move_ab(apk_path, instruction_set, oat_dir); 2114749dafad09d85f2aaf6902a7ff16b4087e3bc4c7Chong Zhang return success ? ok() : error(); 2115749dafad09d85f2aaf6902a7ff16b4087e3bc4c7Chong Zhang} 2116749dafad09d85f2aaf6902a7ff16b4087e3bc4c7Chong Zhang 2117749dafad09d85f2aaf6902a7ff16b4087e3bc4c7Chong Zhangbinder::Status InstalldNativeService::deleteOdex(const std::string& apkPath, 2118749dafad09d85f2aaf6902a7ff16b4087e3bc4c7Chong Zhang const std::string& instructionSet, const std::string& outputPath) { 2119c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang ENFORCE_UID(AID_SYSTEM); 2120c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang std::lock_guard<std::recursive_mutex> lock(mLock); 2121c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 2122c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang const char* apk_path = apkPath.c_str(); 2123c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang const char* instruction_set = instructionSet.c_str(); 2124c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang const char* oat_dir = outputPath.c_str(); 2125c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 2126c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang bool res = delete_odex(apk_path, instruction_set, oat_dir); 2127c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang return res ? ok() : error(); 2128c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang} 2129c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang 2130c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhangbinder::Status InstalldNativeService::reconcileSecondaryDexFile( 2131c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang const std::string& dexPath, const std::string& packageName, int32_t uid, 2132c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang const std::vector<std::string>& isas, const std::unique_ptr<std::string>& volumeUuid, 2133c5619c7a6dcc1137fde7520351ad5284e3e958abChong Zhang int32_t storage_flag, bool* _aidl_return) { 2134575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber ENFORCE_UID(AID_SYSTEM); 2135575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber CHECK_ARGUMENT_UUID(volumeUuid); 2136575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber CHECK_ARGUMENT_PACKAGE_NAME(packageName); 2137575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber 2138575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber std::lock_guard<std::recursive_mutex> lock(mLock); 2139575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber bool result = android::installd::reconcile_secondary_dex_file( 2140575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber dexPath, packageName, uid, isas, volumeUuid, storage_flag, _aidl_return); 2141575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber return result ? ok() : error(); 2142575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber} 2143575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber 2144575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huberbinder::Status InstalldNativeService::invalidateMounts() { 2145575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber ENFORCE_UID(AID_SYSTEM); 2146575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock); 2147575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber 2148575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber mQuotaDevices.clear(); 2149a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber 2150a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber std::ifstream in("/proc/mounts"); 2151a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber if (!in.is_open()) { 2152a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber return error("Failed to read mounts"); 2153a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber } 2154a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber 2155a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber std::string source; 2156a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber std::string target; 2157a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber std::string ignored; 2158a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber struct dqblk dq; 2159a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber while (!in.eof()) { 2160a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber std::getline(in, source, ' '); 2161a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber std::getline(in, target, ' '); 2162a2eb22c1de262aa3fa7c356537ac2fe165afdf3dAndreas Huber std::getline(in, ignored); 2163e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber 2164e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber if (source.compare(0, 11, "/dev/block/") == 0) { 2165e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0, 2166e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber reinterpret_cast<char*>(&dq)) == 0) { 2167e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber LOG(DEBUG) << "Found " << source << " with quota"; 2168e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber mQuotaDevices[target] = source; 2169e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber 2170e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber // ext4 only enables DQUOT_USAGE_ENABLED by default, so we 2171e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber // need to kick it again to enable DQUOT_LIMITS_ENABLED. 2172e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber if (quotactl(QCMD(Q_QUOTAON, USRQUOTA), source.c_str(), QFMT_VFS_V1, nullptr) != 0 2173e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber && errno != EBUSY) { 2174e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber PLOG(ERROR) << "Failed to enable USRQUOTA on " << source; 2175e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber } 2176e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber if (quotactl(QCMD(Q_QUOTAON, GRPQUOTA), source.c_str(), QFMT_VFS_V1, nullptr) != 0 2177e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber && errno != EBUSY) { 2178e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber PLOG(ERROR) << "Failed to enable GRPQUOTA on " << source; 2179e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber } 2180e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber } 2181e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber } 2182e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber } 2183e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber return ok(); 2184e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber} 2185e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber 2186e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huberstd::string InstalldNativeService::findQuotaDeviceForUuid( 2187e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber const std::unique_ptr<std::string>& uuid) { 2188e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock); 2189e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber auto path = create_data_path(uuid ? uuid->c_str() : nullptr); 2190e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber return mQuotaDevices[path]; 2191e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber} 2192e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber 2193e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huberbinder::Status InstalldNativeService::isQuotaSupported( 2194e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber const std::unique_ptr<std::string>& volumeUuid, bool* _aidl_return) { 2195e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber *_aidl_return = !findQuotaDeviceForUuid(volumeUuid).empty(); 2196e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber return ok(); 2197e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber} 2198e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber 2199e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber} // namespace installd 2200e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber} // namespace android 2201e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber