194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/*
294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood** Copyright 2008, The Android Open Source Project
394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood**
4d93707342a61e66bc3eb2145628158452f577f42Dave Allison** Licensed under the Apache License, Version 2.0 (the "License");
5d93707342a61e66bc3eb2145628158452f577f42Dave Allison** you may not use this file except in compliance with the License.
6d93707342a61e66bc3eb2145628158452f577f42Dave Allison** You may obtain a copy of the License at
794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood**
8d93707342a61e66bc3eb2145628158452f577f42Dave Allison**     http://www.apache.org/licenses/LICENSE-2.0
994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood**
10d93707342a61e66bc3eb2145628158452f577f42Dave Allison** Unless required by applicable law or agreed to in writing, software
11d93707342a61e66bc3eb2145628158452f577f42Dave Allison** distributed under the License is distributed on an "AS IS" BASIS,
12d93707342a61e66bc3eb2145628158452f577f42Dave Allison** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d93707342a61e66bc3eb2145628158452f577f42Dave Allison** See the License for the specific language governing permissions and
1494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood** limitations under the License.
1594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood*/
1694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
17f3e30b936ef103dc0f3d8697e0f86ba82b49609eJeff Sharkey#include "InstalldNativeService.h"
1802d0de56c75347a0cb8d5a8565dc8c4ee7616057Andreas Gampe
19466459b68da52edf20962c3c80e2fe0325569c18Jeff Sharkey#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
20466459b68da52edf20962c3c80e2fe0325569c18Jeff Sharkey
2102d0de56c75347a0cb8d5a8565dc8c4ee7616057Andreas Gampe#include <errno.h>
2202d0de56c75347a0cb8d5a8565dc8c4ee7616057Andreas Gampe#include <inttypes.h>
233dfae0c008576c873c4039bb4c2e54a6adf3720aJeff Sharkey#include <fstream>
243dfae0c008576c873c4039bb4c2e54a6adf3720aJeff Sharkey#include <fts.h>
250354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe#include <regex>
2602d0de56c75347a0cb8d5a8565dc8c4ee7616057Andreas Gampe#include <stdlib.h>
273dfae0c008576c873c4039bb4c2e54a6adf3720aJeff Sharkey#include <string.h>
2802d0de56c75347a0cb8d5a8565dc8c4ee7616057Andreas Gampe#include <sys/capability.h>
2902d0de56c75347a0cb8d5a8565dc8c4ee7616057Andreas Gampe#include <sys/file.h>
3002d0de56c75347a0cb8d5a8565dc8c4ee7616057Andreas Gampe#include <sys/resource.h>
313dfae0c008576c873c4039bb4c2e54a6adf3720aJeff Sharkey#include <sys/quota.h>
3202d0de56c75347a0cb8d5a8565dc8c4ee7616057Andreas Gampe#include <sys/stat.h>
333dfae0c008576c873c4039bb4c2e54a6adf3720aJeff Sharkey#include <sys/statvfs.h>
34cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey#include <sys/types.h>
356a1648e2f161cb1d7c46aa9d27e8062521a9f314Calin Juravle#include <sys/wait.h>
36cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey#include <sys/xattr.h>
3702d0de56c75347a0cb8d5a8565dc8c4ee7616057Andreas Gampe#include <unistd.h>
3841ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey
39afa58d175cc3e9adaa4f8df9bc7a8fac5798a50aAndreas Gampe#include <android-base/logging.h>
40e4ec9eb7b4c452493589983970ba5ccc501728d1Elliott Hughes#include <android-base/stringprintf.h>
416727c2d0bfc876c62d6ee60d8a05d26bef1d56efDavid Sehr#include <android-base/strings.h>
4264b59cc1c89225813295d1b5d6bf4183615da204Roland Levillain#include <android-base/unique_fd.h>
4302d0de56c75347a0cb8d5a8565dc8c4ee7616057Andreas Gampe#include <cutils/fs.h>
4490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey#include <cutils/properties.h>
450378aaf257aee92539d30543914a50c4481c6a18Brian Carlstrom#include <cutils/sched_policy.h>
467823e124e00576e20e47ec717cbe8bc89f0f2bf2Mark Salyzyn#include <log/log.h>               // TODO: Move everything to base/logging.
47e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey#include <logwrap/logwrap.h>
4802d0de56c75347a0cb8d5a8565dc8c4ee7616057Andreas Gampe#include <private/android_filesystem_config.h>
49e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey#include <selinux/android.h>
5002d0de56c75347a0cb8d5a8565dc8c4ee7616057Andreas Gampe#include <system/thread_defs.h>
51466459b68da52edf20962c3c80e2fe0325569c18Jeff Sharkey#include <utils/Trace.h>
52e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey
536c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey#include "dexopt.h"
54f3e30b936ef103dc0f3d8697e0f86ba82b49609eJeff Sharkey#include "globals.h"
55f3e30b936ef103dc0f3d8697e0f86ba82b49609eJeff Sharkey#include "installd_deps.h"
56f3e30b936ef103dc0f3d8697e0f86ba82b49609eJeff Sharkey#include "otapreopt_utils.h"
57f3e30b936ef103dc0f3d8697e0f86ba82b49609eJeff Sharkey#include "utils.h"
586c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey
5988ddd94834dae9c5862a07a1e4432b171b2f5d9fJeff Sharkey#include "CacheTracker.h"
60df2d754b38796e0c49c70e0a67f7d383e3079ff2Jeff Sharkey#include "MatchExtensionGen.h"
61df2d754b38796e0c49c70e0a67f7d383e3079ff2Jeff Sharkey
6202d0de56c75347a0cb8d5a8565dc8c4ee7616057Andreas Gampe#ifndef LOG_TAG
6302d0de56c75347a0cb8d5a8565dc8c4ee7616057Andreas Gampe#define LOG_TAG "installd"
6402d0de56c75347a0cb8d5a8565dc8c4ee7616057Andreas Gampe#endif
6541ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey
6641ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkeyusing android::base::StringPrintf;
6766b1a12e7a120f85042669bb58f1db864616b506Jeff Sharkeyusing std::endl;
6894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
6902d0de56c75347a0cb8d5a8565dc8c4ee7616057Andreas Gampenamespace android {
7002d0de56c75347a0cb8d5a8565dc8c4ee7616057Andreas Gampenamespace installd {
7194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
72cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkeystatic constexpr const char* kCpPath = "/system/bin/cp";
73cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkeystatic constexpr const char* kXattrDefault = "user.default";
74e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey
7540bd3eff694ef1c660af2806bcc51bb5ac038c16Janis Danisevskisstatic constexpr const int MIN_RESTRICTED_HOME_SDK_VERSION = 24; // > M
76eecb2d205366351af42fd0cd9e1a95de3980764eJanis Danisevskis
770354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampestatic constexpr const char* PKG_LIB_POSTFIX = "/lib";
780354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampestatic constexpr const char* CACHE_DIR_POSTFIX = "/cache";
790354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampestatic constexpr const char* CODE_CACHE_DIR_POSTFIX = "/code_cache";
800354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe
815cb903e0a976a143cd70441dcbd0fcb5a9630daaJaekyun Seokstatic constexpr const char *kIdMapPath = "/system/bin/idmap";
820354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampestatic constexpr const char* IDMAP_PREFIX = "/data/resource-cache/";
830354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampestatic constexpr const char* IDMAP_SUFFIX = "@idmap";
840354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe
850354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampe// NOTE: keep in sync with Installer
860354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampestatic constexpr int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
870354bd0eaf24de533e86885b811f816f1e4d15c8Andreas Gampestatic constexpr int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9;
883dfae0c008576c873c4039bb4c2e54a6adf3720aJeff Sharkeystatic constexpr int FLAG_USE_QUOTA = 1 << 12;
8988ddd94834dae9c5862a07a1e4432b171b2f5d9fJeff Sharkeystatic constexpr int FLAG_FREE_CACHE_V2 = 1 << 13;
90871a8f236ef2a055b9955b47a342b2c44c020ef7Jeff Sharkeystatic constexpr int FLAG_FREE_CACHE_V2_DEFY_QUOTA = 1 << 14;
91871a8f236ef2a055b9955b47a342b2c44c020ef7Jeff Sharkeystatic constexpr int FLAG_FREE_CACHE_NOOP = 1 << 15;
92e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkeystatic constexpr int FLAG_FORCE = 1 << 16;
936a1648e2f161cb1d7c46aa9d27e8062521a9f314Calin Juravle
940274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkeynamespace {
950274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey
960274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkeyconstexpr const char* kDump = "android.permission.DUMP";
970274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey
98423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkeystatic binder::Status ok() {
99423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    return binder::Status::ok();
100423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey}
101423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey
102423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkeystatic binder::Status exception(uint32_t code, const std::string& msg) {
103423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    return binder::Status::fromExceptionCode(code, String8(msg.c_str()));
104423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey}
105423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey
106423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkeystatic binder::Status error() {
107423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    return binder::Status::fromServiceSpecificError(errno);
108423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey}
109423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey
110423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkeystatic binder::Status error(const std::string& msg) {
111423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    PLOG(ERROR) << msg;
112423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    return binder::Status::fromServiceSpecificError(errno, String8(msg.c_str()));
113423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey}
114423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey
115423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkeystatic binder::Status error(uint32_t code, const std::string& msg) {
116423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    LOG(ERROR) << msg << " (" << code << ")";
117423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    return binder::Status::fromServiceSpecificError(code, String8(msg.c_str()));
118423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey}
119423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey
1200274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkeybinder::Status checkPermission(const char* permission) {
1210274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    pid_t pid;
1220274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    uid_t uid;
1230274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey
1240274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    if (checkCallingPermission(String16(permission), reinterpret_cast<int32_t*>(&pid),
1250274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey            reinterpret_cast<int32_t*>(&uid))) {
126423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        return ok();
1270274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    } else {
128423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        return exception(binder::Status::EX_SECURITY,
129423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey                StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, permission));
1300274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    }
1310274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey}
1320274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey
1330274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkeybinder::Status checkUid(uid_t expectedUid) {
1340274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    uid_t uid = IPCThreadState::self()->getCallingUid();
1350274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    if (uid == expectedUid || uid == AID_ROOT) {
136423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        return ok();
1370274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    } else {
138423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        return exception(binder::Status::EX_SECURITY,
139423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey                StringPrintf("UID %d is not expected UID %d", uid, expectedUid));
140423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    }
141423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey}
142423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey
143423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkeybinder::Status checkArgumentUuid(const std::unique_ptr<std::string>& uuid) {
144423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    if (!uuid || is_valid_filename(*uuid)) {
145423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        return ok();
146423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    } else {
147423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
148423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey                StringPrintf("UUID %s is malformed", uuid->c_str()));
149423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    }
150423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey}
151423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey
152423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkeybinder::Status checkArgumentPackageName(const std::string& packageName) {
153423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    if (is_valid_package_name(packageName.c_str())) {
154423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        return ok();
155423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    } else {
156423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
157423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey                StringPrintf("Package name %s is malformed", packageName.c_str()));
1580274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    }
1590274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey}
1600274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey
1610274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey#define ENFORCE_UID(uid) {                                  \
1620274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    binder::Status status = checkUid((uid));                \
1630274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    if (!status.isOk()) {                                   \
1640274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey        return status;                                      \
1650274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    }                                                       \
1660274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey}
1670274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey
168423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey#define CHECK_ARGUMENT_UUID(uuid) {                         \
169423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    binder::Status status = checkArgumentUuid((uuid));      \
170423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    if (!status.isOk()) {                                   \
171423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        return status;                                      \
172423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    }                                                       \
173423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey}
174423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey
175423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey#define CHECK_ARGUMENT_PACKAGE_NAME(packageName) {          \
176423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    binder::Status status =                                 \
177423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey            checkArgumentPackageName((packageName));        \
178423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    if (!status.isOk()) {                                   \
179423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        return status;                                      \
180423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    }                                                       \
181423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey}
182423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey
1830274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey}  // namespace
1840274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey
1850274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkeystatus_t InstalldNativeService::start() {
1860274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    IPCThreadState::self()->disableBackgroundScheduling(true);
1870274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    status_t ret = BinderService<InstalldNativeService>::publish();
1880274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    if (ret != android::OK) {
1890274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey        return ret;
1900274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    }
1910274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    sp<ProcessState> ps(ProcessState::self());
1920274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    ps->startThreadPool();
1930274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    ps->giveThreadPoolName();
1940274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    return android::OK;
1950274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey}
1960274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey
1970274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkeystatus_t InstalldNativeService::dump(int fd, const Vector<String16> & /* args */) {
19866b1a12e7a120f85042669bb58f1db864616b506Jeff Sharkey    auto out = std::fstream(StringPrintf("/proc/self/fd/%d", fd));
1990274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    const binder::Status dump_permission = checkPermission(kDump);
2000274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    if (!dump_permission.isOk()) {
20166b1a12e7a120f85042669bb58f1db864616b506Jeff Sharkey        out << dump_permission.toString8() << endl;
2020274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey        return PERMISSION_DENIED;
2030274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    }
20466b1a12e7a120f85042669bb58f1db864616b506Jeff Sharkey    std::lock_guard<std::recursive_mutex> lock(mLock);
20566b1a12e7a120f85042669bb58f1db864616b506Jeff Sharkey
20688ddd94834dae9c5862a07a1e4432b171b2f5d9fJeff Sharkey    out << "installd is happy!" << endl;
20788ddd94834dae9c5862a07a1e4432b171b2f5d9fJeff Sharkey
208b26786d647b624498c11405075e5223d1853f30aJeff Sharkey    {
209d712f0ccc120357e1267a04ac6de9dd732b27e76Jeff Sharkey        std::lock_guard<std::recursive_mutex> lock(mMountsLock);
210d712f0ccc120357e1267a04ac6de9dd732b27e76Jeff Sharkey        out << endl << "Storage mounts:" << endl;
211d712f0ccc120357e1267a04ac6de9dd732b27e76Jeff Sharkey        for (const auto& n : mStorageMounts) {
212d712f0ccc120357e1267a04ac6de9dd732b27e76Jeff Sharkey            out << "    " << n.first << " = " << n.second << endl;
213d712f0ccc120357e1267a04ac6de9dd732b27e76Jeff Sharkey        }
214d712f0ccc120357e1267a04ac6de9dd732b27e76Jeff Sharkey
215d712f0ccc120357e1267a04ac6de9dd732b27e76Jeff Sharkey        out << endl << "Quota reverse mounts:" << endl;
216d712f0ccc120357e1267a04ac6de9dd732b27e76Jeff Sharkey        for (const auto& n : mQuotaReverseMounts) {
217b26786d647b624498c11405075e5223d1853f30aJeff Sharkey            out << "    " << n.first << " = " << n.second << endl;
218b26786d647b624498c11405075e5223d1853f30aJeff Sharkey        }
21966b1a12e7a120f85042669bb58f1db864616b506Jeff Sharkey    }
22088ddd94834dae9c5862a07a1e4432b171b2f5d9fJeff Sharkey
221b26786d647b624498c11405075e5223d1853f30aJeff Sharkey    {
222d712f0ccc120357e1267a04ac6de9dd732b27e76Jeff Sharkey        std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
223b26786d647b624498c11405075e5223d1853f30aJeff Sharkey        out << endl << "Per-UID cache quotas:" << endl;
224b26786d647b624498c11405075e5223d1853f30aJeff Sharkey        for (const auto& n : mCacheQuotas) {
225b26786d647b624498c11405075e5223d1853f30aJeff Sharkey            out << "    " << n.first << " = " << n.second << endl;
226b26786d647b624498c11405075e5223d1853f30aJeff Sharkey        }
22788ddd94834dae9c5862a07a1e4432b171b2f5d9fJeff Sharkey    }
22888ddd94834dae9c5862a07a1e4432b171b2f5d9fJeff Sharkey
22966b1a12e7a120f85042669bb58f1db864616b506Jeff Sharkey    out << endl;
23066b1a12e7a120f85042669bb58f1db864616b506Jeff Sharkey    out.flush();
2310274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey
2320274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    return NO_ERROR;
2330274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey}
2340274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey
23522f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey/**
23622f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey * Perform restorecon of the given path, but only perform recursive restorecon
23722f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey * if the label of that top-level file actually changed.  This can save us
23822f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey * significant time by avoiding no-op traversals of large filesystem trees.
23922f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey */
24035b83dff3de2b5fe781a060566ee09266b3c2617Jeff Sharkeystatic int restorecon_app_data_lazy(const std::string& path, const std::string& seInfo, uid_t uid,
24135b83dff3de2b5fe781a060566ee09266b3c2617Jeff Sharkey        bool existing) {
24222f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey    int res = 0;
24322f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey    char* before = nullptr;
24422f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey    char* after = nullptr;
24522f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey
24622f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey    // Note that SELINUX_ANDROID_RESTORECON_DATADATA flag is set by
24722f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey    // libselinux. Not needed here.
24822f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey
2498567ebfaa428d6454431067da68765adde328800Jeff Sharkey    if (lgetfilecon(path.c_str(), &before) < 0) {
25022f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey        PLOG(ERROR) << "Failed before getfilecon for " << path;
25122f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey        goto fail;
25222f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey    }
2530274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid, 0) < 0) {
25422f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey        PLOG(ERROR) << "Failed top-level restorecon for " << path;
25522f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey        goto fail;
25622f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey    }
2578567ebfaa428d6454431067da68765adde328800Jeff Sharkey    if (lgetfilecon(path.c_str(), &after) < 0) {
25822f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey        PLOG(ERROR) << "Failed after getfilecon for " << path;
25922f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey        goto fail;
26022f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey    }
26122f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey
26222f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey    // If the initial top-level restorecon above changed the label, then go
26322f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey    // back and restorecon everything recursively
26422f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey    if (strcmp(before, after)) {
26535b83dff3de2b5fe781a060566ee09266b3c2617Jeff Sharkey        if (existing) {
26635b83dff3de2b5fe781a060566ee09266b3c2617Jeff Sharkey            LOG(DEBUG) << "Detected label change from " << before << " to " << after << " at "
26735b83dff3de2b5fe781a060566ee09266b3c2617Jeff Sharkey                    << path << "; running recursive restorecon";
26835b83dff3de2b5fe781a060566ee09266b3c2617Jeff Sharkey        }
2690274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey        if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid,
27022f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey                SELINUX_ANDROID_RESTORECON_RECURSE) < 0) {
27122f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey            PLOG(ERROR) << "Failed recursive restorecon for " << path;
27222f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey            goto fail;
27322f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey        }
27422f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey    }
27522f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey
27622f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey    goto done;
27722f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkeyfail:
27822f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey    res = -1;
27922f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkeydone:
28022f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey    free(before);
28122f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey    free(after);
28222f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey    return res;
28322f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey}
28422f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey
2850274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkeystatic int restorecon_app_data_lazy(const std::string& parent, const char* name,
28635b83dff3de2b5fe781a060566ee09266b3c2617Jeff Sharkey        const std::string& seInfo, uid_t uid, bool existing) {
28735b83dff3de2b5fe781a060566ee09266b3c2617Jeff Sharkey    return restorecon_app_data_lazy(StringPrintf("%s/%s", parent.c_str(), name), seInfo, uid,
28835b83dff3de2b5fe781a060566ee09266b3c2617Jeff Sharkey            existing);
2898567ebfaa428d6454431067da68765adde328800Jeff Sharkey}
2908567ebfaa428d6454431067da68765adde328800Jeff Sharkey
29122f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkeystatic int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid) {
2921f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey    if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) {
2931f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey        PLOG(ERROR) << "Failed to prepare " << path;
2941f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey        return -1;
2951f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey    }
2961f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey    return 0;
2971f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey}
2981f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey
299e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey/**
300e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey * Ensure that we have a hard-limit quota to protect against abusive apps;
301e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey * they should never use more than 90% of blocks or 50% of inodes.
302e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey */
303e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkeystatic int prepare_app_quota(const std::unique_ptr<std::string>& uuid, const std::string& device,
304e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey        uid_t uid) {
305e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey    if (device.empty()) return 0;
306e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey
307e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey    struct dqblk dq;
308e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey    if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
309e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey            reinterpret_cast<char*>(&dq)) != 0) {
310e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey        PLOG(WARNING) << "Failed to find quota for " << uid;
311e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey        return -1;
312e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey    }
313e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey
314e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey    if ((dq.dqb_bhardlimit == 0) || (dq.dqb_ihardlimit == 0)) {
315e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey        auto path = create_data_path(uuid ? uuid->c_str() : nullptr);
316e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey        struct statvfs stat;
317e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey        if (statvfs(path.c_str(), &stat) != 0) {
318e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey            PLOG(WARNING) << "Failed to statvfs " << path;
319e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey            return -1;
320e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey        }
321e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey
322e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey        dq.dqb_valid = QIF_LIMITS;
323e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey        dq.dqb_bhardlimit = (((stat.f_blocks * stat.f_frsize) / 10) * 9) / QIF_DQBLKSIZE;
324e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey        dq.dqb_ihardlimit = (stat.f_files / 2);
325e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey        if (quotactl(QCMD(Q_SETQUOTA, USRQUOTA), device.c_str(), uid,
326e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey                reinterpret_cast<char*>(&dq)) != 0) {
327e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey            PLOG(WARNING) << "Failed to set hard quota for " << uid;
328e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey            return -1;
329e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey        } else {
330e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey            LOG(DEBUG) << "Applied hard quotas for " << uid;
331e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey            return 0;
332e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey        }
333e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey    } else {
334e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey        // Hard quota already set; assume it's reasonable
335e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey        return 0;
336e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey    }
337e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey}
338e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey
3390274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkeybinder::Status InstalldNativeService::createAppData(const std::unique_ptr<std::string>& uuid,
3400274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey        const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
34136a900a0db526d63e899ed5d5b0a463ad7f9236eJeff Sharkey        const std::string& seInfo, int32_t targetSdkVersion, int64_t* _aidl_return) {
3420274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    ENFORCE_UID(AID_SYSTEM);
343423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    CHECK_ARGUMENT_UUID(uuid);
344423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3457a9059e8ed297a8e025c843b632c7c8571682b46Jeff Sharkey    std::lock_guard<std::recursive_mutex> lock(mLock);
3460274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey
3470274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
3480274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey    const char* pkgname = packageName.c_str();
3490274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey
35036a900a0db526d63e899ed5d5b0a463ad7f9236eJeff Sharkey    // Assume invalid inode unless filled in below
35136a900a0db526d63e899ed5d5b0a463ad7f9236eJeff Sharkey    if (_aidl_return != nullptr) *_aidl_return = -1;
35236a900a0db526d63e899ed5d5b0a463ad7f9236eJeff Sharkey
35324ef15bd009204b73ebf0e94ba3d868177a5f44cJeff Sharkey    int32_t uid = multiuser_get_uid(userId, appId);
35424ef15bd009204b73ebf0e94ba3d868177a5f44cJeff Sharkey    int32_t cacheGid = multiuser_get_cache_gid(userId, appId);
3553dfae0c008576c873c4039bb4c2e54a6adf3720aJeff Sharkey    mode_t targetMode = targetSdkVersion >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
3563dfae0c008576c873c4039bb4c2e54a6adf3720aJeff Sharkey
35724ef15bd009204b73ebf0e94ba3d868177a5f44cJeff Sharkey    // If UID doesn't have a specific cache GID, use UID value
35824ef15bd009204b73ebf0e94ba3d868177a5f44cJeff Sharkey    if (cacheGid == -1) {
35924ef15bd009204b73ebf0e94ba3d868177a5f44cJeff Sharkey        cacheGid = uid;
36024ef15bd009204b73ebf0e94ba3d868177a5f44cJeff Sharkey    }
36124ef15bd009204b73ebf0e94ba3d868177a5f44cJeff Sharkey
362aa7ddfd8347fa947618a7668b013521e95722c5cJeff Sharkey    if (flags & FLAG_STORAGE_CE) {
3630274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey        auto path = create_data_user_ce_package_path(uuid_, userId, pkgname);
36435b83dff3de2b5fe781a060566ee09266b3c2617Jeff Sharkey        bool existing = (access(path.c_str(), F_OK) == 0);
36535b83dff3de2b5fe781a060566ee09266b3c2617Jeff Sharkey
3663dfae0c008576c873c4039bb4c2e54a6adf3720aJeff Sharkey        if (prepare_app_dir(path, targetMode, uid) ||
3673dfae0c008576c873c4039bb4c2e54a6adf3720aJeff Sharkey                prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid) ||
3683dfae0c008576c873c4039bb4c2e54a6adf3720aJeff Sharkey                prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid)) {
369423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey            return error("Failed to prepare " + path);
37022f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey        }
37122f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey
37222f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey        // Consider restorecon over contents if label changed
37335b83dff3de2b5fe781a060566ee09266b3c2617Jeff Sharkey        if (restorecon_app_data_lazy(path, seInfo, uid, existing) ||
37435b83dff3de2b5fe781a060566ee09266b3c2617Jeff Sharkey                restorecon_app_data_lazy(path, "cache", seInfo, uid, existing) ||
37535b83dff3de2b5fe781a060566ee09266b3c2617Jeff Sharkey                restorecon_app_data_lazy(path, "code_cache", seInfo, uid, existing)) {
376423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey            return error("Failed to restorecon " + path);
377c7d1b2250e8245a7e4e144758bc3ccd33b8d6319Jeff Sharkey        }
3781f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey
3791f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey        // Remember inode numbers of cache directories so that we can clear
3801f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey        // contents while CE storage is locked
3811f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey        if (write_path_inode(path, "cache", kXattrInodeCache) ||
3821f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey                write_path_inode(path, "code_cache", kXattrInodeCodeCache)) {
383423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey            return error("Failed to write_path_inode for " + path);
384c7d1b2250e8245a7e4e144758bc3ccd33b8d6319Jeff Sharkey        }
38536a900a0db526d63e899ed5d5b0a463ad7f9236eJeff Sharkey
38636a900a0db526d63e899ed5d5b0a463ad7f9236eJeff Sharkey        // And return the CE inode of the top-level data directory so we can
38736a900a0db526d63e899ed5d5b0a463ad7f9236eJeff Sharkey        // clear contents while CE storage is locked
38836a900a0db526d63e899ed5d5b0a463ad7f9236eJeff Sharkey        if ((_aidl_return != nullptr)
38936a900a0db526d63e899ed5d5b0a463ad7f9236eJeff Sharkey                && get_path_inode(path, reinterpret_cast<ino_t*>(_aidl_return)) != 0) {
39036a900a0db526d63e899ed5d5b0a463ad7f9236eJeff Sharkey            return error("Failed to get_path_inode for " + path);
39136a900a0db526d63e899ed5d5b0a463ad7f9236eJeff Sharkey        }
39294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
393aa7ddfd8347fa947618a7668b013521e95722c5cJeff Sharkey    if (flags & FLAG_STORAGE_DE) {
3940274c977e3b10b52936fd5b2eb464857f0ca6358Jeff Sharkey        auto path = create_data_user_de_package_path(uuid_, userId, pkgname);
39535b83dff3de2b5fe781a060566ee09266b3c2617Jeff Sharkey        bool existing = (access(path.c_str(), F_OK) == 0);
39635b83dff3de2b5fe781a060566ee09266b3c2617Jeff Sharkey
3973dfae0c008576c873c4039bb4c2e54a6adf3720aJeff Sharkey        if (prepare_app_dir(path, targetMode, uid) ||
3983dfae0c008576c873c4039bb4c2e54a6adf3720aJeff Sharkey                prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid) ||
3993dfae0c008576c873c4039bb4c2e54a6adf3720aJeff Sharkey                prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid)) {
400423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey            return error("Failed to prepare " + path);
401c7d1b2250e8245a7e4e144758bc3ccd33b8d6319Jeff Sharkey        }
4026a1648e2f161cb1d7c46aa9d27e8062521a9f314Calin Juravle
40322f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey        // Consider restorecon over contents if label changed
4047b6c840c4281aeb2cc42ed022d1708fec0cda2ecJeff Sharkey        if (restorecon_app_data_lazy(path, seInfo, uid, existing) ||
4057b6c840c4281aeb2cc42ed022d1708fec0cda2ecJeff Sharkey                restorecon_app_data_lazy(path, "cache", seInfo, uid, existing) ||
4067b6c840c4281aeb2cc42ed022d1708fec0cda2ecJeff Sharkey                restorecon_app_data_lazy(path, "code_cache", seInfo, uid, existing)) {
407423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey            return error("Failed to restorecon " + path);
40822f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey        }
40922f6fd53c3edaa1862cbc3ea54a0f461173c72fbJeff Sharkey
410e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey        if (prepare_app_quota(uuid, findQuotaDeviceForUuid(uuid), uid)) {
411e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey            return error("Failed to set hard quota " + path);
412e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey        }
413e59c85cc0e78bfcc8fec6acc8e37e6a472ffc07fJeff Sharkey
41490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (property_get_bool("dalvik.vm.usejitprofiles", false)) {
415114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            const std::string profile_dir =
416114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle                    create_primary_current_profile_package_dir_path(userId, pkgname);
4176a1648e2f161cb1d7c46aa9d27e8062521a9f314Calin Juravle            // read-write-execute only for the app user.
418114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            if (fs_prepare_dir_strict(profile_dir.c_str(), 0700, uid, uid) != 0) {
419114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle                return error("Failed to prepare " + profile_dir);
4206a1648e2f161cb1d7c46aa9d27e8062521a9f314Calin Juravle            }
421114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            const std::string profile_file = create_current_profile_path(userId, pkgname,
422114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle                    /*is_secondary_dex*/false);
423bc56e7dcf07e633867e1525435373a1231216b22Calin Juravle            // read-write only for the app user.
424bc56e7dcf07e633867e1525435373a1231216b22Calin Juravle            if (fs_prepare_file_strict(profile_file.c_str(), 0600, uid, uid) != 0) {
425114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle                return error("Failed to prepare " + profile_file);
426bc56e7dcf07e633867e1525435373a1231216b22Calin Juravle            }
427114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            const std::string ref_profile_path =
428114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle                    create_primary_reference_profile_package_dir_path(pkgname);
4296a1648e2f161cb1d7c46aa9d27e8062521a9f314Calin Juravle            // dex2oat/profman runs under the shared app gid and it needs to read/write reference
4306a1648e2f161cb1d7c46aa9d27e8062521a9f314Calin Juravle            // profiles.
431adddd9876e145879169369913b5afe469b17c02dJeff Sharkey            int shared_app_gid = multiuser_get_shared_gid(0, appId);
4322e6dc9baaaf5d50b42ce36435e13c2559808b837Jeff Sharkey            if ((shared_app_gid != -1) && fs_prepare_dir_strict(
4336a1648e2f161cb1d7c46aa9d27e8062521a9f314Calin Juravle                    ref_profile_path.c_str(), 0700, shared_app_gid, shared_app_gid) != 0) {
434423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey                return error("Failed to prepare " + ref_profile_path);
4356a1648e2f161cb1d7c46aa9d27e8062521a9f314Calin Juravle            }
4366a1648e2f161cb1d7c46aa9d27e8062521a9f314Calin Juravle        }
43794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
438423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    return ok();
43994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
44094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
441c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkeybinder::Status InstalldNativeService::migrateAppData(const std::unique_ptr<std::string>& uuid,
442c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey        const std::string& packageName, int32_t userId, int32_t flags) {
443c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey    ENFORCE_UID(AID_SYSTEM);
444423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    CHECK_ARGUMENT_UUID(uuid);
445423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    CHECK_ARGUMENT_PACKAGE_NAME(packageName);
4467a9059e8ed297a8e025c843b632c7c8571682b46Jeff Sharkey    std::lock_guard<std::recursive_mutex> lock(mLock);
447423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey
448c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
449c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey    const char* pkgname = packageName.c_str();
450c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey
451cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey    // This method only exists to upgrade system apps that have requested
452cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey    // forceDeviceEncrypted, so their default storage always lives in a
453cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey    // consistent location.  This only works on non-FBE devices, since we
454cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey    // never want to risk exposing data on a device with real CE/DE storage.
455cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey
456c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey    auto ce_path = create_data_user_ce_package_path(uuid_, userId, pkgname);
457c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey    auto de_path = create_data_user_de_package_path(uuid_, userId, pkgname);
458cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey
459cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey    // If neither directory is marked as default, assume CE is default
460cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey    if (getxattr(ce_path.c_str(), kXattrDefault, nullptr, 0) == -1
461cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey            && getxattr(de_path.c_str(), kXattrDefault, nullptr, 0) == -1) {
462cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey        if (setxattr(ce_path.c_str(), kXattrDefault, nullptr, 0, 0) != 0) {
463423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey            return error("Failed to mark default storage " + ce_path);
464cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey        }
465cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey    }
466cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey
467cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey    // Migrate default data location if needed
468cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey    auto target = (flags & FLAG_STORAGE_DE) ? de_path : ce_path;
469cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey    auto source = (flags & FLAG_STORAGE_DE) ? ce_path : de_path;
470cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey
471cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey    if (getxattr(target.c_str(), kXattrDefault, nullptr, 0) == -1) {
472cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey        LOG(WARNING) << "Requested default storage " << target
473cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey                << " is not active; migrating from " << source;
474cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey        if (delete_dir_contents_and_dir(target) != 0) {
475423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey            return error("Failed to delete " + target);
476cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey        }
477cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey        if (rename(source.c_str(), target.c_str()) != 0) {
478423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey            return error("Failed to rename " + source + " to " + target);
479cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey        }
480cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey    }
481cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey
482423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    return ok();
483cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey}
484cc6281cf8146cddb8ace7cbd58c67321639c1520Jeff Sharkey
4856a1648e2f161cb1d7c46aa9d27e8062521a9f314Calin Juravle
486475c6f9743e5f6696c38fb22b8b8e9d49a82ab56Jeff Sharkeybinder::Status InstalldNativeService::clearAppProfiles(const std::string& packageName) {
487475c6f9743e5f6696c38fb22b8b8e9d49a82ab56Jeff Sharkey    ENFORCE_UID(AID_SYSTEM);
488423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    CHECK_ARGUMENT_PACKAGE_NAME(packageName);
4897a9059e8ed297a8e025c843b632c7c8571682b46Jeff Sharkey    std::lock_guard<std::recursive_mutex> lock(mLock);
490423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey
491423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    binder::Status res = ok();
492114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    if (!clear_primary_reference_profile(packageName)) {
493423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        res = error("Failed to clear reference profile for " + packageName);
494423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    }
495114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    if (!clear_primary_current_profiles(packageName)) {
496423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        res = error("Failed to clear current profiles for " + packageName);
497423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    }
498423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    return res;
4996a1648e2f161cb1d7c46aa9d27e8062521a9f314Calin Juravle}
5006a1648e2f161cb1d7c46aa9d27e8062521a9f314Calin Juravle
501c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkeybinder::Status InstalldNativeService::clearAppData(const std::unique_ptr<std::string>& uuid,
502c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey        const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode) {
503c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey    ENFORCE_UID(AID_SYSTEM);
504423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    CHECK_ARGUMENT_UUID(uuid);
505423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    CHECK_ARGUMENT_PACKAGE_NAME(packageName);
5067a9059e8ed297a8e025c843b632c7c8571682b46Jeff Sharkey    std::lock_guard<std::recursive_mutex> lock(mLock);
507423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey
508c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
509c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey    const char* pkgname = packageName.c_str();
510c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey
511423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    binder::Status res = ok();
512aa7ddfd8347fa947618a7668b013521e95722c5cJeff Sharkey    if (flags & FLAG_STORAGE_CE) {
513c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey        auto path = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInode);
5141f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey        if (flags & FLAG_CLEAR_CACHE_ONLY) {
5151f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey            path = read_path_inode(path, "cache", kXattrInodeCache);
5161f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey        } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
5171f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey            path = read_path_inode(path, "code_cache", kXattrInodeCodeCache);
5181f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey        }
519c7d1b2250e8245a7e4e144758bc3ccd33b8d6319Jeff Sharkey        if (access(path.c_str(), F_OK) == 0) {
520423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey            if (delete_dir_contents(path) != 0) {
521423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey                res = error("Failed to delete contents of " + path);
522423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey            }
523c7d1b2250e8245a7e4e144758bc3ccd33b8d6319Jeff Sharkey        }
52494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
525aa7ddfd8347fa947618a7668b013521e95722c5cJeff Sharkey    if (flags & FLAG_STORAGE_DE) {
5261f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey        std::string suffix = "";
5271f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey        bool only_cache = false;
5281f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey        if (flags & FLAG_CLEAR_CACHE_ONLY) {
5291f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey            suffix = CACHE_DIR_POSTFIX;
5301f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey            only_cache = true;
5311f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey        } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
5321f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey            suffix = CODE_CACHE_DIR_POSTFIX;
5331f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey            only_cache = true;
5341f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey        }
5351f6a7f117dcfa0e2cdb870a1bd4b20d34363ad73Jeff Sharkey
536c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey        auto path = create_data_user_de_package_path(uuid_, userId, pkgname) + suffix;
537c7d1b2250e8245a7e4e144758bc3ccd33b8d6319Jeff Sharkey        if (access(path.c_str(), F_OK) == 0) {
538423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey            if (delete_dir_contents(path) != 0) {
539423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey                res = error("Failed to delete contents of " + path);
540423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey            }
541c7d1b2250e8245a7e4e144758bc3ccd33b8d6319Jeff Sharkey        }
542edae669f18eb99b9316891fdde627e2f385c3c64Calin Juravle        if (!only_cache) {
543114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            if (!clear_primary_current_profile(packageName, userId)) {
544423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey                res = error("Failed to clear current profile for " + packageName);
545edae669f18eb99b9316891fdde627e2f385c3c64Calin Juravle            }
546edae669f18eb99b9316891fdde627e2f385c3c64Calin Juravle        }
54794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
548423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    return res;
549c7d1b2250e8245a7e4e144758bc3ccd33b8d6319Jeff Sharkey}
55094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
55176268c56febde9a77183387fbd4baabe6694e6b5Calin Juravlestatic int destroy_app_reference_profile(const std::string& pkgname) {
5527535e8e1995398befc866062d63c05d90eb70cccCalin Juravle    return delete_dir_contents_and_dir(
553114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        create_primary_reference_profile_package_dir_path(pkgname),
5547535e8e1995398befc866062d63c05d90eb70cccCalin Juravle        /*ignore_if_missing*/ true);
5557535e8e1995398befc866062d63c05d90eb70cccCalin Juravle}
5567535e8e1995398befc866062d63c05d90eb70cccCalin Juravle
55776268c56febde9a77183387fbd4baabe6694e6b5Calin Juravlestatic int destroy_app_current_profiles(const std::string& pkgname, userid_t userid) {
558b06f98aabc5381fd6366526d9b31b5d0345481b6Calin Juravle    return delete_dir_contents_and_dir(
559114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        create_primary_current_profile_package_dir_path(userid, pkgname),
560b06f98aabc5381fd6366526d9b31b5d0345481b6Calin Juravle        /*ignore_if_missing*/ true);
561edae669f18eb99b9316891fdde627e2f385c3c64Calin Juravle}
562edae669f18eb99b9316891fdde627e2f385c3c64Calin Juravle
563475c6f9743e5f6696c38fb22b8b8e9d49a82ab56Jeff Sharkeybinder::Status InstalldNativeService::destroyAppProfiles(const std::string& packageName) {
564475c6f9743e5f6696c38fb22b8b8e9d49a82ab56Jeff Sharkey    ENFORCE_UID(AID_SYSTEM);
565423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    CHECK_ARGUMENT_PACKAGE_NAME(packageName);
5667a9059e8ed297a8e025c843b632c7c8571682b46Jeff Sharkey    std::lock_guard<std::recursive_mutex> lock(mLock);
567423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey
568423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    binder::Status res = ok();
569edae669f18eb99b9316891fdde627e2f385c3c64Calin Juravle    std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
570edae669f18eb99b9316891fdde627e2f385c3c64Calin Juravle    for (auto user : users) {
57176268c56febde9a77183387fbd4baabe6694e6b5Calin Juravle        if (destroy_app_current_profiles(packageName, user) != 0) {
572423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey            res = error("Failed to destroy current profiles for " + packageName);
573423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        }
574edae669f18eb99b9316891fdde627e2f385c3c64Calin Juravle    }
57576268c56febde9a77183387fbd4baabe6694e6b5Calin Juravle    if (destroy_app_reference_profile(packageName) != 0) {
576423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        res = error("Failed to destroy reference profile for " + packageName);
577423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    }
578423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    return res;
579caa6b809a5ed024a8f3f551c5c109a5ad50ab772Calin Juravle}
580caa6b809a5ed024a8f3f551c5c109a5ad50ab772Calin Juravle
581c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkeybinder::Status InstalldNativeService::destroyAppData(const std::unique_ptr<std::string>& uuid,
582c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey        const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode) {
583c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey    ENFORCE_UID(AID_SYSTEM);
584423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    CHECK_ARGUMENT_UUID(uuid);
585423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    CHECK_ARGUMENT_PACKAGE_NAME(packageName);
5867a9059e8ed297a8e025c843b632c7c8571682b46Jeff Sharkey    std::lock_guard<std::recursive_mutex> lock(mLock);
587423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey
588c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
589c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey    const char* pkgname = packageName.c_str();
590c1e93e7d746e07791b0667c80ad43a407c515fa8Jeff Sharkey
591423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    binder::Status res = ok();
592aa7ddfd8347fa947618a7668b013521e95722c5cJeff Sharkey    if (flags & FLAG_STORAGE_CE) {
593423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        auto path = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInode);
594423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        if (delete_dir_contents_and_dir(path) != 0) {
595423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey            res = error("Failed to delete " + path);
596423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        }
59794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
598aa7ddfd8347fa947618a7668b013521e95722c5cJeff Sharkey    if (flags & FLAG_STORAGE_DE) {
599423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        auto path = create_data_user_de_package_path(uuid_, userId, pkgname);
600423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        if (delete_dir_contents_and_dir(path) != 0) {
601423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey            res = error("Failed to delete " + path);
602423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey        }
60376268c56febde9a77183387fbd4baabe6694e6b5Calin Juravle        destroy_app_current_profiles(packageName, userId);
6047535e8e1995398befc866062d63c05d90eb70cccCalin Juravle        // TODO(calin): If the package is still installed by other users it's probably
6057535e8e1995398befc866062d63c05d90eb70cccCalin Juravle        // beneficial to keep the reference profile around.
6067535e8e1995398befc866062d63c05d90eb70cccCalin Juravle        // Verify if it's ok to do that.
60776268c56febde9a77183387fbd4baabe6694e6b5Calin Juravle        destroy_app_reference_profile(packageName);
60894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
609423e746ac7d4b3a3d772dd0e01bdb9fd6029d439Jeff Sharkey    return res;
61094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
61194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
612e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkeystatic gid_t get_cache_gid(uid_t uid) {
613e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey    int32_t gid = multiuser_get_cache_gid(multiuser_get_user_id(uid), multiuser_get_app_id(uid));
614e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey    return (gid != -1) ? gid : uid;
615e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey}
616e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey
617e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkeybinder::Status InstalldNativeService::fixupAppData(const std::unique_ptr<std::string>& uuid,
618e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey        int32_t flags) {
619e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey    ENFORCE_UID(AID_SYSTEM);
620e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey    CHECK_ARGUMENT_UUID(uuid);
621e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey    std::lock_guard<std::recursive_mutex> lock(mLock);
622e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey
623e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
624e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey    for (auto user : get_known_users(uuid_)) {
625e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey        ATRACE_BEGIN("fixup user");
626e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey        FTS* fts;
627e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey        FTSENT* p;
628d9ff77fa4b934b54e287ba259cb02a0eee0d9ce8Jeff Sharkey        auto ce_path = create_data_user_ce_path(uuid_, user);
629d9ff77fa4b934b54e287ba259cb02a0eee0d9ce8Jeff Sharkey        auto de_path = create_data_user_de_path(uuid_, user);
630d9ff77fa4b934b54e287ba259cb02a0eee0d9ce8Jeff Sharkey        char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(), nullptr };
631e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey        if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
632e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey            return error("Failed to fts_open");
633e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey        }
634e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey        while ((p = fts_read(fts)) != nullptr) {
635e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey            if (p->fts_info == FTS_D && p->fts_level == 1) {
636e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                // Track down inodes of cache directories
637e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                uint64_t raw = 0;
638e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                ino_t inode_cache = 0;
639e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                ino_t inode_code_cache = 0;
640e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                if (getxattr(p->fts_path, kXattrInodeCache, &raw, sizeof(raw)) == sizeof(raw)) {
641e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                    inode_cache = raw;
642e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                }
643e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                if (getxattr(p->fts_path, kXattrInodeCodeCache, &raw, sizeof(raw)) == sizeof(raw)) {
644e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                    inode_code_cache = raw;
645e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                }
646e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey
647e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                // Figure out expected GID of each child
648e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                FTSENT* child = fts_children(fts, 0);
649e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                while (child != nullptr) {
650e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                    if ((child->fts_statp->st_ino == inode_cache)
651e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                            || (child->fts_statp->st_ino == inode_code_cache)
652e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                            || !strcmp(child->fts_name, "cache")
653e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                            || !strcmp(child->fts_name, "code_cache")) {
654e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                        child->fts_number = get_cache_gid(p->fts_statp->st_uid);
655e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                    } else {
656e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                        child->fts_number = p->fts_statp->st_uid;
657e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                    }
658e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                    child = child->fts_link;
659e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                }
660e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey            } else if (p->fts_level >= 2) {
661e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                if (p->fts_level > 2) {
662e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                    // Inherit GID from parent once we're deeper into tree
663e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                    p->fts_number = p->fts_parent->fts_number;
664e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                }
665e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey
666e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                uid_t uid = p->fts_parent->fts_statp->st_uid;
667e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                gid_t cache_gid = get_cache_gid(uid);
668e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                gid_t expected = p->fts_number;
669e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                gid_t actual = p->fts_statp->st_gid;
670e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                if (actual == expected) {
671e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey#if FIXUP_DEBUG
672e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                    LOG(DEBUG) << "Ignoring " << p->fts_path << " with expected GID " << expected;
673e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey#endif
674e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                    if (!(flags & FLAG_FORCE)) {
675e12d5964a8d14abe7f2eb6e57469cbe7f7391a19Jeff Sharkey                        fts_set(fts, p, FTS_SKIP);
676