diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-22 16:17:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-22 16:17:15 -0400 |
commit | 6eaaaac97433575894570a990aa27310040a8177 (patch) | |
tree | 0d61224358c40309096a0c026ad0d1c7120fa0d6 /kernel | |
parent | 06b8147c5dbd385b5b97ca74e19f6f3951ebc1cb (diff) | |
parent | a1ef5adb4cad43460ebba23c5a78cf4a55bb6a5b (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus
* git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus:
remove CONFIG_KMOD from core kernel code
remove CONFIG_KMOD from lib
remove CONFIG_KMOD from sparc64
rework try_then_request_module to do less in non-modular kernels
remove mention of CONFIG_KMOD from documentation
make CONFIG_KMOD invisible
modules: Take a shortcut for checking if an address is in a module
module: turn longs into ints for module sizes
Shrink struct module: CONFIG_UNUSED_SYMBOLS ifdefs
module: reorder struct module to save space on 64 bit builds
module: generic each_symbol iterator function
module: don't use stop_machine for waiting rmmod
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/exec_domain.c | 2 | ||||
-rw-r--r-- | kernel/kmod.c | 2 | ||||
-rw-r--r-- | kernel/module.c | 336 | ||||
-rw-r--r-- | kernel/sysctl.c | 4 |
4 files changed, 207 insertions, 137 deletions
diff --git a/kernel/exec_domain.c b/kernel/exec_domain.c index a9e6bad9f706..c1ef192aa655 100644 --- a/kernel/exec_domain.c +++ b/kernel/exec_domain.c | |||
@@ -65,7 +65,7 @@ lookup_exec_domain(u_long personality) | |||
65 | goto out; | 65 | goto out; |
66 | } | 66 | } |
67 | 67 | ||
68 | #ifdef CONFIG_KMOD | 68 | #ifdef CONFIG_MODULES |
69 | read_unlock(&exec_domains_lock); | 69 | read_unlock(&exec_domains_lock); |
70 | request_module("personality-%ld", pers); | 70 | request_module("personality-%ld", pers); |
71 | read_lock(&exec_domains_lock); | 71 | read_lock(&exec_domains_lock); |
diff --git a/kernel/kmod.c b/kernel/kmod.c index 8df97d3dfda8..90d7af1c1655 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c | |||
@@ -42,7 +42,7 @@ extern int max_threads; | |||
42 | 42 | ||
43 | static struct workqueue_struct *khelper_wq; | 43 | static struct workqueue_struct *khelper_wq; |
44 | 44 | ||
45 | #ifdef CONFIG_KMOD | 45 | #ifdef CONFIG_MODULES |
46 | 46 | ||
47 | /* | 47 | /* |
48 | modprobe_path is set via /proc/sys. | 48 | modprobe_path is set via /proc/sys. |
diff --git a/kernel/module.c b/kernel/module.c index 5f80478b746d..d8b5605132a0 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,156 +157,186 @@ 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 | 180 | ||
231 | for (i = 0; i < num; i++) { | 181 | for (j = 0; j < arrsize; j++) { |
232 | ks = lookup_symbol(name, arr[i].start, arr[i].stop); | 182 | for (i = 0; i < arr[j].stop - arr[j].start; i++) |
233 | if (!ks || !arr[i].check(gplok, warn, name)) | 183 | if (fn(&arr[j], owner, i, data)) |
234 | continue; | 184 | return true; |
235 | |||
236 | if (crc) | ||
237 | *crc = symversion(arr[i].crcs, ks - arr[i].start); | ||
238 | return ks; | ||
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 | } |
304 | 327 | ||
328 | /* lookup symbol in given range of kernel_symbols */ | ||
329 | static const struct kernel_symbol *lookup_symbol(const char *name, | ||
330 | const struct kernel_symbol *start, | ||
331 | const struct kernel_symbol *stop) | ||
332 | { | ||
333 | const struct kernel_symbol *ks = start; | ||
334 | for (; ks < stop; ks++) | ||
335 | if (strcmp(ks->name, name) == 0) | ||
336 | return ks; | ||
337 | return NULL; | ||
338 | } | ||
339 | |||
305 | /* Search for module by name: must hold module_mutex. */ | 340 | /* Search for module by name: must hold module_mutex. */ |
306 | static struct module *find_module(const char *name) | 341 | static struct module *find_module(const char *name) |
307 | { | 342 | { |
@@ -639,8 +674,8 @@ static int __try_stop_module(void *_sref) | |||
639 | { | 674 | { |
640 | struct stopref *sref = _sref; | 675 | struct stopref *sref = _sref; |
641 | 676 | ||
642 | /* If it's not unused, quit unless we are told to block. */ | 677 | /* If it's not unused, quit unless we're forcing. */ |
643 | if ((sref->flags & O_NONBLOCK) && module_refcount(sref->mod) != 0) { | 678 | if (module_refcount(sref->mod) != 0) { |
644 | if (!(*sref->forced = try_force_unload(sref->flags))) | 679 | if (!(*sref->forced = try_force_unload(sref->flags))) |
645 | return -EWOULDBLOCK; | 680 | return -EWOULDBLOCK; |
646 | } | 681 | } |
@@ -652,9 +687,16 @@ static int __try_stop_module(void *_sref) | |||
652 | 687 | ||
653 | static int try_stop_module(struct module *mod, int flags, int *forced) | 688 | static int try_stop_module(struct module *mod, int flags, int *forced) |
654 | { | 689 | { |
655 | struct stopref sref = { mod, flags, forced }; | 690 | if (flags & O_NONBLOCK) { |
691 | struct stopref sref = { mod, flags, forced }; | ||
656 | 692 | ||
657 | return stop_machine_run(__try_stop_module, &sref, NR_CPUS); | 693 | return stop_machine_run(__try_stop_module, &sref, NR_CPUS); |
694 | } else { | ||
695 | /* We don't need to stop the machine for this. */ | ||
696 | mod->state = MODULE_STATE_GOING; | ||
697 | synchronize_sched(); | ||
698 | return 0; | ||
699 | } | ||
658 | } | 700 | } |
659 | 701 | ||
660 | unsigned int module_refcount(struct module *mod) | 702 | unsigned int module_refcount(struct module *mod) |
@@ -1445,8 +1487,10 @@ static int verify_export_symbols(struct module *mod) | |||
1445 | { mod->syms, mod->num_syms }, | 1487 | { mod->syms, mod->num_syms }, |
1446 | { mod->gpl_syms, mod->num_gpl_syms }, | 1488 | { mod->gpl_syms, mod->num_gpl_syms }, |
1447 | { mod->gpl_future_syms, mod->num_gpl_future_syms }, | 1489 | { mod->gpl_future_syms, mod->num_gpl_future_syms }, |
1490 | #ifdef CONFIG_UNUSED_SYMBOLS | ||
1448 | { mod->unused_syms, mod->num_unused_syms }, | 1491 | { mod->unused_syms, mod->num_unused_syms }, |
1449 | { mod->unused_gpl_syms, mod->num_unused_gpl_syms }, | 1492 | { mod->unused_gpl_syms, mod->num_unused_gpl_syms }, |
1493 | #endif | ||
1450 | }; | 1494 | }; |
1451 | 1495 | ||
1452 | for (i = 0; i < ARRAY_SIZE(arr); i++) { | 1496 | for (i = 0; i < ARRAY_SIZE(arr); i++) { |
@@ -1526,7 +1570,7 @@ static int simplify_symbols(Elf_Shdr *sechdrs, | |||
1526 | } | 1570 | } |
1527 | 1571 | ||
1528 | /* Update size with this section: return offset. */ | 1572 | /* Update size with this section: return offset. */ |
1529 | static long get_offset(unsigned long *size, Elf_Shdr *sechdr) | 1573 | static long get_offset(unsigned int *size, Elf_Shdr *sechdr) |
1530 | { | 1574 | { |
1531 | long ret; | 1575 | long ret; |
1532 | 1576 | ||
@@ -1738,6 +1782,20 @@ static inline void add_kallsyms(struct module *mod, | |||
1738 | } | 1782 | } |
1739 | #endif /* CONFIG_KALLSYMS */ | 1783 | #endif /* CONFIG_KALLSYMS */ |
1740 | 1784 | ||
1785 | static void *module_alloc_update_bounds(unsigned long size) | ||
1786 | { | ||
1787 | void *ret = module_alloc(size); | ||
1788 | |||
1789 | if (ret) { | ||
1790 | /* Update module bounds. */ | ||
1791 | if ((unsigned long)ret < module_addr_min) | ||
1792 | module_addr_min = (unsigned long)ret; | ||
1793 | if ((unsigned long)ret + size > module_addr_max) | ||
1794 | module_addr_max = (unsigned long)ret + size; | ||
1795 | } | ||
1796 | return ret; | ||
1797 | } | ||
1798 | |||
1741 | /* Allocate and load the module: note that size of section 0 is always | 1799 | /* Allocate and load the module: note that size of section 0 is always |
1742 | zero, and we rely on this for optional sections. */ | 1800 | zero, and we rely on this for optional sections. */ |
1743 | static struct module *load_module(void __user *umod, | 1801 | static struct module *load_module(void __user *umod, |
@@ -1764,10 +1822,12 @@ static struct module *load_module(void __user *umod, | |||
1764 | unsigned int gplfutureindex; | 1822 | unsigned int gplfutureindex; |
1765 | unsigned int gplfuturecrcindex; | 1823 | unsigned int gplfuturecrcindex; |
1766 | unsigned int unwindex = 0; | 1824 | unsigned int unwindex = 0; |
1825 | #ifdef CONFIG_UNUSED_SYMBOLS | ||
1767 | unsigned int unusedindex; | 1826 | unsigned int unusedindex; |
1768 | unsigned int unusedcrcindex; | 1827 | unsigned int unusedcrcindex; |
1769 | unsigned int unusedgplindex; | 1828 | unsigned int unusedgplindex; |
1770 | unsigned int unusedgplcrcindex; | 1829 | unsigned int unusedgplcrcindex; |
1830 | #endif | ||
1771 | unsigned int markersindex; | 1831 | unsigned int markersindex; |
1772 | unsigned int markersstringsindex; | 1832 | unsigned int markersstringsindex; |
1773 | struct module *mod; | 1833 | struct module *mod; |
@@ -1850,13 +1910,15 @@ static struct module *load_module(void __user *umod, | |||
1850 | exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab"); | 1910 | exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab"); |
1851 | gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl"); | 1911 | gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl"); |
1852 | gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future"); | 1912 | 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"); | 1913 | crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab"); |
1856 | gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl"); | 1914 | gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl"); |
1857 | gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future"); | 1915 | gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future"); |
1916 | #ifdef CONFIG_UNUSED_SYMBOLS | ||
1917 | unusedindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused"); | ||
1918 | unusedgplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused_gpl"); | ||
1858 | unusedcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused"); | 1919 | unusedcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused"); |
1859 | unusedgplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused_gpl"); | 1920 | unusedgplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused_gpl"); |
1921 | #endif | ||
1860 | setupindex = find_sec(hdr, sechdrs, secstrings, "__param"); | 1922 | setupindex = find_sec(hdr, sechdrs, secstrings, "__param"); |
1861 | exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table"); | 1923 | exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table"); |
1862 | obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm"); | 1924 | obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm"); |
@@ -1935,7 +1997,7 @@ static struct module *load_module(void __user *umod, | |||
1935 | layout_sections(mod, hdr, sechdrs, secstrings); | 1997 | layout_sections(mod, hdr, sechdrs, secstrings); |
1936 | 1998 | ||
1937 | /* Do the allocs. */ | 1999 | /* Do the allocs. */ |
1938 | ptr = module_alloc(mod->core_size); | 2000 | ptr = module_alloc_update_bounds(mod->core_size); |
1939 | if (!ptr) { | 2001 | if (!ptr) { |
1940 | err = -ENOMEM; | 2002 | err = -ENOMEM; |
1941 | goto free_percpu; | 2003 | goto free_percpu; |
@@ -1943,7 +2005,7 @@ static struct module *load_module(void __user *umod, | |||
1943 | memset(ptr, 0, mod->core_size); | 2005 | memset(ptr, 0, mod->core_size); |
1944 | mod->module_core = ptr; | 2006 | mod->module_core = ptr; |
1945 | 2007 | ||
1946 | ptr = module_alloc(mod->init_size); | 2008 | ptr = module_alloc_update_bounds(mod->init_size); |
1947 | if (!ptr && mod->init_size) { | 2009 | if (!ptr && mod->init_size) { |
1948 | err = -ENOMEM; | 2010 | err = -ENOMEM; |
1949 | goto free_core; | 2011 | goto free_core; |
@@ -2018,14 +2080,15 @@ static struct module *load_module(void __user *umod, | |||
2018 | mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr; | 2080 | mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr; |
2019 | mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size / | 2081 | mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size / |
2020 | sizeof(*mod->gpl_future_syms); | 2082 | 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; | 2083 | mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr; |
2026 | if (gplfuturecrcindex) | 2084 | if (gplfuturecrcindex) |
2027 | mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr; | 2085 | mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr; |
2028 | 2086 | ||
2087 | #ifdef CONFIG_UNUSED_SYMBOLS | ||
2088 | mod->num_unused_syms = sechdrs[unusedindex].sh_size / | ||
2089 | sizeof(*mod->unused_syms); | ||
2090 | mod->num_unused_gpl_syms = sechdrs[unusedgplindex].sh_size / | ||
2091 | sizeof(*mod->unused_gpl_syms); | ||
2029 | mod->unused_syms = (void *)sechdrs[unusedindex].sh_addr; | 2092 | mod->unused_syms = (void *)sechdrs[unusedindex].sh_addr; |
2030 | if (unusedcrcindex) | 2093 | if (unusedcrcindex) |
2031 | mod->unused_crcs = (void *)sechdrs[unusedcrcindex].sh_addr; | 2094 | mod->unused_crcs = (void *)sechdrs[unusedcrcindex].sh_addr; |
@@ -2033,13 +2096,17 @@ static struct module *load_module(void __user *umod, | |||
2033 | if (unusedgplcrcindex) | 2096 | if (unusedgplcrcindex) |
2034 | mod->unused_gpl_crcs | 2097 | mod->unused_gpl_crcs |
2035 | = (void *)sechdrs[unusedgplcrcindex].sh_addr; | 2098 | = (void *)sechdrs[unusedgplcrcindex].sh_addr; |
2099 | #endif | ||
2036 | 2100 | ||
2037 | #ifdef CONFIG_MODVERSIONS | 2101 | #ifdef CONFIG_MODVERSIONS |
2038 | if ((mod->num_syms && !crcindex) || | 2102 | if ((mod->num_syms && !crcindex) |
2039 | (mod->num_gpl_syms && !gplcrcindex) || | 2103 | || (mod->num_gpl_syms && !gplcrcindex) |
2040 | (mod->num_gpl_future_syms && !gplfuturecrcindex) || | 2104 | || (mod->num_gpl_future_syms && !gplfuturecrcindex) |
2041 | (mod->num_unused_syms && !unusedcrcindex) || | 2105 | #ifdef CONFIG_UNUSED_SYMBOLS |
2042 | (mod->num_unused_gpl_syms && !unusedgplcrcindex)) { | 2106 | || (mod->num_unused_syms && !unusedcrcindex) |
2107 | || (mod->num_unused_gpl_syms && !unusedgplcrcindex) | ||
2108 | #endif | ||
2109 | ) { | ||
2043 | printk(KERN_WARNING "%s: No versions for exported symbols.\n", mod->name); | 2110 | printk(KERN_WARNING "%s: No versions for exported symbols.\n", mod->name); |
2044 | err = try_to_force_load(mod, "nocrc"); | 2111 | err = try_to_force_load(mod, "nocrc"); |
2045 | if (err) | 2112 | if (err) |
@@ -2512,7 +2579,7 @@ static int m_show(struct seq_file *m, void *p) | |||
2512 | struct module *mod = list_entry(p, struct module, list); | 2579 | struct module *mod = list_entry(p, struct module, list); |
2513 | char buf[8]; | 2580 | char buf[8]; |
2514 | 2581 | ||
2515 | seq_printf(m, "%s %lu", | 2582 | seq_printf(m, "%s %u", |
2516 | mod->name, mod->init_size + mod->core_size); | 2583 | mod->name, mod->init_size + mod->core_size); |
2517 | print_unload_info(m, mod); | 2584 | print_unload_info(m, mod); |
2518 | 2585 | ||
@@ -2595,6 +2662,9 @@ struct module *__module_text_address(unsigned long addr) | |||
2595 | { | 2662 | { |
2596 | struct module *mod; | 2663 | struct module *mod; |
2597 | 2664 | ||
2665 | if (addr < module_addr_min || addr > module_addr_max) | ||
2666 | return NULL; | ||
2667 | |||
2598 | list_for_each_entry(mod, &modules, list) | 2668 | list_for_each_entry(mod, &modules, list) |
2599 | if (within(addr, mod->module_init, mod->init_text_size) | 2669 | if (within(addr, mod->module_init, mod->init_text_size) |
2600 | || within(addr, mod->module_core, mod->core_text_size)) | 2670 | || within(addr, mod->module_core, mod->core_text_size)) |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 6b16e16428d8..b859e6b5a767 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -110,7 +110,7 @@ static int min_percpu_pagelist_fract = 8; | |||
110 | 110 | ||
111 | static int ngroups_max = NGROUPS_MAX; | 111 | static int ngroups_max = NGROUPS_MAX; |
112 | 112 | ||
113 | #ifdef CONFIG_KMOD | 113 | #ifdef CONFIG_MODULES |
114 | extern char modprobe_path[]; | 114 | extern char modprobe_path[]; |
115 | #endif | 115 | #endif |
116 | #ifdef CONFIG_CHR_DEV_SG | 116 | #ifdef CONFIG_CHR_DEV_SG |
@@ -475,7 +475,7 @@ static struct ctl_table kern_table[] = { | |||
475 | .proc_handler = &ftrace_enable_sysctl, | 475 | .proc_handler = &ftrace_enable_sysctl, |
476 | }, | 476 | }, |
477 | #endif | 477 | #endif |
478 | #ifdef CONFIG_KMOD | 478 | #ifdef CONFIG_MODULES |
479 | { | 479 | { |
480 | .ctl_name = KERN_MODPROBE, | 480 | .ctl_name = KERN_MODPROBE, |
481 | .procname = "modprobe", | 481 | .procname = "modprobe", |