Mount private volumes at /mnt/expand, which is where we have new
SELinux policy waiting for us. Also ensure that foundational
directories are ready when mounting.
Create local fs_prepare_dir() wrapper that sets SELinux context
based on path, avoiding the need for a later restorecon.
Use UUID as directory name for public volumes. Wait a few seconds
before issuing first signal when force unmounting.
Bug:
19993667
Change-Id: If22595380faaae321705b06c87d877419620da48
VolumeBase(Type::kPrivate), mRawDevice(device), mKeyRaw(keyRaw) {
setId(StringPrintf("private:%u,%u", major(device), minor(device)));
mRawDevPath = StringPrintf("/dev/block/vold/%s", getId().c_str());
- mPath = StringPrintf("/mnt/secure/%s", getId().c_str());
}
PrivateVolume::~PrivateVolume() {
return -EIO;
}
- if (Ext4::check(mDmDevPath.c_str(), mPath.c_str())) {
- PLOG(ERROR) << getId() << " failed filesystem check";
- return -EIO;
- }
-
+ mPath = StringPrintf("/mnt/expand/%s", mFsUuid.c_str());
setPath(mPath);
- if (fs_prepare_dir(mPath.c_str(), 0700, AID_ROOT, AID_ROOT)) {
+ if (PrepareDir(mPath, 0700, AID_ROOT, AID_ROOT)) {
PLOG(ERROR) << getId() << " failed to create mount point " << mPath;
- return -errno;
+ return -EIO;
+ }
+
+ if (Ext4::check(mDmDevPath.c_str(), mPath.c_str())) {
+ PLOG(ERROR) << getId() << " failed filesystem check";
+ return -EIO;
}
if (Ext4::doMount(mDmDevPath.c_str(), mPath.c_str(), false, false, true)) {
return -EIO;
}
+ // Verify that common directories are ready to roll
+ if (PrepareDir(mPath + "/app", 0771, AID_SYSTEM, AID_SYSTEM) ||
+ PrepareDir(mPath + "/user", 0711, AID_SYSTEM, AID_SYSTEM) ||
+ PrepareDir(mPath + "/media", 0770, AID_MEDIA_RW, AID_MEDIA_RW) ||
+ PrepareDir(mPath + "/local", 0751, AID_ROOT, AID_ROOT) ||
+ PrepareDir(mPath + "/local/tmp", 0771, AID_SHELL, AID_SHELL)) {
+ PLOG(ERROR) << getId() << " failed to prepare";
+ return -EIO;
+ }
+
return OK;
}
// Use UUID as stable name, if available
std::string stableName = getId();
if (!mFsUuid.empty()) {
- stableName = "public:" + mFsUuid;
+ stableName = mFsUuid;
}
mRawPath = StringPrintf("/mnt/media_rw/%s", stableName.c_str());
}
}
+status_t PrepareDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid) {
+ const char* cpath = path.c_str();
+
+ char* secontext = nullptr;
+ if (sehandle) {
+ if (!selabel_lookup(sehandle, &secontext, cpath, S_IFDIR)) {
+ setfscreatecon(secontext);
+ }
+ }
+
+ int res = fs_prepare_dir(cpath, mode, uid, gid);
+
+ if (secontext) {
+ setfscreatecon(nullptr);
+ freecon(secontext);
+ }
+
+ if (res == 0) {
+ return OK;
+ } else {
+ return -errno;
+ }
+}
+
status_t ForceUnmount(const std::string& path) {
const char* cpath = path.c_str();
if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
return OK;
}
- PLOG(WARNING) << "Failed to unmount " << path << "; sending SIGTERM";
- Process::killProcessesWithOpenFiles(cpath, SIGTERM);
+ PLOG(WARNING) << "Failed to unmount " << path;
+
sleep(5);
+ Process::killProcessesWithOpenFiles(cpath, SIGTERM);
if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
return OK;
}
- PLOG(WARNING) << "Failed to unmount " << path << "; sending SIGKILL";
- Process::killProcessesWithOpenFiles(cpath, SIGKILL);
+ PLOG(WARNING) << "Failed to unmount " << path;
+
sleep(5);
+ Process::killProcessesWithOpenFiles(cpath, SIGKILL);
if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
return OK;
}
- PLOG(ERROR) << "Failed to unmount " << path << "; giving up";
+ PLOG(ERROR) << "Failed to unmount " << path;
+
return -errno;
}
status_t CreateDeviceNode(const std::string& path, dev_t dev);
status_t DestroyDeviceNode(const std::string& path);
+/* 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);
+
/* Really unmounts the path, killing active processes along the way */
status_t ForceUnmount(const std::string& path);