diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 343 |
1 files changed, 207 insertions, 136 deletions
diff --git a/kernel/module.c b/kernel/module.c index 5f80478b746d..61d212120df4 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -70,6 +70,9 @@ static DECLARE_WAIT_QUEUE_HEAD(module_wq); | |||
70 | 70 | ||
71 | static BLOCKING_NOTIFIER_HEAD(module_notify_list); | 71 | static BLOCKING_NOTIFIER_HEAD(module_notify_list); |
72 | 72 | ||
73 | /* Bounds of module allocation, for speeding __module_text_address */ | ||
74 | static unsigned long module_addr_min = -1UL, module_addr_max = 0; | ||
75 | |||
73 | int register_module_notifier(struct notifier_block * nb) | 76 | int register_module_notifier(struct notifier_block * nb) |
74 | { | 77 | { |
75 | return blocking_notifier_chain_register(&module_notify_list, nb); | 78 | return blocking_notifier_chain_register(&module_notify_list, nb); |
@@ -134,17 +137,19 @@ extern const struct kernel_symbol __start___ksymtab_gpl[]; | |||
134 | extern const struct kernel_symbol __stop___ksymtab_gpl[]; | 137 | extern const struct kernel_symbol __stop___ksymtab_gpl[]; |
135 | extern const struct kernel_symbol __start___ksymtab_gpl_future[]; | 138 | extern const struct kernel_symbol __start___ksymtab_gpl_future[]; |
136 | extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; | 139 | extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; |
137 | extern const struct kernel_symbol __start___ksymtab_unused[]; | ||
138 | extern const struct kernel_symbol __stop___ksymtab_unused[]; | ||
139 | extern const struct kernel_symbol __start___ksymtab_unused_gpl[]; | ||
140 | extern const struct kernel_symbol __stop___ksymtab_unused_gpl[]; | ||
141 | extern const struct kernel_symbol __start___ksymtab_gpl_future[]; | 140 | extern const struct kernel_symbol __start___ksymtab_gpl_future[]; |
142 | extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; | 141 | extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; |
143 | extern const unsigned long __start___kcrctab[]; | 142 | extern const unsigned long __start___kcrctab[]; |
144 | extern const unsigned long __start___kcrctab_gpl[]; | 143 | extern const unsigned long __start___kcrctab_gpl[]; |
145 | extern const unsigned long __start___kcrctab_gpl_future[]; | 144 | extern const unsigned long __start___kcrctab_gpl_future[]; |
145 | #ifdef CONFIG_UNUSED_SYMBOLS | ||
146 | extern const struct kernel_symbol __start___ksymtab_unused[]; | ||
147 | extern const struct kernel_symbol __stop___ksymtab_unused[]; | ||
148 | extern const struct kernel_symbol __start___ksymtab_unused_gpl[]; | ||
149 | extern const struct kernel_symbol __stop___ksymtab_unused_gpl[]; | ||
146 | extern const unsigned long __start___kcrctab_unused[]; | 150 | extern const unsigned long __start___kcrctab_unused[]; |
147 | extern const unsigned long __start___kcrctab_unused_gpl[]; | 151 | extern const unsigned long __start___kcrctab_unused_gpl[]; |
152 | #endif | ||
148 | 153 | ||
149 | #ifndef CONFIG_MODVERSIONS | 154 | #ifndef CONFIG_MODVERSIONS |
150 | #define symversion(base, idx) NULL | 155 | #define symversion(base, idx) NULL |
@@ -152,152 +157,170 @@ extern const unsigned long __start___kcrctab_unused_gpl[]; | |||
152 | #define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL) | 157 | #define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL) |
153 | #endif | 158 | #endif |
154 | 159 | ||
155 | /* lookup symbol in given range of kernel_symbols */ | ||
156 | static const struct kernel_symbol *lookup_symbol(const char *name, | ||
157 | const struct kernel_symbol *start, | ||
158 | const struct kernel_symbol *stop) | ||
159 | { | ||
160 | const struct kernel_symbol *ks = start; | ||
161 | for (; ks < stop; ks++) | ||
162 | if (strcmp(ks->name, name) == 0) | ||
163 | return ks; | ||
164 | return NULL; | ||
165 | } | ||
166 | |||
167 | static bool always_ok(bool gplok, bool warn, const char *name) | ||
168 | { | ||
169 | return true; | ||
170 | } | ||
171 | |||
172 | static bool printk_unused_warning(bool gplok, bool warn, const char *name) | ||
173 | { | ||
174 | if (warn) { | ||
175 | printk(KERN_WARNING "Symbol %s is marked as UNUSED, " | ||
176 | "however this module is using it.\n", name); | ||
177 | printk(KERN_WARNING | ||
178 | "This symbol will go away in the future.\n"); | ||
179 | printk(KERN_WARNING | ||
180 | "Please evalute if this is the right api to use and if " | ||
181 | "it really is, submit a report the linux kernel " | ||
182 | "mailinglist together with submitting your code for " | ||
183 | "inclusion.\n"); | ||
184 | } | ||
185 | return true; | ||
186 | } | ||
187 | |||
188 | static bool gpl_only_unused_warning(bool gplok, bool warn, const char *name) | ||
189 | { | ||
190 | if (!gplok) | ||
191 | return false; | ||
192 | return printk_unused_warning(gplok, warn, name); | ||
193 | } | ||
194 | |||
195 | static bool gpl_only(bool gplok, bool warn, const char *name) | ||
196 | { | ||
197 | return gplok; | ||
198 | } | ||
199 | |||
200 | static bool warn_if_not_gpl(bool gplok, bool warn, const char *name) | ||
201 | { | ||
202 | if (!gplok && warn) { | ||
203 | printk(KERN_WARNING "Symbol %s is being used " | ||
204 | "by a non-GPL module, which will not " | ||
205 | "be allowed in the future\n", name); | ||
206 | printk(KERN_WARNING "Please see the file " | ||
207 | "Documentation/feature-removal-schedule.txt " | ||
208 | "in the kernel source tree for more details.\n"); | ||
209 | } | ||
210 | return true; | ||
211 | } | ||
212 | |||
213 | struct symsearch { | 160 | struct symsearch { |
214 | const struct kernel_symbol *start, *stop; | 161 | const struct kernel_symbol *start, *stop; |
215 | const unsigned long *crcs; | 162 | const unsigned long *crcs; |
216 | bool (*check)(bool gplok, bool warn, const char *name); | 163 | enum { |
164 | NOT_GPL_ONLY, | ||
165 | GPL_ONLY, | ||
166 | WILL_BE_GPL_ONLY, | ||
167 | } licence; | ||
168 | bool unused; | ||
217 | }; | 169 | }; |
218 | 170 | ||
219 | /* Look through this array of symbol tables for a symbol match which | 171 | static bool each_symbol_in_section(const struct symsearch *arr, |
220 | * passes the check function. */ | 172 | unsigned int arrsize, |
221 | static const struct kernel_symbol *search_symarrays(const struct symsearch *arr, | 173 | struct module *owner, |
222 | unsigned int num, | 174 | bool (*fn)(const struct symsearch *syms, |
223 | const char *name, | 175 | struct module *owner, |
224 | bool gplok, | 176 | unsigned int symnum, void *data), |
225 | bool warn, | 177 | void *data) |
226 | const unsigned long **crc) | ||
227 | { | 178 | { |
228 | unsigned int i; | 179 | unsigned int i, j; |
229 | const struct kernel_symbol *ks; | ||
230 | |||
231 | for (i = 0; i < num; i++) { | ||
232 | ks = lookup_symbol(name, arr[i].start, arr[i].stop); | ||
233 | if (!ks || !arr[i].check(gplok, warn, name)) | ||
234 | continue; | ||
235 | 180 | ||
236 | if (crc) | 181 | for (j = 0; j < arrsize; j++) { |
237 | *crc = symversion(arr[i].crcs, ks - arr[i].start); | 182 | for (i = 0; i < arr[j].stop - arr[j].start; i++) |
238 | return ks; | 183 | if (fn(&arr[j], owner, i, data)) |
184 | return true; | ||
239 | } | 185 | } |
240 | return NULL; | 186 | |
187 | return false; | ||
241 | } | 188 | } |
242 | 189 | ||
243 | /* Find a symbol, return value, (optional) crc and (optional) module | 190 | /* Returns true as soon as fn returns true, otherwise false. */ |
244 | * which owns it */ | 191 | static bool each_symbol(bool (*fn)(const struct symsearch *arr, |
245 | static unsigned long find_symbol(const char *name, | 192 | struct module *owner, |
246 | struct module **owner, | 193 | unsigned int symnum, void *data), |
247 | const unsigned long **crc, | 194 | void *data) |
248 | bool gplok, | ||
249 | bool warn) | ||
250 | { | 195 | { |
251 | struct module *mod; | 196 | struct module *mod; |
252 | const struct kernel_symbol *ks; | ||
253 | const struct symsearch arr[] = { | 197 | const struct symsearch arr[] = { |
254 | { __start___ksymtab, __stop___ksymtab, __start___kcrctab, | 198 | { __start___ksymtab, __stop___ksymtab, __start___kcrctab, |
255 | always_ok }, | 199 | NOT_GPL_ONLY, false }, |
256 | { __start___ksymtab_gpl, __stop___ksymtab_gpl, | 200 | { __start___ksymtab_gpl, __stop___ksymtab_gpl, |
257 | __start___kcrctab_gpl, gpl_only }, | 201 | __start___kcrctab_gpl, |
202 | GPL_ONLY, false }, | ||
258 | { __start___ksymtab_gpl_future, __stop___ksymtab_gpl_future, | 203 | { __start___ksymtab_gpl_future, __stop___ksymtab_gpl_future, |
259 | __start___kcrctab_gpl_future, warn_if_not_gpl }, | 204 | __start___kcrctab_gpl_future, |
205 | WILL_BE_GPL_ONLY, false }, | ||
206 | #ifdef CONFIG_UNUSED_SYMBOLS | ||
260 | { __start___ksymtab_unused, __stop___ksymtab_unused, | 207 | { __start___ksymtab_unused, __stop___ksymtab_unused, |
261 | __start___kcrctab_unused, printk_unused_warning }, | 208 | __start___kcrctab_unused, |
209 | NOT_GPL_ONLY, true }, | ||
262 | { __start___ksymtab_unused_gpl, __stop___ksymtab_unused_gpl, | 210 | { __start___ksymtab_unused_gpl, __stop___ksymtab_unused_gpl, |
263 | __start___kcrctab_unused_gpl, gpl_only_unused_warning }, | 211 | __start___kcrctab_unused_gpl, |
212 | GPL_ONLY, true }, | ||
213 | #endif | ||
264 | }; | 214 | }; |
265 | 215 | ||
266 | /* Core kernel first. */ | 216 | if (each_symbol_in_section(arr, ARRAY_SIZE(arr), NULL, fn, data)) |
267 | ks = search_symarrays(arr, ARRAY_SIZE(arr), name, gplok, warn, crc); | 217 | return true; |
268 | if (ks) { | ||
269 | if (owner) | ||
270 | *owner = NULL; | ||
271 | return ks->value; | ||
272 | } | ||
273 | 218 | ||
274 | /* Now try modules. */ | ||
275 | list_for_each_entry(mod, &modules, list) { | 219 | list_for_each_entry(mod, &modules, list) { |
276 | struct symsearch arr[] = { | 220 | struct symsearch arr[] = { |
277 | { mod->syms, mod->syms + mod->num_syms, mod->crcs, | 221 | { mod->syms, mod->syms + mod->num_syms, mod->crcs, |
278 | always_ok }, | 222 | NOT_GPL_ONLY, false }, |
279 | { mod->gpl_syms, mod->gpl_syms + mod->num_gpl_syms, | 223 | { mod->gpl_syms, mod->gpl_syms + mod->num_gpl_syms, |
280 | mod->gpl_crcs, gpl_only }, | 224 | mod->gpl_crcs, |
225 | GPL_ONLY, false }, | ||
281 | { mod->gpl_future_syms, | 226 | { mod->gpl_future_syms, |
282 | mod->gpl_future_syms + mod->num_gpl_future_syms, | 227 | mod->gpl_future_syms + mod->num_gpl_future_syms, |
283 | mod->gpl_future_crcs, warn_if_not_gpl }, | 228 | mod->gpl_future_crcs, |
229 | WILL_BE_GPL_ONLY, false }, | ||
230 | #ifdef CONFIG_UNUSED_SYMBOLS | ||
284 | { mod->unused_syms, | 231 | { mod->unused_syms, |
285 | mod->unused_syms + mod->num_unused_syms, | 232 | mod->unused_syms + mod->num_unused_syms, |
286 | mod->unused_crcs, printk_unused_warning }, | 233 | mod->unused_crcs, |
234 | NOT_GPL_ONLY, true }, | ||
287 | { mod->unused_gpl_syms, | 235 | { mod->unused_gpl_syms, |
288 | mod->unused_gpl_syms + mod->num_unused_gpl_syms, | 236 | mod->unused_gpl_syms + mod->num_unused_gpl_syms, |
289 | mod->unused_gpl_crcs, gpl_only_unused_warning }, | 237 | mod->unused_gpl_crcs, |
238 | GPL_ONLY, true }, | ||
239 | #endif | ||
290 | }; | 240 | }; |
291 | 241 | ||
292 | ks = search_symarrays(arr, ARRAY_SIZE(arr), | 242 | if (each_symbol_in_section(arr, ARRAY_SIZE(arr), mod, fn, data)) |
293 | name, gplok, warn, crc); | 243 | return true; |
294 | if (ks) { | 244 | } |
295 | if (owner) | 245 | return false; |
296 | *owner = mod; | 246 | } |
297 | return ks->value; | 247 | |
248 | struct find_symbol_arg { | ||
249 | /* Input */ | ||
250 | const char *name; | ||
251 | bool gplok; | ||
252 | bool warn; | ||
253 | |||
254 | /* Output */ | ||
255 | struct module *owner; | ||
256 | const unsigned long *crc; | ||
257 | unsigned long value; | ||
258 | }; | ||
259 | |||
260 | static bool find_symbol_in_section(const struct symsearch *syms, | ||
261 | struct module *owner, | ||
262 | unsigned int symnum, void *data) | ||
263 | { | ||
264 | struct find_symbol_arg *fsa = data; | ||
265 | |||
266 | if (strcmp(syms->start[symnum].name, fsa->name) != 0) | ||
267 | return false; | ||
268 | |||
269 | if (!fsa->gplok) { | ||
270 | if (syms->licence == GPL_ONLY) | ||
271 | return false; | ||
272 | if (syms->licence == WILL_BE_GPL_ONLY && fsa->warn) { | ||
273 | printk(KERN_WARNING "Symbol %s is being used " | ||
274 | "by a non-GPL module, which will not " | ||
275 | "be allowed in the future\n", fsa->name); | ||
276 | printk(KERN_WARNING "Please see the file " | ||
277 | "Documentation/feature-removal-schedule.txt " | ||
278 | "in the kernel source tree for more details.\n"); | ||
298 | } | 279 | } |
299 | } | 280 | } |
300 | 281 | ||
282 | #ifdef CONFIG_UNUSED_SYMBOLS | ||
283 | if (syms->unused && fsa->warn) { | ||
284 | printk(KERN_WARNING "Symbol %s is marked as UNUSED, " | ||
285 | "however this module is using it.\n", fsa->name); | ||
286 | printk(KERN_WARNING | ||
287 | "This symbol will go away in the future.\n"); | ||
288 | printk(KERN_WARNING | ||
289 | "Please evalute if this is the right api to use and if " | ||
290 | "it really is, submit a report the linux kernel " | ||
291 | "mailinglist together with submitting your code for " | ||
292 | "inclusion.\n"); | ||
293 | } | ||
294 | #endif | ||
295 | |||
296 | fsa->owner = owner; | ||
297 | fsa->crc = symversion(syms->crcs, symnum); | ||
298 | fsa->value = syms->start[symnum].value; | ||
299 | return true; | ||
300 | } | ||
301 | |||
302 | /* Find a symbol, return value, (optional) crc and (optional) module | ||
303 | * which owns it */ | ||
304 | static unsigned long find_symbol(const char *name, | ||
305 | struct module **owner, | ||
306 | const unsigned long **crc, | ||
307 | bool gplok, | ||
308 | bool warn) | ||
309 | { | ||
310 | struct find_symbol_arg fsa; | ||
311 | |||
312 | fsa.name = name; | ||
313 | fsa.gplok = gplok; | ||
314 | fsa.warn = warn; | ||
315 | |||
316 | if (each_symbol(find_symbol_in_section, &fsa)) { | ||
317 | if (owner) | ||
318 | *owner = fsa.owner; | ||
319 | if (crc) | ||
320 | *crc = fsa.crc; | ||
321 | return fsa.value; | ||
322 | } | ||
323 | |||
301 | DEBUGP("Failed to find symbol %s\n", name); | 324 | DEBUGP("Failed to find symbol %s\n", name); |
302 | return -ENOENT; | 325 | return -ENOENT; |
303 | } | 326 | } |
@@ -639,8 +662,8 @@ static int __try_stop_module(void *_sref) | |||
639 | { | 662 | { |
640 | struct stopref *sref = _sref; | 663 | struct stopref *sref = _sref; |
641 | 664 | ||
642 | /* If it's not unused, quit unless we are told to block. */ | 665 | /* If it's not unused, quit unless we're forcing. */ |
643 | if ((sref->flags & O_NONBLOCK) && module_refcount(sref->mod) != 0) { | 666 | if (module_refcount(sref->mod) != 0) { |
644 | if (!(*sref->forced = try_force_unload(sref->flags))) | 667 | if (!(*sref->forced = try_force_unload(sref->flags))) |
645 | return -EWOULDBLOCK; | 668 | return -EWOULDBLOCK; |
646 | } | 669 | } |
@@ -652,9 +675,16 @@ static int __try_stop_module(void *_sref) | |||
652 | 675 | ||
653 | static int try_stop_module(struct module *mod, int flags, int *forced) | 676 | static int try_stop_module(struct module *mod, int flags, int *forced) |
654 | { | 677 | { |
655 | struct stopref sref = { mod, flags, forced }; | 678 | if (flags & O_NONBLOCK) { |
679 | struct stopref sref = { mod, flags, forced }; | ||
656 | 680 | ||
657 | return stop_machine_run(__try_stop_module, &sref, NR_CPUS); | 681 | return stop_machine(__try_stop_module, &sref, NULL); |
682 | } else { | ||
683 | /* We don't need to stop the machine for this. */ | ||
684 | mod->state = MODULE_STATE_GOING; | ||
685 | synchronize_sched(); | ||
686 | return 0; | ||
687 | } | ||
658 | } | 688 | } |
659 | 689 | ||
660 | unsigned int module_refcount(struct module *mod) | 690 | unsigned int module_refcount(struct module *mod) |
@@ -1386,7 +1416,7 @@ static int __unlink_module(void *_mod) | |||
1386 | static void free_module(struct module *mod) | 1416 | static void free_module(struct module *mod) |
1387 | { | 1417 | { |
1388 | /* Delete from various lists */ | 1418 | /* Delete from various lists */ |
1389 | stop_machine_run(__unlink_module, mod, NR_CPUS); | 1419 | stop_machine(__unlink_module, mod, NULL); |
1390 | remove_notes_attrs(mod); | 1420 | remove_notes_attrs(mod); |
1391 | remove_sect_attrs(mod); | 1421 | remove_sect_attrs(mod); |
1392 | mod_kobject_remove(mod); | 1422 | mod_kobject_remove(mod); |
@@ -1445,8 +1475,10 @@ static int verify_export_symbols(struct module *mod) | |||
1445 | { mod->syms, mod->num_syms }, | 1475 | { mod->syms, mod->num_syms }, |
1446 | { mod->gpl_syms, mod->num_gpl_syms }, | 1476 | { mod->gpl_syms, mod->num_gpl_syms }, |
1447 | { mod->gpl_future_syms, mod->num_gpl_future_syms }, | 1477 | { mod->gpl_future_syms, mod->num_gpl_future_syms }, |
1478 | #ifdef CONFIG_UNUSED_SYMBOLS | ||
1448 | { mod->unused_syms, mod->num_unused_syms }, | 1479 | { mod->unused_syms, mod->num_unused_syms }, |
1449 | { mod->unused_gpl_syms, mod->num_unused_gpl_syms }, | 1480 | { mod->unused_gpl_syms, mod->num_unused_gpl_syms }, |
1481 | #endif | ||
1450 | }; | 1482 | }; |
1451 | 1483 | ||
1452 | for (i = 0; i < ARRAY_SIZE(arr); i++) { | 1484 | for (i = 0; i < ARRAY_SIZE(arr); i++) { |
@@ -1526,7 +1558,7 @@ static int simplify_symbols(Elf_Shdr *sechdrs, | |||
1526 | } | 1558 | } |
1527 | 1559 | ||
1528 | /* Update size with this section: return offset. */ | 1560 | /* Update size with this section: return offset. */ |
1529 | static long get_offset(unsigned long *size, Elf_Shdr *sechdr) | 1561 | static long get_offset(unsigned int *size, Elf_Shdr *sechdr) |
1530 | { | 1562 | { |
1531 | long ret; | 1563 | long ret; |
1532 | 1564 | ||
@@ -1659,6 +1691,19 @@ static void setup_modinfo(struct module *mod, Elf_Shdr *sechdrs, | |||
1659 | } | 1691 | } |
1660 | 1692 | ||
1661 | #ifdef CONFIG_KALLSYMS | 1693 | #ifdef CONFIG_KALLSYMS |
1694 | |||
1695 | /* lookup symbol in given range of kernel_symbols */ | ||
1696 | static const struct kernel_symbol *lookup_symbol(const char *name, | ||
1697 | const struct kernel_symbol *start, | ||
1698 | const struct kernel_symbol *stop) | ||
1699 | { | ||
1700 | const struct kernel_symbol *ks = start; | ||
1701 | for (; ks < stop; ks++) | ||
1702 | if (strcmp(ks->name, name) == 0) | ||
1703 | return ks; | ||
1704 | return NULL; | ||
1705 | } | ||
1706 | |||
1662 | static int is_exported(const char *name, const struct module *mod) | 1707 | static int is_exported(const char *name, const struct module *mod) |
1663 | { | 1708 | { |
1664 | if (!mod && lookup_symbol(name, __start___ksymtab, __stop___ksymtab)) | 1709 | if (!mod && lookup_symbol(name, __start___ksymtab, __stop___ksymtab)) |
@@ -1738,6 +1783,20 @@ static inline void add_kallsyms(struct module *mod, | |||
1738 | } | 1783 | } |
1739 | #endif /* CONFIG_KALLSYMS */ | 1784 | #endif /* CONFIG_KALLSYMS */ |
1740 | 1785 | ||
1786 | static void *module_alloc_update_bounds(unsigned long size) | ||
1787 | { | ||
1788 | void *ret = module_alloc(size); | ||
1789 | |||
1790 | if (ret) { | ||
1791 | /* Update module bounds. */ | ||
1792 | if ((unsigned long)ret < module_addr_min) | ||
1793 | module_addr_min = (unsigned long)ret; | ||
1794 | if ((unsigned long)ret + size > module_addr_max) | ||
1795 | module_addr_max = (unsigned long)ret + size; | ||
1796 | } | ||
1797 | return ret; | ||
1798 | } | ||
1799 | |||
1741 | /* Allocate and load the module: note that size of section 0 is always | 1800 | /* Allocate and load the module: note that size of section 0 is always |
1742 | zero, and we rely on this for optional sections. */ | 1801 | zero, and we rely on this for optional sections. */ |
1743 | static struct module *load_module(void __user *umod, | 1802 | static struct module *load_module(void __user *umod, |
@@ -1764,10 +1823,12 @@ static struct module *load_module(void __user *umod, | |||
1764 | unsigned int gplfutureindex; | 1823 | unsigned int gplfutureindex; |
1765 | unsigned int gplfuturecrcindex; | 1824 | unsigned int gplfuturecrcindex; |
1766 | unsigned int unwindex = 0; | 1825 | unsigned int unwindex = 0; |
1826 | #ifdef CONFIG_UNUSED_SYMBOLS | ||
1767 | unsigned int unusedindex; | 1827 | unsigned int unusedindex; |
1768 | unsigned int unusedcrcindex; | 1828 | unsigned int unusedcrcindex; |
1769 | unsigned int unusedgplindex; | 1829 | unsigned int unusedgplindex; |
1770 | unsigned int unusedgplcrcindex; | 1830 | unsigned int unusedgplcrcindex; |
1831 | #endif | ||
1771 | unsigned int markersindex; | 1832 | unsigned int markersindex; |
1772 | unsigned int markersstringsindex; | 1833 | unsigned int markersstringsindex; |
1773 | struct module *mod; | 1834 | struct module *mod; |
@@ -1850,13 +1911,15 @@ static struct module *load_module(void __user *umod, | |||
1850 | exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab"); | 1911 | exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab"); |
1851 | gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl"); | 1912 | gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl"); |
1852 | gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future"); | 1913 | gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future"); |
1853 | unusedindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused"); | ||
1854 | unusedgplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused_gpl"); | ||
1855 | crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab"); | 1914 | crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab"); |
1856 | gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl"); | 1915 | gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl"); |
1857 | gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future"); | 1916 | gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future"); |
1917 | #ifdef CONFIG_UNUSED_SYMBOLS | ||
1918 | unusedindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused"); | ||
1919 | unusedgplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused_gpl"); | ||
1858 | unusedcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused"); | 1920 | unusedcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused"); |
1859 | unusedgplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused_gpl"); | 1921 | unusedgplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused_gpl"); |
1922 | #endif | ||
1860 | setupindex = find_sec(hdr, sechdrs, secstrings, "__param"); | 1923 | setupindex = find_sec(hdr, sechdrs, secstrings, "__param"); |
1861 | exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table"); | 1924 | exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table"); |
1862 | obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm"); | 1925 | obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm"); |
@@ -1935,7 +1998,7 @@ static struct module *load_module(void __user *umod, | |||
1935 | layout_sections(mod, hdr, sechdrs, secstrings); | 1998 | layout_sections(mod, hdr, sechdrs, secstrings); |
1936 | 1999 | ||
1937 | /* Do the allocs. */ | 2000 | /* Do the allocs. */ |
1938 | ptr = module_alloc(mod->core_size); | 2001 | ptr = module_alloc_update_bounds(mod->core_size); |
1939 | if (!ptr) { | 2002 | if (!ptr) { |
1940 | err = -ENOMEM; | 2003 | err = -ENOMEM; |
1941 | goto free_percpu; | 2004 | goto free_percpu; |
@@ -1943,7 +2006,7 @@ static struct module *load_module(void __user *umod, | |||
1943 | memset(ptr, 0, mod->core_size); | 2006 | memset(ptr, 0, mod->core_size); |
1944 | mod->module_core = ptr; | 2007 | mod->module_core = ptr; |
1945 | 2008 | ||
1946 | ptr = module_alloc(mod->init_size); | 2009 | ptr = module_alloc_update_bounds(mod->init_size); |
1947 | if (!ptr && mod->init_size) { | 2010 | if (!ptr && mod->init_size) { |
1948 | err = -ENOMEM; | 2011 | err = -ENOMEM; |
1949 | goto free_core; | 2012 | goto free_core; |
@@ -2018,14 +2081,15 @@ static struct module *load_module(void __user *umod, | |||
2018 | mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr; | 2081 | mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr; |
2019 | mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size / | 2082 | mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size / |
2020 | sizeof(*mod->gpl_future_syms); | 2083 | sizeof(*mod->gpl_future_syms); |
2021 | mod->num_unused_syms = sechdrs[unusedindex].sh_size / | ||
2022 | sizeof(*mod->unused_syms); | ||
2023 | mod->num_unused_gpl_syms = sechdrs[unusedgplindex].sh_size / | ||
2024 | sizeof(*mod->unused_gpl_syms); | ||
2025 | mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr; | 2084 | mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr; |
2026 | if (gplfuturecrcindex) | 2085 | if (gplfuturecrcindex) |
2027 | mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr; | 2086 | mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr; |
2028 | 2087 | ||
2088 | #ifdef CONFIG_UNUSED_SYMBOLS | ||
2089 | mod->num_unused_syms = sechdrs[unusedindex].sh_size / | ||
2090 | sizeof(*mod->unused_syms); | ||
2091 | mod->num_unused_gpl_syms = sechdrs[unusedgplindex].sh_size / | ||
2092 | sizeof(*mod->unused_gpl_syms); | ||
2029 | mod->unused_syms = (void *)sechdrs[unusedindex].sh_addr; | 2093 | mod->unused_syms = (void *)sechdrs[unusedindex].sh_addr; |
2030 | if (unusedcrcindex) | 2094 | if (unusedcrcindex) |
2031 | mod->unused_crcs = (void *)sechdrs[unusedcrcindex].sh_addr; | 2095 | mod->unused_crcs = (void *)sechdrs[unusedcrcindex].sh_addr; |
@@ -2033,13 +2097,17 @@ static struct module *load_module(void __user *umod, | |||
2033 | if (unusedgplcrcindex) | 2097 | if (unusedgplcrcindex) |
2034 | mod->unused_gpl_crcs | 2098 | mod->unused_gpl_crcs |
2035 | = (void *)sechdrs[unusedgplcrcindex].sh_addr; | 2099 | = (void *)sechdrs[unusedgplcrcindex].sh_addr; |
2100 | #endif | ||
2036 | 2101 | ||
2037 | #ifdef CONFIG_MODVERSIONS | 2102 | #ifdef CONFIG_MODVERSIONS |
2038 | if ((mod->num_syms && !crcindex) || | 2103 | if ((mod->num_syms && !crcindex) |
2039 | (mod->num_gpl_syms && !gplcrcindex) || | 2104 | || (mod->num_gpl_syms && !gplcrcindex) |
2040 | (mod->num_gpl_future_syms && !gplfuturecrcindex) || | 2105 | || (mod->num_gpl_future_syms && !gplfuturecrcindex) |
2041 | (mod->num_unused_syms && !unusedcrcindex) || | 2106 | #ifdef CONFIG_UNUSED_SYMBOLS |
2042 | (mod->num_unused_gpl_syms && !unusedgplcrcindex)) { | 2107 | || (mod->num_unused_syms && !unusedcrcindex) |
2108 | || (mod->num_unused_gpl_syms && !unusedgplcrcindex) | ||
2109 | #endif | ||
2110 | ) { | ||
2043 | printk(KERN_WARNING "%s: No versions for exported symbols.\n", mod->name); | 2111 | printk(KERN_WARNING "%s: No versions for exported symbols.\n", mod->name); |
2044 | err = try_to_force_load(mod, "nocrc"); | 2112 | err = try_to_force_load(mod, "nocrc"); |
2045 | if (err) | 2113 | if (err) |
@@ -2129,7 +2197,7 @@ static struct module *load_module(void __user *umod, | |||
2129 | /* Now sew it into the lists so we can get lockdep and oops | 2197 | /* Now sew it into the lists so we can get lockdep and oops |
2130 | * info during argument parsing. Noone should access us, since | 2198 | * info during argument parsing. Noone should access us, since |
2131 | * strong_try_module_get() will fail. */ | 2199 | * strong_try_module_get() will fail. */ |
2132 | stop_machine_run(__link_module, mod, NR_CPUS); | 2200 | stop_machine(__link_module, mod, NULL); |
2133 | 2201 | ||
2134 | /* Size of section 0 is 0, so this works well if no params */ | 2202 | /* Size of section 0 is 0, so this works well if no params */ |
2135 | err = parse_args(mod->name, mod->args, | 2203 | err = parse_args(mod->name, mod->args, |
@@ -2163,7 +2231,7 @@ static struct module *load_module(void __user *umod, | |||
2163 | return mod; | 2231 | return mod; |
2164 | 2232 | ||
2165 | unlink: | 2233 | unlink: |
2166 | stop_machine_run(__unlink_module, mod, NR_CPUS); | 2234 | stop_machine(__unlink_module, mod, NULL); |
2167 | module_arch_cleanup(mod); | 2235 | module_arch_cleanup(mod); |
2168 | cleanup: | 2236 | cleanup: |
2169 | kobject_del(&mod->mkobj.kobj); | 2237 | kobject_del(&mod->mkobj.kobj); |
@@ -2512,7 +2580,7 @@ static int m_show(struct seq_file *m, void *p) | |||
2512 | struct module *mod = list_entry(p, struct module, list); | 2580 | struct module *mod = list_entry(p, struct module, list); |
2513 | char buf[8]; | 2581 | char buf[8]; |
2514 | 2582 | ||
2515 | seq_printf(m, "%s %lu", | 2583 | seq_printf(m, "%s %u", |
2516 | mod->name, mod->init_size + mod->core_size); | 2584 | mod->name, mod->init_size + mod->core_size); |
2517 | print_unload_info(m, mod); | 2585 | print_unload_info(m, mod); |
2518 | 2586 | ||
@@ -2595,6 +2663,9 @@ struct module *__module_text_address(unsigned long addr) | |||
2595 | { | 2663 | { |
2596 | struct module *mod; | 2664 | struct module *mod; |
2597 | 2665 | ||
2666 | if (addr < module_addr_min || addr > module_addr_max) | ||
2667 | return NULL; | ||
2668 | |||
2598 | list_for_each_entry(mod, &modules, list) | 2669 | list_for_each_entry(mod, &modules, list) |
2599 | if (within(addr, mod->module_init, mod->init_text_size) | 2670 | if (within(addr, mod->module_init, mod->init_text_size) |
2600 | || within(addr, mod->module_core, mod->core_text_size)) | 2671 | || within(addr, mod->module_core, mod->core_text_size)) |