summaryrefslogtreecommitdiff
path: root/kernel/module.c
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2003-04-29 17:17:33 -0700
committerChristoph Hellwig <hch@lst.de>2003-04-29 17:17:33 -0700
commit67ac5b866bda838d9838faedad0435e3e84fb2bd (patch)
treebabf99dad94799fca5953c91bdf07488895ffbca /kernel/module.c
parentd1f880abc403575e9166ec673a855877352d3af3 (diff)
[PATCH] complete modinfo section
Restores .modinfo section, and uses it to store license and vermagic.
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c87
1 files changed, 60 insertions, 27 deletions
diff --git a/kernel/module.c b/kernel/module.c
index ccba086ce6bc..17e2884ce495 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -939,12 +939,12 @@ EXPORT_SYMBOL_GPL(__symbol_get);
/* Change all symbols so that sh_value encodes the pointer directly. */
static int simplify_symbols(Elf_Shdr *sechdrs,
unsigned int symindex,
- unsigned int strindex,
+ const char *strtab,
unsigned int versindex,
struct module *mod)
{
Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr;
- const char *strtab = (char *)sechdrs[strindex].sh_addr;
+
unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
int ret = 0;
@@ -1063,13 +1063,9 @@ static inline int license_is_gpl_compatible(const char *license)
|| strcmp(license, "Dual MPL/GPL") == 0);
}
-static void set_license(struct module *mod, Elf_Shdr *sechdrs, int licenseidx)
+static void set_license(struct module *mod, const char *license)
{
- char *license;
-
- if (licenseidx)
- license = (char *)sechdrs[licenseidx].sh_addr;
- else
+ if (!license)
license = "unspecified";
mod->license_gplok = license_is_gpl_compatible(license);
@@ -1080,6 +1076,40 @@ static void set_license(struct module *mod, Elf_Shdr *sechdrs, int licenseidx)
}
}
+/* Parse tag=value strings from .modinfo section */
+static char *next_string(char *string, unsigned long *secsize)
+{
+ /* Skip non-zero chars */
+ while (string[0]) {
+ string++;
+ if ((*secsize)-- <= 1)
+ return NULL;
+ }
+
+ /* Skip any zero padding. */
+ while (!string[0]) {
+ string++;
+ if ((*secsize)-- <= 1)
+ return NULL;
+ }
+ return string;
+}
+
+static char *get_modinfo(Elf_Shdr *sechdrs,
+ unsigned int info,
+ const char *tag)
+{
+ char *p;
+ unsigned int taglen = strlen(tag);
+ unsigned long size = sechdrs[info].sh_size;
+
+ for (p = (char *)sechdrs[info].sh_addr; p; p = next_string(p, &size)) {
+ if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=')
+ return p + taglen + 1;
+ }
+ return NULL;
+}
+
/* Allocate and load the module: note that size of section 0 is always
zero, and we rely on this for optional sections. */
static struct module *load_module(void __user *umod,
@@ -1088,9 +1118,9 @@ static struct module *load_module(void __user *umod,
{
Elf_Ehdr *hdr;
Elf_Shdr *sechdrs;
- char *secstrings, *args;
- unsigned int i, symindex, exportindex, strindex, setupindex, exindex,
- modindex, obsparmindex, licenseindex, gplindex, vmagindex,
+ char *secstrings, *args, *modmagic, *strtab = NULL;
+ unsigned int i, symindex = 0, strindex = 0, setupindex, exindex,
+ exportindex, modindex, obsparmindex, infoindex, gplindex,
crcindex, gplcrcindex, versindex;
long arglen;
struct module *mod;
@@ -1124,6 +1154,7 @@ static struct module *load_module(void __user *umod,
/* Convenience variables */
sechdrs = (void *)hdr + hdr->e_shoff;
secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+ sechdrs[0].sh_addr = 0;
/* And these should exist, but gcc whinges if we don't init them */
symindex = strindex = 0;
@@ -1137,6 +1168,7 @@ static struct module *load_module(void __user *umod,
if (sechdrs[i].sh_type == SHT_SYMTAB) {
symindex = i;
strindex = sechdrs[i].sh_link;
+ strtab = (char *)hdr + sechdrs[strindex].sh_offset;
}
#ifndef CONFIG_MODULE_UNLOAD
/* Don't load .exit sections */
@@ -1145,12 +1177,6 @@ static struct module *load_module(void __user *umod,
#endif
}
-#ifdef CONFIG_KALLSYMS
- /* Keep symbol and string tables for decoding later. */
- sechdrs[symindex].sh_flags |= SHF_ALLOC;
- sechdrs[strindex].sh_flags |= SHF_ALLOC;
-#endif
-
modindex = find_sec(hdr, sechdrs, secstrings,
".gnu.linkonce.this_module");
if (!modindex) {
@@ -1168,9 +1194,16 @@ static struct module *load_module(void __user *umod,
setupindex = find_sec(hdr, sechdrs, secstrings, "__param");
exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table");
obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm");
- licenseindex = find_sec(hdr, sechdrs, secstrings, ".init.license");
- vmagindex = find_sec(hdr, sechdrs, secstrings, "__vermagic");
versindex = find_sec(hdr, sechdrs, secstrings, "__versions");
+ infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo");
+
+ /* Don't keep modinfo section */
+ sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
+#ifdef CONFIG_KALLSYMS
+ /* Keep symbol and string tables for decoding later. */
+ sechdrs[symindex].sh_flags |= SHF_ALLOC;
+ sechdrs[strindex].sh_flags |= SHF_ALLOC;
+#endif
/* Check module struct version now, before we try to use module. */
if (!check_modstruct_version(sechdrs, versindex, mod)) {
@@ -1178,14 +1211,15 @@ static struct module *load_module(void __user *umod,
goto free_hdr;
}
+ modmagic = get_modinfo(sechdrs, infoindex, "vermagic");
/* This is allowed: modprobe --force will invalidate it. */
- if (!vmagindex) {
+ if (!modmagic) {
tainted |= TAINT_FORCED_MODULE;
printk(KERN_WARNING "%s: no version magic, tainting kernel.\n",
mod->name);
- } else if (!same_magic((char *)sechdrs[vmagindex].sh_addr, vermagic)) {
+ } else if (!same_magic(modmagic, vermagic)) {
printk(KERN_ERR "%s: version magic '%s' should be '%s'\n",
- mod->name, (char*)sechdrs[vmagindex].sh_addr, vermagic);
+ mod->name, modmagic, vermagic);
err = -ENOEXEC;
goto free_hdr;
}
@@ -1265,11 +1299,11 @@ static struct module *load_module(void __user *umod,
/* Now we've moved module, initialize linked lists, etc. */
module_unload_init(mod);
- /* Set up license info based on contents of section */
- set_license(mod, sechdrs, licenseindex);
+ /* Set up license info based on the info section */
+ set_license(mod, get_modinfo(sechdrs, infoindex, "license"));
/* Fix up syms, so that st_value is a pointer to location. */
- err = simplify_symbols(sechdrs, symindex, strindex, versindex, mod);
+ err = simplify_symbols(sechdrs, symindex, strtab, versindex, mod);
if (err < 0)
goto cleanup;
@@ -1300,8 +1334,7 @@ static struct module *load_module(void __user *umod,
for (i = 1; i < hdr->e_shnum; i++) {
const char *strtab = (char *)sechdrs[strindex].sh_addr;
if (sechdrs[i].sh_type == SHT_REL)
- err = apply_relocate(sechdrs, strtab, symindex, i,
- mod);
+ err = apply_relocate(sechdrs, strtab, symindex, i,mod);
else if (sechdrs[i].sh_type == SHT_RELA)
err = apply_relocate_add(sechdrs, strtab, symindex, i,
mod);