diff options
| author | Jeff Garzik <jeff@garzik.org> | 2006-03-29 17:18:49 -0500 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2006-03-29 17:18:49 -0500 |
| commit | e02a4cabfcb9a999b74a2e2e6f13ffcb7ff2d606 (patch) | |
| tree | 2f3db60be4c57eca2a4c3ab3f3122dcf1ec0c624 /kernel/module.c | |
| parent | 600511e86babe3727264a0883a3a264f6fb6caf5 (diff) | |
| parent | f3cab8a0b1a772dc8b055b7affa567a366627c9e (diff) | |
Merge branch 'master'
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 205 |
1 files changed, 17 insertions, 188 deletions
diff --git a/kernel/module.c b/kernel/module.c index 54623c714bba..bd088a7c1499 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -64,26 +64,17 @@ static DEFINE_SPINLOCK(modlist_lock); | |||
| 64 | static DEFINE_MUTEX(module_mutex); | 64 | static DEFINE_MUTEX(module_mutex); |
| 65 | static LIST_HEAD(modules); | 65 | static LIST_HEAD(modules); |
| 66 | 66 | ||
| 67 | static DEFINE_MUTEX(notify_mutex); | 67 | static BLOCKING_NOTIFIER_HEAD(module_notify_list); |
| 68 | static struct notifier_block * module_notify_list; | ||
| 69 | 68 | ||
| 70 | int register_module_notifier(struct notifier_block * nb) | 69 | int register_module_notifier(struct notifier_block * nb) |
| 71 | { | 70 | { |
| 72 | int err; | 71 | return blocking_notifier_chain_register(&module_notify_list, nb); |
| 73 | mutex_lock(¬ify_mutex); | ||
| 74 | err = notifier_chain_register(&module_notify_list, nb); | ||
| 75 | mutex_unlock(¬ify_mutex); | ||
| 76 | return err; | ||
| 77 | } | 72 | } |
| 78 | EXPORT_SYMBOL(register_module_notifier); | 73 | EXPORT_SYMBOL(register_module_notifier); |
| 79 | 74 | ||
| 80 | int unregister_module_notifier(struct notifier_block * nb) | 75 | int unregister_module_notifier(struct notifier_block * nb) |
| 81 | { | 76 | { |
| 82 | int err; | 77 | return blocking_notifier_chain_unregister(&module_notify_list, nb); |
| 83 | mutex_lock(¬ify_mutex); | ||
| 84 | err = notifier_chain_unregister(&module_notify_list, nb); | ||
| 85 | mutex_unlock(¬ify_mutex); | ||
| 86 | return err; | ||
| 87 | } | 78 | } |
| 88 | EXPORT_SYMBOL(unregister_module_notifier); | 79 | EXPORT_SYMBOL(unregister_module_notifier); |
| 89 | 80 | ||
| @@ -136,7 +127,7 @@ extern const unsigned long __start___kcrctab_gpl_future[]; | |||
| 136 | #ifndef CONFIG_MODVERSIONS | 127 | #ifndef CONFIG_MODVERSIONS |
| 137 | #define symversion(base, idx) NULL | 128 | #define symversion(base, idx) NULL |
| 138 | #else | 129 | #else |
| 139 | #define symversion(base, idx) ((base) ? ((base) + (idx)) : NULL) | 130 | #define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL) |
| 140 | #endif | 131 | #endif |
| 141 | 132 | ||
| 142 | /* lookup symbol in given range of kernel_symbols */ | 133 | /* lookup symbol in given range of kernel_symbols */ |
| @@ -233,24 +224,6 @@ static unsigned long __find_symbol(const char *name, | |||
| 233 | return 0; | 224 | return 0; |
| 234 | } | 225 | } |
| 235 | 226 | ||
| 236 | /* Find a symbol in this elf symbol table */ | ||
| 237 | static unsigned long find_local_symbol(Elf_Shdr *sechdrs, | ||
| 238 | unsigned int symindex, | ||
| 239 | const char *strtab, | ||
| 240 | const char *name) | ||
| 241 | { | ||
| 242 | unsigned int i; | ||
| 243 | Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr; | ||
| 244 | |||
| 245 | /* Search (defined) internal symbols first. */ | ||
| 246 | for (i = 1; i < sechdrs[symindex].sh_size/sizeof(*sym); i++) { | ||
| 247 | if (sym[i].st_shndx != SHN_UNDEF | ||
| 248 | && strcmp(name, strtab + sym[i].st_name) == 0) | ||
| 249 | return sym[i].st_value; | ||
| 250 | } | ||
| 251 | return 0; | ||
| 252 | } | ||
| 253 | |||
| 254 | /* Search for module by name: must hold module_mutex. */ | 227 | /* Search for module by name: must hold module_mutex. */ |
| 255 | static struct module *find_module(const char *name) | 228 | static struct module *find_module(const char *name) |
| 256 | { | 229 | { |
| @@ -785,139 +758,6 @@ static struct module_attribute *modinfo_attrs[] = { | |||
| 785 | NULL, | 758 | NULL, |
| 786 | }; | 759 | }; |
| 787 | 760 | ||
| 788 | #ifdef CONFIG_OBSOLETE_MODPARM | ||
| 789 | /* Bounds checking done below */ | ||
| 790 | static int obsparm_copy_string(const char *val, struct kernel_param *kp) | ||
| 791 | { | ||
| 792 | strcpy(kp->arg, val); | ||
| 793 | return 0; | ||
| 794 | } | ||
| 795 | |||
| 796 | static int set_obsolete(const char *val, struct kernel_param *kp) | ||
| 797 | { | ||
| 798 | unsigned int min, max; | ||
| 799 | unsigned int size, maxsize; | ||
| 800 | int dummy; | ||
| 801 | char *endp; | ||
| 802 | const char *p; | ||
| 803 | struct obsolete_modparm *obsparm = kp->arg; | ||
| 804 | |||
| 805 | if (!val) { | ||
| 806 | printk(KERN_ERR "Parameter %s needs an argument\n", kp->name); | ||
| 807 | return -EINVAL; | ||
| 808 | } | ||
| 809 | |||
| 810 | /* type is: [min[-max]]{b,h,i,l,s} */ | ||
| 811 | p = obsparm->type; | ||
| 812 | min = simple_strtol(p, &endp, 10); | ||
| 813 | if (endp == obsparm->type) | ||
| 814 | min = max = 1; | ||
| 815 | else if (*endp == '-') { | ||
| 816 | p = endp+1; | ||
| 817 | max = simple_strtol(p, &endp, 10); | ||
| 818 | } else | ||
| 819 | max = min; | ||
| 820 | switch (*endp) { | ||
| 821 | case 'b': | ||
| 822 | return param_array(kp->name, val, min, max, obsparm->addr, | ||
| 823 | 1, param_set_byte, &dummy); | ||
| 824 | case 'h': | ||
| 825 | return param_array(kp->name, val, min, max, obsparm->addr, | ||
| 826 | sizeof(short), param_set_short, &dummy); | ||
| 827 | case 'i': | ||
| 828 | return param_array(kp->name, val, min, max, obsparm->addr, | ||
| 829 | sizeof(int), param_set_int, &dummy); | ||
| 830 | case 'l': | ||
| 831 | return param_array(kp->name, val, min, max, obsparm->addr, | ||
| 832 | sizeof(long), param_set_long, &dummy); | ||
| 833 | case 's': | ||
| 834 | return param_array(kp->name, val, min, max, obsparm->addr, | ||
| 835 | sizeof(char *), param_set_charp, &dummy); | ||
| 836 | |||
| 837 | case 'c': | ||
| 838 | /* Undocumented: 1-5c50 means 1-5 strings of up to 49 chars, | ||
| 839 | and the decl is "char xxx[5][50];" */ | ||
| 840 | p = endp+1; | ||
| 841 | maxsize = simple_strtol(p, &endp, 10); | ||
| 842 | /* We check lengths here (yes, this is a hack). */ | ||
| 843 | p = val; | ||
| 844 | while (p[size = strcspn(p, ",")]) { | ||
| 845 | if (size >= maxsize) | ||
| 846 | goto oversize; | ||
| 847 | p += size+1; | ||
| 848 | } | ||
| 849 | if (size >= maxsize) | ||
| 850 | goto oversize; | ||
| 851 | return param_array(kp->name, val, min, max, obsparm->addr, | ||
| 852 | maxsize, obsparm_copy_string, &dummy); | ||
| 853 | } | ||
| 854 | printk(KERN_ERR "Unknown obsolete parameter type %s\n", obsparm->type); | ||
| 855 | return -EINVAL; | ||
| 856 | oversize: | ||
| 857 | printk(KERN_ERR | ||
| 858 | "Parameter %s doesn't fit in %u chars.\n", kp->name, maxsize); | ||
| 859 | return -EINVAL; | ||
| 860 | } | ||
| 861 | |||
| 862 | static int obsolete_params(const char *name, | ||
| 863 | char *args, | ||
| 864 | struct obsolete_modparm obsparm[], | ||
| 865 | unsigned int num, | ||
| 866 | Elf_Shdr *sechdrs, | ||
| 867 | unsigned int symindex, | ||
| 868 | const char *strtab) | ||
| 869 | { | ||
| 870 | struct kernel_param *kp; | ||
| 871 | unsigned int i; | ||
| 872 | int ret; | ||
| 873 | |||
| 874 | kp = kmalloc(sizeof(kp[0]) * num, GFP_KERNEL); | ||
| 875 | if (!kp) | ||
| 876 | return -ENOMEM; | ||
| 877 | |||
| 878 | for (i = 0; i < num; i++) { | ||
| 879 | char sym_name[128 + sizeof(MODULE_SYMBOL_PREFIX)]; | ||
| 880 | |||
| 881 | snprintf(sym_name, sizeof(sym_name), "%s%s", | ||
| 882 | MODULE_SYMBOL_PREFIX, obsparm[i].name); | ||
| 883 | |||
| 884 | kp[i].name = obsparm[i].name; | ||
| 885 | kp[i].perm = 000; | ||
| 886 | kp[i].set = set_obsolete; | ||
| 887 | kp[i].get = NULL; | ||
| 888 | obsparm[i].addr | ||
| 889 | = (void *)find_local_symbol(sechdrs, symindex, strtab, | ||
| 890 | sym_name); | ||
| 891 | if (!obsparm[i].addr) { | ||
| 892 | printk("%s: falsely claims to have parameter %s\n", | ||
| 893 | name, obsparm[i].name); | ||
| 894 | ret = -EINVAL; | ||
| 895 | goto out; | ||
| 896 | } | ||
| 897 | kp[i].arg = &obsparm[i]; | ||
| 898 | } | ||
| 899 | |||
| 900 | ret = parse_args(name, args, kp, num, NULL); | ||
| 901 | out: | ||
| 902 | kfree(kp); | ||
| 903 | return ret; | ||
| 904 | } | ||
| 905 | #else | ||
| 906 | static int obsolete_params(const char *name, | ||
| 907 | char *args, | ||
| 908 | struct obsolete_modparm obsparm[], | ||
| 909 | unsigned int num, | ||
| 910 | Elf_Shdr *sechdrs, | ||
| 911 | unsigned int symindex, | ||
| 912 | const char *strtab) | ||
| 913 | { | ||
| 914 | if (num != 0) | ||
| 915 | printk(KERN_WARNING "%s: Ignoring obsolete parameters\n", | ||
| 916 | name); | ||
| 917 | return 0; | ||
| 918 | } | ||
| 919 | #endif /* CONFIG_OBSOLETE_MODPARM */ | ||
| 920 | |||
| 921 | static const char vermagic[] = VERMAGIC_STRING; | 761 | static const char vermagic[] = VERMAGIC_STRING; |
| 922 | 762 | ||
| 923 | #ifdef CONFIG_MODVERSIONS | 763 | #ifdef CONFIG_MODVERSIONS |
| @@ -1874,27 +1714,17 @@ static struct module *load_module(void __user *umod, | |||
| 1874 | set_fs(old_fs); | 1714 | set_fs(old_fs); |
| 1875 | 1715 | ||
| 1876 | mod->args = args; | 1716 | mod->args = args; |
| 1877 | if (obsparmindex) { | 1717 | if (obsparmindex) |
| 1878 | err = obsolete_params(mod->name, mod->args, | 1718 | printk(KERN_WARNING "%s: Ignoring obsolete parameters\n", |
| 1879 | (struct obsolete_modparm *) | 1719 | mod->name); |
| 1880 | sechdrs[obsparmindex].sh_addr, | 1720 | |
| 1881 | sechdrs[obsparmindex].sh_size | 1721 | /* Size of section 0 is 0, so this works well if no params */ |
| 1882 | / sizeof(struct obsolete_modparm), | 1722 | err = parse_args(mod->name, mod->args, |
| 1883 | sechdrs, symindex, | 1723 | (struct kernel_param *) |
| 1884 | (char *)sechdrs[strindex].sh_addr); | 1724 | sechdrs[setupindex].sh_addr, |
| 1885 | if (setupindex) | 1725 | sechdrs[setupindex].sh_size |
| 1886 | printk(KERN_WARNING "%s: Ignoring new-style " | 1726 | / sizeof(struct kernel_param), |
| 1887 | "parameters in presence of obsolete ones\n", | 1727 | NULL); |
| 1888 | mod->name); | ||
| 1889 | } else { | ||
| 1890 | /* Size of section 0 is 0, so this works well if no params */ | ||
| 1891 | err = parse_args(mod->name, mod->args, | ||
| 1892 | (struct kernel_param *) | ||
| 1893 | sechdrs[setupindex].sh_addr, | ||
| 1894 | sechdrs[setupindex].sh_size | ||
| 1895 | / sizeof(struct kernel_param), | ||
| 1896 | NULL); | ||
| 1897 | } | ||
| 1898 | if (err < 0) | 1728 | if (err < 0) |
| 1899 | goto arch_cleanup; | 1729 | goto arch_cleanup; |
| 1900 | 1730 | ||
| @@ -1977,9 +1807,8 @@ sys_init_module(void __user *umod, | |||
| 1977 | /* Drop lock so they can recurse */ | 1807 | /* Drop lock so they can recurse */ |
| 1978 | mutex_unlock(&module_mutex); | 1808 | mutex_unlock(&module_mutex); |
| 1979 | 1809 | ||
| 1980 | mutex_lock(¬ify_mutex); | 1810 | blocking_notifier_call_chain(&module_notify_list, |
| 1981 | notifier_call_chain(&module_notify_list, MODULE_STATE_COMING, mod); | 1811 | MODULE_STATE_COMING, mod); |
| 1982 | mutex_unlock(¬ify_mutex); | ||
| 1983 | 1812 | ||
| 1984 | /* Start the module */ | 1813 | /* Start the module */ |
| 1985 | if (mod->init != NULL) | 1814 | if (mod->init != NULL) |
