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