Replace mkdirs() with setupAppDir().

vold historically offerred functionality to create directories on behalf
of others. This functionality was purely used to create app-specific
data/obb/media dirs. Make this more explicit by renaming the method to
indicate this.

Additionally, in the past, we never needed to care about the UID set on
these directories, because sdcardfs would take care of that for us
automatically. But with sdcardfs going away, we need to make sure the
UID of the app-specific directories is set correctly. Allow the caller
to pass this in as an argument.

Bug: 146419093
Test: atest FuseDaemonHostTest
Change-Id: Ibeb5fdc91b40d53583bc0960ee11c4d640549c34
gugelfrei
Martijn Coenen 5 years ago
parent da4d63eaff
commit 13ff668775

@ -55,6 +55,7 @@
using namespace std::chrono_literals; using namespace std::chrono_literals;
using android::base::ReadFileToString; using android::base::ReadFileToString;
using android::base::StartsWith;
using android::base::StringPrintf; using android::base::StringPrintf;
namespace android { namespace android {
@ -114,6 +115,27 @@ status_t DestroyDeviceNode(const std::string& path) {
} }
} }
int PrepareDirsFromRoot(std::string path, std::string root, mode_t mode, uid_t uid, gid_t gid) {
int ret = 0;
if (!StartsWith(path, root)) {
return -1;
}
std::string to_create_from_root = path.substr(root.length());
size_t pos = 0;
while ((pos = to_create_from_root.find('/')) != std::string::npos) {
auto component = to_create_from_root.substr(0, pos);
to_create_from_root.erase(0, pos + 1);
root = root + component + "/";
ret = fs_prepare_dir(root.c_str(), mode, uid, gid);
if (ret) {
break;
}
}
return ret;
}
status_t PrepareDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid) { status_t PrepareDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid) {
std::lock_guard<std::mutex> lock(kSecurityLock); std::lock_guard<std::mutex> lock(kSecurityLock);
const char* cpath = path.c_str(); const char* cpath = path.c_str();

@ -48,6 +48,12 @@ extern bool sSleepOnUnmount;
status_t CreateDeviceNode(const std::string& path, dev_t dev); status_t CreateDeviceNode(const std::string& path, dev_t dev);
status_t DestroyDeviceNode(const std::string& path); status_t DestroyDeviceNode(const std::string& path);
/*
* Recursively calls fs_prepare_dir() on all components in 'path', starting at 'root'.
* 'path' must start with 'root'
*/
int PrepareDirsFromRoot(std::string path, std::string root, mode_t mode, uid_t uid, gid_t gid);
/* fs_prepare_dir wrapper that creates with SELinux context */ /* fs_prepare_dir wrapper that creates with SELinux context */
status_t PrepareDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid); status_t PrepareDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid);

