author | Baocheng Sun <baocheng.sun@amlogic.com> | 2018-01-12 01:59:41 (GMT) |
---|---|---|
committer | Baocheng Sun <baocheng.sun@amlogic.com> | 2018-01-19 05:58:09 (GMT) |
commit | 99b34704afebdf2c4ae0eee2aeeaa25dbd016d1a (patch) | |
tree | 393cc9657cac461c0467e7f85ba13aac70d01edf | |
parent | 3e08e2c68e393382cb647334d34997bfff56c8b1 (diff) | |
download | droidvold-99b34704afebdf2c4ae0eee2aeeaa25dbd016d1a.zip droidvold-99b34704afebdf2c4ae0eee2aeeaa25dbd016d1a.tar.gz droidvold-99b34704afebdf2c4ae0eee2aeeaa25dbd016d1a.tar.bz2 |
droidvold: add sdcardfs support [1/4]
PD# 153584
add sdcardfs support
Change-Id: I6638694ea159126cf99e3934ddda4d5e18626371
-rw-r--r-- | Android.mk | 1 | ||||
-rw-r--r-- | Disk.cpp | 9 | ||||
-rw-r--r-- | Disk.h | 1 | ||||
-rw-r--r-- | DroidVold.cpp | 9 | ||||
-rw-r--r-- | DroidVold.h | 1 | ||||
-rw-r--r-- | PublicVolume.cpp | 50 | ||||
-rw-r--r-- | PublicVolume.h | 3 | ||||
-rw-r--r-- | VolumeManager.cpp | 11 | ||||
-rw-r--r-- | VolumeManager.h | 1 | ||||
-rw-r--r-- | fs/Sdcardfs.cpp | 171 | ||||
-rw-r--r-- | fs/Sdcardfs.h | 38 | ||||
-rw-r--r-- | main.cpp | 2 |
12 files changed, 285 insertions, 12 deletions
@@ -12,6 +12,7 @@ common_src_files := \ fs/Exfat.cpp \ fs/Hfsplus.cpp \ fs/Iso9660.cpp \ + fs/Sdcardfs.cpp \ Disk.cpp \ VolumeBase.cpp \ PublicVolume.cpp \ @@ -135,6 +135,15 @@ std::shared_ptr<VolumeBase> Disk::findVolume(const std::string& id) { return nullptr; } +std::shared_ptr<VolumeBase> Disk::findVolumeByPath(const std::string& path) { + for (auto vol : mVolumes) { + if (vol->getPath() == path) { + return vol; + } + } + return nullptr; +} + void Disk::listVolumes(VolumeBase::Type type, std::list<std::string>& list) { for (auto vol : mVolumes) { if (vol->getType() == type) { @@ -66,6 +66,7 @@ public: int getFlags() { return mFlags; } std::shared_ptr<VolumeBase> findVolume(const std::string& id); + std::shared_ptr<VolumeBase> findVolumeByPath(const std::string& path); void listVolumes(VolumeBase::Type type, std::list<std::string>& list); diff --git a/DroidVold.cpp b/DroidVold.cpp index 3d6086a..a1db38f 100644 --- a/DroidVold.cpp +++ b/DroidVold.cpp @@ -181,6 +181,15 @@ void DroidVold::sendBroadcast(int event, const std::string& message) { */ } +Return<int32_t> DroidVold::getDiskFlag(const hidl_string &path) { + int32_t flag = 0; + std::string mPath = path; + + flag = VolumeManager::Instance()->getDiskFlag(mPath); + + return flag; +} + } // namespace implementation } // namespace V1_0 } // namespace droidvold diff --git a/DroidVold.h b/DroidVold.h index 346742f..0c576cf 100644 --- a/DroidVold.h +++ b/DroidVold.h @@ -56,6 +56,7 @@ public: Return<Result> mount(const hidl_string& id, uint32_t flag, uint32_t uid) override; Return<Result> unmount(const hidl_string& id) override; Return<Result> format(const hidl_string& id, const hidl_string& type) override; + Return<int32_t> getDiskFlag(const hidl_string &path) override; static DroidVold *Instance(); void sendBroadcast(int event, const std::string& message); diff --git a/PublicVolume.cpp b/PublicVolume.cpp index 1a41ab0..1977f24 100644 --- a/PublicVolume.cpp +++ b/PublicVolume.cpp @@ -20,6 +20,7 @@ #include "fs/Hfsplus.h" #include "fs/Iso9660.h" #include "fs/Ext4.h" +#include "fs/Sdcardfs.h" #include "PublicVolume.h" #include "Utils.h" #include "VolumeManager.h" @@ -46,7 +47,7 @@ namespace droidvold { static const char* kChownPath = "/system/bin/chown"; PublicVolume::PublicVolume(const std::string& physicalDevName, const bool isPhysical) : - VolumeBase(Type::kPublic), mFusePid(0), mJustPhysicalDev(isPhysical) { + VolumeBase(Type::kPublic), mJustPhysicalDev(isPhysical) { setId(physicalDevName); mDevPath = StringPrintf("/dev/block/%s", getId().c_str()); } @@ -108,6 +109,11 @@ status_t PublicVolume::doMount() { } mRawPath = StringPrintf("/mnt/media_rw/%s", stableName.c_str()); + mFuseDefault = StringPrintf("/mnt/runtime/default/%s", stableName.c_str()); + mFuseRead = StringPrintf("/mnt/runtime/read/%s", stableName.c_str()); + mFuseWrite = StringPrintf("/mnt/runtime/write/%s", stableName.c_str()); + + VolumeManager *vm = VolumeManager::Instance(); //if (!mJustPhysicalDev && mFsType == "vfat") { if (mFsType == "vfat") { @@ -124,13 +130,27 @@ status_t PublicVolume::doMount() { } setInternalPath(mRawPath); - setPath(mRawPath); + + if (getMountFlags() & MountFlags::kVisible) { + setPath(StringPrintf("/storage/%s", stableName.c_str())); + } else { + setPath(mRawPath); + } if (prepareDir(mRawPath, 0700, AID_ROOT, AID_ROOT)) { PLOG(ERROR) << getId() << " failed to create mount points"; return -errno; } + if (prepareDir(mFuseDefault.c_str(), 0700, AID_ROOT, AID_ROOT) || + prepareDir(mFuseRead.c_str(), 0700, AID_ROOT, AID_ROOT) || + prepareDir(mFuseWrite.c_str(), 0700, AID_ROOT, AID_ROOT)) { + rmdir(mRawPath.c_str()); + PLOG(ERROR) << getId() << " failed to create FUSE mount points"; + return -errno; + } + + // Mount device status_t mountStatus = -1; @@ -156,6 +176,7 @@ status_t PublicVolume::doMount() { if (mountStatus) { PLOG(ERROR) << " failed to mount " << mDevPath << " as " << mFsType; + rmdir(mRawPath.c_str()); return -EIO; } else { LOG(INFO) << "successfully mount " << mDevPath << " as " << mFsType; @@ -180,6 +201,16 @@ status_t PublicVolume::doMount() { LOG(VERBOSE) << "Finished restorecon of " << mRawPath; } + + // mount sdcardfs + if (getMountFlags() & MountFlags::kPrimary) { + sdcardfs::run_sdcardfs(mRawPath, stableName, + 1023, 1023, getMountUserId(), false, true); + } else { + sdcardfs::run_sdcardfs(mRawPath, stableName, + 1023, 1023, getMountUserId(), false, false); + } + return OK; } @@ -200,16 +231,19 @@ status_t PublicVolume::doUnmount() { vm->unmountLoopIfNeed(stableName.c_str()); #endif + ForceUnmount(mFuseDefault); + ForceUnmount(mFuseRead); + ForceUnmount(mFuseWrite); ForceUnmount(mRawPath); - if (mFusePid > 0) { - kill(mFusePid, SIGTERM); - TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, 0)); - mFusePid = 0; - } - + rmdir(mFuseDefault.c_str()); + rmdir(mFuseRead.c_str()); + rmdir(mFuseWrite.c_str()); rmdir(mRawPath.c_str()); + mFuseDefault.clear(); + mFuseRead.clear(); + mFuseWrite.clear(); mRawPath.clear(); return OK; diff --git a/PublicVolume.h b/PublicVolume.h index 787776c..b196a4d 100644 --- a/PublicVolume.h +++ b/PublicVolume.h @@ -66,9 +66,6 @@ private: std::string mFuseRead; std::string mFuseWrite; - /* PID of FUSE wrapper */ - pid_t mFusePid; - /* Filesystem type */ std::string mFsType; /* Filesystem UUID */ diff --git a/VolumeManager.cpp b/VolumeManager.cpp index d6bdc0d..5b82180 100644 --- a/VolumeManager.cpp +++ b/VolumeManager.cpp @@ -424,3 +424,14 @@ void VolumeManager::coldboot(const char *path) { closedir(d); } } +int VolumeManager::getDiskFlag(const std::string &path) { + if (mDebug) + LOG(DEBUG) << "getdisk flag path=" << path; + for (auto disk : mDisks) { + auto vol = disk->findVolumeByPath(path); + if (vol != nullptr) { + return disk->getFlags(); + } + } + return 0; +} diff --git a/VolumeManager.h b/VolumeManager.h index 73b5b2b..59b8c69 100644 --- a/VolumeManager.h +++ b/VolumeManager.h @@ -112,6 +112,7 @@ public: bool isMountpointMounted(const char *mp); int mkdirs(char* path); void coldboot(const char *path); + int getDiskFlag(const std::string &path); private: VolumeManager(); diff --git a/fs/Sdcardfs.cpp b/fs/Sdcardfs.cpp new file mode 100644 index 0000000..faaa883 --- a/dev/null +++ b/fs/Sdcardfs.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/mount.h> +#include <sys/wait.h> +#include <linux/fs.h> +#include <sys/ioctl.h> + +#include <linux/kdev_t.h> + +#define LOG_TAG "droidVold" + +#include <android-base/logging.h> +#include <android-base/strings.h> +#include <android-base/file.h> +#include <android-base/macros.h> +#include <android-base/stringprintf.h> +#include <cutils/log.h> +#include <cutils/properties.h> +#include <cutils/multiuser.h> + +#include <private/android_filesystem_config.h> + +#include "Utils.h" + +#define PROP_SDCARDFS_DEVICE "ro.sys.sdcardfs" +#define PROP_SDCARDFS_USER "persist.sys.sdcardfs" + +using android::base::StringPrintf; + +namespace android { +namespace droidvold { +namespace sdcardfs { + +static bool supports_sdcardfs(void) { + std::string filesystems; + if (!android::base::ReadFileToString("/proc/filesystems", &filesystems)) { + PLOG(ERROR) << "Could not read /proc/filesystems"; + return false; + } + for (const auto& fs : android::base::Split(filesystems, "\n")) { + if (fs.find("sdcardfs") != std::string::npos) return true; + } + return false; +} + +static bool should_use_sdcardfs(void) { + char property[PROPERTY_VALUE_MAX]; + + // Allow user to have a strong opinion about state + property_get(PROP_SDCARDFS_USER, property, ""); + if (!strcmp(property, "force_on")) { + LOG(WARNING) << "User explicitly enabled sdcardfs"; + return supports_sdcardfs(); + } else if (!strcmp(property, "force_off")) { + LOG(WARNING) << "User explicitly disabled sdcardfs"; + return false; + } + + // Fall back to device opinion about state + if (property_get_bool(PROP_SDCARDFS_DEVICE, true)) { + LOG(WARNING) << "Device explicitly enabled sdcardfs"; + return supports_sdcardfs(); + } else { + LOG(WARNING) << "Device explicitly disabled sdcardfs"; + return false; + } +} + + +static bool sdcardfs_setup(const std::string& source_path, const std::string& dest_path, uid_t fsuid, + gid_t fsgid, bool multi_user, userid_t userid, gid_t gid, mode_t mask) { + std::string opts = android::base::StringPrintf("fsuid=%d,fsgid=%d,%smask=%d,userid=%d,gid=%d", + fsuid, fsgid, multi_user?"multiuser,":"", mask, userid, gid); + + if (mount(source_path.c_str(), dest_path.c_str(), "sdcardfs", + MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str()) == -1) { + PLOG(ERROR) << "failed to mount sdcardfs filesystem"; + return false; + } + + return true; +} + +static bool sdcardfs_setup_bind_remount(const std::string& source_path, const std::string& dest_path, + gid_t gid, mode_t mask) { + std::string opts = android::base::StringPrintf("mask=%d,gid=%d", mask, gid); + + if (mount(source_path.c_str(), dest_path.c_str(), nullptr, + MS_BIND, nullptr) != 0) { + PLOG(ERROR) << "failed to bind mount sdcardfs filesystem"; + return false; + } + + if (mount(source_path.c_str(), dest_path.c_str(), "none", + MS_REMOUNT | MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str()) != 0) { + PLOG(ERROR) << "failed to mount sdcardfs filesystem"; + if (umount2(dest_path.c_str(), MNT_DETACH)) + PLOG(WARNING) << "Failed to unmount bind"; + return false; + } + + return true; +} + + +int run_sdcardfs(const std::string& source_path, const std::string& label, uid_t uid, + gid_t gid, userid_t userid, bool multi_user, bool full_write) { + std::string dest_path_default = "/mnt/runtime/default/" + label; + std::string dest_path_read = "/mnt/runtime/read/" + label; + std::string dest_path_write = "/mnt/runtime/write/" + label; + + umask(0); + if (multi_user) { + // Multi-user storage is fully isolated per user, so "other" + // permissions are completely masked off. + if (!sdcardfs_setup(source_path, dest_path_default, uid, gid, multi_user, userid, + AID_SDCARD_RW, 0006) + || !sdcardfs_setup_bind_remount(dest_path_default, dest_path_read, AID_EVERYBODY, 0027) + || !sdcardfs_setup_bind_remount(dest_path_default, dest_path_write, + AID_EVERYBODY, full_write ? 0007 : 0027)) { + PLOG(ERROR) << "failed to sdcardfs_setup"; + } + } else { + // Physical storage is readable by all users on device, but + // the Android directories are masked off to a single user + // deep inside attr_from_stat(). + if (!sdcardfs_setup(source_path, dest_path_default, uid, gid, multi_user, userid, + AID_SDCARD_RW, 0006) + || !sdcardfs_setup_bind_remount(dest_path_default, dest_path_read, + AID_EVERYBODY, full_write ? 0027 : 0022) + || !sdcardfs_setup_bind_remount(dest_path_default, dest_path_write, + AID_EVERYBODY, full_write ? 0007 : 0022)) { + PLOG(ERROR) << "failed to sdcardfs_setup"; + } + } + + return 0; +} + + +} // namespace sdcardfs +} // namespace droidvold +} // namespace android diff --git a/fs/Sdcardfs.h b/fs/Sdcardfs.h new file mode 100644 index 0000000..c43dd0d --- a/dev/null +++ b/fs/Sdcardfs.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_VOLD_SDCARD_H +#define ANDROID_VOLD_SDCARD_H + + +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#include <string> +#include <cutils/multiuser.h> + +namespace android { +namespace droidvold { +namespace sdcardfs { + +int run_sdcardfs(const std::string& source_path, const std::string& label, uid_t uid, + gid_t gid, userid_t userid, bool multi_user, bool full_write); + +} // namespace sdcardfs +} // namespace droidvold +} // namespace android + +#endif @@ -67,7 +67,7 @@ int main(int argc, char** argv) { LOG(INFO) << "doildVold 1.0 firing up"; - android::ProcessState::initWithDriver("/dev/hwbinder"); + //android::ProcessState::initWithDriver("/dev/hwbinder"); configureRpcThreadpool(4, true); VolumeManager *vm; |