Commit 67ac5b86 authored by Rusty Russell's avatar Rusty Russell Committed by Christoph Hellwig

[PATCH] complete modinfo section

Restores .modinfo section, and uses it to store license and vermagic.
parent d1f880ab
...@@ -20,10 +20,7 @@ ...@@ -20,10 +20,7 @@
#include <asm/module.h> #include <asm/module.h>
/* Not Yet Implemented */ /* Not Yet Implemented */
#define MODULE_AUTHOR(name)
#define MODULE_DESCRIPTION(desc)
#define MODULE_SUPPORTED_DEVICE(name) #define MODULE_SUPPORTED_DEVICE(name)
#define MODULE_PARM_DESC(var,desc)
#define print_modules() #define print_modules()
/* v850 toolchain uses a `_' prefix for all user symbols */ /* v850 toolchain uses a `_' prefix for all user symbols */
...@@ -58,12 +55,11 @@ search_extable(const struct exception_table_entry *first, ...@@ -58,12 +55,11 @@ search_extable(const struct exception_table_entry *first,
unsigned long value); unsigned long value);
#ifdef MODULE #ifdef MODULE
#define ___module_cat(a,b) a ## b #define ___module_cat(a,b) __mod_ ## a ## b
#define __module_cat(a,b) ___module_cat(a,b) #define __module_cat(a,b) ___module_cat(a,b)
/* For userspace: you can also call me... */ #define __MODULE_INFO(tag, name, info) \
#define MODULE_ALIAS(alias) \ static const char __module_cat(name,__LINE__)[] \
static const char __module_cat(__alias_,__LINE__)[] \ __attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info
__attribute__((section(".modinfo"),unused)) = "alias=" alias
#define MODULE_GENERIC_TABLE(gtype,name) \ #define MODULE_GENERIC_TABLE(gtype,name) \
extern const struct gtype##_id __mod_##gtype##_table \ extern const struct gtype##_id __mod_##gtype##_table \
...@@ -71,6 +67,19 @@ extern const struct gtype##_id __mod_##gtype##_table \ ...@@ -71,6 +67,19 @@ extern const struct gtype##_id __mod_##gtype##_table \
#define THIS_MODULE (&__this_module) #define THIS_MODULE (&__this_module)
#else /* !MODULE */
#define MODULE_GENERIC_TABLE(gtype,name)
#define __MODULE_INFO(tag, name, info)
#define THIS_MODULE ((struct module *)0)
#endif
/* Generic info of form tag = "info" */
#define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info)
/* For userspace: you can also call me... */
#define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias)
/* /*
* The following license idents are currently accepted as indicating free * The following license idents are currently accepted as indicating free
* software modules * software modules
...@@ -97,17 +106,18 @@ extern const struct gtype##_id __mod_##gtype##_table \ ...@@ -97,17 +106,18 @@ extern const struct gtype##_id __mod_##gtype##_table \
* 2. So the community can ignore bug reports including proprietary modules * 2. So the community can ignore bug reports including proprietary modules
* 3. So vendors can do likewise based on their own policies * 3. So vendors can do likewise based on their own policies
*/ */
#define MODULE_LICENSE(license) \ #define MODULE_LICENSE(_license) MODULE_INFO(license, _license)
static const char __module_license[] \
__attribute__((section(".init.license"), unused)) = license
#else /* !MODULE */ /* Author, ideally of form NAME <EMAIL>[, NAME <EMAIL>]*[ and NAME <EMAIL>] */
#define MODULE_AUTHOR(_author) MODULE_INFO(author, _author)
#define MODULE_ALIAS(alias) /* What your module does. */
#define MODULE_GENERIC_TABLE(gtype,name) #define MODULE_DESCRIPTION(_description) MODULE_INFO(description, _description)
#define THIS_MODULE ((struct module *)0)
#define MODULE_LICENSE(license) /* One for each parameter, describing how to use it. Some files do
#endif multiple of these per line, so can't just use MODULE_INFO. */
#define MODULE_PARM_DESC(_parm, desc) \
__MODULE_INFO(parm, _parm, #_parm ":" desc)
#define MODULE_DEVICE_TABLE(type,name) \ #define MODULE_DEVICE_TABLE(type,name) \
MODULE_GENERIC_TABLE(type##_device,name) MODULE_GENERIC_TABLE(type##_device,name)
......
...@@ -939,12 +939,12 @@ EXPORT_SYMBOL_GPL(__symbol_get); ...@@ -939,12 +939,12 @@ EXPORT_SYMBOL_GPL(__symbol_get);
/* Change all symbols so that sh_value encodes the pointer directly. */ /* Change all symbols so that sh_value encodes the pointer directly. */
static int simplify_symbols(Elf_Shdr *sechdrs, static int simplify_symbols(Elf_Shdr *sechdrs,
unsigned int symindex, unsigned int symindex,
unsigned int strindex, const char *strtab,
unsigned int versindex, unsigned int versindex,
struct module *mod) struct module *mod)
{ {
Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr; 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); unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
int ret = 0; int ret = 0;
...@@ -1063,13 +1063,9 @@ static inline int license_is_gpl_compatible(const char *license) ...@@ -1063,13 +1063,9 @@ static inline int license_is_gpl_compatible(const char *license)
|| strcmp(license, "Dual MPL/GPL") == 0); || 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 (!license)
if (licenseidx)
license = (char *)sechdrs[licenseidx].sh_addr;
else
license = "unspecified"; license = "unspecified";
mod->license_gplok = license_is_gpl_compatible(license); mod->license_gplok = license_is_gpl_compatible(license);
...@@ -1080,6 +1076,40 @@ static void set_license(struct module *mod, Elf_Shdr *sechdrs, int licenseidx) ...@@ -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 /* Allocate and load the module: note that size of section 0 is always
zero, and we rely on this for optional sections. */ zero, and we rely on this for optional sections. */
static struct module *load_module(void __user *umod, static struct module *load_module(void __user *umod,
...@@ -1088,9 +1118,9 @@ static struct module *load_module(void __user *umod, ...@@ -1088,9 +1118,9 @@ static struct module *load_module(void __user *umod,
{ {
Elf_Ehdr *hdr; Elf_Ehdr *hdr;
Elf_Shdr *sechdrs; Elf_Shdr *sechdrs;
char *secstrings, *args; char *secstrings, *args, *modmagic, *strtab = NULL;
unsigned int i, symindex, exportindex, strindex, setupindex, exindex, unsigned int i, symindex = 0, strindex = 0, setupindex, exindex,
modindex, obsparmindex, licenseindex, gplindex, vmagindex, exportindex, modindex, obsparmindex, infoindex, gplindex,
crcindex, gplcrcindex, versindex; crcindex, gplcrcindex, versindex;
long arglen; long arglen;
struct module *mod; struct module *mod;
...@@ -1124,6 +1154,7 @@ static struct module *load_module(void __user *umod, ...@@ -1124,6 +1154,7 @@ static struct module *load_module(void __user *umod,
/* Convenience variables */ /* Convenience variables */
sechdrs = (void *)hdr + hdr->e_shoff; sechdrs = (void *)hdr + hdr->e_shoff;
secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 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 */ /* And these should exist, but gcc whinges if we don't init them */
symindex = strindex = 0; symindex = strindex = 0;
...@@ -1137,6 +1168,7 @@ static struct module *load_module(void __user *umod, ...@@ -1137,6 +1168,7 @@ static struct module *load_module(void __user *umod,
if (sechdrs[i].sh_type == SHT_SYMTAB) { if (sechdrs[i].sh_type == SHT_SYMTAB) {
symindex = i; symindex = i;
strindex = sechdrs[i].sh_link; strindex = sechdrs[i].sh_link;
strtab = (char *)hdr + sechdrs[strindex].sh_offset;
} }
#ifndef CONFIG_MODULE_UNLOAD #ifndef CONFIG_MODULE_UNLOAD
/* Don't load .exit sections */ /* Don't load .exit sections */
...@@ -1145,12 +1177,6 @@ static struct module *load_module(void __user *umod, ...@@ -1145,12 +1177,6 @@ static struct module *load_module(void __user *umod,
#endif #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, modindex = find_sec(hdr, sechdrs, secstrings,
".gnu.linkonce.this_module"); ".gnu.linkonce.this_module");
if (!modindex) { if (!modindex) {
...@@ -1168,9 +1194,16 @@ static struct module *load_module(void __user *umod, ...@@ -1168,9 +1194,16 @@ static struct module *load_module(void __user *umod,
setupindex = find_sec(hdr, sechdrs, secstrings, "__param"); setupindex = find_sec(hdr, sechdrs, secstrings, "__param");
exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table"); exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table");
obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm"); 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"); 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. */ /* Check module struct version now, before we try to use module. */
if (!check_modstruct_version(sechdrs, versindex, mod)) { if (!check_modstruct_version(sechdrs, versindex, mod)) {
...@@ -1178,14 +1211,15 @@ static struct module *load_module(void __user *umod, ...@@ -1178,14 +1211,15 @@ static struct module *load_module(void __user *umod,
goto free_hdr; goto free_hdr;
} }
modmagic = get_modinfo(sechdrs, infoindex, "vermagic");
/* This is allowed: modprobe --force will invalidate it. */ /* This is allowed: modprobe --force will invalidate it. */
if (!vmagindex) { if (!modmagic) {
tainted |= TAINT_FORCED_MODULE; tainted |= TAINT_FORCED_MODULE;
printk(KERN_WARNING "%s: no version magic, tainting kernel.\n", printk(KERN_WARNING "%s: no version magic, tainting kernel.\n",
mod->name); 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", 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; err = -ENOEXEC;
goto free_hdr; goto free_hdr;
} }
...@@ -1265,11 +1299,11 @@ static struct module *load_module(void __user *umod, ...@@ -1265,11 +1299,11 @@ static struct module *load_module(void __user *umod,
/* Now we've moved module, initialize linked lists, etc. */ /* Now we've moved module, initialize linked lists, etc. */
module_unload_init(mod); module_unload_init(mod);
/* Set up license info based on contents of section */ /* Set up license info based on the info section */
set_license(mod, sechdrs, licenseindex); set_license(mod, get_modinfo(sechdrs, infoindex, "license"));
/* Fix up syms, so that st_value is a pointer to location. */ /* 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) if (err < 0)
goto cleanup; goto cleanup;
...@@ -1300,8 +1334,7 @@ static struct module *load_module(void __user *umod, ...@@ -1300,8 +1334,7 @@ static struct module *load_module(void __user *umod,
for (i = 1; i < hdr->e_shnum; i++) { for (i = 1; i < hdr->e_shnum; i++) {
const char *strtab = (char *)sechdrs[strindex].sh_addr; const char *strtab = (char *)sechdrs[strindex].sh_addr;
if (sechdrs[i].sh_type == SHT_REL) if (sechdrs[i].sh_type == SHT_REL)
err = apply_relocate(sechdrs, strtab, symindex, i, err = apply_relocate(sechdrs, strtab, symindex, i,mod);
mod);
else if (sechdrs[i].sh_type == SHT_RELA) else if (sechdrs[i].sh_type == SHT_RELA)
err = apply_relocate_add(sechdrs, strtab, symindex, i, err = apply_relocate_add(sechdrs, strtab, symindex, i,
mod); mod);
......
...@@ -404,9 +404,7 @@ add_header(struct buffer *b) ...@@ -404,9 +404,7 @@ add_header(struct buffer *b)
buf_printf(b, "#include <linux/vermagic.h>\n"); buf_printf(b, "#include <linux/vermagic.h>\n");
buf_printf(b, "#include <linux/compiler.h>\n"); buf_printf(b, "#include <linux/compiler.h>\n");
buf_printf(b, "\n"); buf_printf(b, "\n");
buf_printf(b, "const char vermagic[]\n"); buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
buf_printf(b, "__attribute__((section(\"__vermagic\"))) =\n");
buf_printf(b, "VERMAGIC_STRING;\n");
} }
/* Record CRCs for unresolved symbols */ /* Record CRCs for unresolved symbols */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment