toolbox/modprobe: Fix fallback path when mod_dirs is empty
Due to GKI, the kernel UTS release string will not always (if ever)
match the vendor's UTS release string that is used to create the
initramfs file structure -- /lib/modules/<vendor uname>. This causes
module load failures when `-d DIR` is omitted. To fix this, we can
include all of the versions under /lib/modules that match the kernel's
major and minor version instead of directly using the value of uname().
In addition, we can also support modules being loaded directly from
/lib/modules.
Test: verify GKI kernel + initramfs with different UTS strings
Test: verify GKI kernel + initramfs with modules directly in /lib/modules
Fixes: 8320778425
("toolbox/modprobe: Fallback to /lib/modules/<uname> ")
Bug: 282917063
Bug: 254835242
Merged-In: I5368f5cff139ba3165323a6a91066be38bfa0736
Change-Id: I5368f5cff139ba3165323a6a91066be38bfa0736
This commit is contained in:
parent
7003fba5f2
commit
e067e96da2
1 changed files with 36 additions and 8 deletions
|
@ -85,6 +85,26 @@ void MyLogger(android::base::LogId id, android::base::LogSeverity severity, cons
|
|||
}
|
||||
}
|
||||
|
||||
// Find directories in format of "/lib/modules/x.y.z-*".
|
||||
static int KernelVersionNameFilter(const dirent* de) {
|
||||
unsigned int major, minor;
|
||||
static std::string kernel_version;
|
||||
utsname uts;
|
||||
|
||||
if (kernel_version.empty()) {
|
||||
if ((uname(&uts) != 0) || (sscanf(uts.release, "%u.%u", &major, &minor) != 2)) {
|
||||
LOG(ERROR) << "Could not parse the kernel version from uname";
|
||||
return 0;
|
||||
}
|
||||
kernel_version = android::base::StringPrintf("%u.%u", major, minor);
|
||||
}
|
||||
|
||||
if (android::base::StartsWith(de->d_name, kernel_version)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
extern "C" int modprobe_main(int argc, char** argv) {
|
||||
|
@ -192,9 +212,22 @@ extern "C" int modprobe_main(int argc, char** argv) {
|
|||
}
|
||||
|
||||
if (mod_dirs.empty()) {
|
||||
utsname uts;
|
||||
uname(&uts);
|
||||
mod_dirs.emplace_back(android::base::StringPrintf("/lib/modules/%s", uts.release));
|
||||
static constexpr auto LIB_MODULES_PREFIX = "/lib/modules/";
|
||||
dirent** kernel_dirs = NULL;
|
||||
|
||||
int n = scandir(LIB_MODULES_PREFIX, &kernel_dirs, KernelVersionNameFilter, NULL);
|
||||
if (n == -1) {
|
||||
PLOG(ERROR) << "Failed to scan dir " << LIB_MODULES_PREFIX;
|
||||
return EXIT_FAILURE;
|
||||
} else if (n > 0) {
|
||||
while (n--) {
|
||||
mod_dirs.emplace_back(LIB_MODULES_PREFIX + std::string(kernel_dirs[n]->d_name));
|
||||
}
|
||||
}
|
||||
free(kernel_dirs);
|
||||
|
||||
// Allow modules to be directly inside /lib/modules
|
||||
mod_dirs.emplace_back(LIB_MODULES_PREFIX);
|
||||
}
|
||||
|
||||
LOG(DEBUG) << "mode is " << mode;
|
||||
|
@ -212,11 +245,6 @@ extern "C" int modprobe_main(int argc, char** argv) {
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
if (mod_dirs.empty()) {
|
||||
LOG(ERROR) << "No module configuration directories given.";
|
||||
print_usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (parameter_count && modules.size() > 1) {
|
||||
LOG(ERROR) << "Only one module may be loaded when specifying module parameters.";
|
||||
print_usage();
|
||||
|
|
Loading…
Reference in a new issue