Loading cmds/installd/InstalldNativeService.cpp +102 −3 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include <sys/file.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/mount.h> #include <sys/resource.h> #include <sys/stat.h> #include <sys/statvfs.h> Loading Loading @@ -86,6 +87,9 @@ static constexpr const mode_t kRollbackFolderMode = 0700; static constexpr const char* kCpPath = "/system/bin/cp"; static constexpr const char* kXattrDefault = "user.default"; static constexpr const char* kDataMirrorCePath = "/data_mirror/data_ce"; static constexpr const char* kDataMirrorDePath = "/data_mirror/data_de"; static constexpr const int MIN_RESTRICTED_HOME_SDK_VERSION = 24; // > M static constexpr const char* PKG_LIB_POSTFIX = "/lib"; Loading @@ -99,6 +103,13 @@ static constexpr size_t kSha256Size = 32; static constexpr const char* kPropApkVerityMode = "ro.apk_verity.mode"; static constexpr const char* kFuseProp = "persist.sys.fuse"; /** * Property to control if app data isolation is enabled. */ static constexpr const char* kAppDataIsolationEnabledProperty = "persist.zygote.app_data_isolation"; static std::atomic<bool> sAppDataIsolationEnabled(false); namespace { constexpr const char* kDump = "android.permission.DUMP"; Loading Loading @@ -258,6 +269,8 @@ status_t InstalldNativeService::start() { sp<ProcessState> ps(ProcessState::self()); ps->startThreadPool(); ps->giveThreadPoolName(); sAppDataIsolationEnabled = android::base::GetBoolProperty( kAppDataIsolationEnabledProperty, false); return android::OK; } Loading Loading @@ -450,10 +463,13 @@ binder::Status InstalldNativeService::createAppData(const std::unique_ptr<std::s // And return the CE inode of the top-level data directory so we can // clear contents while CE storage is locked if ((_aidl_return != nullptr) && get_path_inode(path, reinterpret_cast<ino_t*>(_aidl_return)) != 0) { if (_aidl_return != nullptr) { ino_t result; if (get_path_inode(path, &result) != 0) { return error("Failed to get_path_inode for " + path); } *_aidl_return = static_cast<uint64_t>(result); } } if (flags & FLAG_STORAGE_DE) { auto path = create_data_user_de_package_path(uuid_, userId, pkgname); Loading Loading @@ -2613,6 +2629,89 @@ binder::Status InstalldNativeService::invalidateMounts() { return ok(); } // Mount volume's CE and DE storage to mirror binder::Status InstalldNativeService::onPrivateVolumeMounted( const std::unique_ptr<std::string>& uuid) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_UUID(uuid); if (!sAppDataIsolationEnabled) { return ok(); } if (!uuid) { return error("Should not happen, mounting uuid == null"); } const char* uuid_ = uuid->c_str(); // Mount CE mirror std::string mirrorVolCePath(StringPrintf("%s/%s", kDataMirrorCePath, uuid_)); std::lock_guard<std::recursive_mutex> lock(mLock); if (fs_prepare_dir(mirrorVolCePath.c_str(), 0700, AID_ROOT, AID_ROOT) != 0) { return error("Failed to create CE mirror"); } auto cePath = StringPrintf("%s/user_ce", create_data_path(uuid_).c_str()); if (TEMP_FAILURE_RETRY(mount(cePath.c_str(), mirrorVolCePath.c_str(), NULL, MS_NOSUID | MS_NODEV | MS_NOATIME | MS_BIND | MS_NOEXEC, nullptr)) == -1) { return error("Failed to mount " + mirrorVolCePath); } // Mount DE mirror std::string mirrorVolDePath(StringPrintf("%s/%s", kDataMirrorDePath, uuid_)); if (fs_prepare_dir(mirrorVolDePath.c_str(), 0700, AID_ROOT, AID_ROOT) != 0) { return error("Failed to create DE mirror"); } auto dePath = StringPrintf("%s/user_de", create_data_path(uuid_).c_str()); if (TEMP_FAILURE_RETRY(mount(dePath.c_str(), mirrorVolDePath.c_str(), NULL, MS_NOSUID | MS_NODEV | MS_NOATIME | MS_BIND | MS_NOEXEC, nullptr)) == -1) { return error("Failed to mount " + mirrorVolDePath); } return ok(); } // Unmount volume's CE and DE storage from mirror binder::Status InstalldNativeService::onPrivateVolumeRemoved( const std::unique_ptr<std::string>& uuid) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_UUID(uuid); if (!sAppDataIsolationEnabled) { return ok(); } if (!uuid) { // It happens when private volume failed to mount. LOG(INFO) << "Ignore unmount uuid=null"; return ok(); } const char* uuid_ = uuid->c_str(); binder::Status res = ok(); std::string mirrorCeVolPath(StringPrintf("%s/%s", kDataMirrorCePath, uuid_)); std::string mirrorDeVolPath(StringPrintf("%s/%s", kDataMirrorDePath, uuid_)); // Unmount CE storage std::lock_guard<std::recursive_mutex> lock(mLock); if (TEMP_FAILURE_RETRY(umount(mirrorCeVolPath.c_str())) != 0) { if (errno != ENOENT) { res = error(StringPrintf("Failed to umount %s %s", mirrorCeVolPath.c_str(), strerror(errno))); } } if (delete_dir_contents_and_dir(mirrorCeVolPath, true) != 0) { res = error("Failed to delete " + mirrorCeVolPath); } // Unmount DE storage if (TEMP_FAILURE_RETRY(umount(mirrorDeVolPath.c_str())) != 0) { if (errno != ENOENT) { res = error(StringPrintf("Failed to umount %s %s", mirrorDeVolPath.c_str(), strerror(errno))); } } if (delete_dir_contents_and_dir(mirrorDeVolPath, true) != 0) { res = error("Failed to delete " + mirrorDeVolPath); } return res; } std::string InstalldNativeService::findDataMediaPath( const std::unique_ptr<std::string>& uuid, userid_t userid) { std::lock_guard<std::recursive_mutex> lock(mMountsLock); Loading cmds/installd/InstalldNativeService.h +2 −0 Original line number Diff line number Diff line Loading @@ -146,6 +146,8 @@ public: binder::Status invalidateMounts(); binder::Status isQuotaSupported(const std::unique_ptr<std::string>& volumeUuid, bool* _aidl_return); binder::Status onPrivateVolumeMounted(const std::unique_ptr<std::string>& volumeUuid); binder::Status onPrivateVolumeRemoved(const std::unique_ptr<std::string>& volumeUuid); binder::Status prepareAppProfile(const std::string& packageName, int32_t userId, int32_t appId, const std::string& profileName, Loading cmds/installd/QuotaUtils.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,10 @@ bool InvalidateQuotaMounts() { std::getline(in, target, ' '); std::getline(in, ignored); if (target.compare(0, 13, "/data_mirror/") == 0) { continue; } if (source.compare(0, 11, "/dev/block/") == 0) { struct dqblk dq; if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0, Loading cmds/installd/binder/android/os/IInstalld.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -109,6 +109,8 @@ interface IInstalld { int appId, @utf8InCpp String seInfo, int user, int snapshotId, int storageflags); void destroyAppDataSnapshot(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName, int userId, long ceSnapshotInode, int snapshotId, int storageFlags); void onPrivateVolumeMounted(@nullable @utf8InCpp String volumeUuid); void onPrivateVolumeRemoved(@nullable @utf8InCpp String volumeUuid); void migrateLegacyObbData(); Loading libs/binder/ndk/include_ndk/android/binder_parcel_utils.h +30 −2 Original line number Diff line number Diff line Loading @@ -420,6 +420,34 @@ static inline binder_status_t AParcel_readVector( AParcel_nullableStdVectorStringElementAllocator); } /** * Convenience API for writing a non-null parcelable. */ template <typename P> static inline binder_status_t AParcel_writeParcelable(AParcel* parcel, const P& p) { binder_status_t status = AParcel_writeInt32(parcel, 1); // non-null if (status != STATUS_OK) { return status; } return p.writeToParcel(parcel); } /** * Convenience API for reading a non-null parcelable. */ template <typename P> static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p) { int32_t null; binder_status_t status = AParcel_readInt32(parcel, &null); if (status != STATUS_OK) { return status; } if (null == 0) { return STATUS_UNEXPECTED_NULL; } return p->readFromParcel(parcel); } /** * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'. */ Loading @@ -427,7 +455,7 @@ template <typename P> binder_status_t AParcel_writeStdVectorParcelableElement(AParcel* parcel, const void* vectorData, size_t index) { const std::vector<P>* vector = static_cast<const std::vector<P>*>(vectorData); return vector->at(index).writeToParcel(parcel); return AParcel_writeParcelable(parcel, vector->at(index)); } /** Loading @@ -437,7 +465,7 @@ template <typename P> binder_status_t AParcel_readStdVectorParcelableElement(const AParcel* parcel, void* vectorData, size_t index) { std::vector<P>* vector = static_cast<std::vector<P>*>(vectorData); return vector->at(index).readFromParcel(parcel); return AParcel_readParcelable(parcel, &vector->at(index)); } /** Loading Loading
cmds/installd/InstalldNativeService.cpp +102 −3 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include <sys/file.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/mount.h> #include <sys/resource.h> #include <sys/stat.h> #include <sys/statvfs.h> Loading Loading @@ -86,6 +87,9 @@ static constexpr const mode_t kRollbackFolderMode = 0700; static constexpr const char* kCpPath = "/system/bin/cp"; static constexpr const char* kXattrDefault = "user.default"; static constexpr const char* kDataMirrorCePath = "/data_mirror/data_ce"; static constexpr const char* kDataMirrorDePath = "/data_mirror/data_de"; static constexpr const int MIN_RESTRICTED_HOME_SDK_VERSION = 24; // > M static constexpr const char* PKG_LIB_POSTFIX = "/lib"; Loading @@ -99,6 +103,13 @@ static constexpr size_t kSha256Size = 32; static constexpr const char* kPropApkVerityMode = "ro.apk_verity.mode"; static constexpr const char* kFuseProp = "persist.sys.fuse"; /** * Property to control if app data isolation is enabled. */ static constexpr const char* kAppDataIsolationEnabledProperty = "persist.zygote.app_data_isolation"; static std::atomic<bool> sAppDataIsolationEnabled(false); namespace { constexpr const char* kDump = "android.permission.DUMP"; Loading Loading @@ -258,6 +269,8 @@ status_t InstalldNativeService::start() { sp<ProcessState> ps(ProcessState::self()); ps->startThreadPool(); ps->giveThreadPoolName(); sAppDataIsolationEnabled = android::base::GetBoolProperty( kAppDataIsolationEnabledProperty, false); return android::OK; } Loading Loading @@ -450,10 +463,13 @@ binder::Status InstalldNativeService::createAppData(const std::unique_ptr<std::s // And return the CE inode of the top-level data directory so we can // clear contents while CE storage is locked if ((_aidl_return != nullptr) && get_path_inode(path, reinterpret_cast<ino_t*>(_aidl_return)) != 0) { if (_aidl_return != nullptr) { ino_t result; if (get_path_inode(path, &result) != 0) { return error("Failed to get_path_inode for " + path); } *_aidl_return = static_cast<uint64_t>(result); } } if (flags & FLAG_STORAGE_DE) { auto path = create_data_user_de_package_path(uuid_, userId, pkgname); Loading Loading @@ -2613,6 +2629,89 @@ binder::Status InstalldNativeService::invalidateMounts() { return ok(); } // Mount volume's CE and DE storage to mirror binder::Status InstalldNativeService::onPrivateVolumeMounted( const std::unique_ptr<std::string>& uuid) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_UUID(uuid); if (!sAppDataIsolationEnabled) { return ok(); } if (!uuid) { return error("Should not happen, mounting uuid == null"); } const char* uuid_ = uuid->c_str(); // Mount CE mirror std::string mirrorVolCePath(StringPrintf("%s/%s", kDataMirrorCePath, uuid_)); std::lock_guard<std::recursive_mutex> lock(mLock); if (fs_prepare_dir(mirrorVolCePath.c_str(), 0700, AID_ROOT, AID_ROOT) != 0) { return error("Failed to create CE mirror"); } auto cePath = StringPrintf("%s/user_ce", create_data_path(uuid_).c_str()); if (TEMP_FAILURE_RETRY(mount(cePath.c_str(), mirrorVolCePath.c_str(), NULL, MS_NOSUID | MS_NODEV | MS_NOATIME | MS_BIND | MS_NOEXEC, nullptr)) == -1) { return error("Failed to mount " + mirrorVolCePath); } // Mount DE mirror std::string mirrorVolDePath(StringPrintf("%s/%s", kDataMirrorDePath, uuid_)); if (fs_prepare_dir(mirrorVolDePath.c_str(), 0700, AID_ROOT, AID_ROOT) != 0) { return error("Failed to create DE mirror"); } auto dePath = StringPrintf("%s/user_de", create_data_path(uuid_).c_str()); if (TEMP_FAILURE_RETRY(mount(dePath.c_str(), mirrorVolDePath.c_str(), NULL, MS_NOSUID | MS_NODEV | MS_NOATIME | MS_BIND | MS_NOEXEC, nullptr)) == -1) { return error("Failed to mount " + mirrorVolDePath); } return ok(); } // Unmount volume's CE and DE storage from mirror binder::Status InstalldNativeService::onPrivateVolumeRemoved( const std::unique_ptr<std::string>& uuid) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_UUID(uuid); if (!sAppDataIsolationEnabled) { return ok(); } if (!uuid) { // It happens when private volume failed to mount. LOG(INFO) << "Ignore unmount uuid=null"; return ok(); } const char* uuid_ = uuid->c_str(); binder::Status res = ok(); std::string mirrorCeVolPath(StringPrintf("%s/%s", kDataMirrorCePath, uuid_)); std::string mirrorDeVolPath(StringPrintf("%s/%s", kDataMirrorDePath, uuid_)); // Unmount CE storage std::lock_guard<std::recursive_mutex> lock(mLock); if (TEMP_FAILURE_RETRY(umount(mirrorCeVolPath.c_str())) != 0) { if (errno != ENOENT) { res = error(StringPrintf("Failed to umount %s %s", mirrorCeVolPath.c_str(), strerror(errno))); } } if (delete_dir_contents_and_dir(mirrorCeVolPath, true) != 0) { res = error("Failed to delete " + mirrorCeVolPath); } // Unmount DE storage if (TEMP_FAILURE_RETRY(umount(mirrorDeVolPath.c_str())) != 0) { if (errno != ENOENT) { res = error(StringPrintf("Failed to umount %s %s", mirrorDeVolPath.c_str(), strerror(errno))); } } if (delete_dir_contents_and_dir(mirrorDeVolPath, true) != 0) { res = error("Failed to delete " + mirrorDeVolPath); } return res; } std::string InstalldNativeService::findDataMediaPath( const std::unique_ptr<std::string>& uuid, userid_t userid) { std::lock_guard<std::recursive_mutex> lock(mMountsLock); Loading
cmds/installd/InstalldNativeService.h +2 −0 Original line number Diff line number Diff line Loading @@ -146,6 +146,8 @@ public: binder::Status invalidateMounts(); binder::Status isQuotaSupported(const std::unique_ptr<std::string>& volumeUuid, bool* _aidl_return); binder::Status onPrivateVolumeMounted(const std::unique_ptr<std::string>& volumeUuid); binder::Status onPrivateVolumeRemoved(const std::unique_ptr<std::string>& volumeUuid); binder::Status prepareAppProfile(const std::string& packageName, int32_t userId, int32_t appId, const std::string& profileName, Loading
cmds/installd/QuotaUtils.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,10 @@ bool InvalidateQuotaMounts() { std::getline(in, target, ' '); std::getline(in, ignored); if (target.compare(0, 13, "/data_mirror/") == 0) { continue; } if (source.compare(0, 11, "/dev/block/") == 0) { struct dqblk dq; if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0, Loading
cmds/installd/binder/android/os/IInstalld.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -109,6 +109,8 @@ interface IInstalld { int appId, @utf8InCpp String seInfo, int user, int snapshotId, int storageflags); void destroyAppDataSnapshot(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName, int userId, long ceSnapshotInode, int snapshotId, int storageFlags); void onPrivateVolumeMounted(@nullable @utf8InCpp String volumeUuid); void onPrivateVolumeRemoved(@nullable @utf8InCpp String volumeUuid); void migrateLegacyObbData(); Loading
libs/binder/ndk/include_ndk/android/binder_parcel_utils.h +30 −2 Original line number Diff line number Diff line Loading @@ -420,6 +420,34 @@ static inline binder_status_t AParcel_readVector( AParcel_nullableStdVectorStringElementAllocator); } /** * Convenience API for writing a non-null parcelable. */ template <typename P> static inline binder_status_t AParcel_writeParcelable(AParcel* parcel, const P& p) { binder_status_t status = AParcel_writeInt32(parcel, 1); // non-null if (status != STATUS_OK) { return status; } return p.writeToParcel(parcel); } /** * Convenience API for reading a non-null parcelable. */ template <typename P> static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p) { int32_t null; binder_status_t status = AParcel_readInt32(parcel, &null); if (status != STATUS_OK) { return status; } if (null == 0) { return STATUS_UNEXPECTED_NULL; } return p->readFromParcel(parcel); } /** * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'. */ Loading @@ -427,7 +455,7 @@ template <typename P> binder_status_t AParcel_writeStdVectorParcelableElement(AParcel* parcel, const void* vectorData, size_t index) { const std::vector<P>* vector = static_cast<const std::vector<P>*>(vectorData); return vector->at(index).writeToParcel(parcel); return AParcel_writeParcelable(parcel, vector->at(index)); } /** Loading @@ -437,7 +465,7 @@ template <typename P> binder_status_t AParcel_readStdVectorParcelableElement(const AParcel* parcel, void* vectorData, size_t index) { std::vector<P>* vector = static_cast<std::vector<P>*>(vectorData); return vector->at(index).readFromParcel(parcel); return AParcel_readParcelable(parcel, &vector->at(index)); } /** Loading