Merge "Revert^4 "Customize StubVolume implementation for ARC""
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index 988d2a7..c62eb25 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -74,6 +74,7 @@
using android::vold::KeyGeneration;
using android::vold::retrieveKey;
using android::vold::retrieveOrGenerateKey;
+using android::vold::SetDefaultAcl;
using android::vold::SetQuotaInherit;
using android::vold::SetQuotaProjectId;
using android::vold::writeStringToFile;
@@ -862,7 +863,15 @@
if (!prepare_dir(misc_ce_path, 01771, AID_SYSTEM, AID_MISC)) return false;
if (!prepare_dir(vendor_ce_path, 0771, AID_ROOT, AID_ROOT)) return false;
}
- if (!prepare_dir(media_ce_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return false;
+ if (!prepare_dir(media_ce_path, 02770, AID_MEDIA_RW, AID_MEDIA_RW)) return false;
+ // On devices without sdcardfs (kernel 5.4+), the path permissions aren't fixed
+ // up automatically; therefore, use a default ACL, to ensure apps with MEDIA_RW
+ // can keep reading external storage; in particular, this allows app cloning
+ // scenarios to work correctly on such devices.
+ int ret = SetDefaultAcl(media_ce_path, 02770, AID_MEDIA_RW, AID_MEDIA_RW, {AID_MEDIA_RW});
+ if (ret != android::OK) {
+ return false;
+ }
if (!prepare_dir(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
diff --git a/Utils.cpp b/Utils.cpp
index d5648f7..98797b2 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -136,8 +136,8 @@
}
// Sets a default ACL on the directory.
-int SetDefaultAcl(const std::string& path, mode_t mode, uid_t uid, gid_t gid,
- std::vector<gid_t> additionalGids) {
+status_t SetDefaultAcl(const std::string& path, mode_t mode, uid_t uid, gid_t gid,
+ std::vector<gid_t> additionalGids) {
if (IsSdcardfsUsed()) {
// sdcardfs magically takes care of this
return OK;
diff --git a/Utils.h b/Utils.h
index 49901c8..a727e63 100644
--- a/Utils.h
+++ b/Utils.h
@@ -51,6 +51,9 @@
status_t CreateDeviceNode(const std::string& path, dev_t dev);
status_t DestroyDeviceNode(const std::string& path);
+status_t SetDefaultAcl(const std::string& path, mode_t mode, uid_t uid, gid_t gid,
+ std::vector<gid_t> additionalGids);
+
status_t AbortFuseConnections();
int SetQuotaInherit(const std::string& path);
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index 03dee48..9f4f7b0 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -377,7 +377,17 @@
ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
- return translate(VolumeManager::Instance()->remountAppStorageDirs(uid, pid, packageNames));
+ return translate(VolumeManager::Instance()->handleAppStorageDirs(uid, pid,
+ false /* doUnmount */, packageNames));
+}
+
+binder::Status VoldNativeService::unmountAppStorageDirs(int uid, int pid,
+ const std::vector<std::string>& packageNames) {
+ ENFORCE_SYSTEM_OR_ROOT;
+ ACQUIRE_LOCK;
+
+ return translate(VolumeManager::Instance()->handleAppStorageDirs(uid, pid,
+ true /* doUnmount */, packageNames));
}
binder::Status VoldNativeService::setupAppDir(const std::string& path, int32_t appUid) {
diff --git a/VoldNativeService.h b/VoldNativeService.h
index 8fd6261..47991c2 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -66,6 +66,8 @@
binder::Status remountUid(int32_t uid, int32_t remountMode);
binder::Status remountAppStorageDirs(int uid, int pid,
const std::vector<std::string>& packageNames);
+ binder::Status unmountAppStorageDirs(int uid, int pid,
+ const std::vector<std::string>& packageNames);
binder::Status ensureAppDirsCreated(const std::vector<std::string>& paths, int32_t appUid);
binder::Status setupAppDir(const std::string& path, int32_t appUid);
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index bbdcd3a..f97397d 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -683,6 +683,43 @@
return true;
}
+// In each app's namespace, unmount obb and data dirs
+static bool umountStorageDirs(int nsFd, const char* android_data_dir, const char* android_obb_dir,
+ int uid, const char* targets[], int size) {
+ // This code is executed after a fork so it's very important that the set of
+ // methods we call here is strictly limited.
+ if (setns(nsFd, CLONE_NEWNS) != 0) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to setns %s", strerror(errno));
+ return false;
+ }
+
+ // Unmount of Android/data/foo needs to be done before Android/data below.
+ bool result = true;
+ for (int i = 0; i < size; i++) {
+ if (TEMP_FAILURE_RETRY(umount2(targets[i], MNT_DETACH)) < 0 && errno != EINVAL &&
+ errno != ENOENT) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to umount %s: %s",
+ targets[i], strerror(errno));
+ result = false;
+ }
+ }
+
+ // Mount tmpfs on Android/data and Android/obb
+ if (TEMP_FAILURE_RETRY(umount2(android_data_dir, MNT_DETACH)) < 0 && errno != EINVAL &&
+ errno != ENOENT) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to umount %s :%s",
+ android_data_dir, strerror(errno));
+ result = false;
+ }
+ if (TEMP_FAILURE_RETRY(umount2(android_obb_dir, MNT_DETACH)) < 0 && errno != EINVAL &&
+ errno != ENOENT) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to umount %s :%s",
+ android_obb_dir, strerror(errno));
+ result = false;
+ }
+ return result;
+}
+
// In each app's namespace, mount tmpfs on obb and data dir, and bind mount obb and data
// package dirs.
static bool remountStorageDirs(int nsFd, const char* android_data_dir, const char* android_obb_dir,
@@ -741,8 +778,8 @@
userId, dirName.c_str(), packageName.c_str());
}
-// Fork the process and remount storage
-bool VolumeManager::forkAndRemountStorage(int uid, int pid,
+// Fork the process and remount / unmount app data and obb dirs
+bool VolumeManager::forkAndRemountStorage(int uid, int pid, bool doUnmount,
const std::vector<std::string>& packageNames) {
userid_t userId = multiuser_get_user_id(uid);
std::string mnt_path = StringPrintf("/proc/%d/ns/mnt", pid);
@@ -776,17 +813,18 @@
}
for (int i = 0; i < size; i++) {
- auto status = EnsureDirExists(sources_cstr[i], 0771, AID_MEDIA_RW, AID_MEDIA_RW);
- if (status != OK) {
- PLOG(ERROR) << "Failed to create dir: " << sources_cstr[i];
- return false;
- }
// Make sure /storage/emulated/... paths are setup correctly
- status = setupAppDir(targets_cstr[i], uid, false /* fixupExistingOnly */);
+ // This needs to be done before EnsureDirExists to ensure Android/ is created.
+ auto status = setupAppDir(targets_cstr[i], uid, false /* fixupExistingOnly */);
if (status != OK) {
PLOG(ERROR) << "Failed to create dir: " << targets_cstr[i];
return false;
}
+ status = EnsureDirExists(sources_cstr[i], 0771, AID_MEDIA_RW, AID_MEDIA_RW);
+ if (status != OK) {
+ PLOG(ERROR) << "Failed to create dir: " << sources_cstr[i];
+ return false;
+ }
}
char android_data_dir[PATH_MAX];
@@ -798,11 +836,20 @@
// Fork a child to mount Android/obb android Android/data dirs, as we don't want it to affect
// original vold process mount namespace.
if (!(child = fork())) {
- if (remountStorageDirs(nsFd, android_data_dir, android_obb_dir, uid,
- sources_cstr, targets_cstr, size)) {
- _exit(0);
+ if (doUnmount) {
+ if (umountStorageDirs(nsFd, android_data_dir, android_obb_dir, uid,
+ targets_cstr, size)) {
+ _exit(0);
+ } else {
+ _exit(1);
+ }
} else {
- _exit(1);
+ if (remountStorageDirs(nsFd, android_data_dir, android_obb_dir, uid,
+ sources_cstr, targets_cstr, size)) {
+ _exit(0);
+ } else {
+ _exit(1);
+ }
}
}
@@ -827,8 +874,8 @@
return true;
}
-int VolumeManager::remountAppStorageDirs(int uid, int pid,
- const std::vector<std::string>& packageNames) {
+int VolumeManager::handleAppStorageDirs(int uid, int pid,
+ bool doUnmount, const std::vector<std::string>& packageNames) {
// Only run the remount if fuse is mounted for that user.
userid_t userId = multiuser_get_user_id(uid);
bool fuseMounted = false;
@@ -842,7 +889,7 @@
}
}
if (fuseMounted) {
- forkAndRemountStorage(uid, pid, packageNames);
+ forkAndRemountStorage(uid, pid, doUnmount, packageNames);
}
return 0;
}
@@ -1092,9 +1139,14 @@
auto vol = std::shared_ptr<android::vold::StubVolume>(
new android::vold::StubVolume(stubId, sourcePath, mountPath, fsType, fsUuid, fsLabel));
- int32_t passedFlags = android::vold::Disk::Flags::kStub;
+ int32_t passedFlags = 0;
passedFlags |= (flags & android::vold::Disk::Flags::kUsb);
passedFlags |= (flags & android::vold::Disk::Flags::kSd);
+ if (flags & android::vold::Disk::Flags::kStubVisible) {
+ passedFlags |= (flags & android::vold::Disk::Flags::kStubVisible);
+ } else {
+ passedFlags |= (flags & android::vold::Disk::Flags::kStubInvisible);
+ }
// StubDisk doesn't have device node corresponds to it. So, a fake device
// number is used.
auto disk = std::shared_ptr<android::vold::Disk>(
diff --git a/VolumeManager.h b/VolumeManager.h
index 9640303..3573b1a 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -115,7 +115,8 @@
int onSecureKeyguardStateChanged(bool isShowing);
int remountUid(uid_t uid, int32_t remountMode) { return 0; }
- int remountAppStorageDirs(int uid, int pid, const std::vector<std::string>& packageNames);
+ int handleAppStorageDirs(int uid, int pid,
+ bool doUnmount, const std::vector<std::string>& packageNames);
/* Aborts all FUSE filesystems, in case the FUSE daemon is no longer up. */
int abortFuse();
@@ -129,7 +130,8 @@
int updateVirtualDisk();
int setDebug(bool enable);
- bool forkAndRemountStorage(int uid, int pid, const std::vector<std::string>& packageNames);
+ bool forkAndRemountStorage(int uid, int pid, bool doUnmount,
+ const std::vector<std::string>& packageNames);
static VolumeManager* Instance();
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index de381d3..19ce9ba 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -54,6 +54,7 @@
void remountUid(int uid, int remountMode);
void remountAppStorageDirs(int uid, int pid, in @utf8InCpp String[] packageNames);
+ void unmountAppStorageDirs(int uid, int pid, in @utf8InCpp String[] packageNames);
void setupAppDir(@utf8InCpp String path, int appUid);
void fixupAppDir(@utf8InCpp String path, int appUid);
diff --git a/model/Disk.h b/model/Disk.h
index 99c98fc..16476dc 100644
--- a/model/Disk.h
+++ b/model/Disk.h
@@ -53,9 +53,12 @@
kUsb = 1 << 3,
/* Flag that disk is EMMC internal */
kEmmc = 1 << 4,
- /* Flag that disk is Stub disk, i.e., disk that is managed from outside
- * Android (e.g., ARC++). */
- kStub = 1 << 5,
+ /* Flag that disk is an invisible Stub disk, i.e., disk that is managed from outside
+ * Android (e.g., ARC++) and invisible to apps. */
+ kStubInvisible = 1 << 5,
+ /* Flag that disk is a visible Stub disk, i.e., disk that is managed from outside
+ * Android (e.g., ARC++) and visible to apps. */
+ kStubVisible = 1 << 6,
};
const std::string& getId() const { return mId; }
@@ -120,7 +123,7 @@
int getMaxMinors();
- bool isStub() { return mFlags & kStub; }
+ bool isStub() { return (mFlags & kStubInvisible) || (mFlags & kStubVisible); }
DISALLOW_COPY_AND_ASSIGN(Disk);
};