toolbox/modprobe: Filter module directories based on kernel page size
When modules for multiple kernels with the same major/minor versions are installed on a device, modprobe will search the module directories based on whatever order scandir() returned them. In this case, it is possible that we will try to load modules with the wrong page size for the running kernel, which can lead to obscure symbol CRC mismatches and ultimately a system crash. Adjust the scandir() filtering function so that the kernel page size is taken into account in addition to the major/minor versions returned by utsname(). The general rule is that module directories ending in "_Nk" contain modules for a page-size of N KiB, whilst the absence of such a suffix implies the default of 4 KiB. Bug: 343971855 Test: Verified that _16k module directory is excluded by modprobe when running in userspace fastboot with 4k pages. Change-Id: I78a0a249028bbb0bcdd78eb14de36e631e233be0
This commit is contained in:
parent
4e1776cedf
commit
c991c3dbed
1 changed files with 16 additions and 1 deletions
|
@ -17,6 +17,7 @@
|
|||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@ -85,6 +86,20 @@ void MyLogger(android::base::LogId id, android::base::LogSeverity severity, cons
|
|||
}
|
||||
}
|
||||
|
||||
static bool ModDirMatchesKernelPageSize(const char* mod_dir) {
|
||||
static const unsigned int kernel_pgsize_kb = getpagesize() / 1024;
|
||||
const char* mod_sfx = strrchr(mod_dir, '_');
|
||||
unsigned int mod_pgsize_kb;
|
||||
int mod_sfx_len;
|
||||
|
||||
if (mod_sfx == NULL || sscanf(mod_sfx, "_%uk%n", &mod_pgsize_kb, &mod_sfx_len) != 1 ||
|
||||
strlen(mod_sfx) != mod_sfx_len) {
|
||||
mod_pgsize_kb = 4;
|
||||
}
|
||||
|
||||
return kernel_pgsize_kb == mod_pgsize_kb;
|
||||
}
|
||||
|
||||
// Find directories in format of "/lib/modules/x.y.z-*".
|
||||
static int KernelVersionNameFilter(const dirent* de) {
|
||||
unsigned int major, minor;
|
||||
|
@ -100,7 +115,7 @@ static int KernelVersionNameFilter(const dirent* de) {
|
|||
}
|
||||
|
||||
if (android::base::StartsWith(de->d_name, kernel_version)) {
|
||||
return 1;
|
||||
return ModDirMatchesKernelPageSize(de->d_name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue