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 @@
#include <asm/module.h>
/* Not Yet Implemented */
#define MODULE_AUTHOR(name)
#define MODULE_DESCRIPTION(desc)
#define MODULE_SUPPORTED_DEVICE(name)
#define MODULE_PARM_DESC(var,desc)
#define print_modules()
/* v850 toolchain uses a `_' prefix for all user symbols */
......@@ -58,12 +55,11 @@ search_extable(const struct exception_table_entry *first,
unsigned long value);
#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)
/* For userspace: you can also call me... */
#define MODULE_ALIAS(alias) \
static const char __module_cat(__alias_,__LINE__)[] \
__attribute__((section(".modinfo"),unused)) = "alias=" alias
#define __MODULE_INFO(tag, name, info) \
static const char __module_cat(name,__LINE__)[] \
__attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info
#define MODULE_GENERIC_TABLE(gtype,name) \
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)
#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
* software modules
......@@ -97,17 +106,18 @@ extern const struct gtype##_id __mod_##gtype##_table \
* 2. So the community can ignore bug reports including proprietary modules
* 3. So vendors can do likewise based on their own policies
*/
#define MODULE_LICENSE(license) \
static const char __module_license[] \
__attribute__((section(".init.license"), unused)) = license
#define MODULE_LICENSE(_license) MODULE_INFO(license, _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)
#define MODULE_GENERIC_TABLE(gtype,name)
#define THIS_MODULE ((struct module *)0)
#define MODULE_LICENSE(license)
#endif
/* What your module does. */
#define MODULE_DESCRIPTION(_description) MODULE_INFO(description, _description)
/* One for each parameter, describing how to use it. Some files do
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) \
MODULE_GENERIC_TABLE(type##_device,name)
......
......@@ -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);
......
......@@ -404,9 +404,7 @@ add_header(struct buffer *b)
buf_printf(b, "#include <linux/vermagic.h>\n");
buf_printf(b, "#include <linux/compiler.h>\n");
buf_printf(b, "\n");
buf_printf(b, "const char vermagic[]\n");
buf_printf(b, "__attribute__((section(\"__vermagic\"))) =\n");
buf_printf(b, "VERMAGIC_STRING;\n");
buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
}
/* 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