diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 200 |
1 files changed, 103 insertions, 97 deletions
diff --git a/kernel/module.c b/kernel/module.c index 88cec1ddb1e3..3965511ae133 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -42,7 +42,6 @@ | |||
| 42 | #include <linux/vermagic.h> | 42 | #include <linux/vermagic.h> |
| 43 | #include <linux/notifier.h> | 43 | #include <linux/notifier.h> |
| 44 | #include <linux/sched.h> | 44 | #include <linux/sched.h> |
| 45 | #include <linux/stop_machine.h> | ||
| 46 | #include <linux/device.h> | 45 | #include <linux/device.h> |
| 47 | #include <linux/string.h> | 46 | #include <linux/string.h> |
| 48 | #include <linux/mutex.h> | 47 | #include <linux/mutex.h> |
| @@ -98,7 +97,7 @@ | |||
| 98 | * 1) List of modules (also safely readable with preempt_disable), | 97 | * 1) List of modules (also safely readable with preempt_disable), |
| 99 | * 2) module_use links, | 98 | * 2) module_use links, |
| 100 | * 3) module_addr_min/module_addr_max. | 99 | * 3) module_addr_min/module_addr_max. |
| 101 | * (delete uses stop_machine/add uses RCU list operations). */ | 100 | * (delete and add uses RCU list operations). */ |
| 102 | DEFINE_MUTEX(module_mutex); | 101 | DEFINE_MUTEX(module_mutex); |
| 103 | EXPORT_SYMBOL_GPL(module_mutex); | 102 | EXPORT_SYMBOL_GPL(module_mutex); |
| 104 | static LIST_HEAD(modules); | 103 | static LIST_HEAD(modules); |
| @@ -158,13 +157,13 @@ static BLOCKING_NOTIFIER_HEAD(module_notify_list); | |||
| 158 | * Protected by module_mutex. */ | 157 | * Protected by module_mutex. */ |
| 159 | static unsigned long module_addr_min = -1UL, module_addr_max = 0; | 158 | static unsigned long module_addr_min = -1UL, module_addr_max = 0; |
| 160 | 159 | ||
| 161 | int register_module_notifier(struct notifier_block * nb) | 160 | int register_module_notifier(struct notifier_block *nb) |
| 162 | { | 161 | { |
| 163 | return blocking_notifier_chain_register(&module_notify_list, nb); | 162 | return blocking_notifier_chain_register(&module_notify_list, nb); |
| 164 | } | 163 | } |
| 165 | EXPORT_SYMBOL(register_module_notifier); | 164 | EXPORT_SYMBOL(register_module_notifier); |
| 166 | 165 | ||
| 167 | int unregister_module_notifier(struct notifier_block * nb) | 166 | int unregister_module_notifier(struct notifier_block *nb) |
| 168 | { | 167 | { |
| 169 | return blocking_notifier_chain_unregister(&module_notify_list, nb); | 168 | return blocking_notifier_chain_unregister(&module_notify_list, nb); |
| 170 | } | 169 | } |
| @@ -628,18 +627,23 @@ static char last_unloaded_module[MODULE_NAME_LEN+1]; | |||
| 628 | 627 | ||
| 629 | EXPORT_TRACEPOINT_SYMBOL(module_get); | 628 | EXPORT_TRACEPOINT_SYMBOL(module_get); |
| 630 | 629 | ||
| 630 | /* MODULE_REF_BASE is the base reference count by kmodule loader. */ | ||
| 631 | #define MODULE_REF_BASE 1 | ||
| 632 | |||
| 631 | /* Init the unload section of the module. */ | 633 | /* Init the unload section of the module. */ |
| 632 | static int module_unload_init(struct module *mod) | 634 | static int module_unload_init(struct module *mod) |
| 633 | { | 635 | { |
| 634 | mod->refptr = alloc_percpu(struct module_ref); | 636 | /* |
| 635 | if (!mod->refptr) | 637 | * Initialize reference counter to MODULE_REF_BASE. |
| 636 | return -ENOMEM; | 638 | * refcnt == 0 means module is going. |
| 639 | */ | ||
| 640 | atomic_set(&mod->refcnt, MODULE_REF_BASE); | ||
| 637 | 641 | ||
| 638 | INIT_LIST_HEAD(&mod->source_list); | 642 | INIT_LIST_HEAD(&mod->source_list); |
| 639 | INIT_LIST_HEAD(&mod->target_list); | 643 | INIT_LIST_HEAD(&mod->target_list); |
| 640 | 644 | ||
| 641 | /* Hold reference count during initialization. */ | 645 | /* Hold reference count during initialization. */ |
| 642 | raw_cpu_write(mod->refptr->incs, 1); | 646 | atomic_inc(&mod->refcnt); |
| 643 | 647 | ||
| 644 | return 0; | 648 | return 0; |
| 645 | } | 649 | } |
| @@ -721,8 +725,6 @@ static void module_unload_free(struct module *mod) | |||
| 721 | kfree(use); | 725 | kfree(use); |
| 722 | } | 726 | } |
| 723 | mutex_unlock(&module_mutex); | 727 | mutex_unlock(&module_mutex); |
| 724 | |||
| 725 | free_percpu(mod->refptr); | ||
| 726 | } | 728 | } |
| 727 | 729 | ||
| 728 | #ifdef CONFIG_MODULE_FORCE_UNLOAD | 730 | #ifdef CONFIG_MODULE_FORCE_UNLOAD |
| @@ -740,60 +742,39 @@ static inline int try_force_unload(unsigned int flags) | |||
| 740 | } | 742 | } |
| 741 | #endif /* CONFIG_MODULE_FORCE_UNLOAD */ | 743 | #endif /* CONFIG_MODULE_FORCE_UNLOAD */ |
| 742 | 744 | ||
| 743 | struct stopref | 745 | /* Try to release refcount of module, 0 means success. */ |
| 746 | static int try_release_module_ref(struct module *mod) | ||
| 744 | { | 747 | { |
| 745 | struct module *mod; | 748 | int ret; |
| 746 | int flags; | ||
| 747 | int *forced; | ||
| 748 | }; | ||
| 749 | 749 | ||
| 750 | /* Whole machine is stopped with interrupts off when this runs. */ | 750 | /* Try to decrement refcnt which we set at loading */ |
| 751 | static int __try_stop_module(void *_sref) | 751 | ret = atomic_sub_return(MODULE_REF_BASE, &mod->refcnt); |
| 752 | { | 752 | BUG_ON(ret < 0); |
| 753 | struct stopref *sref = _sref; | 753 | if (ret) |
| 754 | /* Someone can put this right now, recover with checking */ | ||
| 755 | ret = atomic_add_unless(&mod->refcnt, MODULE_REF_BASE, 0); | ||
| 756 | |||
| 757 | return ret; | ||
| 758 | } | ||
| 754 | 759 | ||
| 760 | static int try_stop_module(struct module *mod, int flags, int *forced) | ||
| 761 | { | ||
| 755 | /* If it's not unused, quit unless we're forcing. */ | 762 | /* If it's not unused, quit unless we're forcing. */ |
| 756 | if (module_refcount(sref->mod) != 0) { | 763 | if (try_release_module_ref(mod) != 0) { |
| 757 | if (!(*sref->forced = try_force_unload(sref->flags))) | 764 | *forced = try_force_unload(flags); |
| 765 | if (!(*forced)) | ||
| 758 | return -EWOULDBLOCK; | 766 | return -EWOULDBLOCK; |
| 759 | } | 767 | } |
| 760 | 768 | ||
| 761 | /* Mark it as dying. */ | 769 | /* Mark it as dying. */ |
| 762 | sref->mod->state = MODULE_STATE_GOING; | 770 | mod->state = MODULE_STATE_GOING; |
| 763 | return 0; | ||
| 764 | } | ||
| 765 | 771 | ||
| 766 | static int try_stop_module(struct module *mod, int flags, int *forced) | 772 | return 0; |
| 767 | { | ||
| 768 | struct stopref sref = { mod, flags, forced }; | ||
| 769 | |||
| 770 | return stop_machine(__try_stop_module, &sref, NULL); | ||
| 771 | } | 773 | } |
| 772 | 774 | ||
| 773 | unsigned long module_refcount(struct module *mod) | 775 | unsigned long module_refcount(struct module *mod) |
| 774 | { | 776 | { |
| 775 | unsigned long incs = 0, decs = 0; | 777 | return (unsigned long)atomic_read(&mod->refcnt) - MODULE_REF_BASE; |
| 776 | int cpu; | ||
| 777 | |||
| 778 | for_each_possible_cpu(cpu) | ||
| 779 | decs += per_cpu_ptr(mod->refptr, cpu)->decs; | ||
| 780 | /* | ||
| 781 | * ensure the incs are added up after the decs. | ||
| 782 | * module_put ensures incs are visible before decs with smp_wmb. | ||
| 783 | * | ||
| 784 | * This 2-count scheme avoids the situation where the refcount | ||
| 785 | * for CPU0 is read, then CPU0 increments the module refcount, | ||
| 786 | * then CPU1 drops that refcount, then the refcount for CPU1 is | ||
| 787 | * read. We would record a decrement but not its corresponding | ||
| 788 | * increment so we would see a low count (disaster). | ||
| 789 | * | ||
| 790 | * Rare situation? But module_refcount can be preempted, and we | ||
| 791 | * might be tallying up 4096+ CPUs. So it is not impossible. | ||
| 792 | */ | ||
| 793 | smp_rmb(); | ||
| 794 | for_each_possible_cpu(cpu) | ||
| 795 | incs += per_cpu_ptr(mod->refptr, cpu)->incs; | ||
| 796 | return incs - decs; | ||
| 797 | } | 778 | } |
| 798 | EXPORT_SYMBOL(module_refcount); | 779 | EXPORT_SYMBOL(module_refcount); |
| 799 | 780 | ||
| @@ -877,8 +858,10 @@ static inline void print_unload_info(struct seq_file *m, struct module *mod) | |||
| 877 | 858 | ||
| 878 | seq_printf(m, " %lu ", module_refcount(mod)); | 859 | seq_printf(m, " %lu ", module_refcount(mod)); |
| 879 | 860 | ||
| 880 | /* Always include a trailing , so userspace can differentiate | 861 | /* |
| 881 | between this and the old multi-field proc format. */ | 862 | * Always include a trailing , so userspace can differentiate |
| 863 | * between this and the old multi-field proc format. | ||
| 864 | */ | ||
| 882 | list_for_each_entry(use, &mod->source_list, source_list) { | 865 | list_for_each_entry(use, &mod->source_list, source_list) { |
| 883 | printed_something = 1; | 866 | printed_something = 1; |
| 884 | seq_printf(m, "%s,", use->source->name); | 867 | seq_printf(m, "%s,", use->source->name); |
| @@ -886,11 +869,11 @@ static inline void print_unload_info(struct seq_file *m, struct module *mod) | |||
| 886 | 869 | ||
| 887 | if (mod->init != NULL && mod->exit == NULL) { | 870 | if (mod->init != NULL && mod->exit == NULL) { |
| 888 | printed_something = 1; | 871 | printed_something = 1; |
| 889 | seq_printf(m, "[permanent],"); | 872 | seq_puts(m, "[permanent],"); |
| 890 | } | 873 | } |
| 891 | 874 | ||
| 892 | if (!printed_something) | 875 | if (!printed_something) |
| 893 | seq_printf(m, "-"); | 876 | seq_puts(m, "-"); |
| 894 | } | 877 | } |
| 895 | 878 | ||
| 896 | void __symbol_put(const char *symbol) | 879 | void __symbol_put(const char *symbol) |
| @@ -935,7 +918,7 @@ void __module_get(struct module *module) | |||
| 935 | { | 918 | { |
| 936 | if (module) { | 919 | if (module) { |
| 937 | preempt_disable(); | 920 | preempt_disable(); |
| 938 | __this_cpu_inc(module->refptr->incs); | 921 | atomic_inc(&module->refcnt); |
| 939 | trace_module_get(module, _RET_IP_); | 922 | trace_module_get(module, _RET_IP_); |
| 940 | preempt_enable(); | 923 | preempt_enable(); |
| 941 | } | 924 | } |
| @@ -948,11 +931,11 @@ bool try_module_get(struct module *module) | |||
| 948 | 931 | ||
| 949 | if (module) { | 932 | if (module) { |
| 950 | preempt_disable(); | 933 | preempt_disable(); |
| 951 | 934 | /* Note: here, we can fail to get a reference */ | |
| 952 | if (likely(module_is_live(module))) { | 935 | if (likely(module_is_live(module) && |
| 953 | __this_cpu_inc(module->refptr->incs); | 936 | atomic_inc_not_zero(&module->refcnt) != 0)) |
| 954 | trace_module_get(module, _RET_IP_); | 937 | trace_module_get(module, _RET_IP_); |
| 955 | } else | 938 | else |
| 956 | ret = false; | 939 | ret = false; |
| 957 | 940 | ||
| 958 | preempt_enable(); | 941 | preempt_enable(); |
| @@ -963,11 +946,12 @@ EXPORT_SYMBOL(try_module_get); | |||
| 963 | 946 | ||
| 964 | void module_put(struct module *module) | 947 | void module_put(struct module *module) |
| 965 | { | 948 | { |
| 949 | int ret; | ||
| 950 | |||
| 966 | if (module) { | 951 | if (module) { |
| 967 | preempt_disable(); | 952 | preempt_disable(); |
| 968 | smp_wmb(); /* see comment in module_refcount */ | 953 | ret = atomic_dec_if_positive(&module->refcnt); |
| 969 | __this_cpu_inc(module->refptr->decs); | 954 | WARN_ON(ret < 0); /* Failed to put refcount */ |
| 970 | |||
| 971 | trace_module_put(module, _RET_IP_); | 955 | trace_module_put(module, _RET_IP_); |
| 972 | preempt_enable(); | 956 | preempt_enable(); |
| 973 | } | 957 | } |
| @@ -978,7 +962,7 @@ EXPORT_SYMBOL(module_put); | |||
| 978 | static inline void print_unload_info(struct seq_file *m, struct module *mod) | 962 | static inline void print_unload_info(struct seq_file *m, struct module *mod) |
| 979 | { | 963 | { |
| 980 | /* We don't know the usage count, or what modules are using. */ | 964 | /* We don't know the usage count, or what modules are using. */ |
| 981 | seq_printf(m, " - -"); | 965 | seq_puts(m, " - -"); |
| 982 | } | 966 | } |
| 983 | 967 | ||
| 984 | static inline void module_unload_free(struct module *mod) | 968 | static inline void module_unload_free(struct module *mod) |
| @@ -1131,7 +1115,7 @@ static unsigned long maybe_relocated(unsigned long crc, | |||
| 1131 | static int check_version(Elf_Shdr *sechdrs, | 1115 | static int check_version(Elf_Shdr *sechdrs, |
| 1132 | unsigned int versindex, | 1116 | unsigned int versindex, |
| 1133 | const char *symname, | 1117 | const char *symname, |
| 1134 | struct module *mod, | 1118 | struct module *mod, |
| 1135 | const unsigned long *crc, | 1119 | const unsigned long *crc, |
| 1136 | const struct module *crc_owner) | 1120 | const struct module *crc_owner) |
| 1137 | { | 1121 | { |
| @@ -1165,7 +1149,7 @@ static int check_version(Elf_Shdr *sechdrs, | |||
| 1165 | return 0; | 1149 | return 0; |
| 1166 | 1150 | ||
| 1167 | bad_version: | 1151 | bad_version: |
| 1168 | printk("%s: disagrees about version of symbol %s\n", | 1152 | pr_warn("%s: disagrees about version of symbol %s\n", |
| 1169 | mod->name, symname); | 1153 | mod->name, symname); |
| 1170 | return 0; | 1154 | return 0; |
| 1171 | } | 1155 | } |
| @@ -1200,7 +1184,7 @@ static inline int same_magic(const char *amagic, const char *bmagic, | |||
| 1200 | static inline int check_version(Elf_Shdr *sechdrs, | 1184 | static inline int check_version(Elf_Shdr *sechdrs, |
| 1201 | unsigned int versindex, | 1185 | unsigned int versindex, |
| 1202 | const char *symname, | 1186 | const char *symname, |
| 1203 | struct module *mod, | 1187 | struct module *mod, |
| 1204 | const unsigned long *crc, | 1188 | const unsigned long *crc, |
| 1205 | const struct module *crc_owner) | 1189 | const struct module *crc_owner) |
| 1206 | { | 1190 | { |
| @@ -1288,15 +1272,13 @@ static inline bool sect_empty(const Elf_Shdr *sect) | |||
| 1288 | return !(sect->sh_flags & SHF_ALLOC) || sect->sh_size == 0; | 1272 | return !(sect->sh_flags & SHF_ALLOC) || sect->sh_size == 0; |
| 1289 | } | 1273 | } |
| 1290 | 1274 | ||
| 1291 | struct module_sect_attr | 1275 | struct module_sect_attr { |
| 1292 | { | ||
| 1293 | struct module_attribute mattr; | 1276 | struct module_attribute mattr; |
| 1294 | char *name; | 1277 | char *name; |
| 1295 | unsigned long address; | 1278 | unsigned long address; |
| 1296 | }; | 1279 | }; |
| 1297 | 1280 | ||
| 1298 | struct module_sect_attrs | 1281 | struct module_sect_attrs { |
| 1299 | { | ||
| 1300 | struct attribute_group grp; | 1282 | struct attribute_group grp; |
| 1301 | unsigned int nsections; | 1283 | unsigned int nsections; |
| 1302 | struct module_sect_attr attrs[0]; | 1284 | struct module_sect_attr attrs[0]; |
| @@ -1550,7 +1532,8 @@ static int module_add_modinfo_attrs(struct module *mod) | |||
| 1550 | (attr->test && attr->test(mod))) { | 1532 | (attr->test && attr->test(mod))) { |
| 1551 | memcpy(temp_attr, attr, sizeof(*temp_attr)); | 1533 | memcpy(temp_attr, attr, sizeof(*temp_attr)); |
| 1552 | sysfs_attr_init(&temp_attr->attr); | 1534 | sysfs_attr_init(&temp_attr->attr); |
| 1553 | error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr); | 1535 | error = sysfs_create_file(&mod->mkobj.kobj, |
| 1536 | &temp_attr->attr); | ||
| 1554 | ++temp_attr; | 1537 | ++temp_attr; |
| 1555 | } | 1538 | } |
| 1556 | } | 1539 | } |
| @@ -1566,7 +1549,7 @@ static void module_remove_modinfo_attrs(struct module *mod) | |||
| 1566 | /* pick a field to test for end of list */ | 1549 | /* pick a field to test for end of list */ |
| 1567 | if (!attr->attr.name) | 1550 | if (!attr->attr.name) |
| 1568 | break; | 1551 | break; |
| 1569 | sysfs_remove_file(&mod->mkobj.kobj,&attr->attr); | 1552 | sysfs_remove_file(&mod->mkobj.kobj, &attr->attr); |
| 1570 | if (attr->free) | 1553 | if (attr->free) |
| 1571 | attr->free(mod); | 1554 | attr->free(mod); |
| 1572 | } | 1555 | } |
| @@ -1697,18 +1680,6 @@ static void mod_sysfs_teardown(struct module *mod) | |||
| 1697 | mod_sysfs_fini(mod); | 1680 | mod_sysfs_fini(mod); |
| 1698 | } | 1681 | } |
| 1699 | 1682 | ||
| 1700 | /* | ||
| 1701 | * unlink the module with the whole machine is stopped with interrupts off | ||
| 1702 | * - this defends against kallsyms not taking locks | ||
| 1703 | */ | ||
| 1704 | static int __unlink_module(void *_mod) | ||
| 1705 | { | ||
| 1706 | struct module *mod = _mod; | ||
| 1707 | list_del(&mod->list); | ||
| 1708 | module_bug_cleanup(mod); | ||
| 1709 | return 0; | ||
| 1710 | } | ||
| 1711 | |||
| 1712 | #ifdef CONFIG_DEBUG_SET_MODULE_RONX | 1683 | #ifdef CONFIG_DEBUG_SET_MODULE_RONX |
| 1713 | /* | 1684 | /* |
| 1714 | * LKM RO/NX protection: protect module's text/ro-data | 1685 | * LKM RO/NX protection: protect module's text/ro-data |
| @@ -1860,7 +1831,12 @@ static void free_module(struct module *mod) | |||
| 1860 | 1831 | ||
| 1861 | /* Now we can delete it from the lists */ | 1832 | /* Now we can delete it from the lists */ |
| 1862 | mutex_lock(&module_mutex); | 1833 | mutex_lock(&module_mutex); |
| 1863 | stop_machine(__unlink_module, mod, NULL); | 1834 | /* Unlink carefully: kallsyms could be walking list. */ |
| 1835 | list_del_rcu(&mod->list); | ||
| 1836 | /* Remove this module from bug list, this uses list_del_rcu */ | ||
| 1837 | module_bug_cleanup(mod); | ||
| 1838 | /* Wait for RCU synchronizing before releasing mod->list and buglist. */ | ||
| 1839 | synchronize_rcu(); | ||
| 1864 | mutex_unlock(&module_mutex); | 1840 | mutex_unlock(&module_mutex); |
| 1865 | 1841 | ||
| 1866 | /* This may be NULL, but that's OK */ | 1842 | /* This may be NULL, but that's OK */ |
| @@ -1955,7 +1931,7 @@ static int simplify_symbols(struct module *mod, const struct load_info *info) | |||
| 1955 | /* We compiled with -fno-common. These are not | 1931 | /* We compiled with -fno-common. These are not |
| 1956 | supposed to happen. */ | 1932 | supposed to happen. */ |
| 1957 | pr_debug("Common symbol: %s\n", name); | 1933 | pr_debug("Common symbol: %s\n", name); |
| 1958 | printk("%s: please compile with -fno-common\n", | 1934 | pr_warn("%s: please compile with -fno-common\n", |
| 1959 | mod->name); | 1935 | mod->name); |
| 1960 | ret = -ENOEXEC; | 1936 | ret = -ENOEXEC; |
| 1961 | break; | 1937 | break; |
| @@ -2259,7 +2235,7 @@ static char elf_type(const Elf_Sym *sym, const struct load_info *info) | |||
| 2259 | } | 2235 | } |
| 2260 | 2236 | ||
| 2261 | static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs, | 2237 | static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs, |
| 2262 | unsigned int shnum) | 2238 | unsigned int shnum) |
| 2263 | { | 2239 | { |
| 2264 | const Elf_Shdr *sec; | 2240 | const Elf_Shdr *sec; |
| 2265 | 2241 | ||
| @@ -2735,7 +2711,7 @@ static int find_module_sections(struct module *mod, struct load_info *info) | |||
| 2735 | * This shouldn't happen with same compiler and binutils | 2711 | * This shouldn't happen with same compiler and binutils |
| 2736 | * building all parts of the module. | 2712 | * building all parts of the module. |
| 2737 | */ | 2713 | */ |
| 2738 | printk(KERN_WARNING "%s: has both .ctors and .init_array.\n", | 2714 | pr_warn("%s: has both .ctors and .init_array.\n", |
| 2739 | mod->name); | 2715 | mod->name); |
| 2740 | return -EINVAL; | 2716 | return -EINVAL; |
| 2741 | } | 2717 | } |
| @@ -3023,8 +2999,10 @@ static int do_init_module(struct module *mod) | |||
| 3023 | if (mod->init != NULL) | 2999 | if (mod->init != NULL) |
| 3024 | ret = do_one_initcall(mod->init); | 3000 | ret = do_one_initcall(mod->init); |
| 3025 | if (ret < 0) { | 3001 | if (ret < 0) { |
| 3026 | /* Init routine failed: abort. Try to protect us from | 3002 | /* |
| 3027 | buggy refcounters. */ | 3003 | * Init routine failed: abort. Try to protect us from |
| 3004 | * buggy refcounters. | ||
| 3005 | */ | ||
| 3028 | mod->state = MODULE_STATE_GOING; | 3006 | mod->state = MODULE_STATE_GOING; |
| 3029 | synchronize_sched(); | 3007 | synchronize_sched(); |
| 3030 | module_put(mod); | 3008 | module_put(mod); |
| @@ -3097,6 +3075,32 @@ static int may_init_module(void) | |||
| 3097 | } | 3075 | } |
| 3098 | 3076 | ||
| 3099 | /* | 3077 | /* |
| 3078 | * Can't use wait_event_interruptible() because our condition | ||
| 3079 | * 'finished_loading()' contains a blocking primitive itself (mutex_lock). | ||
| 3080 | */ | ||
| 3081 | static int wait_finished_loading(struct module *mod) | ||
| 3082 | { | ||
| 3083 | DEFINE_WAIT_FUNC(wait, woken_wake_function); | ||
| 3084 | int ret = 0; | ||
| 3085 | |||
| 3086 | add_wait_queue(&module_wq, &wait); | ||
| 3087 | for (;;) { | ||
| 3088 | if (finished_loading(mod->name)) | ||
| 3089 | break; | ||
| 3090 | |||
| 3091 | if (signal_pending(current)) { | ||
| 3092 | ret = -ERESTARTSYS; | ||
| 3093 | break; | ||
| 3094 | } | ||
| 3095 | |||
| 3096 | wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); | ||
| 3097 | } | ||
| 3098 | remove_wait_queue(&module_wq, &wait); | ||
| 3099 | |||
| 3100 | return ret; | ||
| 3101 | } | ||
| 3102 | |||
| 3103 | /* | ||
| 3100 | * We try to place it in the list now to make sure it's unique before | 3104 | * We try to place it in the list now to make sure it's unique before |
| 3101 | * we dedicate too many resources. In particular, temporary percpu | 3105 | * we dedicate too many resources. In particular, temporary percpu |
| 3102 | * memory exhaustion. | 3106 | * memory exhaustion. |
| @@ -3116,8 +3120,8 @@ again: | |||
| 3116 | || old->state == MODULE_STATE_UNFORMED) { | 3120 | || old->state == MODULE_STATE_UNFORMED) { |
| 3117 | /* Wait in case it fails to load. */ | 3121 | /* Wait in case it fails to load. */ |
| 3118 | mutex_unlock(&module_mutex); | 3122 | mutex_unlock(&module_mutex); |
| 3119 | err = wait_event_interruptible(module_wq, | 3123 | |
| 3120 | finished_loading(mod->name)); | 3124 | err = wait_finished_loading(mod); |
| 3121 | if (err) | 3125 | if (err) |
| 3122 | goto out_unlocked; | 3126 | goto out_unlocked; |
| 3123 | goto again; | 3127 | goto again; |
| @@ -3176,7 +3180,7 @@ out: | |||
| 3176 | 3180 | ||
| 3177 | static int unknown_module_param_cb(char *param, char *val, const char *modname) | 3181 | static int unknown_module_param_cb(char *param, char *val, const char *modname) |
| 3178 | { | 3182 | { |
| 3179 | /* Check for magic 'dyndbg' arg */ | 3183 | /* Check for magic 'dyndbg' arg */ |
| 3180 | int ret = ddebug_dyndbg_module_param_cb(param, val, modname); | 3184 | int ret = ddebug_dyndbg_module_param_cb(param, val, modname); |
| 3181 | if (ret != 0) | 3185 | if (ret != 0) |
| 3182 | pr_warn("%s: unknown parameter '%s' ignored\n", modname, param); | 3186 | pr_warn("%s: unknown parameter '%s' ignored\n", modname, param); |
| @@ -3326,6 +3330,8 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
| 3326 | /* Unlink carefully: kallsyms could be walking list. */ | 3330 | /* Unlink carefully: kallsyms could be walking list. */ |
| 3327 | list_del_rcu(&mod->list); | 3331 | list_del_rcu(&mod->list); |
| 3328 | wake_up_all(&module_wq); | 3332 | wake_up_all(&module_wq); |
| 3333 | /* Wait for RCU synchronizing before releasing mod->list. */ | ||
| 3334 | synchronize_rcu(); | ||
| 3329 | mutex_unlock(&module_mutex); | 3335 | mutex_unlock(&module_mutex); |
| 3330 | free_module: | 3336 | free_module: |
| 3331 | module_deallocate(mod, info); | 3337 | module_deallocate(mod, info); |
| @@ -3659,8 +3665,8 @@ static int m_show(struct seq_file *m, void *p) | |||
| 3659 | 3665 | ||
| 3660 | /* Informative for users. */ | 3666 | /* Informative for users. */ |
| 3661 | seq_printf(m, " %s", | 3667 | seq_printf(m, " %s", |
| 3662 | mod->state == MODULE_STATE_GOING ? "Unloading": | 3668 | mod->state == MODULE_STATE_GOING ? "Unloading" : |
| 3663 | mod->state == MODULE_STATE_COMING ? "Loading": | 3669 | mod->state == MODULE_STATE_COMING ? "Loading" : |
| 3664 | "Live"); | 3670 | "Live"); |
| 3665 | /* Used by oprofile and other similar tools. */ | 3671 | /* Used by oprofile and other similar tools. */ |
| 3666 | seq_printf(m, " 0x%pK", mod->module_core); | 3672 | seq_printf(m, " 0x%pK", mod->module_core); |
| @@ -3669,7 +3675,7 @@ static int m_show(struct seq_file *m, void *p) | |||
| 3669 | if (mod->taints) | 3675 | if (mod->taints) |
| 3670 | seq_printf(m, " %s", module_flags(mod, buf)); | 3676 | seq_printf(m, " %s", module_flags(mod, buf)); |
| 3671 | 3677 | ||
| 3672 | seq_printf(m, "\n"); | 3678 | seq_puts(m, "\n"); |
| 3673 | return 0; | 3679 | return 0; |
| 3674 | } | 3680 | } |
| 3675 | 3681 | ||
