diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 198 | 
1 files changed, 167 insertions, 31 deletions
diff --git a/kernel/module.c b/kernel/module.c index bbe04862e1b0..05625d5dc758 100644 --- a/kernel/module.c +++ b/kernel/module.c  | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Rewritten by Rusty Russell, on the backs of many others... | 1 | /* | 
| 2 | Copyright (C) 2002 Richard Henderson | 2 | Copyright (C) 2002 Richard Henderson | 
| 3 | Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM. | 3 | Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM. | 
| 4 | 4 | ||
| @@ -16,7 +16,6 @@ | |||
| 16 | along with this program; if not, write to the Free Software | 16 | along with this program; if not, write to the Free Software | 
| 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 
| 18 | */ | 18 | */ | 
| 19 | #include <linux/config.h> | ||
| 20 | #include <linux/module.h> | 19 | #include <linux/module.h> | 
| 21 | #include <linux/moduleloader.h> | 20 | #include <linux/moduleloader.h> | 
| 22 | #include <linux/init.h> | 21 | #include <linux/init.h> | 
| @@ -40,9 +39,11 @@ | |||
| 40 | #include <linux/string.h> | 39 | #include <linux/string.h> | 
| 41 | #include <linux/sched.h> | 40 | #include <linux/sched.h> | 
| 42 | #include <linux/mutex.h> | 41 | #include <linux/mutex.h> | 
| 42 | #include <linux/unwind.h> | ||
| 43 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> | 
| 44 | #include <asm/semaphore.h> | 44 | #include <asm/semaphore.h> | 
| 45 | #include <asm/cacheflush.h> | 45 | #include <asm/cacheflush.h> | 
| 46 | #include <linux/license.h> | ||
| 46 | 47 | ||
| 47 | #if 0 | 48 | #if 0 | 
| 48 | #define DEBUGP printk | 49 | #define DEBUGP printk | 
| @@ -120,9 +121,17 @@ extern const struct kernel_symbol __start___ksymtab_gpl[]; | |||
| 120 | extern const struct kernel_symbol __stop___ksymtab_gpl[]; | 121 | extern const struct kernel_symbol __stop___ksymtab_gpl[]; | 
| 121 | extern const struct kernel_symbol __start___ksymtab_gpl_future[]; | 122 | extern const struct kernel_symbol __start___ksymtab_gpl_future[]; | 
| 122 | extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; | 123 | extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; | 
| 124 | extern const struct kernel_symbol __start___ksymtab_unused[]; | ||
| 125 | extern const struct kernel_symbol __stop___ksymtab_unused[]; | ||
| 126 | extern const struct kernel_symbol __start___ksymtab_unused_gpl[]; | ||
| 127 | extern const struct kernel_symbol __stop___ksymtab_unused_gpl[]; | ||
| 128 | extern const struct kernel_symbol __start___ksymtab_gpl_future[]; | ||
| 129 | extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; | ||
| 123 | extern const unsigned long __start___kcrctab[]; | 130 | extern const unsigned long __start___kcrctab[]; | 
| 124 | extern const unsigned long __start___kcrctab_gpl[]; | 131 | extern const unsigned long __start___kcrctab_gpl[]; | 
| 125 | extern const unsigned long __start___kcrctab_gpl_future[]; | 132 | extern const unsigned long __start___kcrctab_gpl_future[]; | 
| 133 | extern const unsigned long __start___kcrctab_unused[]; | ||
| 134 | extern const unsigned long __start___kcrctab_unused_gpl[]; | ||
| 126 | 135 | ||
| 127 | #ifndef CONFIG_MODVERSIONS | 136 | #ifndef CONFIG_MODVERSIONS | 
| 128 | #define symversion(base, idx) NULL | 137 | #define symversion(base, idx) NULL | 
| @@ -142,6 +151,17 @@ static const struct kernel_symbol *lookup_symbol(const char *name, | |||
| 142 | return NULL; | 151 | return NULL; | 
| 143 | } | 152 | } | 
| 144 | 153 | ||
| 154 | static void printk_unused_warning(const char *name) | ||
| 155 | { | ||
| 156 | printk(KERN_WARNING "Symbol %s is marked as UNUSED, " | ||
| 157 | "however this module is using it.\n", name); | ||
| 158 | printk(KERN_WARNING "This symbol will go away in the future.\n"); | ||
| 159 | printk(KERN_WARNING "Please evalute if this is the right api to use, " | ||
| 160 | "and if it really is, submit a report the linux kernel " | ||
| 161 | "mailinglist together with submitting your code for " | ||
| 162 | "inclusion.\n"); | ||
| 163 | } | ||
| 164 | |||
| 145 | /* Find a symbol, return value, crc and module which owns it */ | 165 | /* Find a symbol, return value, crc and module which owns it */ | 
| 146 | static unsigned long __find_symbol(const char *name, | 166 | static unsigned long __find_symbol(const char *name, | 
| 147 | struct module **owner, | 167 | struct module **owner, | 
| @@ -184,6 +204,25 @@ static unsigned long __find_symbol(const char *name, | |||
| 184 | return ks->value; | 204 | return ks->value; | 
| 185 | } | 205 | } | 
| 186 | 206 | ||
| 207 | ks = lookup_symbol(name, __start___ksymtab_unused, | ||
| 208 | __stop___ksymtab_unused); | ||
| 209 | if (ks) { | ||
| 210 | printk_unused_warning(name); | ||
| 211 | *crc = symversion(__start___kcrctab_unused, | ||
| 212 | (ks - __start___ksymtab_unused)); | ||
| 213 | return ks->value; | ||
| 214 | } | ||
| 215 | |||
| 216 | if (gplok) | ||
| 217 | ks = lookup_symbol(name, __start___ksymtab_unused_gpl, | ||
| 218 | __stop___ksymtab_unused_gpl); | ||
| 219 | if (ks) { | ||
| 220 | printk_unused_warning(name); | ||
| 221 | *crc = symversion(__start___kcrctab_unused_gpl, | ||
| 222 | (ks - __start___ksymtab_unused_gpl)); | ||
| 223 | return ks->value; | ||
| 224 | } | ||
| 225 | |||
| 187 | /* Now try modules. */ | 226 | /* Now try modules. */ | 
| 188 | list_for_each_entry(mod, &modules, list) { | 227 | list_for_each_entry(mod, &modules, list) { | 
| 189 | *owner = mod; | 228 | *owner = mod; | 
| @@ -202,6 +241,23 @@ static unsigned long __find_symbol(const char *name, | |||
| 202 | return ks->value; | 241 | return ks->value; | 
| 203 | } | 242 | } | 
| 204 | } | 243 | } | 
| 244 | ks = lookup_symbol(name, mod->unused_syms, mod->unused_syms + mod->num_unused_syms); | ||
| 245 | if (ks) { | ||
| 246 | printk_unused_warning(name); | ||
| 247 | *crc = symversion(mod->unused_crcs, (ks - mod->unused_syms)); | ||
| 248 | return ks->value; | ||
| 249 | } | ||
| 250 | |||
| 251 | if (gplok) { | ||
| 252 | ks = lookup_symbol(name, mod->unused_gpl_syms, | ||
| 253 | mod->unused_gpl_syms + mod->num_unused_gpl_syms); | ||
| 254 | if (ks) { | ||
| 255 | printk_unused_warning(name); | ||
| 256 | *crc = symversion(mod->unused_gpl_crcs, | ||
| 257 | (ks - mod->unused_gpl_syms)); | ||
| 258 | return ks->value; | ||
| 259 | } | ||
| 260 | } | ||
| 205 | ks = lookup_symbol(name, mod->gpl_future_syms, | 261 | ks = lookup_symbol(name, mod->gpl_future_syms, | 
| 206 | (mod->gpl_future_syms + | 262 | (mod->gpl_future_syms + | 
| 207 | mod->num_gpl_future_syms)); | 263 | mod->num_gpl_future_syms)); | 
| @@ -877,6 +933,15 @@ static ssize_t module_sect_show(struct module_attribute *mattr, | |||
| 877 | return sprintf(buf, "0x%lx\n", sattr->address); | 933 | return sprintf(buf, "0x%lx\n", sattr->address); | 
| 878 | } | 934 | } | 
| 879 | 935 | ||
| 936 | static void free_sect_attrs(struct module_sect_attrs *sect_attrs) | ||
| 937 | { | ||
| 938 | int section; | ||
| 939 | |||
| 940 | for (section = 0; section < sect_attrs->nsections; section++) | ||
| 941 | kfree(sect_attrs->attrs[section].name); | ||
| 942 | kfree(sect_attrs); | ||
| 943 | } | ||
| 944 | |||
| 880 | static void add_sect_attrs(struct module *mod, unsigned int nsect, | 945 | static void add_sect_attrs(struct module *mod, unsigned int nsect, | 
| 881 | char *secstrings, Elf_Shdr *sechdrs) | 946 | char *secstrings, Elf_Shdr *sechdrs) | 
| 882 | { | 947 | { | 
| @@ -893,21 +958,26 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect, | |||
| 893 | + nloaded * sizeof(sect_attrs->attrs[0]), | 958 | + nloaded * sizeof(sect_attrs->attrs[0]), | 
| 894 | sizeof(sect_attrs->grp.attrs[0])); | 959 | sizeof(sect_attrs->grp.attrs[0])); | 
| 895 | size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.attrs[0]); | 960 | size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.attrs[0]); | 
| 896 | if (! (sect_attrs = kmalloc(size[0] + size[1], GFP_KERNEL))) | 961 | sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL); | 
| 962 | if (sect_attrs == NULL) | ||
| 897 | return; | 963 | return; | 
| 898 | 964 | ||
| 899 | /* Setup section attributes. */ | 965 | /* Setup section attributes. */ | 
| 900 | sect_attrs->grp.name = "sections"; | 966 | sect_attrs->grp.name = "sections"; | 
| 901 | sect_attrs->grp.attrs = (void *)sect_attrs + size[0]; | 967 | sect_attrs->grp.attrs = (void *)sect_attrs + size[0]; | 
| 902 | 968 | ||
| 969 | sect_attrs->nsections = 0; | ||
| 903 | sattr = §_attrs->attrs[0]; | 970 | sattr = §_attrs->attrs[0]; | 
| 904 | gattr = §_attrs->grp.attrs[0]; | 971 | gattr = §_attrs->grp.attrs[0]; | 
| 905 | for (i = 0; i < nsect; i++) { | 972 | for (i = 0; i < nsect; i++) { | 
| 906 | if (! (sechdrs[i].sh_flags & SHF_ALLOC)) | 973 | if (! (sechdrs[i].sh_flags & SHF_ALLOC)) | 
| 907 | continue; | 974 | continue; | 
| 908 | sattr->address = sechdrs[i].sh_addr; | 975 | sattr->address = sechdrs[i].sh_addr; | 
| 909 | strlcpy(sattr->name, secstrings + sechdrs[i].sh_name, | 976 | sattr->name = kstrdup(secstrings + sechdrs[i].sh_name, | 
| 910 | MODULE_SECT_NAME_LEN); | 977 | GFP_KERNEL); | 
| 978 | if (sattr->name == NULL) | ||
| 979 | goto out; | ||
| 980 | sect_attrs->nsections++; | ||
| 911 | sattr->mattr.show = module_sect_show; | 981 | sattr->mattr.show = module_sect_show; | 
| 912 | sattr->mattr.store = NULL; | 982 | sattr->mattr.store = NULL; | 
| 913 | sattr->mattr.attr.name = sattr->name; | 983 | sattr->mattr.attr.name = sattr->name; | 
| @@ -923,7 +993,7 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect, | |||
| 923 | mod->sect_attrs = sect_attrs; | 993 | mod->sect_attrs = sect_attrs; | 
| 924 | return; | 994 | return; | 
| 925 | out: | 995 | out: | 
| 926 | kfree(sect_attrs); | 996 | free_sect_attrs(sect_attrs); | 
| 927 | } | 997 | } | 
| 928 | 998 | ||
| 929 | static void remove_sect_attrs(struct module *mod) | 999 | static void remove_sect_attrs(struct module *mod) | 
| @@ -933,13 +1003,13 @@ static void remove_sect_attrs(struct module *mod) | |||
| 933 | &mod->sect_attrs->grp); | 1003 | &mod->sect_attrs->grp); | 
| 934 | /* We are positive that no one is using any sect attrs | 1004 | /* We are positive that no one is using any sect attrs | 
| 935 | * at this point. Deallocate immediately. */ | 1005 | * at this point. Deallocate immediately. */ | 
| 936 | kfree(mod->sect_attrs); | 1006 | free_sect_attrs(mod->sect_attrs); | 
| 937 | mod->sect_attrs = NULL; | 1007 | mod->sect_attrs = NULL; | 
| 938 | } | 1008 | } | 
| 939 | } | 1009 | } | 
| 940 | 1010 | ||
| 941 | |||
| 942 | #else | 1011 | #else | 
| 1012 | |||
| 943 | static inline void add_sect_attrs(struct module *mod, unsigned int nsect, | 1013 | static inline void add_sect_attrs(struct module *mod, unsigned int nsect, | 
| 944 | char *sectstrings, Elf_Shdr *sechdrs) | 1014 | char *sectstrings, Elf_Shdr *sechdrs) | 
| 945 | { | 1015 | { | 
| @@ -998,6 +1068,12 @@ static int mod_sysfs_setup(struct module *mod, | |||
| 998 | { | 1068 | { | 
| 999 | int err; | 1069 | int err; | 
| 1000 | 1070 | ||
| 1071 | if (!module_subsys.kset.subsys) { | ||
| 1072 | printk(KERN_ERR "%s: module_subsys not initialized\n", | ||
| 1073 | mod->name); | ||
| 1074 | err = -EINVAL; | ||
| 1075 | goto out; | ||
| 1076 | } | ||
| 1001 | memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj)); | 1077 | memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj)); | 
| 1002 | err = kobject_set_name(&mod->mkobj.kobj, "%s", mod->name); | 1078 | err = kobject_set_name(&mod->mkobj.kobj, "%s", mod->name); | 
| 1003 | if (err) | 1079 | if (err) | 
| @@ -1051,6 +1127,8 @@ static void free_module(struct module *mod) | |||
| 1051 | remove_sect_attrs(mod); | 1127 | remove_sect_attrs(mod); | 
| 1052 | mod_kobject_remove(mod); | 1128 | mod_kobject_remove(mod); | 
| 1053 | 1129 | ||
| 1130 | unwind_remove_table(mod->unwind_info, 0); | ||
| 1131 | |||
| 1054 | /* Arch-specific cleanup. */ | 1132 | /* Arch-specific cleanup. */ | 
| 1055 | module_arch_cleanup(mod); | 1133 | module_arch_cleanup(mod); | 
| 1056 | 1134 | ||
| @@ -1063,6 +1141,9 @@ static void free_module(struct module *mod) | |||
| 1063 | if (mod->percpu) | 1141 | if (mod->percpu) | 
| 1064 | percpu_modfree(mod->percpu); | 1142 | percpu_modfree(mod->percpu); | 
| 1065 | 1143 | ||
| 1144 | /* Free lock-classes: */ | ||
| 1145 | lockdep_free_key_range(mod->module_core, mod->core_size); | ||
| 1146 | |||
| 1066 | /* Finally, free the core (containing the module structure) */ | 1147 | /* Finally, free the core (containing the module structure) */ | 
| 1067 | module_free(mod, mod->module_core); | 1148 | module_free(mod, mod->module_core); | 
| 1068 | } | 1149 | } | 
| @@ -1248,16 +1329,6 @@ static void layout_sections(struct module *mod, | |||
| 1248 | } | 1329 | } | 
| 1249 | } | 1330 | } | 
| 1250 | 1331 | ||
| 1251 | static inline int license_is_gpl_compatible(const char *license) | ||
| 1252 | { | ||
| 1253 | return (strcmp(license, "GPL") == 0 | ||
| 1254 | || strcmp(license, "GPL v2") == 0 | ||
| 1255 | || strcmp(license, "GPL and additional rights") == 0 | ||
| 1256 | || strcmp(license, "Dual BSD/GPL") == 0 | ||
| 1257 | || strcmp(license, "Dual MIT/GPL") == 0 | ||
| 1258 | || strcmp(license, "Dual MPL/GPL") == 0); | ||
| 1259 | } | ||
| 1260 | |||
| 1261 | static void set_license(struct module *mod, const char *license) | 1332 | static void set_license(struct module *mod, const char *license) | 
| 1262 | { | 1333 | { | 
| 1263 | if (!license) | 1334 | if (!license) | 
| @@ -1326,7 +1397,7 @@ int is_exported(const char *name, const struct module *mod) | |||
| 1326 | if (!mod && lookup_symbol(name, __start___ksymtab, __stop___ksymtab)) | 1397 | if (!mod && lookup_symbol(name, __start___ksymtab, __stop___ksymtab)) | 
| 1327 | return 1; | 1398 | return 1; | 
| 1328 | else | 1399 | else | 
| 1329 | if (lookup_symbol(name, mod->syms, mod->syms + mod->num_syms)) | 1400 | if (mod && lookup_symbol(name, mod->syms, mod->syms + mod->num_syms)) | 
| 1330 | return 1; | 1401 | return 1; | 
| 1331 | else | 1402 | else | 
| 1332 | return 0; | 1403 | return 0; | 
| @@ -1409,10 +1480,27 @@ static struct module *load_module(void __user *umod, | |||
| 1409 | Elf_Ehdr *hdr; | 1480 | Elf_Ehdr *hdr; | 
| 1410 | Elf_Shdr *sechdrs; | 1481 | Elf_Shdr *sechdrs; | 
| 1411 | char *secstrings, *args, *modmagic, *strtab = NULL; | 1482 | char *secstrings, *args, *modmagic, *strtab = NULL; | 
| 1412 | unsigned int i, symindex = 0, strindex = 0, setupindex, exindex, | 1483 | unsigned int i; | 
| 1413 | exportindex, modindex, obsparmindex, infoindex, gplindex, | 1484 | unsigned int symindex = 0; | 
| 1414 | crcindex, gplcrcindex, versindex, pcpuindex, gplfutureindex, | 1485 | unsigned int strindex = 0; | 
| 1415 | gplfuturecrcindex; | 1486 | unsigned int setupindex; | 
| 1487 | unsigned int exindex; | ||
| 1488 | unsigned int exportindex; | ||
| 1489 | unsigned int modindex; | ||
| 1490 | unsigned int obsparmindex; | ||
| 1491 | unsigned int infoindex; | ||
| 1492 | unsigned int gplindex; | ||
| 1493 | unsigned int crcindex; | ||
| 1494 | unsigned int gplcrcindex; | ||
| 1495 | unsigned int versindex; | ||
| 1496 | unsigned int pcpuindex; | ||
| 1497 | unsigned int gplfutureindex; | ||
| 1498 | unsigned int gplfuturecrcindex; | ||
| 1499 | unsigned int unwindex = 0; | ||
| 1500 | unsigned int unusedindex; | ||
| 1501 | unsigned int unusedcrcindex; | ||
| 1502 | unsigned int unusedgplindex; | ||
| 1503 | unsigned int unusedgplcrcindex; | ||
| 1416 | struct module *mod; | 1504 | struct module *mod; | 
| 1417 | long err = 0; | 1505 | long err = 0; | 
| 1418 | void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ | 1506 | void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ | 
| @@ -1493,15 +1581,22 @@ static struct module *load_module(void __user *umod, | |||
| 1493 | exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab"); | 1581 | exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab"); | 
| 1494 | gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl"); | 1582 | gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl"); | 
| 1495 | gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future"); | 1583 | gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future"); | 
| 1584 | unusedindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused"); | ||
| 1585 | unusedgplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused_gpl"); | ||
| 1496 | crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab"); | 1586 | crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab"); | 
| 1497 | gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl"); | 1587 | gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl"); | 
| 1498 | gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future"); | 1588 | gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future"); | 
| 1589 | unusedcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused"); | ||
| 1590 | unusedgplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused_gpl"); | ||
| 1499 | setupindex = find_sec(hdr, sechdrs, secstrings, "__param"); | 1591 | setupindex = find_sec(hdr, sechdrs, secstrings, "__param"); | 
| 1500 | exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table"); | 1592 | exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table"); | 
| 1501 | obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm"); | 1593 | obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm"); | 
| 1502 | versindex = find_sec(hdr, sechdrs, secstrings, "__versions"); | 1594 | versindex = find_sec(hdr, sechdrs, secstrings, "__versions"); | 
| 1503 | infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo"); | 1595 | infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo"); | 
| 1504 | pcpuindex = find_pcpusec(hdr, sechdrs, secstrings); | 1596 | pcpuindex = find_pcpusec(hdr, sechdrs, secstrings); | 
| 1597 | #ifdef ARCH_UNWIND_SECTION_NAME | ||
| 1598 | unwindex = find_sec(hdr, sechdrs, secstrings, ARCH_UNWIND_SECTION_NAME); | ||
| 1599 | #endif | ||
| 1505 | 1600 | ||
| 1506 | /* Don't keep modinfo section */ | 1601 | /* Don't keep modinfo section */ | 
| 1507 | sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC; | 1602 | sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC; | 
| @@ -1510,6 +1605,8 @@ static struct module *load_module(void __user *umod, | |||
| 1510 | sechdrs[symindex].sh_flags |= SHF_ALLOC; | 1605 | sechdrs[symindex].sh_flags |= SHF_ALLOC; | 
| 1511 | sechdrs[strindex].sh_flags |= SHF_ALLOC; | 1606 | sechdrs[strindex].sh_flags |= SHF_ALLOC; | 
| 1512 | #endif | 1607 | #endif | 
| 1608 | if (unwindex) | ||
| 1609 | sechdrs[unwindex].sh_flags |= SHF_ALLOC; | ||
| 1513 | 1610 | ||
| 1514 | /* Check module struct version now, before we try to use module. */ | 1611 | /* Check module struct version now, before we try to use module. */ | 
| 1515 | if (!check_modstruct_version(sechdrs, versindex, mod)) { | 1612 | if (!check_modstruct_version(sechdrs, versindex, mod)) { | 
| @@ -1639,14 +1736,27 @@ static struct module *load_module(void __user *umod, | |||
| 1639 | mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr; | 1736 | mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr; | 
| 1640 | mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size / | 1737 | mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size / | 
| 1641 | sizeof(*mod->gpl_future_syms); | 1738 | sizeof(*mod->gpl_future_syms); | 
| 1739 | mod->num_unused_syms = sechdrs[unusedindex].sh_size / | ||
| 1740 | sizeof(*mod->unused_syms); | ||
| 1741 | mod->num_unused_gpl_syms = sechdrs[unusedgplindex].sh_size / | ||
| 1742 | sizeof(*mod->unused_gpl_syms); | ||
| 1642 | mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr; | 1743 | mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr; | 
| 1643 | if (gplfuturecrcindex) | 1744 | if (gplfuturecrcindex) | 
| 1644 | mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr; | 1745 | mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr; | 
| 1645 | 1746 | ||
| 1747 | mod->unused_syms = (void *)sechdrs[unusedindex].sh_addr; | ||
| 1748 | if (unusedcrcindex) | ||
| 1749 | mod->unused_crcs = (void *)sechdrs[unusedcrcindex].sh_addr; | ||
| 1750 | mod->unused_gpl_syms = (void *)sechdrs[unusedgplindex].sh_addr; | ||
| 1751 | if (unusedgplcrcindex) | ||
| 1752 | mod->unused_crcs = (void *)sechdrs[unusedgplcrcindex].sh_addr; | ||
| 1753 | |||
| 1646 | #ifdef CONFIG_MODVERSIONS | 1754 | #ifdef CONFIG_MODVERSIONS | 
| 1647 | if ((mod->num_syms && !crcindex) || | 1755 | if ((mod->num_syms && !crcindex) || | 
| 1648 | (mod->num_gpl_syms && !gplcrcindex) || | 1756 | (mod->num_gpl_syms && !gplcrcindex) || | 
| 1649 | (mod->num_gpl_future_syms && !gplfuturecrcindex)) { | 1757 | (mod->num_gpl_future_syms && !gplfuturecrcindex) || | 
| 1758 | (mod->num_unused_syms && !unusedcrcindex) || | ||
| 1759 | (mod->num_unused_gpl_syms && !unusedgplcrcindex)) { | ||
| 1650 | printk(KERN_WARNING "%s: No versions for exported symbols." | 1760 | printk(KERN_WARNING "%s: No versions for exported symbols." | 
| 1651 | " Tainting kernel.\n", mod->name); | 1761 | " Tainting kernel.\n", mod->name); | 
| 1652 | add_taint(TAINT_FORCED_MODULE); | 1762 | add_taint(TAINT_FORCED_MODULE); | 
| @@ -1738,6 +1848,11 @@ static struct module *load_module(void __user *umod, | |||
| 1738 | goto arch_cleanup; | 1848 | goto arch_cleanup; | 
| 1739 | add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); | 1849 | add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); | 
| 1740 | 1850 | ||
| 1851 | /* Size of section 0 is 0, so this works well if no unwind info. */ | ||
| 1852 | mod->unwind_info = unwind_add_table(mod, | ||
| 1853 | (void *)sechdrs[unwindex].sh_addr, | ||
| 1854 | sechdrs[unwindex].sh_size); | ||
| 1855 | |||
| 1741 | /* Get rid of temporary copy */ | 1856 | /* Get rid of temporary copy */ | 
| 1742 | vfree(hdr); | 1857 | vfree(hdr); | 
| 1743 | 1858 | ||
| @@ -1836,6 +1951,7 @@ sys_init_module(void __user *umod, | |||
| 1836 | mod->state = MODULE_STATE_LIVE; | 1951 | mod->state = MODULE_STATE_LIVE; | 
| 1837 | /* Drop initial reference. */ | 1952 | /* Drop initial reference. */ | 
| 1838 | module_put(mod); | 1953 | module_put(mod); | 
| 1954 | unwind_remove_table(mod->unwind_info, 1); | ||
| 1839 | module_free(mod, mod->module_init); | 1955 | module_free(mod, mod->module_init); | 
| 1840 | mod->module_init = NULL; | 1956 | mod->module_init = NULL; | 
| 1841 | mod->init_size = 0; | 1957 | mod->init_size = 0; | 
| @@ -1923,10 +2039,8 @@ const char *module_address_lookup(unsigned long addr, | |||
| 1923 | return NULL; | 2039 | return NULL; | 
| 1924 | } | 2040 | } | 
| 1925 | 2041 | ||
| 1926 | struct module *module_get_kallsym(unsigned int symnum, | 2042 | struct module *module_get_kallsym(unsigned int symnum, unsigned long *value, | 
| 1927 | unsigned long *value, | 2043 | char *type, char *name, size_t namelen) | 
| 1928 | char *type, | ||
| 1929 | char namebuf[128]) | ||
| 1930 | { | 2044 | { | 
| 1931 | struct module *mod; | 2045 | struct module *mod; | 
| 1932 | 2046 | ||
| @@ -1935,9 +2049,8 @@ struct module *module_get_kallsym(unsigned int symnum, | |||
| 1935 | if (symnum < mod->num_symtab) { | 2049 | if (symnum < mod->num_symtab) { | 
| 1936 | *value = mod->symtab[symnum].st_value; | 2050 | *value = mod->symtab[symnum].st_value; | 
| 1937 | *type = mod->symtab[symnum].st_info; | 2051 | *type = mod->symtab[symnum].st_info; | 
| 1938 | strncpy(namebuf, | 2052 | strlcpy(name, mod->strtab + mod->symtab[symnum].st_name, | 
| 1939 | mod->strtab + mod->symtab[symnum].st_name, | 2053 | namelen); | 
| 1940 | 127); | ||
| 1941 | mutex_unlock(&module_mutex); | 2054 | mutex_unlock(&module_mutex); | 
| 1942 | return mod; | 2055 | return mod; | 
| 1943 | } | 2056 | } | 
| @@ -2066,6 +2179,29 @@ const struct exception_table_entry *search_module_extables(unsigned long addr) | |||
| 2066 | return e; | 2179 | return e; | 
| 2067 | } | 2180 | } | 
| 2068 | 2181 | ||
| 2182 | /* | ||
| 2183 | * Is this a valid module address? | ||
| 2184 | */ | ||
| 2185 | int is_module_address(unsigned long addr) | ||
| 2186 | { | ||
| 2187 | unsigned long flags; | ||
| 2188 | struct module *mod; | ||
| 2189 | |||
| 2190 | spin_lock_irqsave(&modlist_lock, flags); | ||
| 2191 | |||
| 2192 | list_for_each_entry(mod, &modules, list) { | ||
| 2193 | if (within(addr, mod->module_core, mod->core_size)) { | ||
| 2194 | spin_unlock_irqrestore(&modlist_lock, flags); | ||
| 2195 | return 1; | ||
| 2196 | } | ||
| 2197 | } | ||
| 2198 | |||
| 2199 | spin_unlock_irqrestore(&modlist_lock, flags); | ||
| 2200 | |||
| 2201 | return 0; | ||
| 2202 | } | ||
| 2203 | |||
| 2204 | |||
| 2069 | /* Is this a valid kernel address? We don't grab the lock: we are oopsing. */ | 2205 | /* Is this a valid kernel address? We don't grab the lock: we are oopsing. */ | 
| 2070 | struct module *__module_text_address(unsigned long addr) | 2206 | struct module *__module_text_address(unsigned long addr) | 
| 2071 | { | 2207 | { | 
