From: Rusty Russell Restores .modinfo section, and uses it to store license and vermagic. include/linux/module.h | 46 +++++++++++++++---------- kernel/module.c | 87 +++++++++++++++++++++++++++++++++---------------- scripts/modpost.c | 4 -- 3 files changed, 89 insertions(+), 48 deletions(-) diff -puN include/linux/module.h~restore-modinfo-section include/linux/module.h --- 25/include/linux/module.h~restore-modinfo-section 2003-04-29 20:51:22.000000000 -0700 +++ 25-akpm/include/linux/module.h 2003-04-29 20:51:25.000000000 -0700 @@ -20,10 +20,7 @@ #include /* 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_ta 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_##g #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_##g * 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 - -#else /* !MODULE */ +#define MODULE_LICENSE(_license) MODULE_INFO(license, _license) -#define MODULE_ALIAS(alias) -#define MODULE_GENERIC_TABLE(gtype,name) -#define THIS_MODULE ((struct module *)0) -#define MODULE_LICENSE(license) -#endif +/* Author, ideally of form NAME [, NAME ]*[ and NAME ] */ +#define MODULE_AUTHOR(_author) MODULE_INFO(author, _author) + +/* 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) diff -puN kernel/module.c~restore-modinfo-section kernel/module.c --- 25/kernel/module.c~restore-modinfo-section 2003-04-29 20:51:22.000000000 -0700 +++ 25-akpm/kernel/module.c 2003-04-29 20:51:25.000000000 -0700 @@ -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_compati || 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 *m } } +/* 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 _ { 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 _ /* 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 _ 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 _ #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 _ 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 _ 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 _ /* 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 _ 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); diff -puN scripts/modpost.c~restore-modinfo-section scripts/modpost.c --- 25/scripts/modpost.c~restore-modinfo-section 2003-04-29 20:51:22.000000000 -0700 +++ 25-akpm/scripts/modpost.c 2003-04-29 20:51:22.000000000 -0700 @@ -404,9 +404,7 @@ add_header(struct buffer *b) buf_printf(b, "#include \n"); buf_printf(b, "#include \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 */ _