Merge "Add fsync for renaming user ce key path"
diff --git a/Android.bp b/Android.bp
index 8f2ba34..44e2317 100644
--- a/Android.bp
+++ b/Android.bp
@@ -129,6 +129,7 @@
"model/PrivateVolume.cpp",
"model/PublicVolume.cpp",
"model/VolumeBase.cpp",
+ "model/StubVolume.cpp",
"secontext.cpp",
],
product_variables: {
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index 5987849..c58ff01 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -479,6 +479,29 @@
return translate(VolumeManager::Instance()->destroyObb(volId));
}
+binder::Status VoldNativeService::createStubVolume(
+ const std::string& sourcePath, const std::string& mountPath, const std::string& fsType,
+ const std::string& fsUuid, const std::string& fsLabel, std::string* _aidl_return) {
+ ENFORCE_UID(AID_SYSTEM);
+ CHECK_ARGUMENT_PATH(sourcePath);
+ CHECK_ARGUMENT_PATH(mountPath);
+ CHECK_ARGUMENT_HEX(fsUuid);
+ // Label limitation seems to be different between fs (including allowed characters), so checking
+ // is quite meaningless.
+ ACQUIRE_LOCK;
+
+ return translate(VolumeManager::Instance()->createStubVolume(sourcePath, mountPath, fsType,
+ fsUuid, fsLabel, _aidl_return));
+}
+
+binder::Status VoldNativeService::destroyStubVolume(const std::string& volId) {
+ ENFORCE_UID(AID_SYSTEM);
+ CHECK_ARGUMENT_ID(volId);
+ ACQUIRE_LOCK;
+
+ return translate(VolumeManager::Instance()->destroyStubVolume(volId));
+}
+
binder::Status VoldNativeService::fstrim(
int32_t fstrimFlags, const android::sp<android::os::IVoldTaskListener>& listener) {
ENFORCE_UID(AID_SYSTEM);
@@ -506,19 +529,36 @@
return ok();
}
-binder::Status VoldNativeService::mountAppFuse(int32_t uid, int32_t pid, int32_t mountId,
+binder::Status VoldNativeService::mountAppFuse(int32_t uid, int32_t mountId,
android::base::unique_fd* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_LOCK;
- return translate(VolumeManager::Instance()->mountAppFuse(uid, pid, mountId, _aidl_return));
+ return translate(VolumeManager::Instance()->mountAppFuse(uid, mountId, _aidl_return));
}
-binder::Status VoldNativeService::unmountAppFuse(int32_t uid, int32_t pid, int32_t mountId) {
+binder::Status VoldNativeService::unmountAppFuse(int32_t uid, int32_t mountId) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_LOCK;
- return translate(VolumeManager::Instance()->unmountAppFuse(uid, pid, mountId));
+ return translate(VolumeManager::Instance()->unmountAppFuse(uid, mountId));
+}
+
+binder::Status VoldNativeService::openAppFuseFile(int32_t uid, int32_t mountId, int32_t fileId,
+ int32_t flags,
+ android::base::unique_fd* _aidl_return) {
+ ENFORCE_UID(AID_SYSTEM);
+ ACQUIRE_LOCK;
+
+ int fd = VolumeManager::Instance()->openAppFuseFile(uid, mountId, fileId, flags);
+ if (fd == -1) {
+ return error("Failed to open AppFuse file for uid: " + std::to_string(uid) +
+ " mountId: " + std::to_string(mountId) + " fileId: " + std::to_string(fileId) +
+ " flags: " + std::to_string(flags));
+ }
+
+ *_aidl_return = android::base::unique_fd(fd);
+ return ok();
}
binder::Status VoldNativeService::fdeCheckPassword(const std::string& password) {
diff --git a/VoldNativeService.h b/VoldNativeService.h
index 40ce3a4..161acb8 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -65,14 +65,21 @@
int32_t ownerGid, std::string* _aidl_return);
binder::Status destroyObb(const std::string& volId);
+ binder::Status createStubVolume(const std::string& sourcePath, const std::string& mountPath,
+ const std::string& fsType, const std::string& fsUuid,
+ const std::string& fsLabel, std::string* _aidl_return);
+ binder::Status destroyStubVolume(const std::string& volId);
+
binder::Status fstrim(int32_t fstrimFlags,
const android::sp<android::os::IVoldTaskListener>& listener);
binder::Status runIdleMaint(const android::sp<android::os::IVoldTaskListener>& listener);
binder::Status abortIdleMaint(const android::sp<android::os::IVoldTaskListener>& listener);
- binder::Status mountAppFuse(int32_t uid, int32_t pid, int32_t mountId,
+ binder::Status mountAppFuse(int32_t uid, int32_t mountId,
android::base::unique_fd* _aidl_return);
- binder::Status unmountAppFuse(int32_t uid, int32_t pid, int32_t mountId);
+ binder::Status unmountAppFuse(int32_t uid, int32_t mountId);
+ binder::Status openAppFuseFile(int32_t uid, int32_t mountId, int32_t fileId, int32_t flags,
+ android::base::unique_fd* _aidl_return);
binder::Status fdeCheckPassword(const std::string& password);
binder::Status fdeRestart();
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index f5eea7e..21136cf 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -63,6 +63,7 @@
#include "fs/Vfat.h"
#include "model/EmulatedVolume.h"
#include "model/ObbVolume.h"
+#include "model/StubVolume.h"
using android::base::StartsWith;
using android::base::StringPrintf;
@@ -90,6 +91,7 @@
VolumeManager::VolumeManager() {
mDebug = false;
mNextObbId = 0;
+ mNextStubVolumeId = 0;
// For security reasons, assume that a secure keyguard is
// showing until we hear otherwise
mSecureKeyguardShowing = true;
@@ -303,6 +305,11 @@
return vol;
}
}
+ for (const auto& vol : mStubVolumes) {
+ if (vol->getId() == id) {
+ return vol;
+ }
+ }
for (const auto& vol : mObbVolumes) {
if (vol->getId() == id) {
return vol;
@@ -558,6 +565,7 @@
for (const auto& disk : mDisks) {
disk->destroy();
}
+ mStubVolumes.clear();
mDisks.clear();
mPendingDisks.clear();
android::vold::sSleepOnUnmount = true;
@@ -572,6 +580,9 @@
if (mInternalEmulated != nullptr) {
mInternalEmulated->unmount();
}
+ for (const auto& stub : mStubVolumes) {
+ stub->unmount();
+ }
for (const auto& disk : mDisks) {
disk->unmountAll();
}
@@ -637,7 +648,7 @@
return android::OK;
}
-static android::status_t mountInNamespace(uid_t uid, int device_fd, const std::string& path) {
+static android::status_t mount(int device_fd, const std::string& path) {
// Remove existing mount.
android::vold::ForceUnmount(path);
@@ -646,10 +657,10 @@
"rootmode=40000,"
"default_permissions,"
"allow_other,"
- "user_id=%d,group_id=%d,"
+ "user_id=0,group_id=0,"
"context=\"u:object_r:app_fuse_file:s0\","
"fscontext=u:object_r:app_fusefs:s0",
- device_fd, uid, uid);
+ device_fd);
const int result =
TEMP_FAILURE_RETRY(mount("/dev/fuse", path.c_str(), "fuse",
@@ -662,101 +673,34 @@
return android::OK;
}
-static android::status_t runCommandInNamespace(const std::string& command, uid_t uid, pid_t pid,
- const std::string& path, int device_fd) {
+static android::status_t runCommand(const std::string& command, uid_t uid, const std::string& path,
+ int device_fd) {
if (DEBUG_APPFUSE) {
- LOG(DEBUG) << "Run app fuse command " << command << " for the path " << path
- << " in namespace " << uid;
+ LOG(DEBUG) << "Run app fuse command " << command << " for the path " << path << " and uid "
+ << uid;
}
- unique_fd dir(open("/proc", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
- if (dir.get() == -1) {
- PLOG(ERROR) << "Failed to open /proc";
- return -errno;
- }
-
- // Obtains process file descriptor.
- const std::string pid_str = StringPrintf("%d", pid);
- const unique_fd pid_fd(openat(dir.get(), pid_str.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
- if (pid_fd.get() == -1) {
- PLOG(ERROR) << "Failed to open /proc/" << pid;
- return -errno;
- }
-
- // Check UID of process.
- {
- struct stat sb;
- const int result = fstat(pid_fd.get(), &sb);
- if (result == -1) {
- PLOG(ERROR) << "Failed to stat /proc/" << pid;
+ if (command == "mount") {
+ return mount(device_fd, path);
+ } else if (command == "unmount") {
+ // If it's just after all FD opened on mount point are closed, umount2 can fail with
+ // EBUSY. To avoid the case, specify MNT_DETACH.
+ if (umount2(path.c_str(), UMOUNT_NOFOLLOW | MNT_DETACH) != 0 && errno != EINVAL &&
+ errno != ENOENT) {
+ PLOG(ERROR) << "Failed to unmount directory.";
return -errno;
}
- if (sb.st_uid != AID_SYSTEM) {
- LOG(ERROR) << "Only system can mount appfuse. UID expected=" << AID_SYSTEM
- << ", actual=" << sb.st_uid;
- return -EPERM;
+ if (rmdir(path.c_str()) != 0) {
+ PLOG(ERROR) << "Failed to remove the mount directory.";
+ return -errno;
}
+ return android::OK;
+ } else {
+ LOG(ERROR) << "Unknown appfuse command " << command;
+ return -EPERM;
}
- // Matches so far, but refuse to touch if in root namespace
- {
- std::string rootName;
- std::string pidName;
- if (!android::vold::Readlinkat(dir.get(), "1/ns/mnt", &rootName) ||
- !android::vold::Readlinkat(pid_fd.get(), "ns/mnt", &pidName)) {
- PLOG(ERROR) << "Failed to read namespaces";
- return -EPERM;
- }
- if (rootName == pidName) {
- LOG(ERROR) << "Don't mount appfuse in root namespace";
- return -EPERM;
- }
- }
-
- // We purposefully leave the namespace open across the fork
- unique_fd ns_fd(openat(pid_fd.get(), "ns/mnt", O_RDONLY)); // not O_CLOEXEC
- if (ns_fd.get() < 0) {
- PLOG(ERROR) << "Failed to open namespace for /proc/" << pid << "/ns/mnt";
- return -errno;
- }
-
- int child = fork();
- if (child == 0) {
- if (setns(ns_fd.get(), CLONE_NEWNS) != 0) {
- PLOG(ERROR) << "Failed to setns";
- _exit(-errno);
- }
-
- if (command == "mount") {
- _exit(mountInNamespace(uid, device_fd, path));
- } else if (command == "unmount") {
- // If it's just after all FD opened on mount point are closed, umount2 can fail with
- // EBUSY. To avoid the case, specify MNT_DETACH.
- if (umount2(path.c_str(), UMOUNT_NOFOLLOW | MNT_DETACH) != 0 && errno != EINVAL &&
- errno != ENOENT) {
- PLOG(ERROR) << "Failed to unmount directory.";
- _exit(-errno);
- }
- if (rmdir(path.c_str()) != 0) {
- PLOG(ERROR) << "Failed to remove the mount directory.";
- _exit(-errno);
- }
- _exit(android::OK);
- } else {
- LOG(ERROR) << "Unknown appfuse command " << command;
- _exit(-EPERM);
- }
- }
-
- if (child == -1) {
- PLOG(ERROR) << "Failed to folk child process";
- return -errno;
- }
-
- android::status_t status;
- TEMP_FAILURE_RETRY(waitpid(child, &status, 0));
-
- return status;
+ return android::OK;
}
int VolumeManager::createObb(const std::string& sourcePath, const std::string& sourceKey,
@@ -785,7 +729,33 @@
return android::OK;
}
-int VolumeManager::mountAppFuse(uid_t uid, pid_t pid, int mountId, unique_fd* device_fd) {
+int VolumeManager::createStubVolume(const std::string& sourcePath, const std::string& mountPath,
+ const std::string& fsType, const std::string& fsUuid,
+ const std::string& fsLabel, std::string* outVolId) {
+ int id = mNextStubVolumeId++;
+ auto vol = std::shared_ptr<android::vold::VolumeBase>(
+ new android::vold::StubVolume(id, sourcePath, mountPath, fsType, fsUuid, fsLabel));
+ vol->create();
+
+ mStubVolumes.push_back(vol);
+ *outVolId = vol->getId();
+ return android::OK;
+}
+
+int VolumeManager::destroyStubVolume(const std::string& volId) {
+ auto i = mStubVolumes.begin();
+ while (i != mStubVolumes.end()) {
+ if ((*i)->getId() == volId) {
+ (*i)->destroy();
+ i = mStubVolumes.erase(i);
+ } else {
+ ++i;
+ }
+ }
+ return android::OK;
+}
+
+int VolumeManager::mountAppFuse(uid_t uid, int mountId, unique_fd* device_fd) {
std::string name = std::to_string(mountId);
// Check mount point name.
@@ -810,10 +780,10 @@
}
// Mount.
- return runCommandInNamespace("mount", uid, pid, path, device_fd->get());
+ return runCommand("mount", uid, path, device_fd->get());
}
-int VolumeManager::unmountAppFuse(uid_t uid, pid_t pid, int mountId) {
+int VolumeManager::unmountAppFuse(uid_t uid, int mountId) {
std::string name = std::to_string(mountId);
// Check mount point name.
@@ -823,5 +793,19 @@
return -1;
}
- return runCommandInNamespace("unmount", uid, pid, path, -1 /* device_fd */);
+ return runCommand("unmount", uid, path, -1 /* device_fd */);
+}
+
+int VolumeManager::openAppFuseFile(uid_t uid, int mountId, int fileId, int flags) {
+ std::string name = std::to_string(mountId);
+
+ // Check mount point name.
+ std::string mountPoint;
+ if (getMountPath(uid, name, &mountPoint) != android::OK) {
+ LOG(ERROR) << "Invalid mount point name";
+ return -1;
+ }
+
+ std::string path = StringPrintf("%s/%d", mountPoint.c_str(), fileId);
+ return TEMP_FAILURE_RETRY(open(path.c_str(), flags));
}
diff --git a/VolumeManager.h b/VolumeManager.h
index eedb1cb..a2d6c5b 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -124,8 +124,14 @@
std::string* outVolId);
int destroyObb(const std::string& volId);
- int mountAppFuse(uid_t uid, pid_t pid, int mountId, android::base::unique_fd* device_fd);
- int unmountAppFuse(uid_t uid, pid_t pid, int mountId);
+ int createStubVolume(const std::string& sourcePath, const std::string& mountPath,
+ const std::string& fsType, const std::string& fsUuid,
+ const std::string& fsLabel, std::string* outVolId);
+ int destroyStubVolume(const std::string& volId);
+
+ int mountAppFuse(uid_t uid, int mountId, android::base::unique_fd* device_fd);
+ int unmountAppFuse(uid_t uid, int mountId);
+ int openAppFuseFile(uid_t uid, int mountId, int fileId, int flags);
private:
VolumeManager();
@@ -146,6 +152,7 @@
std::list<std::shared_ptr<android::vold::Disk>> mDisks;
std::list<std::shared_ptr<android::vold::Disk>> mPendingDisks;
std::list<std::shared_ptr<android::vold::VolumeBase>> mObbVolumes;
+ std::list<std::shared_ptr<android::vold::VolumeBase>> mStubVolumes;
std::unordered_map<userid_t, int> mAddedUsers;
std::unordered_set<userid_t> mStartedUsers;
@@ -156,6 +163,7 @@
std::shared_ptr<android::vold::VolumeBase> mPrimary;
int mNextObbId;
+ int mNextStubVolumeId;
bool mSecureKeyguardShowing;
};
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index 4ed861f..976eab1 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -58,8 +58,8 @@
void runIdleMaint(IVoldTaskListener listener);
void abortIdleMaint(IVoldTaskListener listener);
- FileDescriptor mountAppFuse(int uid, int pid, int mountId);
- void unmountAppFuse(int uid, int pid, int mountId);
+ FileDescriptor mountAppFuse(int uid, int mountId);
+ void unmountAppFuse(int uid, int mountId);
void fdeCheckPassword(@utf8InCpp String password);
void fdeRestart();
@@ -105,6 +105,13 @@
void restoreCheckpoint(@utf8InCpp String device);
void markBootAttempt();
+ @utf8InCpp String createStubVolume(@utf8InCpp String sourcePath,
+ @utf8InCpp String mountPath, @utf8InCpp String fsType,
+ @utf8InCpp String fsUuid, @utf8InCpp String fsLabel);
+ void destroyStubVolume(@utf8InCpp String volId);
+
+ FileDescriptor openAppFuseFile(int uid, int mountId, int fileId, int flags);
+
const int ENCRYPTION_FLAG_NO_UI = 4;
const int ENCRYPTION_STATE_NONE = 1;
@@ -151,4 +158,5 @@
const int VOLUME_TYPE_EMULATED = 2;
const int VOLUME_TYPE_ASEC = 3;
const int VOLUME_TYPE_OBB = 4;
+ const int VOLUME_TYPE_STUB = 5;
}
diff --git a/model/StubVolume.cpp b/model/StubVolume.cpp
new file mode 100644
index 0000000..edd0861
--- /dev/null
+++ b/model/StubVolume.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2018 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 "StubVolume.h"
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+
+using android::base::StringPrintf;
+
+namespace android {
+namespace vold {
+
+StubVolume::StubVolume(int id, const std::string& sourcePath, const std::string& mountPath,
+ const std::string& fsType, const std::string& fsUuid,
+ const std::string& fsLabel)
+ : VolumeBase(Type::kStub),
+ mSourcePath(sourcePath),
+ mMountPath(mountPath),
+ mFsType(fsType),
+ mFsUuid(fsUuid),
+ mFsLabel(fsLabel) {
+ setId(StringPrintf("stub:%d", id));
+}
+
+StubVolume::~StubVolume() {}
+
+status_t StubVolume::doCreate() {
+ return OK;
+}
+
+status_t StubVolume::doDestroy() {
+ return OK;
+}
+
+status_t StubVolume::doMount() {
+ auto listener = getListener();
+ if (listener) listener->onVolumeMetadataChanged(getId(), mFsType, mFsUuid, mFsLabel);
+ setInternalPath(mSourcePath);
+ setPath(mMountPath);
+ return OK;
+}
+
+status_t StubVolume::doUnmount() {
+ return OK;
+}
+
+// TODO: return error instead.
+status_t StubVolume::doFormat(const std::string& fsType) {
+ return OK;
+}
+
+} // namespace vold
+} // namespace android
diff --git a/model/StubVolume.h b/model/StubVolume.h
new file mode 100644
index 0000000..538cae9
--- /dev/null
+++ b/model/StubVolume.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 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_STUB_VOLUME_H
+#define ANDROID_VOLD_STUB_VOLUME_H
+
+#include "VolumeBase.h"
+
+namespace android {
+namespace vold {
+
+/*
+ * A vold representation of volumes managed from outside Android (e.g., ARC++).
+ *
+ * Used for the case when events such that mounting and unmounting are
+ * actually handled from outside vold, and vold only need to keep track on those
+ * vents instead of talking to kernel directly.
+ */
+class StubVolume : public VolumeBase {
+ public:
+ StubVolume(int id, const std::string& sourcePath, const std::string& mountPath,
+ const std::string& fsType, const std::string& fsUuid, const std::string& fsLabel);
+ virtual ~StubVolume();
+
+ protected:
+ status_t doCreate() override;
+ status_t doDestroy() override;
+ status_t doMount() override;
+ status_t doUnmount() override;
+ status_t doFormat(const std::string& fsType) override;
+
+ private:
+ const std::string mSourcePath;
+ const std::string mMountPath;
+ const std::string mFsType;
+ const std::string mFsUuid;
+ const std::string mFsLabel;
+
+ DISALLOW_COPY_AND_ASSIGN(StubVolume);
+};
+
+} // namespace vold
+} // namespace android
+
+#endif
diff --git a/model/VolumeBase.h b/model/VolumeBase.h
index 6532a80..92a83f0 100644
--- a/model/VolumeBase.h
+++ b/model/VolumeBase.h
@@ -54,6 +54,7 @@
kEmulated,
kAsec,
kObb,
+ kStub,
};
enum MountFlags {