From e31f840a0a081cca2ab2a418c9611a01e3b54a98 Mon Sep 17 00:00:00 2001 From: Steve Muckle Date: Wed, 31 Jul 2019 14:34:52 -0700 Subject: [PATCH] libmodprobe: add support for a blacklist If the blacklist is enabled, blacklisted modules are treated as though they are not present. Change-Id: Ie8712f24298e78f92d5028b1ca3a8a3e07a9190a --- libmodprobe/include/modprobe/modprobe.h | 5 ++++ libmodprobe/libmodprobe.cpp | 32 +++++++++++++++++++++++++ libmodprobe/libmodprobe_ext.cpp | 3 +++ libmodprobe/libmodprobe_ext_test.cpp | 3 +++ libmodprobe/libmodprobe_test.cpp | 30 +++++++++++++++-------- 5 files changed, 63 insertions(+), 10 deletions(-) diff --git a/libmodprobe/include/modprobe/modprobe.h b/libmodprobe/include/modprobe/modprobe.h index 05136bda4..03fb0a3ac 100644 --- a/libmodprobe/include/modprobe/modprobe.h +++ b/libmodprobe/include/modprobe/modprobe.h @@ -16,6 +16,7 @@ #pragma once +#include #include #include #include @@ -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& args); bool ParseLoadCallback(const std::vector& args); bool ParseOptionsCallback(const std::vector& args); + bool ParseBlacklistCallback(const std::vector& args); void ParseCfg(const std::string& cfg, std::function&)> f); std::vector> module_aliases_; @@ -50,4 +53,6 @@ class Modprobe { std::vector> module_post_softdep_; std::vector module_load_; std::unordered_map module_options_; + std::set module_blacklist_; + bool blacklist_enabled = false; }; diff --git a/libmodprobe/libmodprobe.cpp b/libmodprobe/libmodprobe.cpp index 37ac32851..354ec7bce 100644 --- a/libmodprobe/libmodprobe.cpp +++ b/libmodprobe/libmodprobe.cpp @@ -194,6 +194,31 @@ bool Modprobe::ParseOptionsCallback(const std::vector& args) { return true; } +bool Modprobe::ParseBlacklistCallback(const std::vector& 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&)> f) { std::string cfg_contents; @@ -231,9 +256,16 @@ Modprobe::Modprobe(const std::vector& 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 Modprobe::GetDependencies(const std::string& module) { auto it = module_deps_.find(module); if (it == module_deps_.end()) { diff --git a/libmodprobe/libmodprobe_ext.cpp b/libmodprobe/libmodprobe_ext.cpp index 52e308fab..3e9ff70cb 100644 --- a/libmodprobe/libmodprobe_ext.cpp +++ b/libmodprobe/libmodprobe_ext.cpp @@ -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 diff --git a/libmodprobe/libmodprobe_ext_test.cpp b/libmodprobe/libmodprobe_ext_test.cpp index 204809fa5..7d817b1f2 100644 --- a/libmodprobe/libmodprobe_ext_test.cpp +++ b/libmodprobe/libmodprobe_ext_test.cpp @@ -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; diff --git a/libmodprobe/libmodprobe_test.cpp b/libmodprobe/libmodprobe_test.cpp index d5a7d6f15..a711631da 100644 --- a/libmodprobe/libmodprobe_test.cpp +++ b/libmodprobe/libmodprobe_test.cpp @@ -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())); + 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, 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())); + 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)); }