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
This commit is contained in:
Martijn Coenen 2019-12-24 12:57:16 +01:00
parent da4d63eaff
commit 13ff668775
7 changed files with 70 additions and 16 deletions

View file

@ -55,6 +55,7 @@
using namespace std::chrono_literals;
using android::base::ReadFileToString;
using android::base::StartsWith;
using android::base::StringPrintf;
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) {
std::lock_guard<std::mutex> lock(kSecurityLock);
const char* cpath = path.c_str();

View file

@ -48,6 +48,12 @@ extern bool sSleepOnUnmount;
status_t CreateDeviceNode(const std::string& path, dev_t dev);
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 */
status_t PrepareDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid);

View file

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

View file

@ -65,7 +65,8 @@ class VoldNativeService : public BinderService<VoldNativeService>, public os::Bn
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,
int32_t ownerGid, std::string* _aidl_return);

View file

@ -81,6 +81,7 @@ using android::vold::BindMount;
using android::vold::CreateDir;
using android::vold::DeleteDirContents;
using android::vold::DeleteDirContentsAndDir;
using android::vold::PrepareDirsFromRoot;
using android::vold::PrivateVolume;
using android::vold::Symlink;
using android::vold::Unlink;
@ -806,16 +807,21 @@ int VolumeManager::unmountAll() {
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
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 {
if (!StartsWith(path, "/storage/")) {
LOG(ERROR) << "Failed to find mounted volume for " << path;
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,

View file

@ -113,13 +113,30 @@ class VolumeManager {
static VolumeManager* Instance();
/*
* Ensure that all directories along given path exist, creating parent
* directories as needed. Validates that given path is absolute and that
* it contains 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.
* Creates a directory 'path' for an application, automatically creating
* directories along the given path if they don't exist yet. 'appDirRoot'
* is the "root" directory for app-specific directories of this kind;
* 'path' must always start with 'appDirRoot'.
*
* 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,
std::string* outVolId);

View file

@ -54,7 +54,7 @@ interface IVold {
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,
int ownerGid);