libmodprobe: add support for a blacklist

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

Change-Id: Ie8712f24298e78f92d5028b1ca3a8a3e07a9190a
This commit is contained in:
Steve Muckle 2019-07-31 14:34:52 -07:00
parent 13700a69d3
commit e31f840a0a
5 changed files with 63 additions and 10 deletions

View file

@ -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;
};

View file

@ -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()) {

View file

@ -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

View file

@ -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;

View file

@ -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));
}