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

Commit e31f840a authored by Steve Muckle's avatar Steve Muckle
Browse files

libmodprobe: add support for a blacklist

If the blacklist is enabled, blacklisted modules are treated as though
they are not present.

Change-Id: Ie8712f24298e78f92d5028b1ca3a8a3e07a9190a
parent 13700a69
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#pragma once

#include <set>
#include <string>
#include <unordered_map>
#include <vector>
@@ -28,6 +29,7 @@ class Modprobe {
    bool LoadWithAliases(const std::string& module_name, bool strict,
                         const std::string& parameters = "");
    bool Remove(const std::string& module_name);
    void EnableBlacklist(bool enable);

  private:
    std::string MakeCanonical(const std::string& module_path);
@@ -42,6 +44,7 @@ class Modprobe {
    bool ParseSoftdepCallback(const std::vector<std::string>& args);
    bool ParseLoadCallback(const std::vector<std::string>& args);
    bool ParseOptionsCallback(const std::vector<std::string>& args);
    bool ParseBlacklistCallback(const std::vector<std::string>& args);
    void ParseCfg(const std::string& cfg, std::function<bool(const std::vector<std::string>&)> f);

    std::vector<std::pair<std::string, std::string>> module_aliases_;
@@ -50,4 +53,6 @@ class Modprobe {
    std::vector<std::pair<std::string, std::string>> module_post_softdep_;
    std::vector<std::string> module_load_;
    std::unordered_map<std::string, std::string> module_options_;
    std::set<std::string> module_blacklist_;
    bool blacklist_enabled = false;
};
+32 −0
Original line number Diff line number Diff line
@@ -194,6 +194,31 @@ bool Modprobe::ParseOptionsCallback(const std::vector<std::string>& args) {
    return true;
}

bool Modprobe::ParseBlacklistCallback(const std::vector<std::string>& args) {
    auto it = args.begin();
    const std::string& type = *it++;

    if (type != "blacklist") {
        LOG(ERROR) << "non-blacklist line encountered in modules.blacklist";
        return false;
    }

    if (args.size() != 2) {
        LOG(ERROR) << "lines in modules.blacklist must have exactly 2 entries, not " << args.size();
        return false;
    }

    const std::string& module = *it++;

    const std::string& canonical_name = MakeCanonical(module);
    if (canonical_name.empty()) {
        return false;
    }
    this->module_blacklist_.emplace(canonical_name);

    return true;
}

void Modprobe::ParseCfg(const std::string& cfg,
                        std::function<bool(const std::vector<std::string>&)> f) {
    std::string cfg_contents;
@@ -231,9 +256,16 @@ Modprobe::Modprobe(const std::vector<std::string>& base_paths) {

        auto options_callback = std::bind(&Modprobe::ParseOptionsCallback, this, _1);
        ParseCfg(base_path + "/modules.options", options_callback);

        auto blacklist_callback = std::bind(&Modprobe::ParseBlacklistCallback, this, _1);
        ParseCfg(base_path + "/modules.blacklist", blacklist_callback);
    }
}

void Modprobe::EnableBlacklist(bool enable) {
    blacklist_enabled = enable;
}

std::vector<std::string> Modprobe::GetDependencies(const std::string& module) {
    auto it = module_deps_.find(module);
    if (it == module_deps_.end()) {
+3 −0
Original line number Diff line number Diff line
@@ -65,6 +65,9 @@ bool Modprobe::Rmmod(const std::string& module_name) {

bool Modprobe::ModuleExists(const std::string& module_name) {
    struct stat fileStat;
    if (blacklist_enabled && module_blacklist_.count(module_name)) {
        return false;
    }
    auto deps = GetDependencies(module_name);
    if (deps.empty()) {
        // missing deps can happen in the case of an alias
+3 −0
Original line number Diff line number Diff line
@@ -67,6 +67,9 @@ bool Modprobe::Rmmod(const std::string& module_name) {

bool Modprobe::ModuleExists(const std::string& module_name) {
    auto deps = GetDependencies(module_name);
    if (blacklist_enabled && module_blacklist_.count(module_name)) {
        return false;
    }
    if (deps.empty()) {
        // missing deps can happen in the case of an alias
        return false;
+21 −11
Original line number Diff line number Diff line
@@ -99,6 +99,10 @@ TEST(libmodprobe, Test) {
            "options test9.ko param_x=1 param_y=2 param_z=3\n"
            "options test100.ko param_1=1\n";

    const std::string modules_blacklist =
            "blacklist test9.ko\n"
            "blacklist test3.ko\n";

    const std::string modules_load =
            "test4.ko\n"
            "test1.ko\n"
@@ -109,17 +113,20 @@ TEST(libmodprobe, Test) {
            "test11.ko\n";

    TemporaryDir dir;
    ASSERT_TRUE(android::base::WriteStringToFile(
            modules_alias, std::string(dir.path) + "/modules.alias", 0600, getuid(), getgid()));

    ASSERT_TRUE(android::base::WriteStringToFile(
            modules_dep, std::string(dir.path) + "/modules.dep", 0600, getuid(), getgid()));
    ASSERT_TRUE(android::base::WriteStringToFile(
            modules_softdep, std::string(dir.path) + "/modules.softdep", 0600, getuid(), getgid()));
    ASSERT_TRUE(android::base::WriteStringToFile(
            modules_options, std::string(dir.path) + "/modules.options", 0600, getuid(), getgid()));
    ASSERT_TRUE(android::base::WriteStringToFile(
            modules_load, std::string(dir.path) + "/modules.load", 0600, getuid(), getgid()));
    auto dir_path = std::string(dir.path);
    ASSERT_TRUE(android::base::WriteStringToFile(modules_alias, dir_path + "/modules.alias", 0600,
                                                 getuid(), getgid()));

    ASSERT_TRUE(android::base::WriteStringToFile(modules_dep, dir_path + "/modules.dep", 0600,
                                                 getuid(), getgid()));
    ASSERT_TRUE(android::base::WriteStringToFile(modules_softdep, dir_path + "/modules.softdep",
                                                 0600, getuid(), getgid()));
    ASSERT_TRUE(android::base::WriteStringToFile(modules_options, dir_path + "/modules.options",
                                                 0600, getuid(), getgid()));
    ASSERT_TRUE(android::base::WriteStringToFile(modules_load, dir_path + "/modules.load", 0600,
                                                 getuid(), getgid()));
    ASSERT_TRUE(android::base::WriteStringToFile(modules_blacklist, dir_path + "/modules.blacklist",
                                                 0600, getuid(), getgid()));

    for (auto i = test_modules.begin(); i != test_modules.end(); ++i) {
        *i = dir.path + *i;
@@ -153,4 +160,7 @@ TEST(libmodprobe, Test) {
    }

    EXPECT_TRUE(modules_loaded == expected_after_remove);

    m.EnableBlacklist(true);
    EXPECT_FALSE(m.LoadWithAliases("test4", true));
}