Linux Kernel Architecture

(Jacob Rumans) #1

Chapter7:Modules


kernel/module.c
static int check_version(Elf_Shdr *sechdrs,
unsigned int versindex,
const char *symname,
struct module *mod,
const unsigned long *crc)
{
unsigned int i, num_versions;
struct modversion_info *versions;

/* Exporting module didn’t supply crcs? OK, we’re already tainted. */
if (!crc)
return 1;
...

If the module (from which the symbol to be resolved originates) does not provide any CRC information,
the function returns 1 directly. This means that the version check was successful — if no information is
available, the check cannot fail.

Otherwise the kernel iterates through all symbolsreferenced by the module, searches for the corre-
sponding entry and compares the checksum returned inversions[i].crcbythemodulewiththe(crc)
returned by the kernel. If the two match, the kernel returns 1; if not, a warning message is issued and the
function terminates with 0:

kernel/module.c
versions = (void *) sechdrs[versindex].sh_addr;
num_versions = sechdrs[versindex].sh_size
/ sizeof(struct modversion_info);

for (i = 0; i < num_versions; i++) {
if (strcmp(versions[i].name, symname) != 0)
continue;

if (versions[i].crc == *crc)
return 1;
printk("%s: disagrees about version of symbol %s\n",
mod->name, symname);
return 0;
}

If the symbol is not found in the version table of the module, no version requirements are applied. As
a result, the function again returns 1 for success. However, the aforementionedtaintedglobal variable
and the instance ofstruct modulefor the module in question are supplied withTAINT_FORCED_MODULE
to note for later that a symbol without version information was used.

kernel/module.c
/* Not in module’s version table. OK, but that taints the kernel. */
if (!(tainted & TAINT_FORCED_MODULE)) {
printk("%s: no version for \"%s\" found: kernel tainted.\n",
mod->name, symname);
add_taint_module(mod, TAINT_FORCED_MODULE);
}
return 1;
}
Free download pdf