Vold mkdirs should use lower filesystem.
If vold's view of /storage is FUSE, it means that creation of
directories in Android/ will go through FUSE as well. The implementation
of fs_mkdirs() tries to opendir() individual parts of the entire path;
so for a path "/storage/emulated/0/Android", it will try to opendir()
"/storage", "/storage/emulated", etc.
By default, "/storage/emulated" is created with 711 permissions; while
vold itself is root, access to /storage/emulated is routed through
MediaProvider (because of FUSE), and MediaProvider doesn't run as root,
nor does it have the capabilities to bypass the ACL. This means that
fs_mkdirs() as it is will fail, because opendir("/storage/emulated")
will fail from MediaProvider.
To prevent this, route these accesses directly to the lower filesystem
(currently, sdcardfs), by renaming the paths.
Bug: 146189163
Test: atest AdoptableHostTest
Change-Id: Idbb41b9ffad9713f3b255c51bd4de16f4d090223
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 8b9c29c..143f53c 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -809,8 +809,9 @@
int VolumeManager::mkdirs(const std::string& path) {
// Only offer to create directories for paths managed by vold
if (StartsWith(path, "/storage/")) {
+ std::string lower_path = "/mnt/runtime/default/" + path.substr(9);
// fs_mkdirs() does symlink checking and relative path enforcement
- return fs_mkdirs(path.c_str(), 0700);
+ return fs_mkdirs(lower_path.c_str(), 0700);
} else {
LOG(ERROR) << "Failed to find mounted volume for " << path;
return -EINVAL;