1 /*
2 ** Copyright 2008, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 **     http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16 
17 #include "InstalldNativeService.h"
18 
19 #include <errno.h>
20 #include <fts.h>
21 #include <inttypes.h>
22 #include <linux/fsverity.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/capability.h>
27 #include <sys/file.h>
28 #include <sys/ioctl.h>
29 #include <sys/mman.h>
30 #include <sys/mount.h>
31 #include <sys/resource.h>
32 #include <sys/stat.h>
33 #include <sys/statvfs.h>
34 #include <sys/types.h>
35 #include <sys/wait.h>
36 #include <sys/xattr.h>
37 #include <unistd.h>
38 #include <algorithm>
39 #include <filesystem>
40 #include <fstream>
41 #include <functional>
42 #include <regex>
43 #include <thread>
44 #include <unordered_set>
45 
46 #include <android-base/file.h>
47 #include <android-base/logging.h>
48 #include <android-base/parseint.h>
49 #include <android-base/properties.h>
50 #include <android-base/scopeguard.h>
51 #include <android-base/stringprintf.h>
52 #include <android-base/strings.h>
53 #include <android-base/unique_fd.h>
54 #include <cutils/ashmem.h>
55 #include <cutils/fs.h>
56 #include <cutils/misc.h>
57 #include <cutils/properties.h>
58 #include <cutils/sched_policy.h>
59 #include <linux/quota.h>
60 #include <log/log.h>               // TODO: Move everything to base/logging.
61 #include <logwrap/logwrap.h>
62 #include <private/android_filesystem_config.h>
63 #include <private/android_projectid_config.h>
64 #include <selinux/android.h>
65 #include <system/thread_defs.h>
66 #include <utils/Trace.h>
67 
68 #include "dexopt.h"
69 #include "globals.h"
70 #include "installd_deps.h"
71 #include "otapreopt_utils.h"
72 #include "utils.h"
73 
74 #include "CacheTracker.h"
75 #include "CrateManager.h"
76 #include "MatchExtensionGen.h"
77 #include "QuotaUtils.h"
78 #include "SysTrace.h"
79 
80 #ifndef LOG_TAG
81 #define LOG_TAG "installd"
82 #endif
83 
84 #define GRANULAR_LOCKS
85 
86 using android::base::ParseUint;
87 using android::base::Split;
88 using android::base::StringPrintf;
89 using android::base::unique_fd;
90 using android::os::ParcelFileDescriptor;
91 using std::endl;
92 
93 namespace android {
94 namespace installd {
95 
96 // An uuid used in unit tests.
97 static constexpr const char* kTestUuid = "TEST";
98 
99 static constexpr const mode_t kRollbackFolderMode = 0700;
100 
101 static constexpr const char* kCpPath = "/system/bin/cp";
102 static constexpr const char* kXattrDefault = "user.default";
103 
104 static constexpr const char* kDataMirrorCePath = "/data_mirror/data_ce";
105 static constexpr const char* kDataMirrorDePath = "/data_mirror/data_de";
106 static constexpr const char* kMiscMirrorCePath = "/data_mirror/misc_ce";
107 static constexpr const char* kMiscMirrorDePath = "/data_mirror/misc_de";
108 
109 static constexpr const int MIN_RESTRICTED_HOME_SDK_VERSION = 24; // > M
110 
111 static constexpr const char* PKG_LIB_POSTFIX = "/lib";
112 static constexpr const char* CACHE_DIR_POSTFIX = "/cache";
113 static constexpr const char* CODE_CACHE_DIR_POSTFIX = "/code_cache";
114 
115 static constexpr const char* kFuseProp = "persist.sys.fuse";
116 
117 /**
118  * Property to control if app data isolation is enabled.
119  */
120 static constexpr const char* kAppDataIsolationEnabledProperty = "persist.zygote.app_data_isolation";
121 static constexpr const char* kMntSdcardfs = "/mnt/runtime/default/";
122 static constexpr const char* kMntFuse = "/mnt/pass_through/0/";
123 
124 static std::atomic<bool> sAppDataIsolationEnabled(false);
125 
126 /**
127  * Flag to control if project ids are supported for internal storage
128  */
129 static std::atomic<bool> sUsingProjectIdsFlag(false);
130 static std::once_flag flag;
131 
132 namespace {
133 
ok()134 static binder::Status ok() {
135     return binder::Status::ok();
136 }
137 
exception(uint32_t code,const std::string & msg)138 static binder::Status exception(uint32_t code, const std::string& msg) {
139     LOG(ERROR) << msg << " (" << code << ")";
140     return binder::Status::fromExceptionCode(code, String8(msg.c_str()));
141 }
142 
error()143 static binder::Status error() {
144     return binder::Status::fromServiceSpecificError(errno);
145 }
146 
error(const std::string & msg)147 static binder::Status error(const std::string& msg) {
148     PLOG(ERROR) << msg;
149     return binder::Status::fromServiceSpecificError(errno, String8(msg.c_str()));
150 }
151 
error(uint32_t code,const std::string & msg)152 static binder::Status error(uint32_t code, const std::string& msg) {
153     LOG(ERROR) << msg << " (" << code << ")";
154     return binder::Status::fromServiceSpecificError(code, String8(msg.c_str()));
155 }
156 
checkUid(uid_t expectedUid)157 binder::Status checkUid(uid_t expectedUid) {
158     uid_t uid = IPCThreadState::self()->getCallingUid();
159     if (uid == expectedUid || uid == AID_ROOT) {
160         return ok();
161     } else {
162         return exception(binder::Status::EX_SECURITY,
163                 StringPrintf("UID %d is not expected UID %d", uid, expectedUid));
164     }
165 }
166 
checkArgumentUuid(const std::optional<std::string> & uuid)167 binder::Status checkArgumentUuid(const std::optional<std::string>& uuid) {
168     if (!uuid || is_valid_filename(*uuid)) {
169         return ok();
170     } else {
171         return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
172                 StringPrintf("UUID %s is malformed", uuid->c_str()));
173     }
174 }
175 
checkArgumentUuidTestOrNull(const std::optional<std::string> & uuid)176 binder::Status checkArgumentUuidTestOrNull(const std::optional<std::string>& uuid) {
177     if (!uuid || strcmp(uuid->c_str(), kTestUuid) == 0) {
178         return ok();
179     } else {
180         return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
181                 StringPrintf("UUID must be null or \"%s\", got: %s", kTestUuid, uuid->c_str()));
182     }
183 }
184 
checkArgumentPackageName(const std::string & packageName)185 binder::Status checkArgumentPackageName(const std::string& packageName) {
186     if (is_valid_package_name(packageName)) {
187         return ok();
188     } else {
189         return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
190                 StringPrintf("Package name %s is malformed", packageName.c_str()));
191     }
192 }
193 
checkArgumentPath(const std::string & path)194 binder::Status checkArgumentPath(const std::string& path) {
195     if (path.empty()) {
196         return exception(binder::Status::EX_ILLEGAL_ARGUMENT, "Missing path");
197     }
198     if (path[0] != '/') {
199         return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
200                 StringPrintf("Path %s is relative", path.c_str()));
201     }
202     if ((path + '/').find("/../") != std::string::npos) {
203         return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
204                 StringPrintf("Path %s is shady", path.c_str()));
205     }
206     for (const char& c : path) {
207         if (c == '\0' || c == '\n') {
208             return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
209                     StringPrintf("Path %s is malformed", path.c_str()));
210         }
211     }
212     return ok();
213 }
214 
checkArgumentPath(const std::optional<std::string> & path)215 binder::Status checkArgumentPath(const std::optional<std::string>& path) {
216     if (path) {
217         return checkArgumentPath(*path);
218     } else {
219         return ok();
220     }
221 }
222 
checkArgumentFileName(const std::string & path)223 binder::Status checkArgumentFileName(const std::string& path) {
224     if (path.empty()) {
225         return exception(binder::Status::EX_ILLEGAL_ARGUMENT, "Missing name");
226     }
227     for (const char& c : path) {
228         if (c == '\0' || c == '\n' || c == '/') {
229             return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
230                              StringPrintf("Name %s is malformed", path.c_str()));
231         }
232     }
233     return ok();
234 }
235 
checkArgumentAppId(int32_t appId)236 binder::Status checkArgumentAppId(int32_t appId) {
237     if (FIRST_APPLICATION_UID <= appId && appId <= LAST_APPLICATION_UID) {
238         return ok();
239     }
240     return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
241                      StringPrintf("appId %d is outside of the range", appId));
242 }
243 
244 #define ENFORCE_UID(uid) {                                  \
245     binder::Status status = checkUid((uid));                \
246     if (!status.isOk()) {                                   \
247         return status;                                      \
248     }                                                       \
249 }
250 
251 // we could have tighter checks, but this is only to avoid hard errors. Negative values are defined
252 // in UserHandle.java and carry specific meanings that may not be handled by certain APIs here.
253 #define ENFORCE_VALID_USER(userId)                                                               \
254     {                                                                                            \
255         if (static_cast<uid_t>(userId) >= std::numeric_limits<uid_t>::max() / AID_USER_OFFSET) { \
256             return error("userId invalid: " + std::to_string(userId));                           \
257         }                                                                                        \
258     }
259 
260 #define ENFORCE_VALID_USER_OR_NULL(userId)             \
261     {                                                  \
262         if (static_cast<uid_t>(userId) != USER_NULL) { \
263             ENFORCE_VALID_USER(userId);                \
264         }                                              \
265     }
266 
267 #define CHECK_ARGUMENT_UUID(uuid) {                         \
268     binder::Status status = checkArgumentUuid((uuid));      \
269     if (!status.isOk()) {                                   \
270         return status;                                      \
271     }                                                       \
272 }
273 
274 #define CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(uuid) {         \
275     auto status = checkArgumentUuidTestOrNull(uuid);        \
276     if (!status.isOk()) {                                   \
277         return status;                                      \
278     }                                                       \
279 }                                                           \
280 
281 #define CHECK_ARGUMENT_PACKAGE_NAME(packageName) {          \
282     binder::Status status =                                 \
283             checkArgumentPackageName((packageName));        \
284     if (!status.isOk()) {                                   \
285         return status;                                      \
286     }                                                       \
287 }
288 
289 #define CHECK_ARGUMENT_PATH(path) {                         \
290     binder::Status status = checkArgumentPath((path));      \
291     if (!status.isOk()) {                                   \
292         return status;                                      \
293     }                                                       \
294 }
295 
296 #define CHECK_ARGUMENT_FILE_NAME(path)                         \
297     {                                                          \
298         binder::Status status = checkArgumentFileName((path)); \
299         if (!status.isOk()) {                                  \
300             return status;                                     \
301         }                                                      \
302     }
303 
304 #define CHECK_ARGUMENT_APP_ID(appId)                         \
305     {                                                        \
306         binder::Status status = checkArgumentAppId((appId)); \
307         if (!status.isOk()) {                                \
308             return status;                                   \
309         }                                                    \
310     }
311 
312 #ifdef GRANULAR_LOCKS
313 
314 /**
315  * This class obtains in constructor and keeps the local strong pointer to the RefLock.
316  * On destruction, it checks if there are any other strong pointers, and remove the map entry if
317  * this was the last one.
318  */
319 template <class Key, class Mutex>
320 struct LocalLockHolder {
321     using WeakPointer = std::weak_ptr<Mutex>;
322     using StrongPointer = std::shared_ptr<Mutex>;
323     using Map = std::unordered_map<Key, WeakPointer>;
324     using MapLock = std::recursive_mutex;
325 
LocalLockHolderandroid::installd::__anon8a917ba90111::LocalLockHolder326     LocalLockHolder(Key key, Map& map, MapLock& mapLock)
327           : mKey(std::move(key)), mMap(map), mMapLock(mapLock) {
328         std::lock_guard lock(mMapLock);
329         auto& weakPtr = mMap[mKey];
330 
331         // Check if the RefLock is still alive.
332         mRefLock = weakPtr.lock();
333         if (!mRefLock) {
334             // Create a new lock.
335             mRefLock = std::make_shared<Mutex>();
336             weakPtr = mRefLock;
337         }
338     }
LocalLockHolderandroid::installd::__anon8a917ba90111::LocalLockHolder339     LocalLockHolder(LocalLockHolder&& other) noexcept
340           : mKey(std::move(other.mKey)),
341             mMap(other.mMap),
342             mMapLock(other.mMapLock),
343             mRefLock(std::move(other.mRefLock)) {
344         other.mRefLock.reset();
345     }
~LocalLockHolderandroid::installd::__anon8a917ba90111::LocalLockHolder346     ~LocalLockHolder() {
347         if (!mRefLock) {
348             return;
349         }
350 
351         std::lock_guard lock(mMapLock);
352         // Clear the strong pointer.
353         mRefLock.reset();
354         auto found = mMap.find(mKey);
355         if (found == mMap.end()) {
356             return;
357         }
358         const auto& weakPtr = found->second;
359         // If this was the last pointer then it's ok to remove the map entry.
360         if (weakPtr.expired()) {
361             mMap.erase(found);
362         }
363     }
364 
lockandroid::installd::__anon8a917ba90111::LocalLockHolder365     void lock() { mRefLock->lock(); }
unlockandroid::installd::__anon8a917ba90111::LocalLockHolder366     void unlock() { mRefLock->unlock(); }
lock_sharedandroid::installd::__anon8a917ba90111::LocalLockHolder367     void lock_shared() { mRefLock->lock_shared(); }
unlock_sharedandroid::installd::__anon8a917ba90111::LocalLockHolder368     void unlock_shared() { mRefLock->unlock_shared(); }
369 
370 private:
371     Key mKey;
372     Map& mMap;
373     MapLock& mMapLock;
374     StrongPointer mRefLock;
375 };
376 
377 using UserLock = LocalLockHolder<userid_t, std::shared_mutex>;
378 using UserWriteLockGuard = std::unique_lock<UserLock>;
379 using UserReadLockGuard = std::shared_lock<UserLock>;
380 
381 using PackageLock = LocalLockHolder<std::string, std::recursive_mutex>;
382 using PackageLockGuard = std::lock_guard<PackageLock>;
383 
384 #define LOCK_USER()                                     \
385     UserLock localUserLock(userId, mUserIdLock, mLock); \
386     UserWriteLockGuard userLock(localUserLock)
387 
388 #define LOCK_USER_READ()                                \
389     UserLock localUserLock(userId, mUserIdLock, mLock); \
390     UserReadLockGuard userLock(localUserLock)
391 
392 #define LOCK_PACKAGE()                                                  \
393     PackageLock localPackageLock(packageName, mPackageNameLock, mLock); \
394     PackageLockGuard packageLock(localPackageLock)
395 
396 #define LOCK_PACKAGE_USER() \
397     LOCK_USER_READ();       \
398     LOCK_PACKAGE()
399 
400 #else
401 
402 #define LOCK_USER() std::lock_guard lock(mLock)
403 #define LOCK_PACKAGE() std::lock_guard lock(mLock)
404 #define LOCK_PACKAGE_USER() \
405     (void)userId;           \
406     std::lock_guard lock(mLock)
407 
408 #endif // GRANULAR_LOCKS
409 
410 }  // namespace
411 
authenticate(const ParcelFileDescriptor & authFd,int32_t uid)412 binder::Status InstalldNativeService::FsveritySetupAuthToken::authenticate(
413         const ParcelFileDescriptor& authFd, int32_t uid) {
414     int open_flags = fcntl(authFd.get(), F_GETFL);
415     if (open_flags < 0) {
416         return exception(binder::Status::EX_SERVICE_SPECIFIC, "fcntl failed");
417     }
418     if ((open_flags & O_ACCMODE) != O_WRONLY && (open_flags & O_ACCMODE) != O_RDWR) {
419         return exception(binder::Status::EX_SECURITY, "Received FD with unexpected open flag");
420     }
421     if (fstat(authFd.get(), &this->mStatFromAuthFd) < 0) {
422         return exception(binder::Status::EX_SERVICE_SPECIFIC, "fstat failed");
423     }
424     if (!S_ISREG(this->mStatFromAuthFd.st_mode)) {
425         return exception(binder::Status::EX_SECURITY, "Not a regular file");
426     }
427     // Don't accept a file owned by a different app.
428     if (this->mStatFromAuthFd.st_uid != (uid_t)uid) {
429         return exception(binder::Status::EX_SERVICE_SPECIFIC, "File not owned by uid");
430     }
431     return ok();
432 }
433 
isSameStat(const struct stat & st) const434 bool InstalldNativeService::FsveritySetupAuthToken::isSameStat(const struct stat& st) const {
435     return memcmp(&st, &mStatFromAuthFd, sizeof(st)) == 0;
436 }
437 
start()438 status_t InstalldNativeService::start() {
439     IPCThreadState::self()->disableBackgroundScheduling(true);
440     status_t ret = BinderService<InstalldNativeService>::publish();
441     if (ret != android::OK) {
442         return ret;
443     }
444     sp<ProcessState> ps(ProcessState::self());
445     ps->startThreadPool();
446     ps->giveThreadPoolName();
447     sAppDataIsolationEnabled = android::base::GetBoolProperty(
448             kAppDataIsolationEnabledProperty, true);
449     return android::OK;
450 }
451 
dump(int fd,const Vector<String16> &)452 status_t InstalldNativeService::dump(int fd, const Vector<String16>& /* args */) {
453     {
454         std::lock_guard<std::recursive_mutex> lock(mMountsLock);
455         dprintf(fd, "Storage mounts:\n");
456         for (const auto& n : mStorageMounts) {
457             dprintf(fd, "    %s = %s\n", n.first.c_str(), n.second.c_str());
458         }
459     }
460 
461     {
462         std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
463         dprintf(fd, "Per-UID cache quotas:\n");
464         for (const auto& n : mCacheQuotas) {
465             dprintf(fd, "    %d = %" PRId64 "\n", n.first, n.second);
466         }
467     }
468 
469     dprintf(fd, "is_dexopt_blocked:%d\n", android::installd::is_dexopt_blocked());
470 
471     return NO_ERROR;
472 }
473 
474 constexpr const char kXattrRestoreconInProgress[] = "user.restorecon_in_progress";
475 
lgetfilecon(const std::string & path)476 static std::string lgetfilecon(const std::string& path) {
477     char* context;
478     if (::lgetfilecon(path.c_str(), &context) < 0) {
479         PLOG(ERROR) << "Failed to lgetfilecon for " << path;
480         return {};
481     }
482     std::string result{context};
483     free(context);
484     return result;
485 }
486 
getRestoreconInProgress(const std::string & path)487 static bool getRestoreconInProgress(const std::string& path) {
488     bool inProgress = false;
489     if (getxattr(path.c_str(), kXattrRestoreconInProgress, &inProgress, sizeof(inProgress)) !=
490         sizeof(inProgress)) {
491         if (errno != ENODATA) {
492             PLOG(ERROR) << "Failed to check in-progress restorecon for " << path;
493         }
494         return false;
495     }
496     return inProgress;
497 }
498 
499 struct RestoreconInProgress {
RestoreconInProgressandroid::installd::RestoreconInProgress500     explicit RestoreconInProgress(const std::string& path) : mPath(path) {
501         bool inProgress = true;
502         if (setxattr(mPath.c_str(), kXattrRestoreconInProgress, &inProgress, sizeof(inProgress),
503                      0) != 0) {
504             PLOG(ERROR) << "Failed to set in-progress restorecon for " << path;
505         }
506     }
~RestoreconInProgressandroid::installd::RestoreconInProgress507     ~RestoreconInProgress() {
508         if (removexattr(mPath.c_str(), kXattrRestoreconInProgress) < 0) {
509             PLOG(ERROR) << "Failed to clear in-progress restorecon for " << mPath;
510         }
511     }
512 
513 private:
514     const std::string& mPath;
515 };
516 
517 /**
518  * Perform restorecon of the given path, but only perform recursive restorecon
519  * if the label of that top-level file actually changed.  This can save us
520  * significant time by avoiding no-op traversals of large filesystem trees.
521  */
restorecon_app_data_lazy(const std::string & path,const std::string & seInfo,uid_t uid,bool existing)522 static int restorecon_app_data_lazy(const std::string& path, const std::string& seInfo, uid_t uid,
523         bool existing) {
524     ScopedTrace tracer("restorecon-lazy");
525     if (!existing) {
526         ScopedTrace tracer("new-path");
527         if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid,
528                 SELINUX_ANDROID_RESTORECON_RECURSE) < 0) {
529             PLOG(ERROR) << "Failed recursive restorecon for " << path;
530             return -1;
531         }
532         return 0;
533     }
534 
535     // Note that SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here.
536 
537     // Check to see if there was an interrupted operation.
538     bool inProgress = getRestoreconInProgress(path);
539     std::string before, after;
540     if (!inProgress) {
541         if (before = lgetfilecon(path); before.empty()) {
542             PLOG(ERROR) << "Failed before getfilecon for " << path;
543             return -1;
544         }
545         if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid, 0) < 0) {
546             PLOG(ERROR) << "Failed top-level restorecon for " << path;
547             return -1;
548         }
549         if (after = lgetfilecon(path); after.empty()) {
550             PLOG(ERROR) << "Failed after getfilecon for " << path;
551             return -1;
552         }
553     }
554 
555     // If the initial top-level restorecon above changed the label, then go
556     // back and restorecon everything recursively
557     if (inProgress || before != after) {
558         if (existing) {
559             LOG(DEBUG) << "Detected label change from " << before << " to " << after << " at "
560                        << path << "; running recursive restorecon";
561         }
562 
563         auto restorecon = [path, seInfo, uid]() {
564             ScopedTrace tracer("label-change");
565 
566             // Temporary mark the folder as "in-progress" to resume in case of reboot/other failure.
567             RestoreconInProgress fence(path);
568 
569             if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid,
570                                                   SELINUX_ANDROID_RESTORECON_RECURSE) < 0) {
571                 PLOG(ERROR) << "Failed recursive restorecon for " << path;
572                 return -1;
573             }
574             return 0;
575         };
576         if (inProgress) {
577             // The previous restorecon was interrupted. It's either crashed (unlikely), or the phone
578             // was rebooted. Possibly because it took too much time. This time let's move it to a
579             // separate thread - so it won't block the rest of the OS.
580             std::thread(restorecon).detach();
581         } else {
582             if (int result = restorecon(); result) {
583                 return result;
584             }
585         }
586     }
587 
588     return 0;
589 }
internal_storage_has_project_id()590 static bool internal_storage_has_project_id() {
591     // The following path is populated in setFirstBoot, so if this file is present
592     // then project ids can be used. Using call once to cache the result of this check
593     // to avoid having to check the file presence again and again.
594     std::call_once(flag, []() {
595         auto using_project_ids =
596                 StringPrintf("%smisc/installd/using_project_ids", android_data_dir.c_str());
597         sUsingProjectIdsFlag = access(using_project_ids.c_str(), F_OK) == 0;
598     });
599     // return sUsingProjectIdsFlag;
600     return false;
601 }
602 
prepare_app_dir(const std::string & path,mode_t target_mode,uid_t uid,gid_t gid,long project_id)603 static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid, gid_t gid,
604                            long project_id) {
605     {
606         ScopedTrace tracer("prepare-dir");
607         if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, gid) != 0) {
608             PLOG(ERROR) << "Failed to prepare " << path;
609             return -1;
610         }
611     }
612     if (internal_storage_has_project_id()) {
613         ScopedTrace tracer("set-quota");
614         return set_quota_project_id(path, project_id, true);
615     }
616     return 0;
617 }
618 
prepare_app_cache_dir(const std::string & parent,const char * name,mode_t target_mode,uid_t uid,gid_t gid,long project_id)619 static int prepare_app_cache_dir(const std::string& parent, const char* name, mode_t target_mode,
620                                  uid_t uid, gid_t gid, long project_id) {
621     auto path = StringPrintf("%s/%s", parent.c_str(), name);
622     int ret;
623     {
624         ScopedTrace tracer("prepare-cache-dir");
625         ret = prepare_app_cache_dir(parent, name, target_mode, uid, gid);
626     }
627     if (ret == 0 && internal_storage_has_project_id()) {
628         ScopedTrace tracer("set-quota-cache-dir");
629         return set_quota_project_id(path, project_id, true);
630     }
631     return ret;
632 }
633 
prepare_app_profile_dir(const std::string & packageName,int32_t appId,int32_t userId)634 static bool prepare_app_profile_dir(const std::string& packageName, int32_t appId, int32_t userId) {
635     ScopedTrace tracer("prepare-app-profile");
636     int32_t uid = multiuser_get_uid(userId, appId);
637     int shared_app_gid = multiuser_get_shared_gid(userId, appId);
638     if (shared_app_gid == -1) {
639         // TODO(calin): this should no longer be possible but do not continue if we don't get
640         // a valid shared gid.
641         PLOG(WARNING) << "Invalid shared_app_gid for " << packageName;
642         return true;
643     }
644 
645     const std::string profile_dir =
646             create_primary_current_profile_package_dir_path(userId, packageName);
647     // read-write-execute only for the app user.
648     if (fs_prepare_dir_strict(profile_dir.c_str(), 0700, uid, uid) != 0) {
649         PLOG(ERROR) << "Failed to prepare " << profile_dir;
650         return false;
651     }
652     if (selinux_android_restorecon(profile_dir.c_str(), 0)) {
653         PLOG(ERROR) << "Failed to restorecon " << profile_dir;
654         return false;
655     }
656 
657     const std::string ref_profile_path =
658             create_primary_reference_profile_package_dir_path(packageName);
659 
660     // Prepare the reference profile directory. Note that we use the non strict version of
661     // fs_prepare_dir. This will fix the permission and the ownership to the correct values.
662     // This is particularly important given that in O there were some fixes for how the
663     // shared_app_gid is computed.
664     //
665     // Note that by the time we get here we know that we are using a correct uid (otherwise
666     // prepare_app_dir and the above fs_prepare_file_strict which check the uid). So we
667     // are sure that the gid being used belongs to the owning app and not someone else.
668     //
669     // dex2oat/profman runs under the shared app gid and it needs to read/write reference profiles.
670     if (fs_prepare_dir(ref_profile_path.c_str(), 0770, AID_SYSTEM, shared_app_gid) != 0) {
671         PLOG(ERROR) << "Failed to prepare " << ref_profile_path;
672         return false;
673     }
674 
675     return true;
676 }
677 
chown_app_dir(const std::string & path,uid_t uid,uid_t previousUid,gid_t cacheGid)678 static bool chown_app_dir(const std::string& path, uid_t uid, uid_t previousUid, gid_t cacheGid) {
679     FTS* fts;
680     char *argv[] = { (char*) path.c_str(), nullptr };
681     if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) {
682         return false;
683     }
684     for (FTSENT* p; (p = fts_read(fts)) != nullptr;) {
685         if (p->fts_info == FTS_D && p->fts_level == 1
686             && (strcmp(p->fts_name, "cache") == 0
687                 || strcmp(p->fts_name, "code_cache") == 0)) {
688             // Mark cache dirs
689             p->fts_number = 1;
690         } else {
691             // Inherit parent's number
692             p->fts_number = p->fts_parent->fts_number;
693         }
694 
695         switch (p->fts_info) {
696         case FTS_D:
697         case FTS_F:
698         case FTS_SL:
699         case FTS_SLNONE:
700             if (p->fts_statp->st_uid == previousUid) {
701                 if (lchown(p->fts_path, uid, p->fts_number ? cacheGid : uid) != 0) {
702                     PLOG(WARNING) << "Failed to lchown " << p->fts_path;
703                 }
704             } else {
705                 LOG(WARNING) << "Ignoring " << p->fts_path << " with unexpected UID "
706                         << p->fts_statp->st_uid << " instead of " << previousUid;
707             }
708             break;
709         }
710     }
711     fts_close(fts);
712     return true;
713 }
714 
chown_app_profile_dir(const std::string & packageName,int32_t appId,int32_t userId)715 static void chown_app_profile_dir(const std::string &packageName, int32_t appId, int32_t userId) {
716     uid_t uid = multiuser_get_uid(userId, appId);
717     gid_t sharedGid = multiuser_get_shared_gid(userId, appId);
718 
719     const std::string profile_dir =
720             create_primary_current_profile_package_dir_path(userId, packageName);
721     char *argv[] = { (char*) profile_dir.c_str(), nullptr };
722     if (FTS* fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr)) {
723         for (FTSENT* p; (p = fts_read(fts)) != nullptr;) {
724             switch (p->fts_info) {
725             case FTS_D:
726             case FTS_F:
727             case FTS_SL:
728             case FTS_SLNONE:
729                 if (lchown(p->fts_path, uid, uid) != 0) {
730                     PLOG(WARNING) << "Failed to lchown " << p->fts_path;
731                 }
732                 break;
733             }
734         }
735         fts_close(fts);
736     }
737 
738     const std::string ref_profile_path =
739             create_primary_reference_profile_package_dir_path(packageName);
740     argv[0] = (char *) ref_profile_path.c_str();
741     if (FTS* fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr)) {
742         for (FTSENT* p; (p = fts_read(fts)) != nullptr;) {
743             if (p->fts_info == FTS_D && p->fts_level == 0) {
744                 if (chown(p->fts_path, AID_SYSTEM, sharedGid) != 0) {
745                     PLOG(WARNING) << "Failed to chown " << p->fts_path;
746                 }
747                 continue;
748             }
749             switch (p->fts_info) {
750             case FTS_D:
751             case FTS_F:
752             case FTS_SL:
753             case FTS_SLNONE:
754                 if (lchown(p->fts_path, sharedGid, sharedGid) != 0) {
755                     PLOG(WARNING) << "Failed to lchown " << p->fts_path;
756                 }
757                 break;
758             }
759         }
760         fts_close(fts);
761     }
762 }
763 
createAppDataDirs(const std::string & path,int32_t uid,int32_t gid,int32_t previousUid,int32_t cacheGid,const std::string & seInfo,mode_t targetMode,long projectIdApp,long projectIdCache)764 static binder::Status createAppDataDirs(const std::string& path, int32_t uid, int32_t gid,
765                                         int32_t previousUid, int32_t cacheGid,
766                                         const std::string& seInfo, mode_t targetMode,
767                                         long projectIdApp, long projectIdCache) {
768     ScopedTrace tracer("create-dirs");
769     struct stat st{};
770     bool parent_dir_exists = (stat(path.c_str(), &st) == 0);
771 
772     auto cache_path = StringPrintf("%s/%s", path.c_str(), "cache");
773     auto code_cache_path = StringPrintf("%s/%s", path.c_str(), "code_cache");
774     bool cache_exists = (access(cache_path.c_str(), F_OK) == 0);
775     bool code_cache_exists = (access(code_cache_path.c_str(), F_OK) == 0);
776 
777     if (parent_dir_exists) {
778         if (previousUid > 0 && previousUid != uid) {
779             if (!chown_app_dir(path, uid, previousUid, cacheGid)) {
780                 return error("Failed to chown " + path);
781             }
782         }
783     }
784 
785     // Prepare only the parent app directory
786     if (prepare_app_dir(path, targetMode, uid, gid, projectIdApp) ||
787         prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid, projectIdCache) ||
788         prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid, projectIdCache)) {
789         return error("Failed to prepare " + path);
790     }
791 
792     // Consider restorecon over contents if label changed
793     if (restorecon_app_data_lazy(path, seInfo, uid, parent_dir_exists)) {
794         return error("Failed to restorecon " + path);
795     }
796 
797     // If the parent dir exists, the restorecon would already have been done
798     // as a part of the recursive restorecon above
799     if (parent_dir_exists && !cache_exists
800             && restorecon_app_data_lazy(cache_path, seInfo, uid, false)) {
801         return error("Failed to restorecon " + cache_path);
802     }
803 
804     // If the parent dir exists, the restorecon would already have been done
805     // as a part of the recursive restorecon above
806     if (parent_dir_exists && !code_cache_exists
807             && restorecon_app_data_lazy(code_cache_path, seInfo, uid, false)) {
808         return error("Failed to restorecon " + code_cache_path);
809     }
810     return ok();
811 }
812 
createAppDataLocked(const std::optional<std::string> & uuid,const std::string & packageName,int32_t userId,int32_t flags,int32_t appId,int32_t previousAppId,const std::string & seInfo,int32_t targetSdkVersion,int64_t * ceDataInode,int64_t * deDataInode)813 binder::Status InstalldNativeService::createAppDataLocked(
814         const std::optional<std::string>& uuid, const std::string& packageName, int32_t userId,
815         int32_t flags, int32_t appId, int32_t previousAppId, const std::string& seInfo,
816         int32_t targetSdkVersion, int64_t* ceDataInode, int64_t* deDataInode) {
817     ENFORCE_UID(AID_SYSTEM);
818     ENFORCE_VALID_USER(userId);
819     CHECK_ARGUMENT_UUID(uuid);
820     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
821 
822     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
823     const char* pkgname = packageName.c_str();
824 
825     // Assume invalid inode unless filled in below
826     if (ceDataInode != nullptr) *ceDataInode = -1;
827     if (deDataInode != nullptr) *deDataInode = -1;
828 
829     int32_t uid = multiuser_get_uid(userId, appId);
830 
831     // If previousAppId > 0, an app is changing its app ID
832     int32_t previousUid =
833             previousAppId > 0 ? (int32_t)multiuser_get_uid(userId, previousAppId) : -1;
834 
835     int32_t cacheGid = multiuser_get_cache_gid(userId, appId);
836     mode_t targetMode = targetSdkVersion >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
837 
838     // If UID doesn't have a specific cache GID, use UID value
839     if (cacheGid == -1) {
840         cacheGid = uid;
841     }
842 
843     long projectIdApp = get_project_id(uid, PROJECT_ID_APP_START);
844     long projectIdCache = get_project_id(uid, PROJECT_ID_APP_CACHE_START);
845 
846     if (flags & FLAG_STORAGE_CE) {
847         ScopedTrace tracer("ce");
848         auto path = create_data_user_ce_package_path(uuid_, userId, pkgname);
849 
850         auto status = createAppDataDirs(path, uid, uid, previousUid, cacheGid, seInfo, targetMode,
851                                         projectIdApp, projectIdCache);
852         if (!status.isOk()) {
853             return status;
854         }
855 
856         // Remember inode numbers of cache directories so that we can clear
857         // contents while CE storage is locked
858         if (write_path_inode(path, "cache", kXattrInodeCache) ||
859                 write_path_inode(path, "code_cache", kXattrInodeCodeCache)) {
860             return error("Failed to write_path_inode for " + path);
861         }
862 
863         // And return the CE inode of the top-level data directory so we can
864         // clear contents while CE storage is locked
865         if (ceDataInode != nullptr) {
866             ino_t result;
867             if (get_path_inode(path, &result) != 0) {
868                 return error("Failed to get_path_inode for " + path);
869             }
870             *ceDataInode = static_cast<uint64_t>(result);
871         }
872     }
873     if (flags & FLAG_STORAGE_DE) {
874         ScopedTrace tracer("de");
875         auto path = create_data_user_de_package_path(uuid_, userId, pkgname);
876 
877         auto status = createAppDataDirs(path, uid, uid, previousUid, cacheGid, seInfo, targetMode,
878                                         projectIdApp, projectIdCache);
879         if (!status.isOk()) {
880             return status;
881         }
882         if (previousUid > 0 && previousUid != uid) {
883             chown_app_profile_dir(packageName, appId, userId);
884         }
885 
886         if (!prepare_app_profile_dir(packageName, appId, userId)) {
887             return error("Failed to prepare profiles for " + packageName);
888         }
889 
890         if (deDataInode != nullptr) {
891             ino_t result;
892             if (get_path_inode(path, &result) != 0) {
893                 return error("Failed to get_path_inode for " + path);
894             }
895             *deDataInode = static_cast<uint64_t>(result);
896         }
897     }
898 
899     if (flags & FLAG_STORAGE_SDK) {
900         ScopedTrace tracer("sdk");
901         // Safe to ignore status since we can retry creating this by calling reconcileSdkData
902         auto ignore = createSdkSandboxDataPackageDirectory(uuid, packageName, userId, appId, flags);
903         if (!ignore.isOk()) {
904             PLOG(WARNING) << "Failed to create sdk data package directory for " << packageName;
905         }
906     } else {
907         ScopedTrace tracer("destroy-sdk");
908         // Package does not need sdk storage. Remove it.
909         destroySdkSandboxDataPackageDirectory(uuid, packageName, userId, flags);
910     }
911 
912     return ok();
913 }
914 
915 /**
916  * Responsible for creating /data/misc_{ce|de}/user/0/sdksandbox/<package-name> directory and other
917  * app level sub directories, such as ./shared
918  */
createSdkSandboxDataPackageDirectory(const std::optional<std::string> & uuid,const std::string & packageName,int32_t userId,int32_t appId,int32_t flags)919 binder::Status InstalldNativeService::createSdkSandboxDataPackageDirectory(
920         const std::optional<std::string>& uuid, const std::string& packageName, int32_t userId,
921         int32_t appId, int32_t flags) {
922     ENFORCE_VALID_USER(userId);
923 
924     int32_t sdkSandboxUid = multiuser_get_sdk_sandbox_uid(userId, appId);
925     if (sdkSandboxUid == -1) {
926         // There no valid sdk sandbox process for this app. Skip creation of data directory
927         return ok();
928     }
929 
930     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
931 
932     constexpr int storageFlags[2] = {FLAG_STORAGE_CE, FLAG_STORAGE_DE};
933     for (int currentFlag : storageFlags) {
934         if ((flags & currentFlag) == 0) {
935             continue;
936         }
937         bool isCeData = (currentFlag == FLAG_STORAGE_CE);
938 
939         // /data/misc_{ce,de}/<user-id>/sdksandbox directory gets created by vold
940         // during user creation
941 
942         // Prepare the package directory
943         auto packagePath = create_data_misc_sdk_sandbox_package_path(uuid_, isCeData, userId,
944                                                                      packageName.c_str());
945 #if SDK_DEBUG
946         LOG(DEBUG) << "Creating app-level sdk data directory: " << packagePath;
947 #endif
948 
949         if (prepare_app_dir(packagePath, 0751, AID_SYSTEM, AID_SYSTEM, 0)) {
950             return error("Failed to prepare " + packagePath);
951         }
952     }
953 
954     return ok();
955 }
956 
createAppData(const std::optional<std::string> & uuid,const std::string & packageName,int32_t userId,int32_t flags,int32_t appId,int32_t previousAppId,const std::string & seInfo,int32_t targetSdkVersion,int64_t * ceDataInode,int64_t * deDataInode)957 binder::Status InstalldNativeService::createAppData(
958         const std::optional<std::string>& uuid, const std::string& packageName, int32_t userId,
959         int32_t flags, int32_t appId, int32_t previousAppId, const std::string& seInfo,
960         int32_t targetSdkVersion, int64_t* ceDataInode, int64_t* deDataInode) {
961     ENFORCE_UID(AID_SYSTEM);
962     ENFORCE_VALID_USER(userId);
963     CHECK_ARGUMENT_UUID(uuid);
964     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
965     LOCK_PACKAGE_USER();
966     return createAppDataLocked(uuid, packageName, userId, flags, appId, previousAppId, seInfo,
967                                targetSdkVersion, ceDataInode, deDataInode);
968 }
969 
createAppData(const android::os::CreateAppDataArgs & args,android::os::CreateAppDataResult * _aidl_return)970 binder::Status InstalldNativeService::createAppData(
971         const android::os::CreateAppDataArgs& args,
972         android::os::CreateAppDataResult* _aidl_return) {
973     ENFORCE_UID(AID_SYSTEM);
974     ENFORCE_VALID_USER(args.userId);
975     // Locking is performed depeer in the callstack.
976 
977     int64_t ceDataInode = -1;
978     int64_t deDataInode = -1;
979     auto status = createAppData(args.uuid, args.packageName, args.userId, args.flags, args.appId,
980                                 args.previousAppId, args.seInfo, args.targetSdkVersion,
981                                 &ceDataInode, &deDataInode);
982     _aidl_return->ceDataInode = ceDataInode;
983     _aidl_return->deDataInode = deDataInode;
984     _aidl_return->exceptionCode = status.exceptionCode();
985     _aidl_return->exceptionMessage = status.exceptionMessage();
986     return ok();
987 }
988 
createAppDataBatched(const std::vector<android::os::CreateAppDataArgs> & args,std::vector<android::os::CreateAppDataResult> * _aidl_return)989 binder::Status InstalldNativeService::createAppDataBatched(
990         const std::vector<android::os::CreateAppDataArgs>& args,
991         std::vector<android::os::CreateAppDataResult>* _aidl_return) {
992     ENFORCE_UID(AID_SYSTEM);
993     for (const auto& arg : args) {
994         ENFORCE_VALID_USER(arg.userId);
995     }
996 
997     // Locking is performed depeer in the callstack.
998 
999     std::vector<android::os::CreateAppDataResult> results;
1000     for (const auto &arg : args) {
1001         android::os::CreateAppDataResult result;
1002         createAppData(arg, &result);
1003         results.push_back(result);
1004     }
1005     *_aidl_return = results;
1006     return ok();
1007 }
1008 
reconcileSdkData(const android::os::ReconcileSdkDataArgs & args)1009 binder::Status InstalldNativeService::reconcileSdkData(
1010         const android::os::ReconcileSdkDataArgs& args) {
1011     ENFORCE_VALID_USER(args.userId);
1012     // Locking is performed depeer in the callstack.
1013 
1014     return reconcileSdkData(args.uuid, args.packageName, args.subDirNames, args.userId, args.appId,
1015                             args.previousAppId, args.seInfo, args.flags);
1016 }
1017 
1018 /**
1019  * Reconciles per-sdk directory under app-level sdk data directory.
1020 
1021  * E.g. `/data/misc_ce/0/sdksandbox/<package-name>/<sdkPackageName>-<randomSuffix>
1022  *
1023  * - If the sdk data package directory is missing, we create it first.
1024  * - If sdkPackageNames is empty, we delete sdk package directory since it's not needed anymore.
1025  * - If a sdk level directory we need to prepare already exist, we skip creating it again. This
1026  *   is to avoid having same per-sdk directory with different suffix.
1027  * - If a sdk level directory exist which is absent from sdkPackageNames, we remove it.
1028  */
reconcileSdkData(const std::optional<std::string> & uuid,const std::string & packageName,const std::vector<std::string> & subDirNames,int userId,int appId,int previousAppId,const std::string & seInfo,int flags)1029 binder::Status InstalldNativeService::reconcileSdkData(const std::optional<std::string>& uuid,
1030                                                        const std::string& packageName,
1031                                                        const std::vector<std::string>& subDirNames,
1032                                                        int userId, int appId, int previousAppId,
1033                                                        const std::string& seInfo, int flags) {
1034     ENFORCE_UID(AID_SYSTEM);
1035     ENFORCE_VALID_USER(userId);
1036     CHECK_ARGUMENT_UUID(uuid);
1037     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
1038     LOCK_PACKAGE_USER();
1039 
1040 #if SDK_DEBUG
1041     LOG(DEBUG) << "Creating per sdk data directory for: " << packageName;
1042 #endif
1043 
1044     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
1045 
1046     // Prepare the sdk package directory in case it's missing
1047     const auto status =
1048             createSdkSandboxDataPackageDirectory(uuid, packageName, userId, appId, flags);
1049     if (!status.isOk()) {
1050         return status;
1051     }
1052 
1053     auto res = ok();
1054     // We have to create sdk data for CE and DE storage
1055     const int storageFlags[2] = {FLAG_STORAGE_CE, FLAG_STORAGE_DE};
1056     for (int currentFlag : storageFlags) {
1057         if ((flags & currentFlag) == 0) {
1058             continue;
1059         }
1060         const bool isCeData = (currentFlag == FLAG_STORAGE_CE);
1061 
1062         const auto packagePath = create_data_misc_sdk_sandbox_package_path(uuid_, isCeData, userId,
1063                                                                            packageName.c_str());
1064 
1065         // Remove existing sub-directories not referred in subDirNames
1066         const std::unordered_set<std::string> expectedSubDirNames(subDirNames.begin(),
1067                                                                   subDirNames.end());
1068         const auto subDirHandler = [&packagePath, &expectedSubDirNames,
1069                                     &res](const std::string& subDirName) {
1070             // Remove the per-sdk directory if it is not referred in
1071             // expectedSubDirNames
1072             if (expectedSubDirNames.find(subDirName) == expectedSubDirNames.end()) {
1073                 auto path = packagePath + "/" + subDirName;
1074                 if (delete_dir_contents_and_dir(path) != 0) {
1075                     res = error("Failed to delete " + path);
1076                     return;
1077                 }
1078             }
1079         };
1080         const int ec = foreach_subdir(packagePath, subDirHandler);
1081         if (ec != 0) {
1082             res = error("Failed to process subdirs for " + packagePath);
1083             continue;
1084         }
1085 
1086         // Now create the subDirNames
1087         for (const auto& subDirName : subDirNames) {
1088             const std::string path =
1089                     create_data_misc_sdk_sandbox_sdk_path(uuid_, isCeData, userId,
1090                                                           packageName.c_str(), subDirName.c_str());
1091 
1092             // Create the directory along with cache and code_cache
1093             const int32_t cacheGid = multiuser_get_cache_gid(userId, appId);
1094             if (cacheGid == -1) {
1095                 return exception(binder::Status::EX_ILLEGAL_STATE,
1096                                  StringPrintf("cacheGid cannot be -1 for sdk data"));
1097             }
1098             const int32_t sandboxUid = multiuser_get_sdk_sandbox_uid(userId, appId);
1099             int32_t previousSandboxUid = multiuser_get_sdk_sandbox_uid(userId, previousAppId);
1100             int32_t appUid = multiuser_get_uid(userId, appId);
1101             long projectIdApp = get_project_id(appUid, PROJECT_ID_APP_START);
1102             long projectIdCache = get_project_id(appUid, PROJECT_ID_APP_CACHE_START);
1103             auto status =
1104                     createAppDataDirs(path, sandboxUid, AID_NOBODY, previousSandboxUid, cacheGid,
1105                                       seInfo, 0700 | S_ISGID, projectIdApp, projectIdCache);
1106             if (!status.isOk()) {
1107                 res = status;
1108                 continue;
1109             }
1110         }
1111     }
1112 
1113     return res;
1114 }
1115 
migrateAppData(const std::optional<std::string> & uuid,const std::string & packageName,int32_t userId,int32_t flags)1116 binder::Status InstalldNativeService::migrateAppData(const std::optional<std::string>& uuid,
1117         const std::string& packageName, int32_t userId, int32_t flags) {
1118     ENFORCE_UID(AID_SYSTEM);
1119     ENFORCE_VALID_USER(userId);
1120     CHECK_ARGUMENT_UUID(uuid);
1121     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
1122     LOCK_PACKAGE_USER();
1123 
1124     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
1125     const char* pkgname = packageName.c_str();
1126 
1127     // This method only exists to upgrade system apps that have requested
1128     // forceDeviceEncrypted, so their default storage always lives in a
1129     // consistent location.  This only works on non-FBE devices, since we
1130     // never want to risk exposing data on a device with real CE/DE storage.
1131 
1132     auto ce_path = create_data_user_ce_package_path(uuid_, userId, pkgname);
1133     auto de_path = create_data_user_de_package_path(uuid_, userId, pkgname);
1134 
1135     // If neither directory is marked as default, assume CE is default
1136     if (getxattr(ce_path.c_str(), kXattrDefault, nullptr, 0) == -1
1137             && getxattr(de_path.c_str(), kXattrDefault, nullptr, 0) == -1) {
1138         if (setxattr(ce_path.c_str(), kXattrDefault, nullptr, 0, 0) != 0) {
1139             return error("Failed to mark default storage " + ce_path);
1140         }
1141     }
1142 
1143     // Migrate default data location if needed
1144     auto target = (flags & FLAG_STORAGE_DE) ? de_path : ce_path;
1145     auto source = (flags & FLAG_STORAGE_DE) ? ce_path : de_path;
1146 
1147     if (getxattr(target.c_str(), kXattrDefault, nullptr, 0) == -1) {
1148         LOG(WARNING) << "Requested default storage " << target
1149                 << " is not active; migrating from " << source;
1150         if (delete_dir_contents_and_dir(target) != 0) {
1151             return error("Failed to delete " + target);
1152         }
1153         if (rename(source.c_str(), target.c_str()) != 0) {
1154             return error("Failed to rename " + source + " to " + target);
1155         }
1156     }
1157 
1158     return ok();
1159 }
1160 
1161 
clearAppProfiles(const std::string & packageName,const std::string & profileName)1162 binder::Status InstalldNativeService::clearAppProfiles(const std::string& packageName,
1163         const std::string& profileName) {
1164     ENFORCE_UID(AID_SYSTEM);
1165     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
1166     CHECK_ARGUMENT_FILE_NAME(profileName);
1167     if (!base::EndsWith(profileName, ".prof")) {
1168         return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
1169                          StringPrintf("Profile name %s does not end with .prof",
1170                                       profileName.c_str()));
1171     }
1172     LOCK_PACKAGE();
1173 
1174     binder::Status res = ok();
1175     if (!clear_primary_reference_profile(packageName, profileName)) {
1176         res = error("Failed to clear reference profile for " + packageName);
1177     }
1178     if (!clear_primary_current_profiles(packageName, profileName)) {
1179         res = error("Failed to clear current profiles for " + packageName);
1180     }
1181     return res;
1182 }
1183 
clearAppData(const std::optional<std::string> & uuid,const std::string & packageName,int32_t userId,int32_t flags,int64_t ceDataInode)1184 binder::Status InstalldNativeService::clearAppData(const std::optional<std::string>& uuid,
1185         const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode) {
1186     ENFORCE_UID(AID_SYSTEM);
1187     ENFORCE_VALID_USER(userId);
1188     CHECK_ARGUMENT_UUID(uuid);
1189     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
1190     LOCK_PACKAGE_USER();
1191 
1192     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
1193     const char* pkgname = packageName.c_str();
1194 
1195     binder::Status res = ok();
1196     if (flags & FLAG_STORAGE_CE) {
1197         auto path = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInode);
1198         if (flags & FLAG_CLEAR_CACHE_ONLY) {
1199             path = read_path_inode(path, "cache", kXattrInodeCache);
1200         } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
1201             path = read_path_inode(path, "code_cache", kXattrInodeCodeCache);
1202         }
1203         if (access(path.c_str(), F_OK) == 0) {
1204             if (delete_dir_contents(path) != 0) {
1205                 res = error("Failed to delete contents of " + path);
1206             } else if ((flags & (FLAG_CLEAR_CACHE_ONLY | FLAG_CLEAR_CODE_CACHE_ONLY)) == 0) {
1207                 remove_path_xattr(path, kXattrInodeCache);
1208                 remove_path_xattr(path, kXattrInodeCodeCache);
1209             }
1210         }
1211     }
1212     if (flags & FLAG_STORAGE_DE) {
1213         std::string suffix;
1214         if (flags & FLAG_CLEAR_CACHE_ONLY) {
1215             suffix = CACHE_DIR_POSTFIX;
1216         } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
1217             suffix = CODE_CACHE_DIR_POSTFIX;
1218         }
1219 
1220         auto path = create_data_user_de_package_path(uuid_, userId, pkgname) + suffix;
1221         if (access(path.c_str(), F_OK) == 0) {
1222             if (delete_dir_contents(path) != 0) {
1223                 res = error("Failed to delete contents of " + path);
1224             }
1225         }
1226     }
1227     if (flags & FLAG_STORAGE_EXTERNAL) {
1228         std::lock_guard<std::recursive_mutex> lock(mMountsLock);
1229         for (const auto& n : mStorageMounts) {
1230             auto extPath = n.second;
1231 
1232             if (android::base::GetBoolProperty(kFuseProp, false)) {
1233                 std::regex re("^\\/mnt\\/pass_through\\/[0-9]+\\/emulated");
1234                 if (std::regex_match(extPath, re)) {
1235                     extPath += "/" + std::to_string(userId);
1236                 }
1237             } else {
1238                 if (n.first.compare(0, 14, "/mnt/media_rw/") != 0) {
1239                     extPath += StringPrintf("/%d", userId);
1240                 } else if (userId != 0) {
1241                     // TODO: support devices mounted under secondary users
1242                     continue;
1243                 }
1244             }
1245 
1246             if (flags & FLAG_CLEAR_CACHE_ONLY) {
1247                 // Clear only cached data from shared storage
1248                 auto path = StringPrintf("%s/Android/data/%s/cache", extPath.c_str(), pkgname);
1249                 if (delete_dir_contents(path, true) != 0) {
1250                     res = error("Failed to delete contents of " + path);
1251                 }
1252             } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
1253                 // No code cache on shared storage
1254             } else {
1255                 // Clear everything on shared storage
1256                 auto path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname);
1257                 if (delete_dir_contents(path, true) != 0) {
1258                     res = error("Failed to delete contents of " + path);
1259                 }
1260                 path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname);
1261                 if (delete_dir_contents(path, true) != 0) {
1262                     res = error("Failed to delete contents of " + path);
1263                 }
1264                 // Note that we explicitly don't delete OBBs - those are only removed on
1265                 // app uninstall.
1266             }
1267         }
1268     }
1269     auto status = clearSdkSandboxDataPackageDirectory(uuid, packageName, userId, flags);
1270     if (!status.isOk()) {
1271         res = status;
1272     }
1273     return res;
1274 }
1275 
clearSdkSandboxDataPackageDirectory(const std::optional<std::string> & uuid,const std::string & packageName,int32_t userId,int32_t flags)1276 binder::Status InstalldNativeService::clearSdkSandboxDataPackageDirectory(
1277         const std::optional<std::string>& uuid, const std::string& packageName, int32_t userId,
1278         int32_t flags) {
1279     ENFORCE_VALID_USER(userId);
1280     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
1281     const char* pkgname = packageName.c_str();
1282 
1283     binder::Status res = ok();
1284     constexpr int storageFlags[2] = {FLAG_STORAGE_CE, FLAG_STORAGE_DE};
1285     for (int i = 0; i < 2; i++) {
1286         int currentFlag = storageFlags[i];
1287         if ((flags & currentFlag) == 0) {
1288             continue;
1289         }
1290         bool isCeData = (currentFlag == FLAG_STORAGE_CE);
1291         std::string suffix;
1292         if (flags & FLAG_CLEAR_CACHE_ONLY) {
1293             suffix = CACHE_DIR_POSTFIX;
1294         } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
1295             suffix = CODE_CACHE_DIR_POSTFIX;
1296         }
1297 
1298         auto appPath = create_data_misc_sdk_sandbox_package_path(uuid_, isCeData, userId, pkgname);
1299         if (access(appPath.c_str(), F_OK) != 0) continue;
1300         const auto subDirHandler = [&appPath, &res, &suffix](const std::string& filename) {
1301             auto filepath = appPath + "/" + filename + suffix;
1302             if (delete_dir_contents(filepath, true) != 0) {
1303                 res = error("Failed to clear contents of " + filepath);
1304             }
1305         };
1306         const int ec = foreach_subdir(appPath, subDirHandler);
1307         if (ec != 0) {
1308             res = error("Failed to process subdirs for " + appPath);
1309         }
1310     }
1311     return res;
1312 }
1313 
destroy_app_reference_profile(const std::string & pkgname)1314 static int destroy_app_reference_profile(const std::string& pkgname) {
1315     return delete_dir_contents_and_dir(
1316         create_primary_reference_profile_package_dir_path(pkgname),
1317         /*ignore_if_missing*/ true);
1318 }
1319 
destroy_app_current_profiles(const std::string & pkgname,userid_t userid)1320 static int destroy_app_current_profiles(const std::string& pkgname, userid_t userid) {
1321     return delete_dir_contents_and_dir(
1322         create_primary_current_profile_package_dir_path(userid, pkgname),
1323         /*ignore_if_missing*/ true);
1324 }
1325 
destroyAppProfiles(const std::string & packageName)1326 binder::Status InstalldNativeService::destroyAppProfiles(const std::string& packageName) {
1327     ENFORCE_UID(AID_SYSTEM);
1328     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
1329     LOCK_PACKAGE();
1330 
1331     binder::Status res = ok();
1332     std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
1333     for (auto user : users) {
1334         if (destroy_app_current_profiles(packageName, user) != 0) {
1335             res = error("Failed to destroy current profiles for " + packageName);
1336         }
1337     }
1338     if (destroy_app_reference_profile(packageName) != 0) {
1339         res = error("Failed to destroy reference profile for " + packageName);
1340     }
1341     return res;
1342 }
1343 
deleteReferenceProfile(const std::string & packageName,const std::string & profileName)1344 binder::Status InstalldNativeService::deleteReferenceProfile(const std::string& packageName,
1345                                                              const std::string& profileName) {
1346     ENFORCE_UID(AID_SYSTEM);
1347     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
1348     LOCK_PACKAGE();
1349 
1350     // This function only supports primary dex'es.
1351     std::string path =
1352             create_reference_profile_path(packageName, profileName, /*is_secondary_dex=*/false);
1353     if (unlink(path.c_str()) != 0) {
1354         if (errno == ENOENT) {
1355             return ok();
1356         } else {
1357             return error("Failed to delete profile " + profileName + " for " + packageName);
1358         }
1359     }
1360     return ok();
1361 }
1362 
destroyAppData(const std::optional<std::string> & uuid,const std::string & packageName,int32_t userId,int32_t flags,int64_t ceDataInode)1363 binder::Status InstalldNativeService::destroyAppData(const std::optional<std::string>& uuid,
1364         const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode) {
1365     ENFORCE_UID(AID_SYSTEM);
1366     ENFORCE_VALID_USER(userId);
1367     CHECK_ARGUMENT_UUID(uuid);
1368     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
1369     LOCK_PACKAGE_USER();
1370 
1371     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
1372     const char* pkgname = packageName.c_str();
1373 
1374     binder::Status res = ok();
1375     if (flags & FLAG_STORAGE_CE) {
1376         auto path = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInode);
1377         if (rename_delete_dir_contents_and_dir(path) != 0) {
1378             res = error("Failed to delete " + path);
1379         }
1380     }
1381     if (flags & FLAG_STORAGE_DE) {
1382         auto path = create_data_user_de_package_path(uuid_, userId, pkgname);
1383         if (rename_delete_dir_contents_and_dir(path) != 0) {
1384             res = error("Failed to delete " + path);
1385         }
1386         if ((flags & FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES) == 0) {
1387             destroy_app_current_profiles(packageName, userId);
1388             // TODO(calin): If the package is still installed by other users it's probably
1389             // beneficial to keep the reference profile around.
1390             // Verify if it's ok to do that.
1391             destroy_app_reference_profile(packageName);
1392         }
1393     }
1394     if (flags & FLAG_STORAGE_EXTERNAL) {
1395         std::lock_guard<std::recursive_mutex> lock(mMountsLock);
1396         for (const auto& n : mStorageMounts) {
1397             auto extPath = n.second;
1398 
1399             if (android::base::GetBoolProperty(kFuseProp, false)) {
1400                 std::regex re("^\\/mnt\\/pass_through\\/[0-9]+\\/emulated");
1401                 if (std::regex_match(extPath, re)) {
1402                     extPath += "/" + std::to_string(userId);
1403                 }
1404             } else {
1405                 if (n.first.compare(0, 14, "/mnt/media_rw/") != 0) {
1406                     extPath += StringPrintf("/%d", userId);
1407                 } else if (userId != 0) {
1408                     // TODO: support devices mounted under secondary users
1409                     continue;
1410                 }
1411             }
1412 
1413             auto path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname);
1414             if (delete_dir_contents_and_dir(path, true) != 0) {
1415                 res = error("Failed to delete contents of " + path);
1416             }
1417             path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname);
1418             if (delete_dir_contents_and_dir(path, true) != 0) {
1419                 res = error("Failed to delete contents of " + path);
1420             }
1421             path = StringPrintf("%s/Android/obb/%s", extPath.c_str(), pkgname);
1422             if (delete_dir_contents_and_dir(path, true) != 0) {
1423                 res = error("Failed to delete contents of " + path);
1424             }
1425         }
1426     }
1427     auto status = destroySdkSandboxDataPackageDirectory(uuid, packageName, userId, flags);
1428     if (!status.isOk()) {
1429         res = status;
1430     }
1431     return res;
1432 }
1433 
destroySdkSandboxDataPackageDirectory(const std::optional<std::string> & uuid,const std::string & packageName,int32_t userId,int32_t flags)1434 binder::Status InstalldNativeService::destroySdkSandboxDataPackageDirectory(
1435         const std::optional<std::string>& uuid, const std::string& packageName, int32_t userId,
1436         int32_t flags) {
1437     ENFORCE_VALID_USER(userId);
1438 
1439     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
1440     const char* pkgname = packageName.c_str();
1441 
1442     binder::Status res = ok();
1443     constexpr int storageFlags[2] = {FLAG_STORAGE_CE, FLAG_STORAGE_DE};
1444     for (int i = 0; i < 2; i++) {
1445         int currentFlag = storageFlags[i];
1446         if ((flags & currentFlag) == 0) {
1447             continue;
1448         }
1449         bool isCeData = (currentFlag == FLAG_STORAGE_CE);
1450         auto appPath = create_data_misc_sdk_sandbox_package_path(uuid_, isCeData, userId, pkgname);
1451         if (rename_delete_dir_contents_and_dir(appPath) != 0) {
1452             res = error("Failed to delete " + appPath);
1453         }
1454     }
1455     return res;
1456 }
1457 
get_cache_gid(uid_t uid)1458 static gid_t get_cache_gid(uid_t uid) {
1459     int32_t gid = multiuser_get_cache_gid(multiuser_get_user_id(uid), multiuser_get_app_id(uid));
1460     return (gid != -1) ? gid : uid;
1461 }
1462 
fixupAppData(const std::optional<std::string> & uuid,int32_t flags)1463 binder::Status InstalldNativeService::fixupAppData(const std::optional<std::string>& uuid,
1464         int32_t flags) {
1465     ENFORCE_UID(AID_SYSTEM);
1466     CHECK_ARGUMENT_UUID(uuid);
1467 
1468     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
1469     for (auto userId : get_known_users(uuid_)) {
1470         LOCK_USER();
1471         atrace_pm_begin("fixup user");
1472         FTS* fts;
1473         FTSENT* p;
1474         auto ce_path = create_data_user_ce_path(uuid_, userId);
1475         auto de_path = create_data_user_de_path(uuid_, userId);
1476         char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(), nullptr };
1477         if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) {
1478             return error("Failed to fts_open");
1479         }
1480         while ((p = fts_read(fts)) != nullptr) {
1481             if (p->fts_info == FTS_D && p->fts_level == 1) {
1482                 // Track down inodes of cache directories
1483                 uint64_t raw = 0;
1484                 ino_t inode_cache = 0;
1485                 ino_t inode_code_cache = 0;
1486                 if (getxattr(p->fts_path, kXattrInodeCache, &raw, sizeof(raw)) == sizeof(raw)) {
1487                     inode_cache = raw;
1488                 }
1489                 if (getxattr(p->fts_path, kXattrInodeCodeCache, &raw, sizeof(raw)) == sizeof(raw)) {
1490                     inode_code_cache = raw;
1491                 }
1492 
1493                 // Figure out expected GID of each child
1494                 FTSENT* child = fts_children(fts, 0);
1495                 while (child != nullptr) {
1496                     if ((child->fts_statp->st_ino == inode_cache)
1497                             || (child->fts_statp->st_ino == inode_code_cache)
1498                             || !strcmp(child->fts_name, "cache")
1499                             || !strcmp(child->fts_name, "code_cache")) {
1500                         child->fts_number = get_cache_gid(p->fts_statp->st_uid);
1501                     } else {
1502                         child->fts_number = p->fts_statp->st_uid;
1503                     }
1504                     child = child->fts_link;
1505                 }
1506             } else if (p->fts_level >= 2) {
1507                 if (p->fts_level > 2) {
1508                     // Inherit GID from parent once we're deeper into tree
1509                     p->fts_number = p->fts_parent->fts_number;
1510                 }
1511 
1512                 uid_t uid = p->fts_parent->fts_statp->st_uid;
1513                 gid_t cache_gid = get_cache_gid(uid);
1514                 gid_t expected = p->fts_number;
1515                 gid_t actual = p->fts_statp->st_gid;
1516                 if (actual == expected) {
1517 #if FIXUP_DEBUG
1518                     LOG(DEBUG) << "Ignoring " << p->fts_path << " with expected GID " << expected;
1519 #endif
1520                     if (!(flags & FLAG_FORCE)) {
1521                         fts_set(fts, p, FTS_SKIP);
1522                     }
1523                 } else if ((actual == uid) || (actual == cache_gid)) {
1524                     // Only consider fixing up when current GID belongs to app
1525                     if (p->fts_info != FTS_D) {
1526                         LOG(INFO) << "Fixing " << p->fts_path << " with unexpected GID " << actual
1527                                 << " instead of " << expected;
1528                     }
1529                     switch (p->fts_info) {
1530                     case FTS_DP:
1531                         // If we're moving towards cache GID, we need to set S_ISGID
1532                         if (expected == cache_gid) {
1533                             if (chmod(p->fts_path, 02771) != 0) {
1534                                 PLOG(WARNING) << "Failed to chmod " << p->fts_path;
1535                             }
1536                         }
1537                         [[fallthrough]]; // also set GID
1538                     case FTS_F:
1539                         if (chown(p->fts_path, -1, expected) != 0) {
1540                             PLOG(WARNING) << "Failed to chown " << p->fts_path;
1541                         }
1542                         break;
1543                     case FTS_SL:
1544                     case FTS_SLNONE:
1545                         if (lchown(p->fts_path, -1, expected) != 0) {
1546                             PLOG(WARNING) << "Failed to chown " << p->fts_path;
1547                         }
1548                         break;
1549                     }
1550                 } else {
1551                     // Ignore all other GID transitions, since they're kinda shady
1552                     LOG(WARNING) << "Ignoring " << p->fts_path << " with unexpected GID " << actual
1553                             << " instead of " << expected;
1554                     if (!(flags & FLAG_FORCE)) {
1555                         fts_set(fts, p, FTS_SKIP);
1556                     }
1557                 }
1558             }
1559         }
1560         fts_close(fts);
1561         atrace_pm_end();
1562     }
1563     return ok();
1564 }
1565 
copy_directory_recursive(const char * from,const char * to)1566 static int32_t copy_directory_recursive(const char* from, const char* to) {
1567     char* argv[] =
1568             {(char*)kCpPath,
1569              (char*)"-F", /* delete any existing destination file first (--remove-destination) */
1570              (char*)"--preserve=mode,ownership,timestamps,xattr", /* preserve properties */
1571              (char*)"-R", /* recurse into subdirectories (DEST must be a directory) */
1572              (char*)"-P", /* Do not follow symlinks [default] */
1573              (char*)"-d", /* don't dereference symlinks */
1574              (char*)from,
1575              (char*)to};
1576 
1577     LOG(DEBUG) << "Copying " << from << " to " << to;
1578     return logwrap_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, LOG_ALOG, false, nullptr);
1579 }
1580 
snapshotAppData(const std::optional<std::string> & volumeUuid,const std::string & packageName,int32_t userId,int32_t snapshotId,int32_t storageFlags,int64_t * _aidl_return)1581 binder::Status InstalldNativeService::snapshotAppData(const std::optional<std::string>& volumeUuid,
1582                                                       const std::string& packageName,
1583                                                       int32_t userId, int32_t snapshotId,
1584                                                       int32_t storageFlags, int64_t* _aidl_return) {
1585     ENFORCE_UID(AID_SYSTEM);
1586     ENFORCE_VALID_USER(userId);
1587     CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid);
1588     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
1589     LOCK_PACKAGE_USER();
1590 
1591     const char* volume_uuid = volumeUuid ? volumeUuid->c_str() : nullptr;
1592     const char* package_name = packageName.c_str();
1593 
1594     binder::Status res = ok();
1595     // Default result to 0, it will be populated with inode of ce data snapshot
1596     // if FLAG_STORAGE_CE has been passed.
1597     if (_aidl_return != nullptr) *_aidl_return = 0;
1598 
1599     bool clear_ce_on_exit = false;
1600     bool clear_de_on_exit = false;
1601 
1602     auto deleter = [&clear_ce_on_exit, &clear_de_on_exit, &volume_uuid, &userId, &package_name,
1603                     &snapshotId] {
1604         if (clear_de_on_exit) {
1605             auto to = create_data_misc_de_rollback_package_path(volume_uuid, userId, snapshotId,
1606                                                                 package_name);
1607             if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) {
1608                 LOG(WARNING) << "Failed to delete app data snapshot: " << to;
1609             }
1610         }
1611 
1612         if (clear_ce_on_exit) {
1613             auto to = create_data_misc_ce_rollback_package_path(volume_uuid, userId, snapshotId,
1614                                                                 package_name);
1615             if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) {
1616                 LOG(WARNING) << "Failed to delete app data snapshot: " << to;
1617             }
1618         }
1619     };
1620 
1621     auto scope_guard = android::base::make_scope_guard(deleter);
1622 
1623     if (storageFlags & FLAG_STORAGE_DE) {
1624         auto from = create_data_user_de_package_path(volume_uuid, userId, package_name);
1625         auto to = create_data_misc_de_rollback_path(volume_uuid, userId, snapshotId);
1626         auto rollback_package_path =
1627                 create_data_misc_de_rollback_package_path(volume_uuid, userId, snapshotId,
1628                                                           package_name);
1629 
1630         int rc = create_dir_if_needed(to.c_str(), kRollbackFolderMode);
1631         if (rc != 0) {
1632             return error(rc, "Failed to create folder " + to);
1633         }
1634 
1635         rc = delete_dir_contents(rollback_package_path, true /* ignore_if_missing */);
1636         if (rc != 0) {
1637             return error(rc, "Failed clearing existing snapshot " + rollback_package_path);
1638         }
1639 
1640         // Check if we have data to copy.
1641         if (access(from.c_str(), F_OK) == 0) {
1642           rc = copy_directory_recursive(from.c_str(), to.c_str());
1643         }
1644         if (rc != 0) {
1645             res = error(rc, "Failed copying " + from + " to " + to);
1646             clear_de_on_exit = true;
1647             return res;
1648         }
1649     }
1650 
1651     // The app may not have any data at all, in which case it's OK to skip here.
1652     auto from_ce = create_data_user_ce_package_path(volume_uuid, userId, package_name);
1653     if (access(from_ce.c_str(), F_OK) != 0) {
1654         LOG(INFO) << "Missing source " << from_ce;
1655         return ok();
1656     }
1657 
1658     // ce_data_inode is not needed when FLAG_CLEAR_CACHE_ONLY is set.
1659     binder::Status clear_cache_result =
1660             clearAppData(volumeUuid, packageName, userId, storageFlags | FLAG_CLEAR_CACHE_ONLY, 0);
1661     if (!clear_cache_result.isOk()) {
1662         // It should be fine to continue snapshot if we for some reason failed
1663         // to clear cache.
1664         LOG(WARNING) << "Failed to clear cache of app " << packageName;
1665     }
1666 
1667     // ce_data_inode is not needed when FLAG_CLEAR_CODE_CACHE_ONLY is set.
1668     binder::Status clear_code_cache_result =
1669             clearAppData(volumeUuid, packageName, userId, storageFlags | FLAG_CLEAR_CODE_CACHE_ONLY,
1670                          0);
1671     if (!clear_code_cache_result.isOk()) {
1672         // It should be fine to continue snapshot if we for some reason failed
1673         // to clear code_cache.
1674         LOG(WARNING) << "Failed to clear code_cache of app " << packageName;
1675     }
1676 
1677     if (storageFlags & FLAG_STORAGE_CE) {
1678         auto from = create_data_user_ce_package_path(volume_uuid, userId, package_name);
1679         auto to = create_data_misc_ce_rollback_path(volume_uuid, userId, snapshotId);
1680         auto rollback_package_path =
1681                 create_data_misc_ce_rollback_package_path(volume_uuid, userId, snapshotId,
1682                                                           package_name);
1683 
1684         int rc = create_dir_if_needed(to.c_str(), kRollbackFolderMode);
1685         if (rc != 0) {
1686             return error(rc, "Failed to create folder " + to);
1687         }
1688 
1689         rc = delete_dir_contents(rollback_package_path, true /* ignore_if_missing */);
1690         if (rc != 0) {
1691             return error(rc, "Failed clearing existing snapshot " + rollback_package_path);
1692         }
1693 
1694         rc = copy_directory_recursive(from.c_str(), to.c_str());
1695         if (rc != 0) {
1696             res = error(rc, "Failed copying " + from + " to " + to);
1697             clear_ce_on_exit = true;
1698             return res;
1699         }
1700         if (_aidl_return != nullptr) {
1701             auto ce_snapshot_path =
1702                     create_data_misc_ce_rollback_package_path(volume_uuid, userId, snapshotId,
1703                                                               package_name);
1704             rc = get_path_inode(ce_snapshot_path, reinterpret_cast<ino_t*>(_aidl_return));
1705             if (rc != 0) {
1706                 res = error(rc, "Failed to get_path_inode for " + ce_snapshot_path);
1707                 clear_ce_on_exit = true;
1708                 return res;
1709             }
1710         }
1711     }
1712 
1713     return res;
1714 }
1715 
restoreAppDataSnapshot(const std::optional<std::string> & volumeUuid,const std::string & packageName,const int32_t appId,const std::string & seInfo,const int32_t userId,const int32_t snapshotId,int32_t storageFlags)1716 binder::Status InstalldNativeService::restoreAppDataSnapshot(
1717         const std::optional<std::string>& volumeUuid, const std::string& packageName,
1718         const int32_t appId, const std::string& seInfo, const int32_t userId,
1719         const int32_t snapshotId, int32_t storageFlags) {
1720     ENFORCE_UID(AID_SYSTEM);
1721     ENFORCE_VALID_USER(userId);
1722     CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid);
1723     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
1724     LOCK_PACKAGE_USER();
1725 
1726     const char* volume_uuid = volumeUuid ? volumeUuid->c_str() : nullptr;
1727     const char* package_name = packageName.c_str();
1728 
1729     auto from_ce = create_data_misc_ce_rollback_package_path(volume_uuid, userId, snapshotId,
1730                                                              package_name);
1731     auto from_de = create_data_misc_de_rollback_package_path(volume_uuid, userId, snapshotId,
1732                                                              package_name);
1733 
1734     const bool needs_ce_rollback = (storageFlags & FLAG_STORAGE_CE) &&
1735         (access(from_ce.c_str(), F_OK) == 0);
1736     const bool needs_de_rollback = (storageFlags & FLAG_STORAGE_DE) &&
1737         (access(from_de.c_str(), F_OK) == 0);
1738 
1739     if (!needs_ce_rollback && !needs_de_rollback) {
1740         return ok();
1741     }
1742 
1743     // We know we're going to rollback one of the CE or DE data, so we clear
1744     // application data first. Note that it's possible that we're asked to
1745     // restore both CE & DE data but that one of the restores fail. Leaving the
1746     // app with no data in those cases is arguably better than leaving the app
1747     // with mismatched / stale data.
1748     LOG(INFO) << "Clearing app data for " << packageName << " to restore snapshot.";
1749     // It's fine to pass 0 as ceDataInode here, because restoreAppDataSnapshot
1750     // can only be called when user unlocks the phone, meaning that CE user data
1751     // is decrypted.
1752     binder::Status res =
1753             clearAppData(volumeUuid, packageName, userId, storageFlags, 0 /* ceDataInode */);
1754     if (!res.isOk()) {
1755         return res;
1756     }
1757 
1758     if (needs_ce_rollback) {
1759         auto to_ce = create_data_user_ce_path(volume_uuid, userId);
1760         int rc = copy_directory_recursive(from_ce.c_str(), to_ce.c_str());
1761         if (rc != 0) {
1762             res = error(rc, "Failed copying " + from_ce + " to " + to_ce);
1763             return res;
1764         }
1765         delete_dir_contents_and_dir(from_ce, true /* ignore_if_missing */);
1766     }
1767 
1768     if (needs_de_rollback) {
1769         auto to_de = create_data_user_de_path(volume_uuid, userId);
1770         int rc = copy_directory_recursive(from_de.c_str(), to_de.c_str());
1771         if (rc != 0) {
1772             if (needs_ce_rollback) {
1773                 auto ce_data = create_data_user_ce_package_path(volume_uuid, userId, package_name);
1774                 LOG(WARNING) << "de_data rollback failed. Erasing rolled back ce_data " << ce_data;
1775                 if (delete_dir_contents(ce_data.c_str(), 1, nullptr) != 0) {
1776                     LOG(WARNING) << "Failed to delete rolled back ce_data " << ce_data;
1777                 }
1778             }
1779             res = error(rc, "Failed copying " + from_de + " to " + to_de);
1780             return res;
1781         }
1782         delete_dir_contents_and_dir(from_de, true /* ignore_if_missing */);
1783     }
1784 
1785     // Finally, restore the SELinux label on the app data.
1786     return restoreconAppData(volumeUuid, packageName, userId, storageFlags, appId, seInfo);
1787 }
1788 
destroyAppDataSnapshot(const std::optional<std::string> & volumeUuid,const std::string & packageName,const int32_t userId,const int64_t ceSnapshotInode,const int32_t snapshotId,int32_t storageFlags)1789 binder::Status InstalldNativeService::destroyAppDataSnapshot(
1790         const std::optional<std::string>& volumeUuid, const std::string& packageName,
1791         const int32_t userId, const int64_t ceSnapshotInode, const int32_t snapshotId,
1792         int32_t storageFlags) {
1793     ENFORCE_UID(AID_SYSTEM);
1794     ENFORCE_VALID_USER(userId);
1795     CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid);
1796     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
1797     LOCK_PACKAGE_USER();
1798 
1799     const char* volume_uuid = volumeUuid ? volumeUuid->c_str() : nullptr;
1800     const char* package_name = packageName.c_str();
1801 
1802     if (storageFlags & FLAG_STORAGE_DE) {
1803         auto de_snapshot_path = create_data_misc_de_rollback_package_path(volume_uuid, userId,
1804                                                                           snapshotId, package_name);
1805 
1806         int res = delete_dir_contents_and_dir(de_snapshot_path, true /* ignore_if_missing */);
1807         if (res != 0) {
1808             return error(res, "Failed clearing snapshot " + de_snapshot_path);
1809         }
1810     }
1811 
1812     if (storageFlags & FLAG_STORAGE_CE) {
1813         auto ce_snapshot_path =
1814                 create_data_misc_ce_rollback_package_path(volume_uuid, userId, snapshotId,
1815                                                           package_name, ceSnapshotInode);
1816         int res = delete_dir_contents_and_dir(ce_snapshot_path, true /* ignore_if_missing */);
1817         if (res != 0) {
1818             return error(res, "Failed clearing snapshot " + ce_snapshot_path);
1819         }
1820     }
1821     return ok();
1822 }
1823 
destroyCeSnapshotsNotSpecified(const std::optional<std::string> & volumeUuid,const int32_t userId,const std::vector<int32_t> & retainSnapshotIds)1824 binder::Status InstalldNativeService::destroyCeSnapshotsNotSpecified(
1825         const std::optional<std::string>& volumeUuid, const int32_t userId,
1826         const std::vector<int32_t>& retainSnapshotIds) {
1827     ENFORCE_UID(AID_SYSTEM);
1828     ENFORCE_VALID_USER(userId);
1829     CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid);
1830     LOCK_USER();
1831 
1832     const char* volume_uuid = volumeUuid ? volumeUuid->c_str() : nullptr;
1833 
1834     auto base_path = create_data_misc_ce_rollback_base_path(volume_uuid, userId);
1835 
1836     std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(base_path.c_str()), closedir);
1837     if (!dir) {
1838         return error(-1, "Failed to open rollback base dir " + base_path);
1839     }
1840 
1841     struct dirent* ent;
1842     while ((ent = readdir(dir.get()))) {
1843         if (ent->d_type != DT_DIR) {
1844             continue;
1845         }
1846 
1847         uint snapshot_id;
1848         bool parse_ok = ParseUint(ent->d_name, &snapshot_id);
1849         if (parse_ok &&
1850                 std::find(retainSnapshotIds.begin(), retainSnapshotIds.end(),
1851                           snapshot_id) == retainSnapshotIds.end()) {
1852             auto rollback_path =
1853                     create_data_misc_ce_rollback_path(volume_uuid, userId, snapshot_id);
1854             int res = delete_dir_contents_and_dir(rollback_path, true /* ignore_if_missing */);
1855             if (res != 0) {
1856                 return error(res, "Failed clearing snapshot " + rollback_path);
1857             }
1858         }
1859     }
1860     return ok();
1861 }
1862 
moveCompleteApp(const std::optional<std::string> & fromUuid,const std::optional<std::string> & toUuid,const std::string & packageName,int32_t appId,const std::string & seInfo,int32_t targetSdkVersion,const std::string & fromCodePath)1863 binder::Status InstalldNativeService::moveCompleteApp(const std::optional<std::string>& fromUuid,
1864         const std::optional<std::string>& toUuid, const std::string& packageName,
1865         int32_t appId, const std::string& seInfo,
1866         int32_t targetSdkVersion, const std::string& fromCodePath) {
1867     ENFORCE_UID(AID_SYSTEM);
1868     CHECK_ARGUMENT_UUID(fromUuid);
1869     CHECK_ARGUMENT_UUID(toUuid);
1870     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
1871     LOCK_PACKAGE();
1872 
1873     const char* from_uuid = fromUuid ? fromUuid->c_str() : nullptr;
1874     const char* to_uuid = toUuid ? toUuid->c_str() : nullptr;
1875     const char* package_name = packageName.c_str();
1876 
1877     binder::Status res = ok();
1878     std::vector<userid_t> users = get_known_users(from_uuid);
1879 
1880     auto to_app_package_path_parent = create_data_app_path(to_uuid);
1881     auto to_app_package_path = StringPrintf("%s/%s", to_app_package_path_parent.c_str(),
1882                                             android::base::Basename(fromCodePath).c_str());
1883 
1884     // Copy app
1885     {
1886         int rc = copy_directory_recursive(fromCodePath.c_str(), to_app_package_path_parent.c_str());
1887         if (rc != 0) {
1888             res = error(rc, "Failed copying " + fromCodePath + " to " + to_app_package_path);
1889             goto fail;
1890         }
1891 
1892         if (selinux_android_restorecon(to_app_package_path.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE) != 0) {
1893             res = error("Failed to restorecon " + to_app_package_path);
1894             goto fail;
1895         }
1896     }
1897 
1898     // Copy private data for all known users
1899     for (auto userId : users) {
1900         LOCK_USER();
1901 
1902         // Data source may not exist for all users; that's okay
1903         auto from_ce = create_data_user_ce_package_path(from_uuid, userId, package_name);
1904         if (access(from_ce.c_str(), F_OK) != 0) {
1905             LOG(INFO) << "Missing source " << from_ce;
1906             continue;
1907         }
1908 
1909         if (!createAppDataLocked(toUuid, packageName, userId, FLAG_STORAGE_CE | FLAG_STORAGE_DE,
1910                                  appId, /* previousAppId */ -1, seInfo, targetSdkVersion, nullptr,
1911                                  nullptr)
1912                      .isOk()) {
1913             res = error("Failed to create package target");
1914             goto fail;
1915         }
1916         {
1917             auto from = create_data_user_de_package_path(from_uuid, userId, package_name);
1918             auto to = create_data_user_de_path(to_uuid, userId);
1919 
1920             int rc = copy_directory_recursive(from.c_str(), to.c_str());
1921             if (rc != 0) {
1922                 res = error(rc, "Failed copying " + from + " to " + to);
1923                 goto fail;
1924             }
1925         }
1926         {
1927             auto from = create_data_user_ce_package_path(from_uuid, userId, package_name);
1928             auto to = create_data_user_ce_path(to_uuid, userId);
1929 
1930             int rc = copy_directory_recursive(from.c_str(), to.c_str());
1931             if (rc != 0) {
1932                 res = error(rc, "Failed copying " + from + " to " + to);
1933                 goto fail;
1934             }
1935         }
1936 
1937         if (!restoreconAppDataLocked(toUuid, packageName, userId, FLAG_STORAGE_CE | FLAG_STORAGE_DE,
1938                                      appId, seInfo)
1939                      .isOk()) {
1940             res = error("Failed to restorecon");
1941             goto fail;
1942         }
1943     }
1944 
1945     // Copy sdk data for all known users
1946     for (auto userId : users) {
1947         LOCK_USER();
1948 
1949         constexpr int storageFlags[2] = {FLAG_STORAGE_CE, FLAG_STORAGE_DE};
1950         for (int currentFlag : storageFlags) {
1951             const bool isCeData = currentFlag == FLAG_STORAGE_CE;
1952 
1953             const auto from = create_data_misc_sdk_sandbox_package_path(from_uuid, isCeData, userId,
1954                                                                         package_name);
1955             if (access(from.c_str(), F_OK) != 0) {
1956                 LOG(INFO) << "Missing source " << from;
1957                 continue;
1958             }
1959             const auto to = create_data_misc_sdk_sandbox_path(to_uuid, isCeData, userId);
1960 
1961             const int rc = copy_directory_recursive(from.c_str(), to.c_str());
1962             if (rc != 0) {
1963                 res = error(rc, "Failed copying " + from + " to " + to);
1964                 goto fail;
1965             }
1966         }
1967 
1968         if (!restoreconSdkDataLocked(toUuid, packageName, userId, FLAG_STORAGE_CE | FLAG_STORAGE_DE,
1969                                      appId, seInfo)
1970                      .isOk()) {
1971             res = error("Failed to restorecon");
1972             goto fail;
1973         }
1974     }
1975     // We let the framework scan the new location and persist that before
1976     // deleting the data in the old location; this ordering ensures that
1977     // we can recover from things like battery pulls.
1978     return ok();
1979 
1980 fail:
1981     // Nuke everything we might have already copied
1982     {
1983         if (delete_dir_contents(to_app_package_path.c_str(), 1, nullptr) != 0) {
1984             LOG(WARNING) << "Failed to rollback " << to_app_package_path;
1985         }
1986     }
1987     for (auto userId : users) {
1988         LOCK_USER();
1989         {
1990             auto to = create_data_user_de_package_path(to_uuid, userId, package_name);
1991             if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) {
1992                 LOG(WARNING) << "Failed to rollback " << to;
1993             }
1994         }
1995         {
1996             auto to = create_data_user_ce_package_path(to_uuid, userId, package_name);
1997             if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) {
1998                 LOG(WARNING) << "Failed to rollback " << to;
1999             }
2000         }
2001     }
2002     for (auto userId : users) {
2003         LOCK_USER();
2004         constexpr int storageFlags[2] = {FLAG_STORAGE_CE, FLAG_STORAGE_DE};
2005         for (int currentFlag : storageFlags) {
2006             const bool isCeData = currentFlag == FLAG_STORAGE_CE;
2007             const auto to = create_data_misc_sdk_sandbox_package_path(to_uuid, isCeData, userId,
2008                                                                       package_name);
2009             if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) {
2010                 LOG(WARNING) << "Failed to rollback " << to;
2011             }
2012         }
2013     }
2014     return res;
2015 }
2016 
createUserData(const std::optional<std::string> & uuid,int32_t userId,int32_t userSerial ATTRIBUTE_UNUSED,int32_t flags)2017 binder::Status InstalldNativeService::createUserData(const std::optional<std::string>& uuid,
2018         int32_t userId, int32_t userSerial ATTRIBUTE_UNUSED, int32_t flags) {
2019     ENFORCE_UID(AID_SYSTEM);
2020     ENFORCE_VALID_USER(userId);
2021     CHECK_ARGUMENT_UUID(uuid);
2022     LOCK_USER();
2023 
2024     ScopedTrace tracer("create-user-data");
2025 
2026     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
2027     if (flags & FLAG_STORAGE_DE) {
2028         if (uuid_ == nullptr) {
2029             if (ensure_config_user_dirs(userId) != 0) {
2030                 return error(StringPrintf("Failed to ensure dirs for %d", userId));
2031             }
2032         }
2033     }
2034 
2035     return ok();
2036 }
2037 
destroyUserData(const std::optional<std::string> & uuid,int32_t userId,int32_t flags)2038 binder::Status InstalldNativeService::destroyUserData(const std::optional<std::string>& uuid,
2039         int32_t userId, int32_t flags) {
2040     ENFORCE_UID(AID_SYSTEM);
2041     ENFORCE_VALID_USER(userId);
2042     CHECK_ARGUMENT_UUID(uuid);
2043     LOCK_USER();
2044 
2045     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
2046     binder::Status res = ok();
2047     if (flags & FLAG_STORAGE_DE) {
2048         auto path = create_data_user_de_path(uuid_, userId);
2049         // Contents only, as vold is responsible for the user_de dir itself.
2050         if (delete_dir_contents(path, true) != 0) {
2051             res = error("Failed to delete contents of " + path);
2052         }
2053         auto sdk_sandbox_de_path =
2054                 create_data_misc_sdk_sandbox_path(uuid_, /*isCeData=*/false, userId);
2055         if (delete_dir_contents_and_dir(sdk_sandbox_de_path, true) != 0) {
2056             res = error("Failed to delete " + sdk_sandbox_de_path);
2057         }
2058         if (uuid_ == nullptr) {
2059             path = create_data_misc_legacy_path(userId);
2060             if (delete_dir_contents_and_dir(path, true) != 0) {
2061                 res = error("Failed to delete " + path);
2062             }
2063             path = create_primary_cur_profile_dir_path(userId);
2064             if (delete_dir_contents_and_dir(path, true) != 0) {
2065                 res = error("Failed to delete " + path);
2066             }
2067         }
2068     }
2069     if (flags & FLAG_STORAGE_CE) {
2070         auto path = create_data_user_ce_path(uuid_, userId);
2071         // Contents only, as vold is responsible for the user_ce dir itself.
2072         if (delete_dir_contents(path, true) != 0) {
2073             res = error("Failed to delete contents of " + path);
2074         }
2075         auto sdk_sandbox_ce_path =
2076                 create_data_misc_sdk_sandbox_path(uuid_, /*isCeData=*/true, userId);
2077         if (delete_dir_contents_and_dir(sdk_sandbox_ce_path, true) != 0) {
2078             res = error("Failed to delete " + sdk_sandbox_ce_path);
2079         }
2080         path = findDataMediaPath(uuid, userId);
2081         // Contents only, as vold is responsible for the media dir itself.
2082         if (delete_dir_contents(path, true) != 0) {
2083             res = error("Failed to delete contents of " + path);
2084         }
2085     }
2086     return res;
2087 }
2088 
freeCache(const std::optional<std::string> & uuid,int64_t targetFreeBytes,int32_t flags)2089 binder::Status InstalldNativeService::freeCache(const std::optional<std::string>& uuid,
2090         int64_t targetFreeBytes, int32_t flags) {
2091     ENFORCE_UID(AID_SYSTEM);
2092     CHECK_ARGUMENT_UUID(uuid);
2093 #ifndef GRANULAR_LOCKS
2094     std::lock_guard lock(mLock);
2095 #endif // !GRANULAR_LOCKS
2096 
2097     auto uuidString = uuid.value_or("");
2098     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
2099     auto data_path = create_data_path(uuid_);
2100     auto noop = (flags & FLAG_FREE_CACHE_NOOP);
2101     auto defy_target = (flags & FLAG_FREE_CACHE_DEFY_TARGET_FREE_BYTES);
2102 
2103     int64_t free = data_disk_free(data_path);
2104     if (free < 0) {
2105         return error("Failed to determine free space for " + data_path);
2106     }
2107 
2108     int64_t needed = targetFreeBytes - free;
2109     if (!defy_target) {
2110         LOG(DEBUG) << "Device " << data_path << " has " << free << " free; requested "
2111                 << targetFreeBytes << "; needed " << needed;
2112 
2113         if (free >= targetFreeBytes) {
2114             return ok();
2115         }
2116     }
2117 
2118     if (flags & FLAG_FREE_CACHE_V2) {
2119         // This new cache strategy fairly removes files from UIDs by deleting
2120         // files from the UIDs which are most over their allocated quota
2121 
2122         // 1. Create trackers for every known UID
2123         atrace_pm_begin("create");
2124         const auto users = get_known_users(uuid_);
2125 #ifdef GRANULAR_LOCKS
2126         std::vector<UserLock> userLocks;
2127         userLocks.reserve(users.size());
2128         std::vector<UserWriteLockGuard> lockGuards;
2129         lockGuards.reserve(users.size());
2130 #endif // GRANULAR_LOCKS
2131         std::unordered_map<uid_t, std::shared_ptr<CacheTracker>> trackers;
2132         for (auto userId : users) {
2133 #ifdef GRANULAR_LOCKS
2134             userLocks.emplace_back(userId, mUserIdLock, mLock);
2135             lockGuards.emplace_back(userLocks.back());
2136 #endif // GRANULAR_LOCKS
2137             FTS *fts;
2138             FTSENT *p;
2139 
2140             // Create a list of data paths whose children have cache directories
2141             auto ce_path = create_data_user_ce_path(uuid_, userId);
2142             auto de_path = create_data_user_de_path(uuid_, userId);
2143             auto media_path = findDataMediaPath(uuid, userId) + "/Android/data/";
2144             auto ce_sdk_path = create_data_misc_sdk_sandbox_path(uuid_, /*isCeData=*/true, userId);
2145             auto de_sdk_path = create_data_misc_sdk_sandbox_path(uuid_, /*isCeData=*/false, userId);
2146 
2147             std::vector<std::string> dataPaths = {ce_path, de_path, media_path};
2148             foreach_subdir(ce_sdk_path, [&ce_sdk_path, &dataPaths](const std::string subDir) {
2149                 const auto fullpath = ce_sdk_path + "/" + subDir;
2150                 dataPaths.push_back(fullpath);
2151             });
2152             foreach_subdir(de_sdk_path, [&de_sdk_path, &dataPaths](const std::string subDir) {
2153                 const auto fullpath = de_sdk_path + "/" + subDir;
2154                 dataPaths.push_back((char*)fullpath.c_str());
2155             });
2156 
2157             char* argv[dataPaths.size() + 1];
2158             for (unsigned int i = 0; i < dataPaths.size(); i++) {
2159                 argv[i] = (char*)dataPaths[i].c_str();
2160             }
2161             argv[dataPaths.size()] = nullptr;
2162 
2163             if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) {
2164                 return error("Failed to fts_open");
2165             }
2166             while ((p = fts_read(fts)) != nullptr) {
2167                 if (p->fts_info == FTS_D && p->fts_level == 1) {
2168                     uid_t uid = p->fts_statp->st_uid;
2169 
2170                     // If uid belongs to sdk sandbox, then the cache should be attributed to the
2171                     // original client app.
2172                     const auto client_uid = multiuser_convert_sdk_sandbox_to_app_uid(uid);
2173                     const bool isSandboxUid = (client_uid != (uid_t)-1);
2174                     if (isSandboxUid) uid = client_uid;
2175 
2176                     if (multiuser_get_app_id(uid) == AID_MEDIA_RW) {
2177                         uid = (multiuser_get_app_id(p->fts_statp->st_gid) - AID_EXT_GID_START)
2178                                 + AID_APP_START;
2179                     }
2180                     auto search = trackers.find(uid);
2181                     if (search != trackers.end()) {
2182                         search->second->addDataPath(p->fts_path);
2183                     } else {
2184                         auto tracker = std::shared_ptr<CacheTracker>(new CacheTracker(
2185                                 multiuser_get_user_id(uid), multiuser_get_app_id(uid), uuidString));
2186                         tracker->addDataPath(p->fts_path);
2187                         {
2188                             std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
2189                             tracker->cacheQuota = mCacheQuotas[uid];
2190                         }
2191                         if (tracker->cacheQuota == 0) {
2192 #if MEASURE_DEBUG
2193                             LOG(WARNING) << "UID " << uid << " has no cache quota; assuming 64MB";
2194 #endif
2195                             tracker->cacheQuota = 67108864;
2196                         }
2197                         trackers[uid] = tracker;
2198                     }
2199                     fts_set(fts, p, FTS_SKIP);
2200                 }
2201             }
2202             fts_close(fts);
2203         }
2204         atrace_pm_end();
2205 
2206         // 2. Populate tracker stats and insert into priority queue
2207         atrace_pm_begin("populate");
2208         auto cmp = [](std::shared_ptr<CacheTracker> left, std::shared_ptr<CacheTracker> right) {
2209             return (left->getCacheRatio() < right->getCacheRatio());
2210         };
2211         std::priority_queue<std::shared_ptr<CacheTracker>,
2212                 std::vector<std::shared_ptr<CacheTracker>>, decltype(cmp)> queue(cmp);
2213         for (const auto& it : trackers) {
2214             it.second->loadStats();
2215             queue.push(it.second);
2216         }
2217         atrace_pm_end();
2218 
2219         // 3. Bounce across the queue, freeing items from whichever tracker is
2220         // the most over their assigned quota
2221         atrace_pm_begin("bounce");
2222         std::shared_ptr<CacheTracker> active;
2223         while (active || !queue.empty()) {
2224             // Only look at apps under quota when explicitly requested
2225             if (active && (active->getCacheRatio() < 10000)
2226                     && !(flags & FLAG_FREE_CACHE_V2_DEFY_QUOTA)) {
2227                 LOG(DEBUG) << "Active ratio " << active->getCacheRatio()
2228                         << " isn't over quota, and defy not requested";
2229                 break;
2230             }
2231 
2232             // Find the best tracker to work with; this might involve swapping
2233             // if the active tracker is no longer the most over quota
2234             bool nextBetter = active && !queue.empty()
2235                     && active->getCacheRatio() < queue.top()->getCacheRatio();
2236             if (!active || nextBetter) {
2237                 if (active) {
2238                     // Current tracker still has items, so we'll consider it
2239                     // again later once it bubbles up to surface
2240                     queue.push(active);
2241                 }
2242                 active = queue.top(); queue.pop();
2243                 active->ensureItems();
2244                 continue;
2245             }
2246 
2247             // If no items remain, go find another tracker
2248             if (active->items.empty()) {
2249                 active = nullptr;
2250                 continue;
2251             } else {
2252                 auto item = active->items.back();
2253                 active->items.pop_back();
2254 
2255                 LOG(DEBUG) << "Purging " << item->toString() << " from " << active->toString();
2256                 if (!noop) {
2257                     item->purge();
2258                 }
2259                 active->cacheUsed -= item->size;
2260                 needed -= item->size;
2261             }
2262 
2263             if (!defy_target) {
2264                 // Verify that we're actually done before bailing, since sneaky
2265                 // apps might be using hardlinks
2266                 if (needed <= 0) {
2267                     free = data_disk_free(data_path);
2268                     needed = targetFreeBytes - free;
2269                     if (needed <= 0) {
2270                         break;
2271                     } else {
2272                         LOG(WARNING) << "Expected to be done but still need " << needed;
2273                     }
2274                 }
2275             }
2276         }
2277         atrace_pm_end();
2278 
2279     } else {
2280         return error("Legacy cache logic no longer supported");
2281     }
2282 
2283     if (!defy_target) {
2284         free = data_disk_free(data_path);
2285         if (free >= targetFreeBytes) {
2286             return ok();
2287         } else {
2288             return error(StringPrintf("Failed to free up %" PRId64 " on %s; final free space %" PRId64,
2289                     targetFreeBytes, data_path.c_str(), free));
2290         }
2291     } else {
2292         return ok();
2293     }
2294 }
2295 
rmdex(const std::string & codePath,const std::string & instructionSet)2296 binder::Status InstalldNativeService::rmdex(const std::string& codePath,
2297         const std::string& instructionSet) {
2298     ENFORCE_UID(AID_SYSTEM);
2299     CHECK_ARGUMENT_PATH(codePath);
2300 
2301     char dex_path[PKG_PATH_MAX];
2302 
2303     const char* path = codePath.c_str();
2304     const char* instruction_set = instructionSet.c_str();
2305 
2306     if (validate_apk_path(path) && validate_system_app_path(path)) {
2307         return error("Invalid path " + codePath);
2308     }
2309 
2310     if (!create_cache_path(dex_path, path, instruction_set)) {
2311         return error("Failed to create cache path for " + codePath);
2312     }
2313 
2314     ALOGV("unlink %s\n", dex_path);
2315     if (unlink(dex_path) < 0) {
2316         // It's ok if we don't have a dalvik cache path. Report error only when the path exists
2317         // but could not be unlinked.
2318         if (errno != ENOENT) {
2319             return error(StringPrintf("Failed to unlink %s", dex_path));
2320         }
2321     }
2322     return ok();
2323 }
2324 
2325 struct stats {
2326     int64_t codeSize;
2327     int64_t dataSize;
2328     int64_t cacheSize;
2329 };
2330 
2331 #if MEASURE_DEBUG
toString(std::vector<int64_t> values)2332 static std::string toString(std::vector<int64_t> values) {
2333     std::stringstream res;
2334     res << "[";
2335     for (size_t i = 0; i < values.size(); i++) {
2336         res << values[i];
2337         if (i < values.size() - 1) {
2338             res << ",";
2339         }
2340     }
2341     res << "]";
2342     return res.str();
2343 }
2344 #endif
2345 
2346 // On devices without sdcardfs, if internal and external are on
2347 // the same volume, a uid such as u0_a123 is used for both
2348 // internal and external storage; therefore, subtract that
2349 // amount from internal to make sure we don't count it double.
2350 // This needs to happen for data, cache and OBB
deductDoubleSpaceIfNeeded(stats * stats,int64_t doubleSpaceToBeDeleted,uid_t uid,const std::string & uuid)2351 static void deductDoubleSpaceIfNeeded(stats* stats, int64_t doubleSpaceToBeDeleted, uid_t uid,
2352                                       const std::string& uuid) {
2353     if (!supports_sdcardfs()) {
2354         stats->dataSize -= doubleSpaceToBeDeleted;
2355         long obbProjectId = get_project_id(uid, PROJECT_ID_EXT_OBB_START);
2356         int64_t appObbSize = GetOccupiedSpaceForProjectId(uuid, obbProjectId);
2357         stats->dataSize -= appObbSize;
2358     }
2359 }
2360 
collectQuotaStats(const std::string & uuid,int32_t userId,int32_t appId,struct stats * stats,struct stats * extStats)2361 static void collectQuotaStats(const std::string& uuid, int32_t userId,
2362         int32_t appId, struct stats* stats, struct stats* extStats) {
2363     int64_t space, doubleSpaceToBeDeleted = 0;
2364     uid_t uid = multiuser_get_uid(userId, appId);
2365     static const bool supportsProjectId = internal_storage_has_project_id();
2366 
2367     if (extStats != nullptr) {
2368         space = get_occupied_app_space_external(uuid, userId, appId);
2369 
2370         if (space != -1) {
2371             extStats->dataSize += space;
2372             doubleSpaceToBeDeleted += space;
2373         }
2374 
2375         space = get_occupied_app_cache_space_external(uuid, userId, appId);
2376         if (space != -1) {
2377             extStats->dataSize += space; // cache counts for "data"
2378             extStats->cacheSize += space;
2379             doubleSpaceToBeDeleted += space;
2380         }
2381     }
2382 
2383     if (stats != nullptr) {
2384         if (!supportsProjectId) {
2385             if ((space = GetOccupiedSpaceForUid(uuid, uid)) != -1) {
2386                 stats->dataSize += space;
2387             }
2388             deductDoubleSpaceIfNeeded(stats, doubleSpaceToBeDeleted, uid, uuid);
2389             int sdkSandboxUid = multiuser_get_sdk_sandbox_uid(userId, appId);
2390             if (sdkSandboxUid != -1) {
2391                 if ((space = GetOccupiedSpaceForUid(uuid, sdkSandboxUid)) != -1) {
2392                     stats->dataSize += space;
2393                 }
2394             }
2395             int cacheGid = multiuser_get_cache_gid(userId, appId);
2396             if (cacheGid != -1) {
2397                 if ((space = GetOccupiedSpaceForGid(uuid, cacheGid)) != -1) {
2398                     stats->cacheSize += space;
2399                 }
2400             }
2401         } else {
2402             long projectId = get_project_id(uid, PROJECT_ID_APP_START);
2403             if ((space = GetOccupiedSpaceForProjectId(uuid, projectId)) != -1) {
2404                 stats->dataSize += space;
2405             }
2406             projectId = get_project_id(uid, PROJECT_ID_APP_CACHE_START);
2407             if ((space = GetOccupiedSpaceForProjectId(uuid, projectId)) != -1) {
2408                 stats->cacheSize += space;
2409                 stats->dataSize += space;
2410             }
2411         }
2412 
2413         int sharedGid = multiuser_get_shared_gid(0, appId);
2414         if (sharedGid != -1) {
2415             if ((space = GetOccupiedSpaceForGid(uuid, sharedGid)) != -1) {
2416                 stats->codeSize += space;
2417             }
2418         }
2419     }
2420 }
2421 
collectManualStats(const std::string & path,struct stats * stats)2422 static void collectManualStats(const std::string& path, struct stats* stats) {
2423     DIR *d;
2424     int dfd;
2425     struct dirent *de;
2426     struct stat s;
2427 
2428     d = opendir(path.c_str());
2429     if (d == nullptr) {
2430         if (errno != ENOENT) {
2431             PLOG(WARNING) << "Failed to open " << path;
2432         }
2433         return;
2434     }
2435     dfd = dirfd(d);
2436     while ((de = readdir(d))) {
2437         const char *name = de->d_name;
2438 
2439         int64_t size = 0;
2440         if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
2441             size = s.st_blocks * 512;
2442         }
2443 
2444         if (de->d_type == DT_DIR) {
2445             if (!strcmp(name, ".")) {
2446                 // Don't recurse, but still count node size
2447             } else if (!strcmp(name, "..")) {
2448                 // Don't recurse or count node size
2449                 continue;
2450             } else {
2451                 // Measure all children nodes
2452                 size = 0;
2453                 calculate_tree_size(StringPrintf("%s/%s", path.c_str(), name), &size);
2454             }
2455 
2456             if (!strcmp(name, "cache") || !strcmp(name, "code_cache")) {
2457                 stats->cacheSize += size;
2458             }
2459         }
2460 
2461         // Legacy symlink isn't owned by app
2462         if (de->d_type == DT_LNK && !strcmp(name, "lib")) {
2463             continue;
2464         }
2465 
2466         // Everything found inside is considered data
2467         stats->dataSize += size;
2468     }
2469     closedir(d);
2470 }
2471 
collectManualStatsForSubDirectories(const std::string & path,struct stats * stats)2472 void collectManualStatsForSubDirectories(const std::string& path, struct stats* stats) {
2473     const auto subDirHandler = [&path, &stats](const std::string& subDir) {
2474         auto fullpath = path + "/" + subDir;
2475         collectManualStats(fullpath, stats);
2476     };
2477     foreach_subdir(path, subDirHandler);
2478 }
2479 
collectManualStatsForUser(const std::string & path,struct stats * stats,bool exclude_apps=false,bool is_sdk_sandbox_storage=false)2480 static void collectManualStatsForUser(const std::string& path, struct stats* stats,
2481                                       bool exclude_apps = false,
2482                                       bool is_sdk_sandbox_storage = false) {
2483     DIR *d;
2484     int dfd;
2485     struct dirent *de;
2486     struct stat s;
2487 
2488     d = opendir(path.c_str());
2489     if (d == nullptr) {
2490         if (errno != ENOENT) {
2491             PLOG(WARNING) << "Failed to open " << path;
2492         }
2493         return;
2494     }
2495     dfd = dirfd(d);
2496     while ((de = readdir(d))) {
2497         if (de->d_type == DT_DIR) {
2498             const char *name = de->d_name;
2499             if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) != 0) {
2500                 continue;
2501             }
2502             int32_t user_uid = multiuser_get_app_id(s.st_uid);
2503             if (!strcmp(name, ".") || !strcmp(name, "..")) {
2504                 continue;
2505             } else if (exclude_apps && (user_uid >= AID_APP_START && user_uid <= AID_APP_END)) {
2506                 continue;
2507             } else if (is_sdk_sandbox_storage) {
2508                 // In case of sdk sandbox storage (e.g. /data/misc_ce/0/sdksandbox/<package-name>),
2509                 // collect individual stats of each subdirectory (shared, storage of each sdk etc.)
2510                 collectManualStatsForSubDirectories(StringPrintf("%s/%s", path.c_str(), name),
2511                                                     stats);
2512             } else {
2513                 collectManualStats(StringPrintf("%s/%s", path.c_str(), name), stats);
2514             }
2515         }
2516     }
2517     closedir(d);
2518 }
2519 
collectManualExternalStatsForUser(const std::string & path,struct stats * stats)2520 static void collectManualExternalStatsForUser(const std::string& path, struct stats* stats) {
2521     FTS *fts;
2522     FTSENT *p;
2523     char *argv[] = { (char*) path.c_str(), nullptr };
2524     if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) {
2525         PLOG(ERROR) << "Failed to fts_open " << path;
2526         return;
2527     }
2528     while ((p = fts_read(fts)) != nullptr) {
2529         p->fts_number = p->fts_parent->fts_number;
2530         switch (p->fts_info) {
2531         case FTS_D:
2532             if (p->fts_level == 3
2533                     && !strcmp(p->fts_parent->fts_name, "obb")
2534                     && !strcmp(p->fts_parent->fts_parent->fts_name, "Android")) {
2535                 p->fts_number = 1;
2536             } else if (p->fts_level == 4
2537                     && !strcmp(p->fts_name, "cache")
2538                     && !strcmp(p->fts_parent->fts_parent->fts_name, "data")
2539                     && !strcmp(p->fts_parent->fts_parent->fts_parent->fts_name, "Android")) {
2540                 p->fts_number = 2;
2541             }
2542             [[fallthrough]]; // to count the directory
2543         case FTS_DEFAULT:
2544         case FTS_F:
2545         case FTS_SL:
2546         case FTS_SLNONE:
2547             int64_t size = (p->fts_statp->st_blocks * 512);
2548             if (p->fts_number == 1) {
2549                 stats->codeSize += size;
2550             } else {
2551                 if (p->fts_number == 2) {
2552                     stats->cacheSize += size;
2553                 }
2554                 stats->dataSize += size;
2555             }
2556             break;
2557         }
2558     }
2559     fts_close(fts);
2560 }
ownsExternalStorage(int32_t appId)2561 static bool ownsExternalStorage(int32_t appId) {
2562     // if project id calculation is supported then, there is no need to
2563     // calculate in a different way and project_id based calculation can work
2564     if (internal_storage_has_project_id()) {
2565         return false;
2566     }
2567 
2568     //  Fetch external storage owner appid  and check if it is the same as the
2569     //  current appId whose size is calculated
2570     struct stat s;
2571     auto _picDir = StringPrintf("%s/Pictures", create_data_media_path(nullptr, 0).c_str());
2572     // check if the stat are present
2573     if (stat(_picDir.c_str(), &s) == 0) {
2574         // fetch the appId from the uid of the media app
2575         return ((int32_t)multiuser_get_app_id(s.st_uid) == appId);
2576     }
2577     return false;
2578 }
getAppSize(const std::optional<std::string> & uuid,const std::vector<std::string> & packageNames,int32_t userId,int32_t flags,int32_t appId,const std::vector<int64_t> & ceDataInodes,const std::vector<std::string> & codePaths,std::vector<int64_t> * _aidl_return)2579 binder::Status InstalldNativeService::getAppSize(const std::optional<std::string>& uuid,
2580         const std::vector<std::string>& packageNames, int32_t userId, int32_t flags,
2581         int32_t appId, const std::vector<int64_t>& ceDataInodes,
2582         const std::vector<std::string>& codePaths, std::vector<int64_t>* _aidl_return) {
2583     ENFORCE_UID(AID_SYSTEM);
2584     CHECK_ARGUMENT_UUID(uuid);
2585     if (packageNames.size() != ceDataInodes.size()) {
2586         return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
2587                          "packageNames/ceDataInodes size mismatch.");
2588     }
2589     for (const auto& packageName : packageNames) {
2590         CHECK_ARGUMENT_PACKAGE_NAME(packageName);
2591     }
2592     for (const auto& codePath : codePaths) {
2593         CHECK_ARGUMENT_PATH(codePath);
2594     }
2595     // NOTE: Locking is relaxed on this method, since it's limited to
2596     // read-only measurements without mutation.
2597 
2598     // When modifying this logic, always verify using tests:
2599     // runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetAppSize
2600 
2601 #if MEASURE_DEBUG
2602     LOG(INFO) << "Measuring user " << userId << " app " << appId;
2603 #endif
2604 
2605     // Here's a summary of the common storage locations across the platform,
2606     // and how they're each tagged:
2607     //
2608     // /data/app/com.example                           UID system
2609     // /data/app/com.example/oat                       UID system
2610     // /data/user/0/com.example                        UID u0_a10      GID u0_a10
2611     // /data/user/0/com.example/cache                  UID u0_a10      GID u0_a10_cache
2612     // /data/media/0/foo.txt                           UID u0_media_rw
2613     // /data/media/0/bar.jpg                           UID u0_media_rw GID u0_media_image
2614     // /data/media/0/Android/data/com.example          UID u0_media_rw GID u0_a10_ext
2615     // /data/media/0/Android/data/com.example/cache    UID u0_media_rw GID u0_a10_ext_cache
2616     // /data/media/obb/com.example                     UID system
2617 
2618     struct stats stats;
2619     struct stats extStats;
2620     memset(&stats, 0, sizeof(stats));
2621     memset(&extStats, 0, sizeof(extStats));
2622 
2623     auto uuidString = uuid.value_or("");
2624     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
2625 
2626     if (!IsQuotaSupported(uuidString)) {
2627         flags &= ~FLAG_USE_QUOTA;
2628     }
2629 
2630     atrace_pm_begin("obb");
2631     for (const auto& packageName : packageNames) {
2632         auto obbCodePath = create_data_media_package_path(uuid_, userId,
2633                 "obb", packageName.c_str());
2634         calculate_tree_size(obbCodePath, &extStats.codeSize);
2635     }
2636     atrace_pm_end();
2637     // Calculating the app size of the external storage owning app in a manual way, since
2638     // calculating it through quota apis also includes external media storage in the app storage
2639     // numbers
2640     if (flags & FLAG_USE_QUOTA && appId >= AID_APP_START && !ownsExternalStorage(appId)) {
2641         atrace_pm_begin("code");
2642         for (const auto& codePath : codePaths) {
2643             calculate_tree_size(codePath, &stats.codeSize, -1,
2644                     multiuser_get_shared_gid(0, appId));
2645         }
2646         atrace_pm_end();
2647 
2648         atrace_pm_begin("quota");
2649         collectQuotaStats(uuidString, userId, appId, &stats, &extStats);
2650         atrace_pm_end();
2651     } else {
2652         atrace_pm_begin("code");
2653         for (const auto& codePath : codePaths) {
2654             calculate_tree_size(codePath, &stats.codeSize);
2655         }
2656         atrace_pm_end();
2657 
2658         for (size_t i = 0; i < packageNames.size(); i++) {
2659             const char* pkgname = packageNames[i].c_str();
2660 
2661             atrace_pm_begin("data");
2662             auto cePath = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInodes[i]);
2663             collectManualStats(cePath, &stats);
2664             auto dePath = create_data_user_de_package_path(uuid_, userId, pkgname);
2665             collectManualStats(dePath, &stats);
2666             atrace_pm_end();
2667 
2668             // In case of sdk sandbox storage (e.g. /data/misc_ce/0/sdksandbox/<package-name>),
2669             // collect individual stats of each subdirectory (shared, storage of each sdk etc.)
2670             if (appId >= AID_APP_START && appId <= AID_APP_END) {
2671                 atrace_pm_begin("sdksandbox");
2672                 auto sdkSandboxCePath =
2673                         create_data_misc_sdk_sandbox_package_path(uuid_, true, userId, pkgname);
2674                 collectManualStatsForSubDirectories(sdkSandboxCePath, &stats);
2675                 auto sdkSandboxDePath =
2676                         create_data_misc_sdk_sandbox_package_path(uuid_, false, userId, pkgname);
2677                 collectManualStatsForSubDirectories(sdkSandboxDePath, &stats);
2678                 atrace_pm_end();
2679             }
2680 
2681             if (!uuid) {
2682                 atrace_pm_begin("profiles");
2683                 calculate_tree_size(
2684                         create_primary_current_profile_package_dir_path(userId, pkgname),
2685                         &stats.dataSize);
2686                 calculate_tree_size(
2687                         create_primary_reference_profile_package_dir_path(pkgname),
2688                         &stats.codeSize);
2689                 atrace_pm_end();
2690             }
2691 
2692             atrace_pm_begin("external");
2693             auto extPath = create_data_media_package_path(uuid_, userId, "data", pkgname);
2694             collectManualStats(extPath, &extStats);
2695             auto mediaPath = create_data_media_package_path(uuid_, userId, "media", pkgname);
2696             calculate_tree_size(mediaPath, &extStats.dataSize);
2697             atrace_pm_end();
2698         }
2699 
2700         if (!uuid) {
2701             atrace_pm_begin("dalvik");
2702             int32_t sharedGid = multiuser_get_shared_gid(0, appId);
2703             if (sharedGid != -1) {
2704                 calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
2705                         sharedGid, -1);
2706             }
2707             atrace_pm_end();
2708         }
2709     }
2710 
2711     std::vector<int64_t> ret;
2712     ret.push_back(stats.codeSize);
2713     ret.push_back(stats.dataSize);
2714     ret.push_back(stats.cacheSize);
2715     ret.push_back(extStats.codeSize);
2716     ret.push_back(extStats.dataSize);
2717     ret.push_back(extStats.cacheSize);
2718 #if MEASURE_DEBUG
2719     LOG(DEBUG) << "Final result " << toString(ret);
2720 #endif
2721     *_aidl_return = ret;
2722     return ok();
2723 }
2724 
2725 struct external_sizes {
2726     int64_t audioSize;
2727     int64_t videoSize;
2728     int64_t imageSize;
2729     int64_t totalSize; // excludes OBBs (Android/obb), but includes app data + cache
2730     int64_t obbSize;
2731 };
2732 
2733 #define PER_USER_RANGE 100000
2734 
getProjectIdForUser(int userId,long projectId)2735 static long getProjectIdForUser(int userId, long projectId) {
2736     return userId * PER_USER_RANGE + projectId;
2737 }
2738 
getExternalSizesForUserWithQuota(const std::string & uuid,int32_t userId,const std::vector<int32_t> & appIds)2739 static external_sizes getExternalSizesForUserWithQuota(const std::string& uuid, int32_t userId, const std::vector<int32_t>& appIds) {
2740     struct external_sizes sizes = {};
2741     int64_t space;
2742 
2743     if (supports_sdcardfs()) {
2744         uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
2745         if ((space = GetOccupiedSpaceForUid(uuid, uid)) != -1) {
2746             sizes.totalSize = space;
2747         }
2748 
2749         gid_t audioGid = multiuser_get_uid(userId, AID_MEDIA_AUDIO);
2750         if ((space = GetOccupiedSpaceForGid(uuid, audioGid)) != -1) {
2751             sizes.audioSize = space;
2752         }
2753 
2754         gid_t videoGid = multiuser_get_uid(userId, AID_MEDIA_VIDEO);
2755         if ((space = GetOccupiedSpaceForGid(uuid, videoGid)) != -1) {
2756             sizes.videoSize = space;
2757         }
2758 
2759         gid_t imageGid = multiuser_get_uid(userId, AID_MEDIA_IMAGE);
2760         if ((space = GetOccupiedSpaceForGid(uuid, imageGid)) != -1) {
2761             sizes.imageSize = space;
2762         }
2763 
2764         if ((space = GetOccupiedSpaceForGid(uuid, AID_MEDIA_OBB)) != -1) {
2765             sizes.obbSize = space;
2766         }
2767     } else {
2768         int64_t totalSize = 0;
2769         long defaultProjectId = getProjectIdForUser(userId, PROJECT_ID_EXT_DEFAULT);
2770         if ((space = GetOccupiedSpaceForProjectId(uuid, defaultProjectId)) != -1) {
2771             // This is all files that are not audio/video/images, excluding
2772             // OBBs and app-private data
2773             totalSize += space;
2774         }
2775 
2776         long audioProjectId = getProjectIdForUser(userId, PROJECT_ID_EXT_MEDIA_AUDIO);
2777         if ((space = GetOccupiedSpaceForProjectId(uuid, audioProjectId)) != -1) {
2778             sizes.audioSize = space;
2779             totalSize += space;
2780         }
2781 
2782         long videoProjectId = getProjectIdForUser(userId, PROJECT_ID_EXT_MEDIA_VIDEO);
2783         if ((space = GetOccupiedSpaceForProjectId(uuid, videoProjectId)) != -1) {
2784             sizes.videoSize = space;
2785             totalSize += space;
2786         }
2787 
2788         long imageProjectId = getProjectIdForUser(userId, PROJECT_ID_EXT_MEDIA_IMAGE);
2789         if ((space = GetOccupiedSpaceForProjectId(uuid, imageProjectId)) != -1) {
2790             sizes.imageSize = space;
2791             totalSize += space;
2792         }
2793 
2794         int64_t totalAppDataSize = 0;
2795         int64_t totalAppCacheSize = 0;
2796         int64_t totalAppObbSize = 0;
2797         for (auto appId : appIds) {
2798             if (appId >= AID_APP_START) {
2799                 // App data
2800                 uid_t uid = multiuser_get_uid(userId, appId);
2801                 long projectId = uid - AID_APP_START + PROJECT_ID_EXT_DATA_START;
2802                 totalAppDataSize += GetOccupiedSpaceForProjectId(uuid, projectId);
2803 
2804                 // App cache
2805                 long cacheProjectId = uid - AID_APP_START + PROJECT_ID_EXT_CACHE_START;
2806                 totalAppCacheSize += GetOccupiedSpaceForProjectId(uuid, cacheProjectId);
2807 
2808                 // App OBBs
2809                 long obbProjectId = uid - AID_APP_START + PROJECT_ID_EXT_OBB_START;
2810                 totalAppObbSize += GetOccupiedSpaceForProjectId(uuid, obbProjectId);
2811             }
2812         }
2813         // Total size should include app data + cache
2814         totalSize += totalAppDataSize;
2815         totalSize += totalAppCacheSize;
2816         sizes.totalSize = totalSize;
2817 
2818         // Only OBB is separate
2819         sizes.obbSize = totalAppObbSize;
2820     }
2821 
2822     return sizes;
2823 }
2824 
getUserSize(const std::optional<std::string> & uuid,int32_t userId,int32_t flags,const std::vector<int32_t> & appIds,std::vector<int64_t> * _aidl_return)2825 binder::Status InstalldNativeService::getUserSize(const std::optional<std::string>& uuid,
2826         int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
2827         std::vector<int64_t>* _aidl_return) {
2828     ENFORCE_UID(AID_SYSTEM);
2829     ENFORCE_VALID_USER(userId);
2830     CHECK_ARGUMENT_UUID(uuid);
2831     // NOTE: Locking is relaxed on this method, since it's limited to
2832     // read-only measurements without mutation.
2833 
2834     // When modifying this logic, always verify using tests:
2835     // runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetUserSize
2836 
2837 #if MEASURE_DEBUG
2838     LOG(INFO) << "Measuring user " << userId;
2839 #endif
2840 
2841     struct stats stats;
2842     struct stats extStats;
2843     memset(&stats, 0, sizeof(stats));
2844     memset(&extStats, 0, sizeof(extStats));
2845 
2846     auto uuidString = uuid.value_or("");
2847     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
2848 
2849     if (!IsQuotaSupported(uuidString)) {
2850         flags &= ~FLAG_USE_QUOTA;
2851     }
2852 
2853     if (flags & FLAG_USE_QUOTA) {
2854         atrace_pm_begin("code");
2855         calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize, -1, -1, true);
2856         atrace_pm_end();
2857 
2858         atrace_pm_begin("data");
2859         auto cePath = create_data_user_ce_path(uuid_, userId);
2860         collectManualStatsForUser(cePath, &stats, true);
2861         auto dePath = create_data_user_de_path(uuid_, userId);
2862         collectManualStatsForUser(dePath, &stats, true);
2863         atrace_pm_end();
2864 
2865         if (!uuid) {
2866             atrace_pm_begin("profile");
2867             auto userProfilePath = create_primary_cur_profile_dir_path(userId);
2868             calculate_tree_size(userProfilePath, &stats.dataSize, -1, -1, true);
2869             auto refProfilePath = create_primary_ref_profile_dir_path();
2870             calculate_tree_size(refProfilePath, &stats.codeSize, -1, -1, true);
2871             atrace_pm_end();
2872         }
2873 
2874         atrace_pm_begin("external");
2875         auto sizes = getExternalSizesForUserWithQuota(uuidString, userId, appIds);
2876         extStats.dataSize += sizes.totalSize;
2877         extStats.codeSize += sizes.obbSize;
2878         atrace_pm_end();
2879 
2880         if (!uuid) {
2881             atrace_pm_begin("dalvik");
2882             calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
2883                     -1, -1, true);
2884             calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize,
2885                     -1, -1, true);
2886             atrace_pm_end();
2887         }
2888         atrace_pm_begin("quota");
2889         int64_t dataSize = extStats.dataSize;
2890         for (auto appId : appIds) {
2891             if (appId >= AID_APP_START) {
2892                 collectQuotaStats(uuidString, userId, appId, &stats, &extStats);
2893 #if MEASURE_DEBUG
2894                 // Sleep to make sure we don't lose logs
2895                 usleep(1);
2896 #endif
2897             }
2898         }
2899         extStats.dataSize = dataSize;
2900         atrace_pm_end();
2901     } else {
2902         atrace_pm_begin("code");
2903         calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize);
2904         atrace_pm_end();
2905 
2906         atrace_pm_begin("data");
2907         auto cePath = create_data_user_ce_path(uuid_, userId);
2908         collectManualStatsForUser(cePath, &stats);
2909         auto dePath = create_data_user_de_path(uuid_, userId);
2910         collectManualStatsForUser(dePath, &stats);
2911         atrace_pm_end();
2912 
2913         atrace_pm_begin("sdksandbox");
2914         auto sdkSandboxCePath = create_data_misc_sdk_sandbox_path(uuid_, true, userId);
2915         collectManualStatsForUser(sdkSandboxCePath, &stats, false, true);
2916         auto sdkSandboxDePath = create_data_misc_sdk_sandbox_path(uuid_, false, userId);
2917         collectManualStatsForUser(sdkSandboxDePath, &stats, false, true);
2918         atrace_pm_end();
2919 
2920         if (!uuid) {
2921             atrace_pm_begin("profile");
2922             auto userProfilePath = create_primary_cur_profile_dir_path(userId);
2923             calculate_tree_size(userProfilePath, &stats.dataSize);
2924             auto refProfilePath = create_primary_ref_profile_dir_path();
2925             calculate_tree_size(refProfilePath, &stats.codeSize);
2926             atrace_pm_end();
2927         }
2928 
2929         atrace_pm_begin("external");
2930         auto dataMediaPath = create_data_media_path(uuid_, userId);
2931         collectManualExternalStatsForUser(dataMediaPath, &extStats);
2932 
2933 #if MEASURE_DEBUG
2934         LOG(DEBUG) << "Measured external data " << extStats.dataSize << " cache "
2935                 << extStats.cacheSize << " code " << extStats.codeSize;
2936 #endif
2937         atrace_pm_end();
2938 
2939         if (!uuid) {
2940             atrace_pm_begin("dalvik");
2941             calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize);
2942             calculate_tree_size(create_primary_cur_profile_dir_path(userId), &stats.dataSize);
2943             atrace_pm_end();
2944         }
2945     }
2946 
2947     std::vector<int64_t> ret;
2948     ret.push_back(stats.codeSize);
2949     ret.push_back(stats.dataSize);
2950     ret.push_back(stats.cacheSize);
2951     ret.push_back(extStats.codeSize);
2952     ret.push_back(extStats.dataSize);
2953     ret.push_back(extStats.cacheSize);
2954 #if MEASURE_DEBUG
2955     LOG(DEBUG) << "Final result " << toString(ret);
2956 #endif
2957     *_aidl_return = ret;
2958     return ok();
2959 }
2960 
getExternalSize(const std::optional<std::string> & uuid,int32_t userId,int32_t flags,const std::vector<int32_t> & appIds,std::vector<int64_t> * _aidl_return)2961 binder::Status InstalldNativeService::getExternalSize(const std::optional<std::string>& uuid,
2962         int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
2963         std::vector<int64_t>* _aidl_return) {
2964     ENFORCE_UID(AID_SYSTEM);
2965     ENFORCE_VALID_USER(userId);
2966     CHECK_ARGUMENT_UUID(uuid);
2967     // NOTE: Locking is relaxed on this method, since it's limited to
2968     // read-only measurements without mutation.
2969 
2970     // When modifying this logic, always verify using tests:
2971     // runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetExternalSize
2972 
2973 #if MEASURE_DEBUG
2974     LOG(INFO) << "Measuring external " << userId;
2975 #endif
2976 
2977     auto uuidString = uuid.value_or("");
2978     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
2979 
2980     int64_t totalSize = 0;
2981     int64_t audioSize = 0;
2982     int64_t videoSize = 0;
2983     int64_t imageSize = 0;
2984     int64_t appSize = 0;
2985     int64_t obbSize = 0;
2986 
2987     if (!IsQuotaSupported(uuidString)) {
2988         flags &= ~FLAG_USE_QUOTA;
2989     }
2990 
2991     if (flags & FLAG_USE_QUOTA) {
2992         atrace_pm_begin("quota");
2993         auto sizes = getExternalSizesForUserWithQuota(uuidString, userId, appIds);
2994         totalSize = sizes.totalSize;
2995         audioSize = sizes.audioSize;
2996         videoSize = sizes.videoSize;
2997         imageSize = sizes.imageSize;
2998         obbSize = sizes.obbSize;
2999         atrace_pm_end();
3000 
3001         atrace_pm_begin("apps");
3002         struct stats extStats;
3003         memset(&extStats, 0, sizeof(extStats));
3004         for (auto appId : appIds) {
3005             if (appId >= AID_APP_START) {
3006                 collectQuotaStats(uuidString, userId, appId, nullptr, &extStats);
3007             }
3008         }
3009         appSize = extStats.dataSize;
3010         atrace_pm_end();
3011     } else {
3012         atrace_pm_begin("manual");
3013         FTS *fts;
3014         FTSENT *p;
3015         auto path = create_data_media_path(uuid_, userId);
3016         char *argv[] = { (char*) path.c_str(), nullptr };
3017         if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) {
3018             return error("Failed to fts_open " + path);
3019         }
3020         while ((p = fts_read(fts)) != nullptr) {
3021             char* ext;
3022             int64_t size = (p->fts_statp->st_blocks * 512);
3023             switch (p->fts_info) {
3024             case FTS_F:
3025                 // Only categorize files not belonging to apps
3026                 if (p->fts_parent->fts_number == 0) {
3027                     ext = strrchr(p->fts_name, '.');
3028                     if (ext != nullptr) {
3029                         switch (MatchExtension(++ext)) {
3030                         case AID_MEDIA_AUDIO: audioSize += size; break;
3031                         case AID_MEDIA_VIDEO: videoSize += size; break;
3032                         case AID_MEDIA_IMAGE: imageSize += size; break;
3033                         }
3034                     }
3035                 }
3036                 [[fallthrough]]; // always count against total
3037             case FTS_D:
3038                 // Ignore data belonging to specific apps
3039                 p->fts_number = p->fts_parent->fts_number;
3040                 if (p->fts_level == 1 && !strcmp(p->fts_name, "Android")) {
3041                     p->fts_number = 1;
3042                 }
3043                 [[fallthrough]]; // always count against total
3044             case FTS_DEFAULT:
3045             case FTS_SL:
3046             case FTS_SLNONE:
3047                 if (p->fts_parent->fts_number == 1) {
3048                     appSize += size;
3049                 }
3050                 totalSize += size;
3051                 break;
3052             }
3053         }
3054         fts_close(fts);
3055         atrace_pm_end();
3056 
3057         atrace_pm_begin("obb");
3058         auto obbPath = StringPrintf("%s/Android/obb",
3059                 create_data_media_path(uuid_, userId).c_str());
3060         calculate_tree_size(obbPath, &obbSize);
3061         if (!(flags & FLAG_USE_QUOTA)) {
3062             totalSize -= obbSize;
3063         }
3064         atrace_pm_end();
3065     }
3066 
3067     std::vector<int64_t> ret;
3068     ret.push_back(totalSize);
3069     ret.push_back(audioSize);
3070     ret.push_back(videoSize);
3071     ret.push_back(imageSize);
3072     ret.push_back(appSize);
3073     ret.push_back(obbSize);
3074 #if MEASURE_DEBUG
3075     LOG(DEBUG) << "Final result " << toString(ret);
3076 #endif
3077     *_aidl_return = ret;
3078     return ok();
3079 }
3080 
getAppCrates(const std::optional<std::string> & uuid,const std::vector<std::string> & packageNames,int32_t userId,std::optional<std::vector<std::optional<CrateMetadata>>> * _aidl_return)3081 binder::Status InstalldNativeService::getAppCrates(
3082         const std::optional<std::string>& uuid,
3083         const std::vector<std::string>& packageNames, int32_t userId,
3084         std::optional<std::vector<std::optional<CrateMetadata>>>* _aidl_return) {
3085     ENFORCE_UID(AID_SYSTEM);
3086     ENFORCE_VALID_USER(userId);
3087     CHECK_ARGUMENT_UUID(uuid);
3088     for (const auto& packageName : packageNames) {
3089         CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3090     }
3091 #ifdef ENABLE_STORAGE_CRATES
3092     LOCK_PACKAGE_USER();
3093 
3094     auto retVector = std::vector<std::optional<CrateMetadata>>();
3095     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
3096 
3097     std::function<void(CratedFolder, CrateMetadata&&)> onCreateCrate =
3098             [&](CratedFolder cratedFolder, CrateMetadata&& crateMetadata) -> void {
3099         if (cratedFolder == nullptr) {
3100             return;
3101         }
3102         retVector.push_back(std::move(crateMetadata));
3103     };
3104 
3105     for (const auto& packageName : packageNames) {
3106 #if CRATE_DEBUG
3107         LOG(DEBUG) << "packageName = " << packageName;
3108 #endif
3109         auto crateManager = std::make_unique<CrateManager>(uuid_, userId, packageName);
3110         crateManager->traverseAllCrates(onCreateCrate);
3111     }
3112 
3113 #if CRATE_DEBUG
3114     LOG(WARNING) << "retVector.size() =" << retVector.size();
3115     for (auto& item : retVector) {
3116         CrateManager::dump(*item);
3117     }
3118 #endif
3119 
3120     *_aidl_return = std::move(retVector);
3121 #else // ENABLE_STORAGE_CRATES
3122     _aidl_return->reset();
3123 
3124     /* prevent compile warning fail */
3125     if (userId < 0) {
3126         return error();
3127     }
3128 #endif // ENABLE_STORAGE_CRATES
3129     return ok();
3130 }
3131 
getUserCrates(const std::optional<std::string> & uuid,int32_t userId,std::optional<std::vector<std::optional<CrateMetadata>>> * _aidl_return)3132 binder::Status InstalldNativeService::getUserCrates(
3133         const std::optional<std::string>& uuid, int32_t userId,
3134         std::optional<std::vector<std::optional<CrateMetadata>>>* _aidl_return) {
3135     ENFORCE_UID(AID_SYSTEM);
3136     ENFORCE_VALID_USER(userId);
3137     CHECK_ARGUMENT_UUID(uuid);
3138 #ifdef ENABLE_STORAGE_CRATES
3139     LOCK_USER();
3140 
3141     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
3142     auto retVector = std::vector<std::optional<CrateMetadata>>();
3143 
3144     std::function<void(CratedFolder, CrateMetadata&&)> onCreateCrate =
3145             [&](CratedFolder cratedFolder, CrateMetadata&& crateMetadata) -> void {
3146         if (cratedFolder == nullptr) {
3147             return;
3148         }
3149         retVector.push_back(std::move(crateMetadata));
3150     };
3151 
3152     std::function<void(FTSENT*)> onHandingPackage = [&](FTSENT* packageDir) -> void {
3153         auto crateManager = std::make_unique<CrateManager>(uuid_, userId, packageDir->fts_name);
3154         crateManager->traverseAllCrates(onCreateCrate);
3155     };
3156     CrateManager::traverseAllPackagesForUser(uuid, userId, onHandingPackage);
3157 
3158 #if CRATE_DEBUG
3159     LOG(DEBUG) << "retVector.size() =" << retVector.size();
3160     for (auto& item : retVector) {
3161         CrateManager::dump(*item);
3162     }
3163 #endif
3164 
3165     *_aidl_return = std::move(retVector);
3166 #else // ENABLE_STORAGE_CRATES
3167     _aidl_return->reset();
3168 
3169     /* prevent compile warning fail */
3170     if (userId < 0) {
3171         return error();
3172     }
3173 #endif // ENABLE_STORAGE_CRATES
3174     return ok();
3175 }
3176 
setAppQuota(const std::optional<std::string> & uuid,int32_t userId,int32_t appId,int64_t cacheQuota)3177 binder::Status InstalldNativeService::setAppQuota(const std::optional<std::string>& uuid,
3178         int32_t userId, int32_t appId, int64_t cacheQuota) {
3179     ENFORCE_UID(AID_SYSTEM);
3180     ENFORCE_VALID_USER(userId);
3181     CHECK_ARGUMENT_UUID(uuid);
3182     std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
3183 
3184     int32_t uid = multiuser_get_uid(userId, appId);
3185     mCacheQuotas[uid] = cacheQuota;
3186 
3187     return ok();
3188 }
3189 
3190 // Dumps the contents of a profile file, using pkgname's dex files for pretty
3191 // printing the result.
dumpProfiles(int32_t uid,const std::string & packageName,const std::string & profileName,const std::string & codePath,bool dumpClassesAndMethods,bool * _aidl_return)3192 binder::Status InstalldNativeService::dumpProfiles(int32_t uid, const std::string& packageName,
3193                                                    const std::string& profileName,
3194                                                    const std::string& codePath,
3195                                                    bool dumpClassesAndMethods, bool* _aidl_return) {
3196     ENFORCE_UID(AID_SYSTEM);
3197     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3198     CHECK_ARGUMENT_PATH(codePath);
3199     LOCK_PACKAGE();
3200 
3201     *_aidl_return = dump_profiles(uid, packageName, profileName, codePath, dumpClassesAndMethods);
3202     return ok();
3203 }
3204 
3205 // Copy the contents of a system profile over the data profile.
copySystemProfile(const std::string & systemProfile,int32_t packageUid,const std::string & packageName,const std::string & profileName,bool * _aidl_return)3206 binder::Status InstalldNativeService::copySystemProfile(const std::string& systemProfile,
3207         int32_t packageUid, const std::string& packageName, const std::string& profileName,
3208         bool* _aidl_return) {
3209     ENFORCE_UID(AID_SYSTEM);
3210     CHECK_ARGUMENT_PATH(systemProfile);
3211     if (!base::EndsWith(systemProfile, ".prof")) {
3212         return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
3213                          StringPrintf("System profile path %s does not end with .prof",
3214                                       systemProfile.c_str()));
3215     }
3216     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3217     CHECK_ARGUMENT_FILE_NAME(profileName);
3218     if (!base::EndsWith(profileName, ".prof")) {
3219         return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
3220                          StringPrintf("Profile name %s does not end with .prof",
3221                                       profileName.c_str()));
3222     }
3223     LOCK_PACKAGE();
3224     *_aidl_return = copy_system_profile(systemProfile, packageUid, packageName, profileName);
3225     return ok();
3226 }
3227 
3228 // TODO: Consider returning error codes.
mergeProfiles(int32_t uid,const std::string & packageName,const std::string & profileName,int * _aidl_return)3229 binder::Status InstalldNativeService::mergeProfiles(int32_t uid, const std::string& packageName,
3230         const std::string& profileName, int* _aidl_return) {
3231     ENFORCE_UID(AID_SYSTEM);
3232     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3233     LOCK_PACKAGE();
3234 
3235     *_aidl_return = analyze_primary_profiles(uid, packageName, profileName);
3236     return ok();
3237 }
3238 
createProfileSnapshot(int32_t appId,const std::string & packageName,const std::string & profileName,const std::string & classpath,bool * _aidl_return)3239 binder::Status InstalldNativeService::createProfileSnapshot(int32_t appId,
3240         const std::string& packageName, const std::string& profileName,
3241         const std::string& classpath, bool* _aidl_return) {
3242     ENFORCE_UID(AID_SYSTEM);
3243     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3244     LOCK_PACKAGE();
3245 
3246     *_aidl_return = create_profile_snapshot(appId, packageName, profileName, classpath);
3247     return ok();
3248 }
3249 
destroyProfileSnapshot(const std::string & packageName,const std::string & profileName)3250 binder::Status InstalldNativeService::destroyProfileSnapshot(const std::string& packageName,
3251         const std::string& profileName) {
3252     ENFORCE_UID(AID_SYSTEM);
3253     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3254     LOCK_PACKAGE();
3255 
3256     std::string snapshot = create_snapshot_profile_path(packageName, profileName);
3257     if ((unlink(snapshot.c_str()) != 0) && (errno != ENOENT)) {
3258         return error("Failed to destroy profile snapshot for " + packageName + ":" + profileName);
3259     }
3260     return ok();
3261 }
3262 
getCStr(const std::optional<std::string> & data,const char * default_value=nullptr)3263 static const char* getCStr(const std::optional<std::string>& data,
3264         const char* default_value = nullptr) {
3265     return data ? data->c_str() : default_value;
3266 }
dexopt(const std::string & apkPath,int32_t uid,const std::string & packageName,const std::string & instructionSet,int32_t dexoptNeeded,const std::optional<std::string> & outputPath,int32_t dexFlags,const std::string & compilerFilter,const std::optional<std::string> & uuid,const std::optional<std::string> & classLoaderContext,const std::optional<std::string> & seInfo,bool downgrade,int32_t targetSdkVersion,const std::optional<std::string> & profileName,const std::optional<std::string> & dexMetadataPath,const std::optional<std::string> & compilationReason,bool * aidl_return)3267 binder::Status InstalldNativeService::dexopt(
3268         const std::string& apkPath, int32_t uid, const std::string& packageName,
3269         const std::string& instructionSet, int32_t dexoptNeeded,
3270         const std::optional<std::string>& outputPath, int32_t dexFlags,
3271         const std::string& compilerFilter, const std::optional<std::string>& uuid,
3272         const std::optional<std::string>& classLoaderContext,
3273         const std::optional<std::string>& seInfo, bool downgrade, int32_t targetSdkVersion,
3274         const std::optional<std::string>& profileName,
3275         const std::optional<std::string>& dexMetadataPath,
3276         const std::optional<std::string>& compilationReason, bool* aidl_return) {
3277     ENFORCE_UID(AID_SYSTEM);
3278     CHECK_ARGUMENT_UUID(uuid);
3279     CHECK_ARGUMENT_PATH(apkPath);
3280     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3281     CHECK_ARGUMENT_PATH(outputPath);
3282     CHECK_ARGUMENT_PATH(dexMetadataPath);
3283     const auto userId = multiuser_get_user_id(uid);
3284     LOCK_PACKAGE_USER();
3285 
3286     const char* oat_dir = getCStr(outputPath);
3287     const char* instruction_set = instructionSet.c_str();
3288     if (oat_dir != nullptr && !createOatDir(packageName, oat_dir, instruction_set).isOk()) {
3289         // Can't create oat dir - let dexopt use cache dir.
3290         oat_dir = nullptr;
3291     }
3292 
3293     const char* apk_path = apkPath.c_str();
3294     const char* pkgname = packageName.c_str();
3295     const char* compiler_filter = compilerFilter.c_str();
3296     const char* volume_uuid = getCStr(uuid);
3297     const char* class_loader_context = getCStr(classLoaderContext);
3298     const char* se_info = getCStr(seInfo);
3299     const char* profile_name = getCStr(profileName);
3300     const char* dm_path = getCStr(dexMetadataPath);
3301     const char* compilation_reason = getCStr(compilationReason);
3302     std::string error_msg;
3303     bool completed = false; // not necessary but for compiler
3304     int res = android::installd::dexopt(apk_path, uid, pkgname, instruction_set, dexoptNeeded,
3305             oat_dir, dexFlags, compiler_filter, volume_uuid, class_loader_context, se_info,
3306             downgrade, targetSdkVersion, profile_name, dm_path, compilation_reason, &error_msg,
3307             &completed);
3308     *aidl_return = completed;
3309     return res ? error(res, error_msg) : ok();
3310 }
3311 
controlDexOptBlocking(bool block)3312 binder::Status InstalldNativeService::controlDexOptBlocking(bool block) {
3313     android::installd::control_dexopt_blocking(block);
3314     return ok();
3315 }
3316 
linkNativeLibraryDirectory(const std::optional<std::string> & uuid,const std::string & packageName,const std::string & nativeLibPath32,int32_t userId)3317 binder::Status InstalldNativeService::linkNativeLibraryDirectory(
3318         const std::optional<std::string>& uuid, const std::string& packageName,
3319         const std::string& nativeLibPath32, int32_t userId) {
3320     ENFORCE_UID(AID_SYSTEM);
3321     CHECK_ARGUMENT_UUID(uuid);
3322     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3323     CHECK_ARGUMENT_PATH(nativeLibPath32);
3324     LOCK_PACKAGE_USER();
3325 
3326     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
3327     const char* pkgname = packageName.c_str();
3328     const char* asecLibDir = nativeLibPath32.c_str();
3329     struct stat s, libStat;
3330     binder::Status res = ok();
3331 
3332     auto _pkgdir = create_data_user_ce_package_path(uuid_, userId, pkgname);
3333     auto _libsymlink = _pkgdir + PKG_LIB_POSTFIX;
3334 
3335     const char* pkgdir = _pkgdir.c_str();
3336     const char* libsymlink = _libsymlink.c_str();
3337 
3338     if (stat(pkgdir, &s) < 0) {
3339         return error("Failed to stat " + _pkgdir);
3340     }
3341 
3342     char *con = nullptr;
3343     if (::lgetfilecon(pkgdir, &con) < 0) {
3344         return error("Failed to lgetfilecon " + _pkgdir);
3345     }
3346 
3347     if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) {
3348         res = error("Failed to chown " + _pkgdir);
3349         goto out;
3350     }
3351 
3352     if (chmod(pkgdir, 0700) < 0) {
3353         res = error("Failed to chmod " + _pkgdir);
3354         goto out;
3355     }
3356 
3357     if (lstat(libsymlink, &libStat) < 0) {
3358         if (errno != ENOENT) {
3359             res = error("Failed to stat " + _libsymlink);
3360             goto out;
3361         }
3362     } else {
3363         if (S_ISDIR(libStat.st_mode)) {
3364             if (delete_dir_contents(libsymlink, 1, nullptr) < 0) {
3365                 res = error("Failed to delete " + _libsymlink);
3366                 goto out;
3367             }
3368         } else if (S_ISLNK(libStat.st_mode)) {
3369             if (unlink(libsymlink) < 0) {
3370                 res = error("Failed to unlink " + _libsymlink);
3371                 goto out;
3372             }
3373         }
3374     }
3375 
3376     if (symlink(asecLibDir, libsymlink) < 0) {
3377         res = error("Failed to symlink " + _libsymlink + " to " + nativeLibPath32);
3378         goto out;
3379     }
3380 
3381     if (lsetfilecon(libsymlink, con) < 0) {
3382         res = error("Failed to lsetfilecon " + _libsymlink);
3383         goto out;
3384     }
3385 
3386 out:
3387     free(con);
3388     if (chmod(pkgdir, s.st_mode) < 0) {
3389         auto msg = "Failed to cleanup chmod " + _pkgdir;
3390         if (res.isOk()) {
3391             res = error(msg);
3392         } else {
3393             PLOG(ERROR) << msg;
3394         }
3395     }
3396 
3397     if (chown(pkgdir, s.st_uid, s.st_gid) < 0) {
3398         auto msg = "Failed to cleanup chown " + _pkgdir;
3399         if (res.isOk()) {
3400             res = error(msg);
3401         } else {
3402             PLOG(ERROR) << msg;
3403         }
3404     }
3405 
3406     return res;
3407 }
3408 
restoreconAppData(const std::optional<std::string> & uuid,const std::string & packageName,int32_t userId,int32_t flags,int32_t appId,const std::string & seInfo)3409 binder::Status InstalldNativeService::restoreconAppData(const std::optional<std::string>& uuid,
3410         const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
3411         const std::string& seInfo) {
3412     ENFORCE_UID(AID_SYSTEM);
3413     ENFORCE_VALID_USER(userId);
3414     CHECK_ARGUMENT_UUID(uuid);
3415     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3416     LOCK_PACKAGE_USER();
3417     return restoreconAppDataLocked(uuid, packageName, userId, flags, appId, seInfo);
3418 }
3419 
restoreconAppDataLocked(const std::optional<std::string> & uuid,const std::string & packageName,int32_t userId,int32_t flags,int32_t appId,const std::string & seInfo)3420 binder::Status InstalldNativeService::restoreconAppDataLocked(
3421         const std::optional<std::string>& uuid, const std::string& packageName, int32_t userId,
3422         int32_t flags, int32_t appId, const std::string& seInfo) {
3423     ENFORCE_UID(AID_SYSTEM);
3424     ENFORCE_VALID_USER(userId);
3425     CHECK_ARGUMENT_UUID(uuid);
3426     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3427 
3428     binder::Status res = ok();
3429 
3430     // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here.
3431     unsigned int seflags = SELINUX_ANDROID_RESTORECON_RECURSE;
3432     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
3433     const char* pkgName = packageName.c_str();
3434     const char* seinfo = seInfo.c_str();
3435 
3436     uid_t uid = multiuser_get_uid(userId, appId);
3437     if (flags & FLAG_STORAGE_CE) {
3438         auto path = create_data_user_ce_package_path(uuid_, userId, pkgName);
3439         if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, seflags) < 0) {
3440             res = error("restorecon failed for " + path);
3441         }
3442     }
3443     if (flags & FLAG_STORAGE_DE) {
3444         auto path = create_data_user_de_package_path(uuid_, userId, pkgName);
3445         if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, seflags) < 0) {
3446             res = error("restorecon failed for " + path);
3447         }
3448     }
3449     return res;
3450 }
3451 
restoreconSdkDataLocked(const std::optional<std::string> & uuid,const std::string & packageName,int32_t userId,int32_t flags,int32_t appId,const std::string & seInfo)3452 binder::Status InstalldNativeService::restoreconSdkDataLocked(
3453         const std::optional<std::string>& uuid, const std::string& packageName, int32_t userId,
3454         int32_t flags, int32_t appId, const std::string& seInfo) {
3455     ENFORCE_UID(AID_SYSTEM);
3456     ENFORCE_VALID_USER(userId);
3457     CHECK_ARGUMENT_UUID(uuid);
3458     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3459 
3460     binder::Status res = ok();
3461 
3462     // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here.
3463     unsigned int seflags = SELINUX_ANDROID_RESTORECON_RECURSE;
3464     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
3465     const char* pkgName = packageName.c_str();
3466     const char* seinfo = seInfo.c_str();
3467 
3468     uid_t uid = multiuser_get_sdk_sandbox_uid(userId, appId);
3469     constexpr int storageFlags[2] = {FLAG_STORAGE_CE, FLAG_STORAGE_DE};
3470     for (int currentFlag : storageFlags) {
3471         if ((flags & currentFlag) == 0) {
3472             continue;
3473         }
3474         const bool isCeData = (currentFlag == FLAG_STORAGE_CE);
3475         const auto packagePath =
3476                 create_data_misc_sdk_sandbox_package_path(uuid_, isCeData, userId, pkgName);
3477         if (access(packagePath.c_str(), F_OK) != 0) {
3478             LOG(INFO) << "Missing source " << packagePath;
3479             continue;
3480         }
3481         const auto subDirHandler = [&packagePath, &seinfo, &uid, &seflags,
3482                                     &res](const std::string& subDir) {
3483             const auto& fullpath = packagePath + "/" + subDir;
3484             if (selinux_android_restorecon_pkgdir(fullpath.c_str(), seinfo, uid, seflags) < 0) {
3485                 res = error("restorecon failed for " + fullpath);
3486             }
3487         };
3488         const auto ec = foreach_subdir(packagePath, subDirHandler);
3489         if (ec != 0) {
3490             res = error("Failed to restorecon for subdirs of " + packagePath);
3491         }
3492     }
3493     return res;
3494 }
3495 
createOatDir(const std::string & packageName,const std::string & oatDir,const std::string & instructionSet)3496 binder::Status InstalldNativeService::createOatDir(const std::string& packageName,
3497                                                    const std::string& oatDir,
3498                                                    const std::string& instructionSet) {
3499     ENFORCE_UID(AID_SYSTEM);
3500     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3501     CHECK_ARGUMENT_PATH(oatDir);
3502     LOCK_PACKAGE();
3503 
3504     const char* oat_dir = oatDir.c_str();
3505     const char* instruction_set = instructionSet.c_str();
3506     char oat_instr_dir[PKG_PATH_MAX];
3507 
3508     if (validate_apk_path(oat_dir)) {
3509         return error("Invalid path " + oatDir);
3510     }
3511     if (fs_prepare_dir(oat_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) {
3512         return error("Failed to prepare " + oatDir);
3513     }
3514     if (selinux_android_restorecon(oat_dir, 0)) {
3515         return error("Failed to restorecon " + oatDir);
3516     }
3517     snprintf(oat_instr_dir, PKG_PATH_MAX, "%s/%s", oat_dir, instruction_set);
3518     if (fs_prepare_dir(oat_instr_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) {
3519         return error(StringPrintf("Failed to prepare %s", oat_instr_dir));
3520     }
3521     return ok();
3522 }
3523 
rmPackageDir(const std::string & packageName,const std::string & packageDir)3524 binder::Status InstalldNativeService::rmPackageDir(const std::string& packageName,
3525                                                    const std::string& packageDir) {
3526     ENFORCE_UID(AID_SYSTEM);
3527     CHECK_ARGUMENT_PATH(packageDir);
3528     LOCK_PACKAGE();
3529 
3530     if (validate_apk_path(packageDir.c_str())) {
3531         return error("Invalid path " + packageDir);
3532     }
3533     if (rm_package_dir(packageDir) != 0) {
3534         return error("Failed to delete " + packageDir);
3535     }
3536     return ok();
3537 }
3538 
linkFile(const std::string & packageName,const std::string & relativePath,const std::string & fromBase,const std::string & toBase)3539 binder::Status InstalldNativeService::linkFile(const std::string& packageName,
3540                                                const std::string& relativePath,
3541                                                const std::string& fromBase,
3542                                                const std::string& toBase) {
3543     ENFORCE_UID(AID_SYSTEM);
3544     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3545     CHECK_ARGUMENT_PATH(fromBase);
3546     CHECK_ARGUMENT_PATH(toBase);
3547     LOCK_PACKAGE();
3548 
3549     const char* relative_path = relativePath.c_str();
3550     const char* from_base = fromBase.c_str();
3551     const char* to_base = toBase.c_str();
3552     char from_path[PKG_PATH_MAX];
3553     char to_path[PKG_PATH_MAX];
3554     snprintf(from_path, PKG_PATH_MAX, "%s/%s", from_base, relative_path);
3555     snprintf(to_path, PKG_PATH_MAX, "%s/%s", to_base, relative_path);
3556 
3557     if (validate_apk_path_subdirs(from_path)) {
3558         return error(StringPrintf("Invalid from path %s", from_path));
3559     }
3560 
3561     if (validate_apk_path_subdirs(to_path)) {
3562         return error(StringPrintf("Invalid to path %s", to_path));
3563     }
3564 
3565     if (link(from_path, to_path) < 0) {
3566         return error(StringPrintf("Failed to link from %s to %s", from_path, to_path));
3567     }
3568 
3569     return ok();
3570 }
3571 
moveAb(const std::string & packageName,const std::string & apkPath,const std::string & instructionSet,const std::string & outputPath)3572 binder::Status InstalldNativeService::moveAb(const std::string& packageName,
3573                                              const std::string& apkPath,
3574                                              const std::string& instructionSet,
3575                                              const std::string& outputPath) {
3576     ENFORCE_UID(AID_SYSTEM);
3577     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3578     CHECK_ARGUMENT_PATH(apkPath);
3579     CHECK_ARGUMENT_PATH(outputPath);
3580     LOCK_PACKAGE();
3581 
3582     const char* apk_path = apkPath.c_str();
3583     const char* instruction_set = instructionSet.c_str();
3584     const char* oat_dir = outputPath.c_str();
3585 
3586     bool success = move_ab(apk_path, instruction_set, oat_dir);
3587     return success ? ok() : error();
3588 }
3589 
deleteOdex(const std::string & packageName,const std::string & apkPath,const std::string & instructionSet,const std::optional<std::string> & outputPath,int64_t * _aidl_return)3590 binder::Status InstalldNativeService::deleteOdex(const std::string& packageName,
3591                                                  const std::string& apkPath,
3592                                                  const std::string& instructionSet,
3593                                                  const std::optional<std::string>& outputPath,
3594                                                  int64_t* _aidl_return) {
3595     ENFORCE_UID(AID_SYSTEM);
3596     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3597     CHECK_ARGUMENT_PATH(apkPath);
3598     CHECK_ARGUMENT_PATH(outputPath);
3599     LOCK_PACKAGE();
3600 
3601     const char* apk_path = apkPath.c_str();
3602     const char* instruction_set = instructionSet.c_str();
3603     const char* oat_dir = outputPath ? outputPath->c_str() : nullptr;
3604 
3605     *_aidl_return = delete_odex(apk_path, instruction_set, oat_dir);
3606     return *_aidl_return == -1 ? error() : ok();
3607 }
3608 
reconcileSecondaryDexFile(const std::string & dexPath,const std::string & packageName,int32_t uid,const std::vector<std::string> & isas,const std::optional<std::string> & volumeUuid,int32_t storage_flag,bool * _aidl_return)3609 binder::Status InstalldNativeService::reconcileSecondaryDexFile(
3610         const std::string& dexPath, const std::string& packageName, int32_t uid,
3611         const std::vector<std::string>& isas, const std::optional<std::string>& volumeUuid,
3612         int32_t storage_flag, bool* _aidl_return) {
3613     ENFORCE_UID(AID_SYSTEM);
3614     CHECK_ARGUMENT_UUID(volumeUuid);
3615     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3616     CHECK_ARGUMENT_PATH(dexPath);
3617     const auto userId = multiuser_get_user_id(uid);
3618     LOCK_PACKAGE_USER();
3619 
3620     bool result = android::installd::reconcile_secondary_dex_file(
3621             dexPath, packageName, uid, isas, volumeUuid, storage_flag, _aidl_return);
3622     return result ? ok() : error();
3623 }
3624 
hashSecondaryDexFile(const std::string & dexPath,const std::string & packageName,int32_t uid,const std::optional<std::string> & volumeUuid,int32_t storageFlag,std::vector<uint8_t> * _aidl_return)3625 binder::Status InstalldNativeService::hashSecondaryDexFile(
3626         const std::string& dexPath, const std::string& packageName, int32_t uid,
3627         const std::optional<std::string>& volumeUuid, int32_t storageFlag,
3628         std::vector<uint8_t>* _aidl_return) {
3629     ENFORCE_UID(AID_SYSTEM);
3630     CHECK_ARGUMENT_UUID(volumeUuid);
3631     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3632     CHECK_ARGUMENT_PATH(dexPath);
3633 
3634     // mLock is not taken here since we will never modify the file system.
3635     // If a file is modified just as we are reading it this may result in an
3636     // anomalous hash, but that's ok.
3637     bool result = android::installd::hash_secondary_dex_file(
3638         dexPath, packageName, uid, volumeUuid, storageFlag, _aidl_return);
3639     return result ? ok() : error();
3640 }
3641 /**
3642  * Returns true if ioctl feature (F2FS_IOC_FS{GET,SET}XATTR) is supported as
3643  * these were introduced in Linux 4.14, so kernel versions before that will fail
3644  * while setting project id attributes. Only when these features are enabled,
3645  * storage calculation using project_id is enabled
3646  */
check_if_ioctl_feature_is_supported()3647 bool check_if_ioctl_feature_is_supported() {
3648     bool result = false;
3649     auto temp_path = StringPrintf("%smisc/installd/ioctl_check", android_data_dir.c_str());
3650     if (access(temp_path.c_str(), F_OK) != 0) {
3651         int fd = open(temp_path.c_str(), O_CREAT | O_TRUNC | O_RDWR | O_CLOEXEC, 0644);
3652         result = set_quota_project_id(temp_path, 0, false) == 0;
3653         close(fd);
3654         // delete the temp file
3655         remove(temp_path.c_str());
3656     }
3657     return result;
3658 }
3659 
setFirstBoot()3660 binder::Status InstalldNativeService::setFirstBoot() {
3661     ENFORCE_UID(AID_SYSTEM);
3662     std::lock_guard<std::recursive_mutex> lock(mMountsLock);
3663     std::string uuid;
3664     if (GetOccupiedSpaceForProjectId(uuid, 0) != -1 && check_if_ioctl_feature_is_supported()) {
3665         auto first_boot_path =
3666                 StringPrintf("%smisc/installd/using_project_ids", android_data_dir.c_str());
3667         if (access(first_boot_path.c_str(), F_OK) != 0) {
3668             close(open(first_boot_path.c_str(), O_CREAT | O_TRUNC | O_RDWR | O_CLOEXEC, 0644));
3669         }
3670     }
3671     return ok();
3672 }
3673 
invalidateMounts()3674 binder::Status InstalldNativeService::invalidateMounts() {
3675     ENFORCE_UID(AID_SYSTEM);
3676     std::lock_guard<std::recursive_mutex> lock(mMountsLock);
3677 
3678     mStorageMounts.clear();
3679 
3680 #if !BYPASS_QUOTA
3681     if (!InvalidateQuotaMounts()) {
3682         return error("Failed to read mounts");
3683     }
3684 #endif
3685 
3686     std::ifstream in("/proc/mounts");
3687     if (!in.is_open()) {
3688         return error("Failed to read mounts");
3689     }
3690 
3691     std::string source;
3692     std::string target;
3693     std::string ignored;
3694     while (!in.eof()) {
3695         std::getline(in, source, ' ');
3696         std::getline(in, target, ' ');
3697         std::getline(in, ignored);
3698 
3699         if (android::base::GetBoolProperty(kFuseProp, false)) {
3700             if (target.find(kMntFuse) == 0) {
3701                 LOG(DEBUG) << "Found storage mount " << source << " at " << target;
3702                 mStorageMounts[source] = target;
3703             }
3704         } else {
3705 #if !BYPASS_SDCARDFS
3706             if (target.find(kMntSdcardfs) == 0) {
3707                 LOG(DEBUG) << "Found storage mount " << source << " at " << target;
3708                 mStorageMounts[source] = target;
3709             }
3710 #endif
3711         }
3712     }
3713     return ok();
3714 }
3715 
3716 // Mount volume's CE and DE storage to mirror
tryMountDataMirror(const std::optional<std::string> & uuid)3717 binder::Status InstalldNativeService::tryMountDataMirror(
3718         const std::optional<std::string>& uuid) {
3719     ENFORCE_UID(AID_SYSTEM);
3720     CHECK_ARGUMENT_UUID(uuid);
3721     if (!sAppDataIsolationEnabled) {
3722         return ok();
3723     }
3724     if (!uuid) {
3725         return error("Should not happen, mounting uuid == null");
3726     }
3727 
3728     const char* uuid_ = uuid->c_str();
3729 
3730     std::lock_guard<std::recursive_mutex> lock(mMountsLock);
3731 
3732     std::string mirrorVolCePath(StringPrintf("%s/%s", kDataMirrorCePath, uuid_));
3733     if (fs_prepare_dir(mirrorVolCePath.c_str(), 0511, AID_SYSTEM, AID_SYSTEM) != 0) {
3734         return error("Failed to create CE data mirror");
3735     }
3736 
3737     std::string mirrorVolDePath(StringPrintf("%s/%s", kDataMirrorDePath, uuid_));
3738     if (fs_prepare_dir(mirrorVolDePath.c_str(), 0511, AID_SYSTEM, AID_SYSTEM) != 0) {
3739         return error("Failed to create DE data mirror");
3740     }
3741 
3742     std::string mirrorVolMiscCePath(StringPrintf("%s/%s", kMiscMirrorCePath, uuid_));
3743     if (fs_prepare_dir(mirrorVolMiscCePath.c_str(), 0511, AID_SYSTEM, AID_SYSTEM) != 0) {
3744         return error("Failed to create CE misc mirror");
3745     }
3746 
3747     std::string mirrorVolMiscDePath(StringPrintf("%s/%s", kMiscMirrorDePath, uuid_));
3748     if (fs_prepare_dir(mirrorVolMiscDePath.c_str(), 0511, AID_SYSTEM, AID_SYSTEM) != 0) {
3749         return error("Failed to create DE misc mirror");
3750     }
3751 
3752     auto cePath = StringPrintf("%s/user", create_data_path(uuid_).c_str());
3753     auto dePath = StringPrintf("%s/user_de", create_data_path(uuid_).c_str());
3754     auto miscCePath = StringPrintf("%s/misc_ce", create_data_path(uuid_).c_str());
3755     auto miscDePath = StringPrintf("%s/misc_de", create_data_path(uuid_).c_str());
3756 
3757     if (access(cePath.c_str(), F_OK) != 0) {
3758         return error("Cannot access CE path: " + cePath);
3759     }
3760     if (access(dePath.c_str(), F_OK) != 0) {
3761         return error("Cannot access DE path: " + dePath);
3762     }
3763     if (access(miscCePath.c_str(), F_OK) != 0) {
3764         return error("Cannot access misc CE path: " + cePath);
3765     }
3766     if (access(miscDePath.c_str(), F_OK) != 0) {
3767         return error("Cannot access misc DE path: " + dePath);
3768     }
3769 
3770     struct stat ceStat, mirrorCeStat;
3771     if (stat(cePath.c_str(), &ceStat) != 0) {
3772         return error("Failed to stat " + cePath);
3773     }
3774     if (stat(mirrorVolCePath.c_str(), &mirrorCeStat) != 0) {
3775         return error("Failed to stat " + mirrorVolCePath);
3776     }
3777 
3778     if (mirrorCeStat.st_ino == ceStat.st_ino && mirrorCeStat.st_dev == ceStat.st_dev) {
3779         // As it's being called by prepareUserStorage, it can be called multiple times.
3780         // Hence, we if we mount it already, we should skip it.
3781         LOG(INFO) << "CE dir is mounted already: " + cePath;
3782         return ok();
3783     }
3784 
3785     // Mount CE mirror
3786     if (TEMP_FAILURE_RETRY(mount(cePath.c_str(), mirrorVolCePath.c_str(), NULL,
3787             MS_NOSUID | MS_NODEV | MS_NOATIME | MS_BIND | MS_NOEXEC, nullptr)) == -1) {
3788         return error("Failed to mount " + mirrorVolCePath);
3789     }
3790 
3791     // Mount DE mirror
3792     if (TEMP_FAILURE_RETRY(mount(dePath.c_str(), mirrorVolDePath.c_str(), NULL,
3793             MS_NOSUID | MS_NODEV | MS_NOATIME | MS_BIND | MS_NOEXEC, nullptr)) == -1) {
3794         return error("Failed to mount " + mirrorVolDePath);
3795     }
3796 
3797     // Mount misc CE mirror
3798     if (TEMP_FAILURE_RETRY(mount(miscCePath.c_str(), mirrorVolMiscCePath.c_str(), NULL,
3799                                  MS_NOSUID | MS_NODEV | MS_NOATIME | MS_BIND | MS_NOEXEC,
3800                                  nullptr)) == -1) {
3801         return error("Failed to mount " + mirrorVolMiscCePath);
3802     }
3803 
3804     // Mount misc DE mirror
3805     if (TEMP_FAILURE_RETRY(mount(miscDePath.c_str(), mirrorVolMiscDePath.c_str(), NULL,
3806                                  MS_NOSUID | MS_NODEV | MS_NOATIME | MS_BIND | MS_NOEXEC,
3807                                  nullptr)) == -1) {
3808         return error("Failed to mount " + mirrorVolMiscDePath);
3809     }
3810 
3811     return ok();
3812 }
3813 
3814 // Unmount volume's CE and DE storage from mirror
onPrivateVolumeRemoved(const std::optional<std::string> & uuid)3815 binder::Status InstalldNativeService::onPrivateVolumeRemoved(
3816         const std::optional<std::string>& uuid) {
3817     ENFORCE_UID(AID_SYSTEM);
3818     CHECK_ARGUMENT_UUID(uuid);
3819     if (!sAppDataIsolationEnabled) {
3820         return ok();
3821     }
3822     if (!uuid) {
3823         // It happens when private volume failed to mount.
3824         LOG(INFO) << "Ignore unmount uuid=null";
3825         return ok();
3826     }
3827     const char* uuid_ = uuid->c_str();
3828 
3829     binder::Status res = ok();
3830 
3831     std::string mirrorCeVolPath(StringPrintf("%s/%s", kDataMirrorCePath, uuid_));
3832     std::string mirrorDeVolPath(StringPrintf("%s/%s", kDataMirrorDePath, uuid_));
3833     std::string mirrorMiscCeVolPath(StringPrintf("%s/%s", kMiscMirrorCePath, uuid_));
3834     std::string mirrorMiscDeVolPath(StringPrintf("%s/%s", kMiscMirrorDePath, uuid_));
3835 
3836     std::lock_guard<std::recursive_mutex> lock(mMountsLock);
3837 
3838     // Unmount CE storage
3839     if (TEMP_FAILURE_RETRY(umount(mirrorCeVolPath.c_str())) != 0) {
3840         if (errno != ENOENT) {
3841             res = error(StringPrintf("Failed to umount %s %s", mirrorCeVolPath.c_str(),
3842                                 strerror(errno)));
3843         }
3844     }
3845     if (delete_dir_contents_and_dir(mirrorCeVolPath, true) != 0) {
3846         res = error("Failed to delete " + mirrorCeVolPath);
3847     }
3848 
3849     // Unmount DE storage
3850     if (TEMP_FAILURE_RETRY(umount(mirrorDeVolPath.c_str())) != 0) {
3851         if (errno != ENOENT) {
3852             res = error(StringPrintf("Failed to umount %s %s", mirrorDeVolPath.c_str(),
3853                                 strerror(errno)));
3854         }
3855     }
3856     if (delete_dir_contents_and_dir(mirrorDeVolPath, true) != 0) {
3857         res = error("Failed to delete " + mirrorDeVolPath);
3858     }
3859 
3860     // Unmount misc CE storage
3861     if (TEMP_FAILURE_RETRY(umount(mirrorMiscCeVolPath.c_str())) != 0) {
3862         if (errno != ENOENT) {
3863             res = error(StringPrintf("Failed to umount %s %s", mirrorMiscCeVolPath.c_str(),
3864                                      strerror(errno)));
3865         }
3866     }
3867     if (delete_dir_contents_and_dir(mirrorMiscCeVolPath, true) != 0) {
3868         res = error("Failed to delete " + mirrorMiscCeVolPath);
3869     }
3870 
3871     // Unmount misc DE storage
3872     if (TEMP_FAILURE_RETRY(umount(mirrorMiscDeVolPath.c_str())) != 0) {
3873         if (errno != ENOENT) {
3874             res = error(StringPrintf("Failed to umount %s %s", mirrorMiscDeVolPath.c_str(),
3875                                      strerror(errno)));
3876         }
3877     }
3878     if (delete_dir_contents_and_dir(mirrorMiscDeVolPath, true) != 0) {
3879         res = error("Failed to delete " + mirrorMiscDeVolPath);
3880     }
3881 
3882     return res;
3883 }
3884 
findDataMediaPath(const std::optional<std::string> & uuid,userid_t userid)3885 std::string InstalldNativeService::findDataMediaPath(
3886         const std::optional<std::string>& uuid, userid_t userid) {
3887     std::lock_guard<std::recursive_mutex> lock(mMountsLock);
3888     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
3889     auto path = StringPrintf("%s/media", create_data_path(uuid_).c_str());
3890     auto resolved = mStorageMounts[path];
3891     if (resolved.empty()) {
3892         LOG(WARNING) << "Failed to find storage mount for " << path;
3893         resolved = path;
3894     }
3895     return StringPrintf("%s/%u", resolved.c_str(), userid);
3896 }
3897 
isQuotaSupported(const std::optional<std::string> & uuid,bool * _aidl_return)3898 binder::Status InstalldNativeService::isQuotaSupported(
3899         const std::optional<std::string>& uuid, bool* _aidl_return) {
3900     *_aidl_return = IsQuotaSupported(uuid.value_or(""));
3901     return ok();
3902 }
3903 
prepareAppProfile(const std::string & packageName,int32_t userId,int32_t appId,const std::string & profileName,const std::string & codePath,const std::optional<std::string> & dexMetadata,bool * _aidl_return)3904 binder::Status InstalldNativeService::prepareAppProfile(const std::string& packageName,
3905         int32_t userId, int32_t appId, const std::string& profileName, const std::string& codePath,
3906         const std::optional<std::string>& dexMetadata, bool* _aidl_return) {
3907     ENFORCE_UID(AID_SYSTEM);
3908     ENFORCE_VALID_USER_OR_NULL(userId);
3909     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3910     CHECK_ARGUMENT_PATH(codePath);
3911     LOCK_PACKAGE_USER();
3912 
3913     *_aidl_return = prepare_app_profile(packageName, userId, appId, profileName, codePath,
3914         dexMetadata);
3915     return ok();
3916 }
3917 
migrateLegacyObbData()3918 binder::Status InstalldNativeService::migrateLegacyObbData() {
3919     ENFORCE_UID(AID_SYSTEM);
3920     // NOTE: The lint warning doesn't apply to the use of system(3) with
3921     // absolute parse and no command line arguments.
3922     if (system("/system/bin/migrate_legacy_obb_data") != 0) { // NOLINT(cert-env33-c)
3923         LOG(ERROR) << "Unable to migrate legacy obb data";
3924     }
3925 
3926     return ok();
3927 }
3928 
cleanupInvalidPackageDirs(const std::optional<std::string> & uuid,int32_t userId,int32_t flags)3929 binder::Status InstalldNativeService::cleanupInvalidPackageDirs(
3930         const std::optional<std::string>& uuid, int32_t userId, int32_t flags) {
3931     ENFORCE_VALID_USER(userId);
3932     const char* uuid_cstr = uuid ? uuid->c_str() : nullptr;
3933 
3934     if (flags & FLAG_STORAGE_CE) {
3935         auto ce_path = create_data_user_ce_path(uuid_cstr, userId);
3936         cleanup_invalid_package_dirs_under_path(ce_path);
3937         auto sdksandbox_ce_path =
3938                 create_data_misc_sdk_sandbox_path(uuid_cstr, /*isCeData=*/true, userId);
3939         cleanup_invalid_package_dirs_under_path(sdksandbox_ce_path);
3940     }
3941 
3942     if (flags & FLAG_STORAGE_DE) {
3943         auto de_path = create_data_user_de_path(uuid_cstr, userId);
3944         cleanup_invalid_package_dirs_under_path(de_path);
3945         auto sdksandbox_de_path =
3946                 create_data_misc_sdk_sandbox_path(uuid_cstr, /*isCeData=*/false, userId);
3947         cleanup_invalid_package_dirs_under_path(sdksandbox_de_path);
3948     }
3949 
3950     return ok();
3951 }
3952 
getOdexVisibility(const std::string & packageName,const std::string & apkPath,const std::string & instructionSet,const std::optional<std::string> & outputPath,int32_t * _aidl_return)3953 binder::Status InstalldNativeService::getOdexVisibility(
3954         const std::string& packageName, const std::string& apkPath,
3955         const std::string& instructionSet, const std::optional<std::string>& outputPath,
3956         int32_t* _aidl_return) {
3957     ENFORCE_UID(AID_SYSTEM);
3958     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
3959     CHECK_ARGUMENT_PATH(apkPath);
3960     CHECK_ARGUMENT_PATH(outputPath);
3961     LOCK_PACKAGE();
3962 
3963     const char* apk_path = apkPath.c_str();
3964     const char* instruction_set = instructionSet.c_str();
3965     const char* oat_dir = outputPath ? outputPath->c_str() : nullptr;
3966 
3967     *_aidl_return = get_odex_visibility(apk_path, instruction_set, oat_dir);
3968     return *_aidl_return == -1 ? error() : ok();
3969 }
3970 
3971 // Creates an auth token to be used in enableFsverity. This token is really to store a proof that
3972 // the caller can write to a file, represented by the authFd. Effectively, system_server as the
3973 // attacker-in-the-middle cannot enable fs-verity on arbitrary app files. If the FD is not writable,
3974 // return null.
3975 //
3976 // app process uid is passed for additional ownership check, such that one app can not be
3977 // authenticated for another app's file. These parameters are assumed trusted for this purpose of
3978 // consistency check.
3979 //
3980 // Notably, creating the token allows us to manage the writable FD easily during enableFsverity.
3981 // Since enabling fs-verity to a file requires no outstanding writable FD, passing the authFd to the
3982 // server allows the server to hold the only reference (as long as the client app doesn't).
createFsveritySetupAuthToken(const ParcelFileDescriptor & authFd,int32_t uid,sp<IFsveritySetupAuthToken> * _aidl_return)3983 binder::Status InstalldNativeService::createFsveritySetupAuthToken(
3984         const ParcelFileDescriptor& authFd, int32_t uid,
3985         sp<IFsveritySetupAuthToken>* _aidl_return) {
3986     CHECK_ARGUMENT_APP_ID(multiuser_get_app_id(uid));
3987     ENFORCE_VALID_USER(multiuser_get_user_id(uid));
3988 
3989     auto token = sp<FsveritySetupAuthToken>::make();
3990     binder::Status status = token->authenticate(authFd, uid);
3991     if (!status.isOk()) {
3992         return status;
3993     }
3994     *_aidl_return = token;
3995     return ok();
3996 }
3997 
3998 // Enables fs-verity for filePath, which must be an absolute path and the same inode as in the auth
3999 // token previously returned from createFsveritySetupAuthToken, and owned by the app uid. As
4000 // installd is more privileged than its client / system server, we attempt to limit what a
4001 // (compromised) client can do.
4002 //
4003 // The reason for this app request to go through installd is to avoid exposing a risky area (PKCS#7
4004 // signature verification) in the kernel to the app as an attack surface (it can't be system server
4005 // because it can't override DAC and manipulate app files). Note that we should be able to drop
4006 // these hops and simply the app calls the ioctl, once all upgrading devices run with a kernel
4007 // without fs-verity built-in signature (https://r.android.com/2650402).
enableFsverity(const sp<IFsveritySetupAuthToken> & authToken,const std::string & filePath,const std::string & packageName,int32_t * _aidl_return)4008 binder::Status InstalldNativeService::enableFsverity(const sp<IFsveritySetupAuthToken>& authToken,
4009                                                      const std::string& filePath,
4010                                                      const std::string& packageName,
4011                                                      int32_t* _aidl_return) {
4012     ENFORCE_UID(AID_SYSTEM);
4013     CHECK_ARGUMENT_PATH(filePath);
4014     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
4015     LOCK_PACKAGE();
4016     if (authToken == nullptr) {
4017         return exception(binder::Status::EX_ILLEGAL_ARGUMENT, "Received a null auth token");
4018     }
4019 
4020     // Authenticate to check the targeting file is the same inode as the authFd. With O_PATH, we
4021     // prevent a malicious client from blocking installd by providing a path to FIFO. After the
4022     // authentication, the actual open is safe.
4023     sp<IBinder> authTokenBinder = IInterface::asBinder(authToken)->localBinder();
4024     if (authTokenBinder == nullptr) {
4025         return exception(binder::Status::EX_SECURITY, "Received a non-local auth token");
4026     }
4027     unique_fd pathFd(open(filePath.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_PATH));
4028     // Returns a constant errno to avoid one app probing file existence of the others, before the
4029     // authentication is done.
4030     const int kFixedErrno = EPERM;
4031     if (pathFd.get() < 0) {
4032         PLOG(DEBUG) << "Failed to open the path";
4033         *_aidl_return = kFixedErrno;
4034         return ok();
4035     }
4036     std::string procFdPath(StringPrintf("/proc/self/fd/%d", pathFd.get()));
4037     struct stat stFromPath;
4038     if (stat(procFdPath.c_str(), &stFromPath) < 0) {
4039         PLOG(DEBUG) << "Failed to stat proc fd " << pathFd.get() << " -> " << filePath;
4040         *_aidl_return = kFixedErrno;
4041         return ok();
4042     }
4043     auto authTokenInstance = sp<FsveritySetupAuthToken>::cast(authTokenBinder);
4044     if (!authTokenInstance->isSameStat(stFromPath)) {
4045         LOG(DEBUG) << "FD authentication failed";
4046         *_aidl_return = kFixedErrno;
4047         return ok();
4048     }
4049 
4050     unique_fd rfd(open(procFdPath.c_str(), O_RDONLY | O_CLOEXEC));
4051     fsverity_enable_arg arg = {};
4052     arg.version = 1;
4053     arg.hash_algorithm = FS_VERITY_HASH_ALG_SHA256;
4054     arg.block_size = 4096;
4055     if (ioctl(rfd.get(), FS_IOC_ENABLE_VERITY, &arg) < 0) {
4056         *_aidl_return = errno;
4057     } else {
4058         *_aidl_return = 0;
4059     }
4060     return ok();
4061 }
4062 
4063 }  // namespace installd
4064 }  // namespace android
4065