Merge "Change AppFuse mount location to vold namespace"
This commit is contained in:
commit
b2455747a9
5 changed files with 73 additions and 104 deletions
|
@ -529,19 +529,36 @@ binder::Status VoldNativeService::abortIdleMaint(
|
|||
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) {
|
||||
|
|
|
@ -75,9 +75,11 @@ class VoldNativeService : public BinderService<VoldNativeService>, public os::Bn
|
|||
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();
|
||||
|
|
|
@ -648,7 +648,7 @@ static android::status_t getMountPath(uid_t uid, const std::string& name, std::s
|
|||
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);
|
||||
|
||||
|
@ -657,10 +657,10 @@ static android::status_t mountInNamespace(uid_t uid, int device_fd, const std::s
|
|||
"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",
|
||||
|
@ -673,101 +673,34 @@ static android::status_t mountInNamespace(uid_t uid, int device_fd, const std::s
|
|||
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,
|
||||
|
@ -822,7 +755,7 @@ int VolumeManager::destroyStubVolume(const std::string& volId) {
|
|||
return android::OK;
|
||||
}
|
||||
|
||||
int VolumeManager::mountAppFuse(uid_t uid, pid_t pid, int mountId, unique_fd* device_fd) {
|
||||
int VolumeManager::mountAppFuse(uid_t uid, int mountId, unique_fd* device_fd) {
|
||||
std::string name = std::to_string(mountId);
|
||||
|
||||
// Check mount point name.
|
||||
|
@ -847,10 +780,10 @@ int VolumeManager::mountAppFuse(uid_t uid, pid_t pid, int mountId, unique_fd* de
|
|||
}
|
||||
|
||||
// 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.
|
||||
|
@ -860,5 +793,19 @@ int VolumeManager::unmountAppFuse(uid_t uid, pid_t pid, int mountId) {
|
|||
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));
|
||||
}
|
||||
|
|
|
@ -129,8 +129,9 @@ class VolumeManager {
|
|||
const std::string& fsLabel, std::string* outVolId);
|
||||
int destroyStubVolume(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 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();
|
||||
|
|
|
@ -58,8 +58,8 @@ interface IVold {
|
|||
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();
|
||||
|
@ -110,6 +110,8 @@ interface IVold {
|
|||
@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;
|
||||
|
|
Loading…
Reference in a new issue