diff options
author | Steve Muckle <smuckle@google.com> | 2019-04-15 17:43:02 -0700 |
---|---|---|
committer | Steve Muckle <smuckle@google.com> | 2019-06-18 13:24:56 -0700 |
commit | 18b981ea7c5f0964941931a71fa55d880bec0c16 (patch) | |
tree | b612ff6ede21cb2e7ea5447f33044608b5780fb5 /init/modalias_handler.cpp | |
parent | 716ba5d91d72f047c2bd017842b0a0a88e2b88ae (diff) |
create libmodprobe, integrate into first_stage_init
Modprobe functionality is required both within first stage init and also
as a standalone binary. Create a library for this using and extending
the logic in modalias_handler.cpp.
First stage init will attempt to load modules from /lib/modules.
Bug: 129780532
Change-Id: Ie3582358fd839c2f64e1b386b30ed551a86aef5d
Diffstat (limited to 'init/modalias_handler.cpp')
-rw-r--r-- | init/modalias_handler.cpp | 135 |
1 files changed, 4 insertions, 131 deletions
diff --git a/init/modalias_handler.cpp b/init/modalias_handler.cpp index a51115628..07b05d8b4 100644 --- a/init/modalias_handler.cpp +++ b/init/modalias_handler.cpp @@ -16,147 +16,20 @@ #include "modalias_handler.h" -#include <fnmatch.h> -#include <sys/syscall.h> - -#include <algorithm> -#include <functional> #include <string> #include <vector> -#include <android-base/chrono_utils.h> -#include <android-base/logging.h> -#include <android-base/unique_fd.h> - -#include "parser.h" +#include <modprobe/modprobe.h> namespace android { namespace init { -Result<void> ModaliasHandler::ParseDepCallback(std::vector<std::string>&& args) { - std::vector<std::string> deps; - - // Set first item as our modules path - std::string::size_type pos = args[0].find(':'); - if (pos != std::string::npos) { - deps.emplace_back(args[0].substr(0, pos)); - } else { - return Error() << "dependency lines must start with name followed by ':'"; - } - - // Remaining items are dependencies of our module - for (auto arg = args.begin() + 1; arg != args.end(); ++arg) { - deps.push_back(*arg); - } - - // Key is striped module name to match names in alias file - std::size_t start = args[0].find_last_of('/'); - std::size_t end = args[0].find(".ko:"); - if ((end - start) <= 1) return Error() << "malformed dependency line"; - auto mod_name = args[0].substr(start + 1, (end - start) - 1); - // module names can have '-', but their file names will have '_' - std::replace(mod_name.begin(), mod_name.end(), '-', '_'); - this->module_deps_[mod_name] = deps; - - return {}; -} - -Result<void> ModaliasHandler::ParseAliasCallback(std::vector<std::string>&& args) { - auto it = args.begin(); - const std::string& type = *it++; - - if (type != "alias") { - return Error() << "we only handle alias lines, got: " << type; - } - - if (args.size() != 3) { - return Error() << "alias lines must have 3 entries"; - } - - std::string& alias = *it++; - std::string& module_name = *it++; - this->module_aliases_.emplace_back(alias, module_name); - - return {}; -} - -ModaliasHandler::ModaliasHandler() { - using namespace std::placeholders; - - static const std::string base_paths[] = { - "/vendor/lib/modules/", - "/lib/modules/", - "/odm/lib/modules/", - }; - - Parser alias_parser; - auto alias_callback = std::bind(&ModaliasHandler::ParseAliasCallback, this, _1); - alias_parser.AddSingleLineParser("alias", alias_callback); - for (const auto& base_path : base_paths) alias_parser.ParseConfig(base_path + "modules.alias"); - - Parser dep_parser; - auto dep_callback = std::bind(&ModaliasHandler::ParseDepCallback, this, _1); - dep_parser.AddSingleLineParser("", dep_callback); - for (const auto& base_path : base_paths) dep_parser.ParseConfig(base_path + "modules.dep"); -} - -Result<void> ModaliasHandler::Insmod(const std::string& path_name, const std::string& args) { - base::unique_fd fd( - TEMP_FAILURE_RETRY(open(path_name.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC))); - if (fd == -1) return ErrnoError() << "Could not open module '" << path_name << "'"; - - int ret = syscall(__NR_finit_module, fd.get(), args.c_str(), 0); - if (ret != 0) { - if (errno == EEXIST) { - // Module already loaded - return {}; - } - return ErrnoError() << "Failed to insmod '" << path_name << "' with args '" << args << "'"; - } - - LOG(INFO) << "Loaded kernel module " << path_name; - return {}; -} - -Result<void> ModaliasHandler::InsmodWithDeps(const std::string& module_name, - const std::string& args) { - if (module_name.empty()) { - return Error() << "Need valid module name"; - } - - auto it = module_deps_.find(module_name); - if (it == module_deps_.end()) { - return Error() << "Module '" << module_name << "' not in dependency file"; - } - auto& dependencies = it->second; - - // load module dependencies in reverse order - for (auto dep = dependencies.rbegin(); dep != dependencies.rend() - 1; ++dep) { - if (auto result = Insmod(*dep, ""); !result) return result; - } - - // load target module itself with args - return Insmod(dependencies[0], args); -} +ModaliasHandler::ModaliasHandler(const std::vector<std::string>& base_paths) + : modprobe_(base_paths) {} void ModaliasHandler::HandleUevent(const Uevent& uevent) { if (uevent.modalias.empty()) return; - - for (const auto& [alias, module] : module_aliases_) { - if (fnmatch(alias.c_str(), uevent.modalias.c_str(), 0) != 0) continue; // Keep looking - - LOG(DEBUG) << "Loading kernel module '" << module << "' for alias '" << uevent.modalias - << "'"; - - if (auto result = InsmodWithDeps(module, ""); !result) { - LOG(ERROR) << "Cannot load module: " << result.error(); - // try another one since there may be another match - continue; - } - - // loading was successful - return; - } + modprobe_.LoadWithAliases(uevent.modalias, true); } } // namespace init |