Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1d662dab authored by Yifan Hong's avatar Yifan Hong Committed by Automerger Merge Worker
Browse files

Merge "Fix allowlist for unreliable pinning." am: 0198ce0c am: 833c1b98

Original change: https://android-review.googlesource.com/c/platform/system/core/+/1393698

Change-Id: I7cbf81d40e1996811faf4a36b0bde44c22a2acf8
parents 464e1794 833c1b98
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -136,13 +136,13 @@ bool ImageManager::BackingImageExists(const std::string& name) {
    return !!FindPartition(*metadata.get(), name);
}

static bool IsTestDir(const std::string& path) {
    return android::base::StartsWith(path, kTestImageMetadataDir) ||
           android::base::StartsWith(path, kOtaTestImageMetadataDir);
bool ImageManager::MetadataDirIsTest() const {
    return IsSubdir(metadata_dir_, kTestImageMetadataDir) ||
           IsSubdir(metadata_dir_, kOtaTestImageMetadataDir);
}

static bool IsUnreliablePinningAllowed(const std::string& path) {
    return android::base::StartsWith(path, "/data/gsi/dsu/") || IsTestDir(path);
bool ImageManager::IsUnreliablePinningAllowed() const {
    return IsSubdir(data_dir_, "/data/gsi/dsu/") || MetadataDirIsTest();
}

FiemapStatus ImageManager::CreateBackingImage(
@@ -159,7 +159,7 @@ FiemapStatus ImageManager::CreateBackingImage(
    if (!FilesystemHasReliablePinning(data_path, &reliable_pinning)) {
        return FiemapStatus::Error();
    }
    if (!reliable_pinning && !IsUnreliablePinningAllowed(data_path)) {
    if (!reliable_pinning && !IsUnreliablePinningAllowed()) {
        // For historical reasons, we allow unreliable pinning for certain use
        // cases (DSUs, testing) because the ultimate use case is either
        // developer-oriented or ephemeral (the intent is to boot immediately
@@ -178,7 +178,7 @@ FiemapStatus ImageManager::CreateBackingImage(
    // if device-mapper is stacked in some complex way not supported by
    // FiemapWriter.
    auto device_path = GetDevicePathForFile(fw.get());
    if (android::base::StartsWith(device_path, "/dev/block/dm-") && !IsTestDir(metadata_dir_)) {
    if (android::base::StartsWith(device_path, "/dev/block/dm-") && !MetadataDirIsTest()) {
        LOG(ERROR) << "Cannot persist images against device-mapper device: " << device_path;

        fw = {};
+48 −0
Original line number Diff line number Diff line
@@ -34,10 +34,13 @@
#include <libdm/dm.h>
#include <libfiemap/image_manager.h>

#include "utility.h"

using namespace android::dm;
using namespace std::literals;
using android::base::unique_fd;
using android::fiemap::ImageManager;
using android::fiemap::IsSubdir;
using android::fs_mgr::BlockDeviceInfo;
using android::fs_mgr::PartitionOpener;
using android::fs_mgr::WaitForFile;
@@ -131,6 +134,51 @@ TEST_F(NativeTest, GetMappedImageDevice) {
    ASSERT_TRUE(manager_->UnmapImageDevice(base_name_));
}

namespace {

struct IsSubdirTestParam {
    std::string child;
    std::string parent;
    bool result;
};

class IsSubdirTest : public ::testing::TestWithParam<IsSubdirTestParam> {};

TEST_P(IsSubdirTest, Test) {
    const auto& param = GetParam();
    EXPECT_EQ(param.result, IsSubdir(param.child, param.parent))
            << "IsSubdir(child=\"" << param.child << "\", parent=\"" << param.parent
            << "\") != " << (param.result ? "true" : "false");
}

std::vector<IsSubdirTestParam> IsSubdirTestValues() {
    // clang-format off
    std::vector<IsSubdirTestParam> base_cases{
            {"/foo/bar",     "/foo",     true},
            {"/foo/bar/baz", "/foo",     true},
            {"/foo",         "/foo",     true},
            {"/foo",         "/",        true},
            {"/",            "/",        true},
            {"/foo",         "/foo/bar", false},
            {"/foo",         "/bar",     false},
            {"/foo-bar",     "/foo",     false},
            {"/",            "/foo",     false},
    };
    // clang-format on
    std::vector<IsSubdirTestParam> ret;
    for (const auto& e : base_cases) {
        ret.push_back(e);
        ret.push_back({e.child + "/", e.parent, e.result});
        ret.push_back({e.child, e.parent + "/", e.result});
        ret.push_back({e.child + "/", e.parent + "/", e.result});
    }
    return ret;
}

INSTANTIATE_TEST_SUITE_P(IsSubdirTest, IsSubdirTest, ::testing::ValuesIn(IsSubdirTestValues()));

}  // namespace

bool Mkdir(const std::string& path) {
    if (mkdir(path.c_str(), 0700) && errno != EEXIST) {
        std::cerr << "Could not mkdir " << path << ": " << strerror(errno) << std::endl;
+2 −0
Original line number Diff line number Diff line
@@ -176,6 +176,8 @@ class ImageManager final : public IImageManager {
    bool MapWithDmLinear(const IPartitionOpener& opener, const std::string& name,
                         const std::chrono::milliseconds& timeout_ms, std::string* path);
    bool UnmapImageDevice(const std::string& name, bool force);
    bool IsUnreliablePinningAllowed() const;
    bool MetadataDirIsTest() const;

    ImageManager(const ImageManager&) = delete;
    ImageManager& operator=(const ImageManager&) = delete;
+25 −0
Original line number Diff line number Diff line
@@ -167,5 +167,30 @@ bool FilesystemHasReliablePinning(const std::string& file, bool* supported) {
    return F2fsPinBeforeAllocate(fd, supported);
}

bool IsSubdir(const std::string& child, const std::string& parent) {
    // Precondition: both are absolute paths.
    CHECK(android::base::StartsWith(child, "/")) << "Not an absolute path: " << child;
    CHECK(android::base::StartsWith(parent, "/")) << "Not an absolute path: " << parent;

    // Remove extraneous "/" at the end.
    std::string_view child_sv = child;
    while (child_sv != "/" && android::base::ConsumeSuffix(&child_sv, "/"))
        ;

    std::string_view parent_sv = parent;
    while (parent_sv != "/" && android::base::ConsumeSuffix(&parent_sv, "/"))
        ;

    // IsSubdir(anything, "/") => true
    if (parent_sv == "/") return true;

    // IsSubdir("/foo", "/foo") => true
    if (parent_sv == child_sv) return true;

    // IsSubdir("/foo/bar", "/foo") => true
    // IsSubdir("/foo-bar", "/foo") => false
    return android::base::StartsWith(child_sv, std::string(parent_sv) + "/");
}

}  // namespace fiemap
}  // namespace android
+4 −0
Original line number Diff line number Diff line
@@ -51,5 +51,9 @@ bool BlockDeviceToName(uint32_t major, uint32_t minor, std::string* bdev_name);
// cases (such as snapshots or adb remount).
bool FilesystemHasReliablePinning(const std::string& file, bool* supported);

// Crude implementation to check if |child| is a subdir of |parent|.
// Assume both are absolute paths.
bool IsSubdir(const std::string& child, const std::string& parent);

}  // namespace fiemap
}  // namespace android