Merge "fs_mgr: overlay: do not allow sub-mounts to be overridden" into qt-r1-dev
This commit is contained in:
commit
afaa2a9016
1 changed files with 184 additions and 3 deletions
|
|
@ -32,7 +32,6 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -517,10 +516,166 @@ bool fs_mgr_overlayfs_teardown_one(const std::string& overlay, const std::string
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool fs_mgr_overlayfs_set_shared_mount(const std::string& mount_point, bool shared_flag) {
|
||||||
|
auto ret = mount(nullptr, mount_point.c_str(), nullptr, shared_flag ? MS_SHARED : MS_PRIVATE,
|
||||||
|
nullptr);
|
||||||
|
if (ret) {
|
||||||
|
PERROR << "__mount(target=" << mount_point
|
||||||
|
<< ",flag=" << (shared_flag ? "MS_SHARED" : "MS_PRIVATE") << ")=" << ret;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fs_mgr_overlayfs_move_mount(const std::string& source, const std::string& target) {
|
||||||
|
auto ret = mount(source.c_str(), target.c_str(), nullptr, MS_MOVE, nullptr);
|
||||||
|
if (ret) {
|
||||||
|
PERROR << "__mount(source=" << source << ",target=" << target << ",flag=MS_MOVE)=" << ret;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mount_info {
|
||||||
|
std::string mount_point;
|
||||||
|
bool shared_flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<mount_info> ReadMountinfoFromFile(const std::string& path) {
|
||||||
|
std::vector<mount_info> info;
|
||||||
|
|
||||||
|
auto file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
|
||||||
|
if (!file) {
|
||||||
|
PERROR << __FUNCTION__ << "(): cannot open file: '" << path << "'";
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t len;
|
||||||
|
size_t alloc_len = 0;
|
||||||
|
char* line = nullptr;
|
||||||
|
while ((len = getline(&line, &alloc_len, file.get())) != -1) {
|
||||||
|
/* if the last character is a newline, shorten the string by 1 byte */
|
||||||
|
if (line[len - 1] == '\n') {
|
||||||
|
line[len - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr char delim[] = " \t";
|
||||||
|
char* save_ptr;
|
||||||
|
if (!strtok_r(line, delim, &save_ptr)) {
|
||||||
|
LERROR << "Error parsing mount ID";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!strtok_r(nullptr, delim, &save_ptr)) {
|
||||||
|
LERROR << "Error parsing parent ID";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!strtok_r(nullptr, delim, &save_ptr)) {
|
||||||
|
LERROR << "Error parsing mount source";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!strtok_r(nullptr, delim, &save_ptr)) {
|
||||||
|
LERROR << "Error parsing root";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* p;
|
||||||
|
if (!(p = strtok_r(nullptr, delim, &save_ptr))) {
|
||||||
|
LERROR << "Error parsing mount_point";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mount_info entry = {p, false};
|
||||||
|
|
||||||
|
if (!strtok_r(nullptr, delim, &save_ptr)) {
|
||||||
|
LERROR << "Error parsing mount_flags";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((p = strtok_r(nullptr, delim, &save_ptr))) {
|
||||||
|
if ((p[0] == '-') && (p[1] == '\0')) break;
|
||||||
|
if (android::base::StartsWith(p, "shared:")) entry.shared_flag = true;
|
||||||
|
}
|
||||||
|
if (!p) {
|
||||||
|
LERROR << "Error parsing fields";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
info.emplace_back(std::move(entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
free(line);
|
||||||
|
if (info.empty()) {
|
||||||
|
LERROR << __FUNCTION__ << "(): failed to load mountinfo from : '" << path << "'";
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
bool fs_mgr_overlayfs_mount(const std::string& mount_point) {
|
bool fs_mgr_overlayfs_mount(const std::string& mount_point) {
|
||||||
auto options = fs_mgr_get_overlayfs_options(mount_point);
|
auto options = fs_mgr_get_overlayfs_options(mount_point);
|
||||||
if (options.empty()) return false;
|
if (options.empty()) return false;
|
||||||
|
|
||||||
|
auto retval = true;
|
||||||
|
auto save_errno = errno;
|
||||||
|
|
||||||
|
struct move_entry {
|
||||||
|
std::string mount_point;
|
||||||
|
std::string dir;
|
||||||
|
bool shared_flag;
|
||||||
|
};
|
||||||
|
std::vector<move_entry> move;
|
||||||
|
auto parent_private = false;
|
||||||
|
auto parent_made_private = false;
|
||||||
|
auto dev_private = false;
|
||||||
|
auto dev_made_private = false;
|
||||||
|
for (auto& entry : ReadMountinfoFromFile("/proc/self/mountinfo")) {
|
||||||
|
if ((entry.mount_point == mount_point) && !entry.shared_flag) {
|
||||||
|
parent_private = true;
|
||||||
|
}
|
||||||
|
if ((entry.mount_point == "/dev") && !entry.shared_flag) {
|
||||||
|
dev_private = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!android::base::StartsWith(entry.mount_point, mount_point + "/")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (std::find_if(move.begin(), move.end(), [&entry](const auto& it) {
|
||||||
|
return android::base::StartsWith(entry.mount_point, it.mount_point + "/");
|
||||||
|
}) != move.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use as the bound directory in /dev.
|
||||||
|
auto new_context = fs_mgr_get_context(entry.mount_point);
|
||||||
|
if (!new_context.empty() && setfscreatecon(new_context.c_str())) {
|
||||||
|
PERROR << "setfscreatecon " << new_context;
|
||||||
|
}
|
||||||
|
move_entry new_entry = {std::move(entry.mount_point), "/dev/TemporaryDir-XXXXXX",
|
||||||
|
entry.shared_flag};
|
||||||
|
const auto target = mkdtemp(new_entry.dir.data());
|
||||||
|
if (!target) {
|
||||||
|
retval = false;
|
||||||
|
save_errno = errno;
|
||||||
|
PERROR << "temporary directory for MS_BIND";
|
||||||
|
setfscreatecon(nullptr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
setfscreatecon(nullptr);
|
||||||
|
|
||||||
|
if (!parent_private && !parent_made_private) {
|
||||||
|
parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false);
|
||||||
|
}
|
||||||
|
if (new_entry.shared_flag) {
|
||||||
|
new_entry.shared_flag = fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, false);
|
||||||
|
}
|
||||||
|
if (!fs_mgr_overlayfs_move_mount(new_entry.mount_point, new_entry.dir)) {
|
||||||
|
retval = false;
|
||||||
|
save_errno = errno;
|
||||||
|
if (new_entry.shared_flag) {
|
||||||
|
fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, true);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
move.emplace_back(std::move(new_entry));
|
||||||
|
}
|
||||||
|
|
||||||
// hijack __mount() report format to help triage
|
// hijack __mount() report format to help triage
|
||||||
auto report = "__mount(source=overlay,target="s + mount_point + ",type=overlay";
|
auto report = "__mount(source=overlay,target="s + mount_point + ",type=overlay";
|
||||||
const auto opt_list = android::base::Split(options, ",");
|
const auto opt_list = android::base::Split(options, ",");
|
||||||
|
|
@ -535,12 +690,38 @@ bool fs_mgr_overlayfs_mount(const std::string& mount_point) {
|
||||||
auto ret = mount("overlay", mount_point.c_str(), "overlay", MS_RDONLY | MS_RELATIME,
|
auto ret = mount("overlay", mount_point.c_str(), "overlay", MS_RDONLY | MS_RELATIME,
|
||||||
options.c_str());
|
options.c_str());
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
retval = false;
|
||||||
|
save_errno = errno;
|
||||||
PERROR << report << ret;
|
PERROR << report << ret;
|
||||||
return false;
|
|
||||||
} else {
|
} else {
|
||||||
LINFO << report << ret;
|
LINFO << report << ret;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Move submounts back.
|
||||||
|
for (const auto& entry : move) {
|
||||||
|
if (!dev_private && !dev_made_private) {
|
||||||
|
dev_made_private = fs_mgr_overlayfs_set_shared_mount("/dev", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fs_mgr_overlayfs_move_mount(entry.dir, entry.mount_point)) {
|
||||||
|
retval = false;
|
||||||
|
save_errno = errno;
|
||||||
|
} else if (entry.shared_flag &&
|
||||||
|
!fs_mgr_overlayfs_set_shared_mount(entry.mount_point, true)) {
|
||||||
|
retval = false;
|
||||||
|
save_errno = errno;
|
||||||
|
}
|
||||||
|
rmdir(entry.dir.c_str());
|
||||||
|
}
|
||||||
|
if (dev_made_private) {
|
||||||
|
fs_mgr_overlayfs_set_shared_mount("/dev", true);
|
||||||
|
}
|
||||||
|
if (parent_made_private) {
|
||||||
|
fs_mgr_overlayfs_set_shared_mount(mount_point, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mount kScratchMountPoint
|
// Mount kScratchMountPoint
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue