[CloneProfile] Create user mount directory before creating bind mounts.
In aosp/2679182 the capability to add bind mounts for clone user
in public volumes was added.
This allows apps in clone profile to access public volume via lower
fs.
However, sometimes, the user mount directory (/user/mount/<user-id>)
is itself not present, resulting in failures of public volume
bind mounts. This CL addresses this.
Bug: 327293687
Test: Manul build and flash
Change-Id: I0680a518cb14983c6f2e636a38ab6dcd476d7eab
diff --git a/Utils.cpp b/Utils.cpp
index 696b0b4..a3db43e 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -1562,15 +1562,9 @@
return -1;
}
- // Shell is neither AID_ROOT nor AID_EVERYBODY. Since it equally needs 'execute' access to
- // /mnt/user/0 to 'adb shell ls /sdcard' for instance, we set the uid bit of /mnt/user/0 to
- // AID_SHELL. This gives shell access along with apps running as group everybody (user 0 apps)
- // These bits should be consistent with what is set in zygote in
- // com_android_internal_os_Zygote#MountEmulatedStorage on volume bind mount during app fork
- result = PrepareDir(pre_fuse_path, 0710, user_id ? AID_ROOT : AID_SHELL,
- multiuser_get_uid(user_id, AID_EVERYBODY));
+ result = PrepareMountDirForUser(user_id);
if (result != android::OK) {
- PLOG(ERROR) << "Failed to prepare directory " << pre_fuse_path;
+ PLOG(ERROR) << "Failed to create Mount Directory for user " << user_id;
return -1;
}
@@ -1808,5 +1802,22 @@
return enabled;
}
+status_t PrepareMountDirForUser(userid_t user_id) {
+ std::string pre_fuse_path(StringPrintf("/mnt/user/%d", user_id));
+ LOG(INFO) << "Creating mount directory " << pre_fuse_path;
+ // Shell is neither AID_ROOT nor AID_EVERYBODY. Since it equally needs 'execute' access to
+ // /mnt/user/0 to 'adb shell ls /sdcard' for instance, we set the uid bit of /mnt/user/0 to
+ // AID_SHELL. This gives shell access along with apps running as group everybody (user 0 apps)
+ // These bits should be consistent with what is set in zygote in
+ // com_android_internal_os_Zygote#MountEmulatedStorage on volume bind mount during app fork
+ auto result = PrepareDir(pre_fuse_path, 0710, user_id ? AID_ROOT : AID_SHELL,
+ multiuser_get_uid(user_id, AID_EVERYBODY));
+ if (result != android::OK) {
+ PLOG(ERROR) << "Failed to prepare directory " << pre_fuse_path;
+ return -1;
+ }
+ return result;
+}
+
} // namespace vold
} // namespace android
diff --git a/Utils.h b/Utils.h
index 690f79e..39723ec 100644
--- a/Utils.h
+++ b/Utils.h
@@ -219,6 +219,8 @@
// referenced inside the current process via the virtual procfs symlink returned here.
std::pair<android::base::unique_fd, std::string> OpenDirInProcfs(std::string_view path);
+status_t PrepareMountDirForUser(userid_t user_id);
+
} // namespace vold
} // namespace android
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index a1ac20d..2171717 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -473,6 +473,13 @@
// No need to bind if the user does not share storage with the mount owner
continue;
}
+ // Create mount directory for the user as there is a chance that no other Volume is
+ // mounted for the user (ex: if the user is just started), so /mnt/user/user_id does
+ // not exist yet.
+ auto mountDirStatus = android::vold::PrepareMountDirForUser(userId);
+ if (mountDirStatus != OK) {
+ LOG(ERROR) << "Failed to create Mount Directory for user " << userId;
+ }
auto bindMountStatus = pvol->bindMountForUser(userId);
if (bindMountStatus != OK) {
LOG(ERROR) << "Bind Mounting Public Volume: " << pvol << " for user: " << userId
diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp
index e86d002..91b1ca2 100644
--- a/model/PublicVolume.cpp
+++ b/model/PublicVolume.cpp
@@ -269,6 +269,12 @@
// No need to bind if the user does not share storage with the mount owner
continue;
}
+ // Create mount directory for the user as there is a chance that no other Volume is mounted
+ // for the user (ex: if the user is just started), so /mnt/user/user_id does not exist yet.
+ auto mountDirStatus = PrepareMountDirForUser(started_user);
+ if (mountDirStatus != OK) {
+ LOG(ERROR) << "Failed to create Mount Directory for user " << started_user;
+ }
auto bindMountStatus = bindMountForUser(started_user);
if (bindMountStatus != OK) {
LOG(ERROR) << "Bind Mounting Public Volume: " << stableName