@ -456,12 +456,14 @@ binder::Status VoldNativeService::remountUid(int32_t uid, int32_t remountMode) {
return translate(VolumeManager::Instance()->remountUid(uid, remountMode)); return translate(VolumeManager::Instance()->remountUid(uid, remountMode));
} }
binder::Status VoldNativeService::mkdirs(const std::string& path) { binder::Status VoldNativeService::setupAppDir(const std::string& path,
const std::string& appDirRoot, int32_t appUid) {
ENFORCE_SYSTEM_OR_ROOT; ENFORCE_SYSTEM_OR_ROOT;
CHECK_ARGUMENT_PATH(path); CHECK_ARGUMENT_PATH(path);
CHECK_ARGUMENT_PATH(appDirRoot);
ACQUIRE_LOCK; ACQUIRE_LOCK;
return translate(VolumeManager::Instance()->mkdirs(path)); return translate(VolumeManager::Instance()->setupAppDir(path, appDirRoot, appUid));
} }
binder::Status VoldNativeService::createObb(const std::string& sourcePath, binder::Status VoldNativeService::createObb(const std::string& sourcePath,

@ -65,7 +65,8 @@ class VoldNativeService : public BinderService<VoldNativeService>, public os::Bn
binder::Status remountUid(int32_t uid, int32_t remountMode); binder::Status remountUid(int32_t uid, int32_t remountMode);
binder::Status mkdirs(const std::string& path); binder::Status setupAppDir(const std::string& path, const std::string& appDirRoot,
int32_t appUid);
binder::Status createObb(const std::string& sourcePath, const std::string& sourceKey, binder::Status createObb(const std::string& sourcePath, const std::string& sourceKey,
int32_t ownerGid, std::string* _aidl_return); int32_t ownerGid, std::string* _aidl_return);

@ -81,6 +81,7 @@ using android::vold::BindMount;
using android::vold::CreateDir; using android::vold::CreateDir;
using android::vold::DeleteDirContents; using android::vold::DeleteDirContents;
using android::vold::DeleteDirContentsAndDir; using android::vold::DeleteDirContentsAndDir;
using android::vold::PrepareDirsFromRoot;
using android::vold::PrivateVolume; using android::vold::PrivateVolume;
using android::vold::Symlink; using android::vold::Symlink;
using android::vold::Unlink; using android::vold::Unlink;
@ -806,16 +807,21 @@ int VolumeManager::unmountAll() {
return 0; return 0;
} }
int VolumeManager::mkdirs(const std::string& path) { int VolumeManager::setupAppDir(const std::string& path, const std::string& appDirRoot,
int32_t appUid) {
// Only offer to create directories for paths managed by vold // Only offer to create directories for paths managed by vold
if (StartsWith(path, "/storage/")) { 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(lower_path.c_str(), 0700);
} else {
LOG(ERROR) << "Failed to find mounted volume for " << path; LOG(ERROR) << "Failed to find mounted volume for " << path;
return -EINVAL; return -EINVAL;
} }
// First create the root which holds app dirs, if needed.
int ret = PrepareDirsFromRoot(appDirRoot, "/storage/", 0771, AID_MEDIA_RW, AID_MEDIA_RW);
if (ret != 0) {
return ret;
}
// Then, create app-specific dirs with the correct UID/GID
return PrepareDirsFromRoot(path, appDirRoot, 0770, appUid, AID_MEDIA_RW);
} }
int VolumeManager::createObb(const std::string& sourcePath, const std::string& sourceKey, int VolumeManager::createObb(const std::string& sourcePath, const std::string& sourceKey,

@ -113,13 +113,30 @@ class VolumeManager {
static VolumeManager* Instance(); static VolumeManager* Instance();
/* /*
* Ensure that all directories along given path exist, creating parent * Creates a directory 'path' for an application, automatically creating
* directories as needed. Validates that given path is absolute and that * directories along the given path if they don't exist yet. 'appDirRoot'
* it contains no relative "." or ".." paths or symlinks. Last path segment * is the "root" directory for app-specific directories of this kind;
* is treated as filename and ignored, unless the path ends with "/". Also * 'path' must always start with 'appDirRoot'.
* ensures that path belongs to a volume managed by vold. *
* Example:
* path = /storage/emulated/0/Android/data/com.foo/files/
* appDirRoot = /storage/emulated/0/Android/data/
*
* This function will set the UID of all app-specific directories below
* 'appDirRoot' to the 'appUid' argument. In the given example, the UID
* of /storage/emulated/0/Android/data/com.foo and
* /storage/emulated/0/Android/data/com.foo/files would be set to 'appUid'.
*
* The UID of the parent directories will be set according to the
* requirements of the underlying filesystem and are of no concern to the
* caller.
*
* Validates that given paths are absolute and that they contain no relative
* "." or ".." paths or symlinks. Last path segment is treated as filename
* and ignored, unless the path ends with "/". Also ensures that path
* belongs to a volume managed by vold.
*/ */
int mkdirs(const std::string& path); int setupAppDir(const std::string& path, const std::string& appDirRoot, int32_t appUid);
int createObb(const std::string& path, const std::string& key, int32_t ownerGid, int createObb(const std::string& path, const std::string& key, int32_t ownerGid,
std::string* outVolId); std::string* outVolId);

@ -54,7 +54,7 @@ interface IVold {
void remountUid(int uid, int remountMode); void remountUid(int uid, int remountMode);
void mkdirs(@utf8InCpp String path); void setupAppDir(@utf8InCpp String path, @utf8InCpp String appDirRoot, int appUid);
@utf8InCpp String createObb(@utf8InCpp String sourcePath, @utf8InCpp String sourceKey, @utf8InCpp String createObb(@utf8InCpp String sourcePath, @utf8InCpp String sourceKey,
int ownerGid); int ownerGid);

Loading…
Cancel
Save