aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-05-19 17:56:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-05-19 17:56:13 -0400
commit98a38a5d60a6e79eaad7f4a9b68cc1bd306ac5c0 (patch)
treebc6e761e7ead6b877c28abe908eaf9745c4f8627
parent7663164f2619e37a1dcad59383e2fcf8c5194107 (diff)
parentf721a465cddbe7f03e6cd2272008da558cf93818 (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: params.c: Use new strtobool function to process boolean inputs debugfs: move to new strtobool Add a strtobool function matching semantics of existing in kernel equivalents modpost: Update 64k section support for binutils 2.18.50 module: Use binary search in lookup_symbol() module: Use the binary search for symbols resolution lib: Add generic binary search function to the kernel. module: Sort exported symbols module: each_symbol_section instead of each_symbol module: split unset_section_ro_nx function. module: undo module RONX protection correctly. module: zero mod->init_ro_size after init is freed. minor ANSI prototype sparse fix module: reorder kparam_array to remove alignment padding on 64 bit builds module: remove 64 bit alignment padding from struct module with CONFIG_TRACE* module: do not hide __modver_version_show declaration behind ifdef module: deal with alignment issues in built-in module versions
-rw-r--r--arch/s390/include/asm/cacheflush.h1
-rw-r--r--arch/s390/mm/pageattr.c5
-rw-r--r--fs/debugfs/file.c17
-rw-r--r--include/asm-generic/vmlinux.lds.h20
-rw-r--r--include/linux/bsearch.h9
-rw-r--r--include/linux/module.h37
-rw-r--r--include/linux/moduleparam.h7
-rw-r--r--include/linux/string.h1
-rw-r--r--kernel/module.c105
-rw-r--r--kernel/params.c23
-rw-r--r--lib/Makefile3
-rw-r--r--lib/bsearch.c53
-rw-r--r--lib/string.c29
-rw-r--r--scripts/mod/modpost.c16
-rw-r--r--scripts/mod/modpost.h27
-rw-r--r--scripts/module-common.lds11
16 files changed, 237 insertions, 127 deletions
diff --git a/arch/s390/include/asm/cacheflush.h b/arch/s390/include/asm/cacheflush.h
index 43a5c78046db..3e20383d0921 100644
--- a/arch/s390/include/asm/cacheflush.h
+++ b/arch/s390/include/asm/cacheflush.h
@@ -11,5 +11,6 @@ void kernel_map_pages(struct page *page, int numpages, int enable);
11int set_memory_ro(unsigned long addr, int numpages); 11int set_memory_ro(unsigned long addr, int numpages);
12int set_memory_rw(unsigned long addr, int numpages); 12int set_memory_rw(unsigned long addr, int numpages);
13int set_memory_nx(unsigned long addr, int numpages); 13int set_memory_nx(unsigned long addr, int numpages);
14int set_memory_x(unsigned long addr, int numpages);
14 15
15#endif /* _S390_CACHEFLUSH_H */ 16#endif /* _S390_CACHEFLUSH_H */
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
index 0607e4b14b27..f05edcc3beff 100644
--- a/arch/s390/mm/pageattr.c
+++ b/arch/s390/mm/pageattr.c
@@ -54,3 +54,8 @@ int set_memory_nx(unsigned long addr, int numpages)
54 return 0; 54 return 0;
55} 55}
56EXPORT_SYMBOL_GPL(set_memory_nx); 56EXPORT_SYMBOL_GPL(set_memory_nx);
57
58int set_memory_x(unsigned long addr, int numpages)
59{
60 return 0;
61}
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 89d394d8fe24..568304d058a3 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -429,25 +429,16 @@ static ssize_t write_file_bool(struct file *file, const char __user *user_buf,
429{ 429{
430 char buf[32]; 430 char buf[32];
431 int buf_size; 431 int buf_size;
432 bool bv;
432 u32 *val = file->private_data; 433 u32 *val = file->private_data;
433 434
434 buf_size = min(count, (sizeof(buf)-1)); 435 buf_size = min(count, (sizeof(buf)-1));
435 if (copy_from_user(buf, user_buf, buf_size)) 436 if (copy_from_user(buf, user_buf, buf_size))
436 return -EFAULT; 437 return -EFAULT;
437 438
438 switch (buf[0]) { 439 if (strtobool(buf, &bv) == 0)
439 case 'y': 440 *val = bv;
440 case 'Y': 441
441 case '1':
442 *val = 1;
443 break;
444 case 'n':
445 case 'N':
446 case '0':
447 *val = 0;
448 break;
449 }
450
451 return count; 442 return count;
452} 443}
453 444
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index bd297a20ab98..b27445e00b6c 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -274,70 +274,70 @@
274 /* Kernel symbol table: Normal symbols */ \ 274 /* Kernel symbol table: Normal symbols */ \
275 __ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \ 275 __ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
276 VMLINUX_SYMBOL(__start___ksymtab) = .; \ 276 VMLINUX_SYMBOL(__start___ksymtab) = .; \
277 *(__ksymtab) \ 277 *(SORT(___ksymtab+*)) \
278 VMLINUX_SYMBOL(__stop___ksymtab) = .; \ 278 VMLINUX_SYMBOL(__stop___ksymtab) = .; \
279 } \ 279 } \
280 \ 280 \
281 /* Kernel symbol table: GPL-only symbols */ \ 281 /* Kernel symbol table: GPL-only symbols */ \
282 __ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) { \ 282 __ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) { \
283 VMLINUX_SYMBOL(__start___ksymtab_gpl) = .; \ 283 VMLINUX_SYMBOL(__start___ksymtab_gpl) = .; \
284 *(__ksymtab_gpl) \ 284 *(SORT(___ksymtab_gpl+*)) \
285 VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \ 285 VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \
286 } \ 286 } \
287 \ 287 \
288 /* Kernel symbol table: Normal unused symbols */ \ 288 /* Kernel symbol table: Normal unused symbols */ \
289 __ksymtab_unused : AT(ADDR(__ksymtab_unused) - LOAD_OFFSET) { \ 289 __ksymtab_unused : AT(ADDR(__ksymtab_unused) - LOAD_OFFSET) { \
290 VMLINUX_SYMBOL(__start___ksymtab_unused) = .; \ 290 VMLINUX_SYMBOL(__start___ksymtab_unused) = .; \
291 *(__ksymtab_unused) \ 291 *(SORT(___ksymtab_unused+*)) \
292 VMLINUX_SYMBOL(__stop___ksymtab_unused) = .; \ 292 VMLINUX_SYMBOL(__stop___ksymtab_unused) = .; \
293 } \ 293 } \
294 \ 294 \
295 /* Kernel symbol table: GPL-only unused symbols */ \ 295 /* Kernel symbol table: GPL-only unused symbols */ \
296 __ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - LOAD_OFFSET) { \ 296 __ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - LOAD_OFFSET) { \
297 VMLINUX_SYMBOL(__start___ksymtab_unused_gpl) = .; \ 297 VMLINUX_SYMBOL(__start___ksymtab_unused_gpl) = .; \
298 *(__ksymtab_unused_gpl) \ 298 *(SORT(___ksymtab_unused_gpl+*)) \
299 VMLINUX_SYMBOL(__stop___ksymtab_unused_gpl) = .; \ 299 VMLINUX_SYMBOL(__stop___ksymtab_unused_gpl) = .; \
300 } \ 300 } \
301 \ 301 \
302 /* Kernel symbol table: GPL-future-only symbols */ \ 302 /* Kernel symbol table: GPL-future-only symbols */ \
303 __ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \ 303 __ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \
304 VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .; \ 304 VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .; \
305 *(__ksymtab_gpl_future) \ 305 *(SORT(___ksymtab_gpl_future+*)) \
306 VMLINUX_SYMBOL(__stop___ksymtab_gpl_future) = .; \ 306 VMLINUX_SYMBOL(__stop___ksymtab_gpl_future) = .; \
307 } \ 307 } \
308 \ 308 \
309 /* Kernel symbol table: Normal symbols */ \ 309 /* Kernel symbol table: Normal symbols */ \
310 __kcrctab : AT(ADDR(__kcrctab) - LOAD_OFFSET) { \ 310 __kcrctab : AT(ADDR(__kcrctab) - LOAD_OFFSET) { \
311 VMLINUX_SYMBOL(__start___kcrctab) = .; \ 311 VMLINUX_SYMBOL(__start___kcrctab) = .; \
312 *(__kcrctab) \ 312 *(SORT(___kcrctab+*)) \
313 VMLINUX_SYMBOL(__stop___kcrctab) = .; \ 313 VMLINUX_SYMBOL(__stop___kcrctab) = .; \
314 } \ 314 } \
315 \ 315 \
316 /* Kernel symbol table: GPL-only symbols */ \ 316 /* Kernel symbol table: GPL-only symbols */ \
317 __kcrctab_gpl : AT(ADDR(__kcrctab_gpl) - LOAD_OFFSET) { \ 317 __kcrctab_gpl : AT(ADDR(__kcrctab_gpl) - LOAD_OFFSET) { \
318 VMLINUX_SYMBOL(__start___kcrctab_gpl) = .; \ 318 VMLINUX_SYMBOL(__start___kcrctab_gpl) = .; \
319 *(__kcrctab_gpl) \ 319 *(SORT(___kcrctab_gpl+*)) \
320 VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .; \ 320 VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .; \
321 } \ 321 } \
322 \ 322 \
323 /* Kernel symbol table: Normal unused symbols */ \ 323 /* Kernel symbol table: Normal unused symbols */ \
324 __kcrctab_unused : AT(ADDR(__kcrctab_unused) - LOAD_OFFSET) { \ 324 __kcrctab_unused : AT(ADDR(__kcrctab_unused) - LOAD_OFFSET) { \
325 VMLINUX_SYMBOL(__start___kcrctab_unused) = .; \ 325 VMLINUX_SYMBOL(__start___kcrctab_unused) = .; \
326 *(__kcrctab_unused) \ 326 *(SORT(___kcrctab_unused+*)) \
327 VMLINUX_SYMBOL(__stop___kcrctab_unused) = .; \ 327 VMLINUX_SYMBOL(__stop___kcrctab_unused) = .; \
328 } \ 328 } \
329 \ 329 \
330 /* Kernel symbol table: GPL-only unused symbols */ \ 330 /* Kernel symbol table: GPL-only unused symbols */ \
331 __kcrctab_unused_gpl : AT(ADDR(__kcrctab_unused_gpl) - LOAD_OFFSET) { \ 331 __kcrctab_unused_gpl : AT(ADDR(__kcrctab_unused_gpl) - LOAD_OFFSET) { \
332 VMLINUX_SYMBOL(__start___kcrctab_unused_gpl) = .; \ 332 VMLINUX_SYMBOL(__start___kcrctab_unused_gpl) = .; \
333 *(__kcrctab_unused_gpl) \ 333 *(SORT(___kcrctab_unused_gpl+*)) \
334 VMLINUX_SYMBOL(__stop___kcrctab_unused_gpl) = .; \ 334 VMLINUX_SYMBOL(__stop___kcrctab_unused_gpl) = .; \
335 } \ 335 } \
336 \ 336 \
337 /* Kernel symbol table: GPL-future-only symbols */ \ 337 /* Kernel symbol table: GPL-future-only symbols */ \
338 __kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - LOAD_OFFSET) { \ 338 __kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - LOAD_OFFSET) { \
339 VMLINUX_SYMBOL(__start___kcrctab_gpl_future) = .; \ 339 VMLINUX_SYMBOL(__start___kcrctab_gpl_future) = .; \
340 *(__kcrctab_gpl_future) \ 340 *(SORT(___kcrctab_gpl_future+*)) \
341 VMLINUX_SYMBOL(__stop___kcrctab_gpl_future) = .; \ 341 VMLINUX_SYMBOL(__stop___kcrctab_gpl_future) = .; \
342 } \ 342 } \
343 \ 343 \
diff --git a/include/linux/bsearch.h b/include/linux/bsearch.h
new file mode 100644
index 000000000000..90b1aa867224
--- /dev/null
+++ b/include/linux/bsearch.h
@@ -0,0 +1,9 @@
1#ifndef _LINUX_BSEARCH_H
2#define _LINUX_BSEARCH_H
3
4#include <linux/types.h>
5
6void *bsearch(const void *key, const void *base, size_t num, size_t size,
7 int (*cmp)(const void *key, const void *elt));
8
9#endif /* _LINUX_BSEARCH_H */
diff --git a/include/linux/module.h b/include/linux/module.h
index 5de42043dff0..d9ca2d5dc6d0 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -64,6 +64,9 @@ struct module_version_attribute {
64 const char *version; 64 const char *version;
65} __attribute__ ((__aligned__(sizeof(void *)))); 65} __attribute__ ((__aligned__(sizeof(void *))));
66 66
67extern ssize_t __modver_version_show(struct module_attribute *,
68 struct module *, char *);
69
67struct module_kobject 70struct module_kobject
68{ 71{
69 struct kobject kobj; 72 struct kobject kobj;
@@ -172,12 +175,7 @@ extern struct module __this_module;
172#define MODULE_VERSION(_version) MODULE_INFO(version, _version) 175#define MODULE_VERSION(_version) MODULE_INFO(version, _version)
173#else 176#else
174#define MODULE_VERSION(_version) \ 177#define MODULE_VERSION(_version) \
175 extern ssize_t __modver_version_show(struct module_attribute *, \ 178 static struct module_version_attribute ___modver_attr = { \
176 struct module *, char *); \
177 static struct module_version_attribute __modver_version_attr \
178 __used \
179 __attribute__ ((__section__ ("__modver"),aligned(sizeof(void *)))) \
180 = { \
181 .mattr = { \ 179 .mattr = { \
182 .attr = { \ 180 .attr = { \
183 .name = "version", \ 181 .name = "version", \
@@ -187,7 +185,10 @@ extern struct module __this_module;
187 }, \ 185 }, \
188 .module_name = KBUILD_MODNAME, \ 186 .module_name = KBUILD_MODNAME, \
189 .version = _version, \ 187 .version = _version, \
190 } 188 }; \
189 static const struct module_version_attribute \
190 __used __attribute__ ((__section__ ("__modver"))) \
191 * __moduleparam_const __modver_attr = &___modver_attr
191#endif 192#endif
192 193
193/* Optional firmware file (or files) needed by the module 194/* Optional firmware file (or files) needed by the module
@@ -223,7 +224,7 @@ struct module_use {
223 extern void *__crc_##sym __attribute__((weak)); \ 224 extern void *__crc_##sym __attribute__((weak)); \
224 static const unsigned long __kcrctab_##sym \ 225 static const unsigned long __kcrctab_##sym \
225 __used \ 226 __used \
226 __attribute__((section("__kcrctab" sec), unused)) \ 227 __attribute__((section("___kcrctab" sec "+" #sym), unused)) \
227 = (unsigned long) &__crc_##sym; 228 = (unsigned long) &__crc_##sym;
228#else 229#else
229#define __CRC_SYMBOL(sym, sec) 230#define __CRC_SYMBOL(sym, sec)
@@ -238,7 +239,7 @@ struct module_use {
238 = MODULE_SYMBOL_PREFIX #sym; \ 239 = MODULE_SYMBOL_PREFIX #sym; \
239 static const struct kernel_symbol __ksymtab_##sym \ 240 static const struct kernel_symbol __ksymtab_##sym \
240 __used \ 241 __used \
241 __attribute__((section("__ksymtab" sec), unused)) \ 242 __attribute__((section("___ksymtab" sec "+" #sym), unused)) \
242 = { (unsigned long)&sym, __kstrtab_##sym } 243 = { (unsigned long)&sym, __kstrtab_##sym }
243 244
244#define EXPORT_SYMBOL(sym) \ 245#define EXPORT_SYMBOL(sym) \
@@ -367,34 +368,35 @@ struct module
367 struct module_notes_attrs *notes_attrs; 368 struct module_notes_attrs *notes_attrs;
368#endif 369#endif
369 370
371 /* The command line arguments (may be mangled). People like
372 keeping pointers to this stuff */
373 char *args;
374
370#ifdef CONFIG_SMP 375#ifdef CONFIG_SMP
371 /* Per-cpu data. */ 376 /* Per-cpu data. */
372 void __percpu *percpu; 377 void __percpu *percpu;
373 unsigned int percpu_size; 378 unsigned int percpu_size;
374#endif 379#endif
375 380
376 /* The command line arguments (may be mangled). People like
377 keeping pointers to this stuff */
378 char *args;
379#ifdef CONFIG_TRACEPOINTS 381#ifdef CONFIG_TRACEPOINTS
380 struct tracepoint * const *tracepoints_ptrs;
381 unsigned int num_tracepoints; 382 unsigned int num_tracepoints;
383 struct tracepoint * const *tracepoints_ptrs;
382#endif 384#endif
383#ifdef HAVE_JUMP_LABEL 385#ifdef HAVE_JUMP_LABEL
384 struct jump_entry *jump_entries; 386 struct jump_entry *jump_entries;
385 unsigned int num_jump_entries; 387 unsigned int num_jump_entries;
386#endif 388#endif
387#ifdef CONFIG_TRACING 389#ifdef CONFIG_TRACING
388 const char **trace_bprintk_fmt_start;
389 unsigned int num_trace_bprintk_fmt; 390 unsigned int num_trace_bprintk_fmt;
391 const char **trace_bprintk_fmt_start;
390#endif 392#endif
391#ifdef CONFIG_EVENT_TRACING 393#ifdef CONFIG_EVENT_TRACING
392 struct ftrace_event_call **trace_events; 394 struct ftrace_event_call **trace_events;
393 unsigned int num_trace_events; 395 unsigned int num_trace_events;
394#endif 396#endif
395#ifdef CONFIG_FTRACE_MCOUNT_RECORD 397#ifdef CONFIG_FTRACE_MCOUNT_RECORD
396 unsigned long *ftrace_callsites;
397 unsigned int num_ftrace_callsites; 398 unsigned int num_ftrace_callsites;
399 unsigned long *ftrace_callsites;
398#endif 400#endif
399 401
400#ifdef CONFIG_MODULE_UNLOAD 402#ifdef CONFIG_MODULE_UNLOAD
@@ -475,8 +477,9 @@ const struct kernel_symbol *find_symbol(const char *name,
475 bool warn); 477 bool warn);
476 478
477/* Walk the exported symbol table */ 479/* Walk the exported symbol table */
478bool each_symbol(bool (*fn)(const struct symsearch *arr, struct module *owner, 480bool each_symbol_section(bool (*fn)(const struct symsearch *arr,
479 unsigned int symnum, void *data), void *data); 481 struct module *owner,
482 void *data), void *data);
480 483
481/* Returns 0 and fills in value, defined and namebuf, or -ERANGE if 484/* Returns 0 and fills in value, defined and namebuf, or -ERANGE if
482 symnum out of range. */ 485 symnum out of range. */
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index 07b41951e3fa..ddaae98c53f9 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -67,9 +67,9 @@ struct kparam_string {
67struct kparam_array 67struct kparam_array
68{ 68{
69 unsigned int max; 69 unsigned int max;
70 unsigned int elemsize;
70 unsigned int *num; 71 unsigned int *num;
71 const struct kernel_param_ops *ops; 72 const struct kernel_param_ops *ops;
72 unsigned int elemsize;
73 void *elem; 73 void *elem;
74}; 74};
75 75
@@ -371,8 +371,9 @@ extern int param_get_invbool(char *buffer, const struct kernel_param *kp);
371 */ 371 */
372#define module_param_array_named(name, array, type, nump, perm) \ 372#define module_param_array_named(name, array, type, nump, perm) \
373 static const struct kparam_array __param_arr_##name \ 373 static const struct kparam_array __param_arr_##name \
374 = { ARRAY_SIZE(array), nump, &param_ops_##type, \ 374 = { .max = ARRAY_SIZE(array), .num = nump, \
375 sizeof(array[0]), array }; \ 375 .ops = &param_ops_##type, \
376 .elemsize = sizeof(array[0]), .elem = array }; \
376 __module_param_call(MODULE_PARAM_PREFIX, name, \ 377 __module_param_call(MODULE_PARAM_PREFIX, name, \
377 &param_array_ops, \ 378 &param_array_ops, \
378 .arr = &__param_arr_##name, \ 379 .arr = &__param_arr_##name, \
diff --git a/include/linux/string.h b/include/linux/string.h
index a716ee2a8adb..a176db2f2c85 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -123,6 +123,7 @@ extern char **argv_split(gfp_t gfp, const char *str, int *argcp);
123extern void argv_free(char **argv); 123extern void argv_free(char **argv);
124 124
125extern bool sysfs_streq(const char *s1, const char *s2); 125extern bool sysfs_streq(const char *s1, const char *s2);
126extern int strtobool(const char *s, bool *res);
126 127
127#ifdef CONFIG_BINARY_PRINTF 128#ifdef CONFIG_BINARY_PRINTF
128int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args); 129int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args);
diff --git a/kernel/module.c b/kernel/module.c
index d5938a5c19c4..22879725678d 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -57,6 +57,7 @@
57#include <linux/kmemleak.h> 57#include <linux/kmemleak.h>
58#include <linux/jump_label.h> 58#include <linux/jump_label.h>
59#include <linux/pfn.h> 59#include <linux/pfn.h>
60#include <linux/bsearch.h>
60 61
61#define CREATE_TRACE_POINTS 62#define CREATE_TRACE_POINTS
62#include <trace/events/module.h> 63#include <trace/events/module.h>
@@ -240,23 +241,24 @@ static bool each_symbol_in_section(const struct symsearch *arr,
240 struct module *owner, 241 struct module *owner,
241 bool (*fn)(const struct symsearch *syms, 242 bool (*fn)(const struct symsearch *syms,
242 struct module *owner, 243 struct module *owner,
243 unsigned int symnum, void *data), 244 void *data),
244 void *data) 245 void *data)
245{ 246{
246 unsigned int i, j; 247 unsigned int j;
247 248
248 for (j = 0; j < arrsize; j++) { 249 for (j = 0; j < arrsize; j++) {
249 for (i = 0; i < arr[j].stop - arr[j].start; i++) 250 if (fn(&arr[j], owner, data))
250 if (fn(&arr[j], owner, i, data)) 251 return true;
251 return true;
252 } 252 }
253 253
254 return false; 254 return false;
255} 255}
256 256
257/* Returns true as soon as fn returns true, otherwise false. */ 257/* Returns true as soon as fn returns true, otherwise false. */
258bool each_symbol(bool (*fn)(const struct symsearch *arr, struct module *owner, 258bool each_symbol_section(bool (*fn)(const struct symsearch *arr,
259 unsigned int symnum, void *data), void *data) 259 struct module *owner,
260 void *data),
261 void *data)
260{ 262{
261 struct module *mod; 263 struct module *mod;
262 static const struct symsearch arr[] = { 264 static const struct symsearch arr[] = {
@@ -309,7 +311,7 @@ bool each_symbol(bool (*fn)(const struct symsearch *arr, struct module *owner,
309 } 311 }
310 return false; 312 return false;
311} 313}
312EXPORT_SYMBOL_GPL(each_symbol); 314EXPORT_SYMBOL_GPL(each_symbol_section);
313 315
314struct find_symbol_arg { 316struct find_symbol_arg {
315 /* Input */ 317 /* Input */
@@ -323,15 +325,12 @@ struct find_symbol_arg {
323 const struct kernel_symbol *sym; 325 const struct kernel_symbol *sym;
324}; 326};
325 327
326static bool find_symbol_in_section(const struct symsearch *syms, 328static bool check_symbol(const struct symsearch *syms,
327 struct module *owner, 329 struct module *owner,
328 unsigned int symnum, void *data) 330 unsigned int symnum, void *data)
329{ 331{
330 struct find_symbol_arg *fsa = data; 332 struct find_symbol_arg *fsa = data;
331 333
332 if (strcmp(syms->start[symnum].name, fsa->name) != 0)
333 return false;
334
335 if (!fsa->gplok) { 334 if (!fsa->gplok) {
336 if (syms->licence == GPL_ONLY) 335 if (syms->licence == GPL_ONLY)
337 return false; 336 return false;
@@ -365,6 +364,30 @@ static bool find_symbol_in_section(const struct symsearch *syms,
365 return true; 364 return true;
366} 365}
367 366
367static int cmp_name(const void *va, const void *vb)
368{
369 const char *a;
370 const struct kernel_symbol *b;
371 a = va; b = vb;
372 return strcmp(a, b->name);
373}
374
375static bool find_symbol_in_section(const struct symsearch *syms,
376 struct module *owner,
377 void *data)
378{
379 struct find_symbol_arg *fsa = data;
380 struct kernel_symbol *sym;
381
382 sym = bsearch(fsa->name, syms->start, syms->stop - syms->start,
383 sizeof(struct kernel_symbol), cmp_name);
384
385 if (sym != NULL && check_symbol(syms, owner, sym - syms->start, data))
386 return true;
387
388 return false;
389}
390
368/* Find a symbol and return it, along with, (optional) crc and 391/* Find a symbol and return it, along with, (optional) crc and
369 * (optional) module which owns it. Needs preempt disabled or module_mutex. */ 392 * (optional) module which owns it. Needs preempt disabled or module_mutex. */
370const struct kernel_symbol *find_symbol(const char *name, 393const struct kernel_symbol *find_symbol(const char *name,
@@ -379,7 +402,7 @@ const struct kernel_symbol *find_symbol(const char *name,
379 fsa.gplok = gplok; 402 fsa.gplok = gplok;
380 fsa.warn = warn; 403 fsa.warn = warn;
381 404
382 if (each_symbol(find_symbol_in_section, &fsa)) { 405 if (each_symbol_section(find_symbol_in_section, &fsa)) {
383 if (owner) 406 if (owner)
384 *owner = fsa.owner; 407 *owner = fsa.owner;
385 if (crc) 408 if (crc)
@@ -1607,27 +1630,28 @@ static void set_section_ro_nx(void *base,
1607 } 1630 }
1608} 1631}
1609 1632
1610/* Setting memory back to RW+NX before releasing it */ 1633static void unset_module_core_ro_nx(struct module *mod)
1611void unset_section_ro_nx(struct module *mod, void *module_region)
1612{ 1634{
1613 unsigned long total_pages; 1635 set_page_attributes(mod->module_core + mod->core_text_size,
1614 1636 mod->module_core + mod->core_size,
1615 if (mod->module_core == module_region) { 1637 set_memory_x);
1616 /* Set core as NX+RW */ 1638 set_page_attributes(mod->module_core,
1617 total_pages = MOD_NUMBER_OF_PAGES(mod->module_core, mod->core_size); 1639 mod->module_core + mod->core_ro_size,
1618 set_memory_nx((unsigned long)mod->module_core, total_pages); 1640 set_memory_rw);
1619 set_memory_rw((unsigned long)mod->module_core, total_pages); 1641}
1620 1642
1621 } else if (mod->module_init == module_region) { 1643static void unset_module_init_ro_nx(struct module *mod)
1622 /* Set init as NX+RW */ 1644{
1623 total_pages = MOD_NUMBER_OF_PAGES(mod->module_init, mod->init_size); 1645 set_page_attributes(mod->module_init + mod->init_text_size,
1624 set_memory_nx((unsigned long)mod->module_init, total_pages); 1646 mod->module_init + mod->init_size,
1625 set_memory_rw((unsigned long)mod->module_init, total_pages); 1647 set_memory_x);
1626 } 1648 set_page_attributes(mod->module_init,
1649 mod->module_init + mod->init_ro_size,
1650 set_memory_rw);
1627} 1651}
1628 1652
1629/* Iterate through all modules and set each module's text as RW */ 1653/* Iterate through all modules and set each module's text as RW */
1630void set_all_modules_text_rw() 1654void set_all_modules_text_rw(void)
1631{ 1655{
1632 struct module *mod; 1656 struct module *mod;
1633 1657
@@ -1648,7 +1672,7 @@ void set_all_modules_text_rw()
1648} 1672}
1649 1673
1650/* Iterate through all modules and set each module's text as RO */ 1674/* Iterate through all modules and set each module's text as RO */
1651void set_all_modules_text_ro() 1675void set_all_modules_text_ro(void)
1652{ 1676{
1653 struct module *mod; 1677 struct module *mod;
1654 1678
@@ -1669,7 +1693,8 @@ void set_all_modules_text_ro()
1669} 1693}
1670#else 1694#else
1671static inline void set_section_ro_nx(void *base, unsigned long text_size, unsigned long ro_size, unsigned long total_size) { } 1695static inline void set_section_ro_nx(void *base, unsigned long text_size, unsigned long ro_size, unsigned long total_size) { }
1672static inline void unset_section_ro_nx(struct module *mod, void *module_region) { } 1696static void unset_module_core_ro_nx(struct module *mod) { }
1697static void unset_module_init_ro_nx(struct module *mod) { }
1673#endif 1698#endif
1674 1699
1675/* Free a module, remove from lists, etc. */ 1700/* Free a module, remove from lists, etc. */
@@ -1696,7 +1721,7 @@ static void free_module(struct module *mod)
1696 destroy_params(mod->kp, mod->num_kp); 1721 destroy_params(mod->kp, mod->num_kp);
1697 1722
1698 /* This may be NULL, but that's OK */ 1723 /* This may be NULL, but that's OK */
1699 unset_section_ro_nx(mod, mod->module_init); 1724 unset_module_init_ro_nx(mod);
1700 module_free(mod, mod->module_init); 1725 module_free(mod, mod->module_init);
1701 kfree(mod->args); 1726 kfree(mod->args);
1702 percpu_modfree(mod); 1727 percpu_modfree(mod);
@@ -1705,7 +1730,7 @@ static void free_module(struct module *mod)
1705 lockdep_free_key_range(mod->module_core, mod->core_size); 1730 lockdep_free_key_range(mod->module_core, mod->core_size);
1706 1731
1707 /* Finally, free the core (containing the module structure) */ 1732 /* Finally, free the core (containing the module structure) */
1708 unset_section_ro_nx(mod, mod->module_core); 1733 unset_module_core_ro_nx(mod);
1709 module_free(mod, mod->module_core); 1734 module_free(mod, mod->module_core);
1710 1735
1711#ifdef CONFIG_MPU 1736#ifdef CONFIG_MPU
@@ -2030,11 +2055,8 @@ static const struct kernel_symbol *lookup_symbol(const char *name,
2030 const struct kernel_symbol *start, 2055 const struct kernel_symbol *start,
2031 const struct kernel_symbol *stop) 2056 const struct kernel_symbol *stop)
2032{ 2057{
2033 const struct kernel_symbol *ks = start; 2058 return bsearch(name, start, stop - start,
2034 for (; ks < stop; ks++) 2059 sizeof(struct kernel_symbol), cmp_name);
2035 if (strcmp(ks->name, name) == 0)
2036 return ks;
2037 return NULL;
2038} 2060}
2039 2061
2040static int is_exported(const char *name, unsigned long value, 2062static int is_exported(const char *name, unsigned long value,
@@ -2931,10 +2953,11 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
2931 mod->symtab = mod->core_symtab; 2953 mod->symtab = mod->core_symtab;
2932 mod->strtab = mod->core_strtab; 2954 mod->strtab = mod->core_strtab;
2933#endif 2955#endif
2934 unset_section_ro_nx(mod, mod->module_init); 2956 unset_module_init_ro_nx(mod);
2935 module_free(mod, mod->module_init); 2957 module_free(mod, mod->module_init);
2936 mod->module_init = NULL; 2958 mod->module_init = NULL;
2937 mod->init_size = 0; 2959 mod->init_size = 0;
2960 mod->init_ro_size = 0;
2938 mod->init_text_size = 0; 2961 mod->init_text_size = 0;
2939 mutex_unlock(&module_mutex); 2962 mutex_unlock(&module_mutex);
2940 2963
diff --git a/kernel/params.c b/kernel/params.c
index 7ab388a48a2e..ed72e1330862 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -297,21 +297,15 @@ EXPORT_SYMBOL(param_ops_charp);
297int param_set_bool(const char *val, const struct kernel_param *kp) 297int param_set_bool(const char *val, const struct kernel_param *kp)
298{ 298{
299 bool v; 299 bool v;
300 int ret;
300 301
301 /* No equals means "set"... */ 302 /* No equals means "set"... */
302 if (!val) val = "1"; 303 if (!val) val = "1";
303 304
304 /* One of =[yYnN01] */ 305 /* One of =[yYnN01] */
305 switch (val[0]) { 306 ret = strtobool(val, &v);
306 case 'y': case 'Y': case '1': 307 if (ret)
307 v = true; 308 return ret;
308 break;
309 case 'n': case 'N': case '0':
310 v = false;
311 break;
312 default:
313 return -EINVAL;
314 }
315 309
316 if (kp->flags & KPARAM_ISBOOL) 310 if (kp->flags & KPARAM_ISBOOL)
317 *(bool *)kp->arg = v; 311 *(bool *)kp->arg = v;
@@ -821,15 +815,18 @@ ssize_t __modver_version_show(struct module_attribute *mattr,
821 return sprintf(buf, "%s\n", vattr->version); 815 return sprintf(buf, "%s\n", vattr->version);
822} 816}
823 817
824extern struct module_version_attribute __start___modver[], __stop___modver[]; 818extern const struct module_version_attribute *__start___modver[];
819extern const struct module_version_attribute *__stop___modver[];
825 820
826static void __init version_sysfs_builtin(void) 821static void __init version_sysfs_builtin(void)
827{ 822{
828 const struct module_version_attribute *vattr; 823 const struct module_version_attribute **p;
829 struct module_kobject *mk; 824 struct module_kobject *mk;
830 int err; 825 int err;
831 826
832 for (vattr = __start___modver; vattr < __stop___modver; vattr++) { 827 for (p = __start___modver; p < __stop___modver; p++) {
828 const struct module_version_attribute *vattr = *p;
829
833 mk = locate_module_kobject(vattr->module_name); 830 mk = locate_module_kobject(vattr->module_name);
834 if (mk) { 831 if (mk) {
835 err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr); 832 err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr);
diff --git a/lib/Makefile b/lib/Makefile
index ef0f28571156..4b49a249064b 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -21,7 +21,8 @@ lib-y += kobject.o kref.o klist.o
21 21
22obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ 22obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
23 bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \ 23 bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \
24 string_helpers.o gcd.o lcm.o list_sort.o uuid.o flex_array.o 24 string_helpers.o gcd.o lcm.o list_sort.o uuid.o flex_array.o \
25 bsearch.o
25obj-y += kstrtox.o 26obj-y += kstrtox.o
26obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o 27obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
27 28
diff --git a/lib/bsearch.c b/lib/bsearch.c
new file mode 100644
index 000000000000..5b54758e2afb
--- /dev/null
+++ b/lib/bsearch.c
@@ -0,0 +1,53 @@
1/*
2 * A generic implementation of binary search for the Linux kernel
3 *
4 * Copyright (C) 2008-2009 Ksplice, Inc.
5 * Author: Tim Abbott <tabbott@ksplice.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; version 2.
10 */
11
12#include <linux/module.h>
13#include <linux/bsearch.h>
14
15/*
16 * bsearch - binary search an array of elements
17 * @key: pointer to item being searched for
18 * @base: pointer to first element to search
19 * @num: number of elements
20 * @size: size of each element
21 * @cmp: pointer to comparison function
22 *
23 * This function does a binary search on the given array. The
24 * contents of the array should already be in ascending sorted order
25 * under the provided comparison function.
26 *
27 * Note that the key need not have the same type as the elements in
28 * the array, e.g. key could be a string and the comparison function
29 * could compare the string with the struct's name field. However, if
30 * the key and elements in the array are of the same type, you can use
31 * the same comparison function for both sort() and bsearch().
32 */
33void *bsearch(const void *key, const void *base, size_t num, size_t size,
34 int (*cmp)(const void *key, const void *elt))
35{
36 size_t start = 0, end = num;
37 int result;
38
39 while (start < end) {
40 size_t mid = start + (end - start) / 2;
41
42 result = cmp(key, base + mid * size);
43 if (result < 0)
44 end = mid;
45 else if (result > 0)
46 start = mid + 1;
47 else
48 return (void *)base + mid * size;
49 }
50
51 return NULL;
52}
53EXPORT_SYMBOL(bsearch);
diff --git a/lib/string.c b/lib/string.c
index f71bead1be3e..01fad9b203e1 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -535,6 +535,35 @@ bool sysfs_streq(const char *s1, const char *s2)
535} 535}
536EXPORT_SYMBOL(sysfs_streq); 536EXPORT_SYMBOL(sysfs_streq);
537 537
538/**
539 * strtobool - convert common user inputs into boolean values
540 * @s: input string
541 * @res: result
542 *
543 * This routine returns 0 iff the first character is one of 'Yy1Nn0'.
544 * Otherwise it will return -EINVAL. Value pointed to by res is
545 * updated upon finding a match.
546 */
547int strtobool(const char *s, bool *res)
548{
549 switch (s[0]) {
550 case 'y':
551 case 'Y':
552 case '1':
553 *res = true;
554 break;
555 case 'n':
556 case 'N':
557 case '0':
558 *res = false;
559 break;
560 default:
561 return -EINVAL;
562 }
563 return 0;
564}
565EXPORT_SYMBOL(strtobool);
566
538#ifndef __HAVE_ARCH_MEMSET 567#ifndef __HAVE_ARCH_MEMSET
539/** 568/**
540 * memset - Fill a region of memory with the given value 569 * memset - Fill a region of memory with the given value
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index cd104afcc5f2..413c53693e62 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -420,11 +420,10 @@ static int parse_elf(struct elf_info *info, const char *filename)
420 return 0; 420 return 0;
421 } 421 }
422 422
423 if (hdr->e_shnum == 0) { 423 if (hdr->e_shnum == SHN_UNDEF) {
424 /* 424 /*
425 * There are more than 64k sections, 425 * There are more than 64k sections,
426 * read count from .sh_size. 426 * read count from .sh_size.
427 * note: it doesn't need shndx2secindex()
428 */ 427 */
429 info->num_sections = TO_NATIVE(sechdrs[0].sh_size); 428 info->num_sections = TO_NATIVE(sechdrs[0].sh_size);
430 } 429 }
@@ -432,8 +431,7 @@ static int parse_elf(struct elf_info *info, const char *filename)
432 info->num_sections = hdr->e_shnum; 431 info->num_sections = hdr->e_shnum;
433 } 432 }
434 if (hdr->e_shstrndx == SHN_XINDEX) { 433 if (hdr->e_shstrndx == SHN_XINDEX) {
435 info->secindex_strings = 434 info->secindex_strings = TO_NATIVE(sechdrs[0].sh_link);
436 shndx2secindex(TO_NATIVE(sechdrs[0].sh_link));
437 } 435 }
438 else { 436 else {
439 info->secindex_strings = hdr->e_shstrndx; 437 info->secindex_strings = hdr->e_shstrndx;
@@ -489,7 +487,7 @@ static int parse_elf(struct elf_info *info, const char *filename)
489 sechdrs[i].sh_offset; 487 sechdrs[i].sh_offset;
490 info->symtab_stop = (void *)hdr + 488 info->symtab_stop = (void *)hdr +
491 sechdrs[i].sh_offset + sechdrs[i].sh_size; 489 sechdrs[i].sh_offset + sechdrs[i].sh_size;
492 sh_link_idx = shndx2secindex(sechdrs[i].sh_link); 490 sh_link_idx = sechdrs[i].sh_link;
493 info->strtab = (void *)hdr + 491 info->strtab = (void *)hdr +
494 sechdrs[sh_link_idx].sh_offset; 492 sechdrs[sh_link_idx].sh_offset;
495 } 493 }
@@ -516,11 +514,9 @@ static int parse_elf(struct elf_info *info, const char *filename)
516 514
517 if (symtab_shndx_idx != ~0U) { 515 if (symtab_shndx_idx != ~0U) {
518 Elf32_Word *p; 516 Elf32_Word *p;
519 if (symtab_idx != 517 if (symtab_idx != sechdrs[symtab_shndx_idx].sh_link)
520 shndx2secindex(sechdrs[symtab_shndx_idx].sh_link))
521 fatal("%s: SYMTAB_SHNDX has bad sh_link: %u!=%u\n", 518 fatal("%s: SYMTAB_SHNDX has bad sh_link: %u!=%u\n",
522 filename, 519 filename, sechdrs[symtab_shndx_idx].sh_link,
523 shndx2secindex(sechdrs[symtab_shndx_idx].sh_link),
524 symtab_idx); 520 symtab_idx);
525 /* Fix endianness */ 521 /* Fix endianness */
526 for (p = info->symtab_shndx_start; p < info->symtab_shndx_stop; 522 for (p = info->symtab_shndx_start; p < info->symtab_shndx_stop;
@@ -1446,7 +1442,7 @@ static unsigned int *reloc_location(struct elf_info *elf,
1446 Elf_Shdr *sechdr, Elf_Rela *r) 1442 Elf_Shdr *sechdr, Elf_Rela *r)
1447{ 1443{
1448 Elf_Shdr *sechdrs = elf->sechdrs; 1444 Elf_Shdr *sechdrs = elf->sechdrs;
1449 int section = shndx2secindex(sechdr->sh_info); 1445 int section = sechdr->sh_info;
1450 1446
1451 return (void *)elf->hdr + sechdrs[section].sh_offset + 1447 return (void *)elf->hdr + sechdrs[section].sh_offset +
1452 r->r_offset; 1448 r->r_offset;
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 0388cfccac8d..2031119080dc 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -145,33 +145,22 @@ static inline int is_shndx_special(unsigned int i)
145 return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE; 145 return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE;
146} 146}
147 147
148/* shndx is in [0..SHN_LORESERVE) U (SHN_HIRESERVE, 0xfffffff], thus: 148/*
149 * shndx == 0 <=> sechdrs[0] 149 * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of
150 * ...... 150 * the way to -256..-1, to avoid conflicting with real section
151 * shndx == SHN_LORESERVE-1 <=> sechdrs[SHN_LORESERVE-1] 151 * indices.
152 * shndx == SHN_HIRESERVE+1 <=> sechdrs[SHN_LORESERVE]
153 * shndx == SHN_HIRESERVE+2 <=> sechdrs[SHN_LORESERVE+1]
154 * ......
155 * fyi: sym->st_shndx is uint16, SHN_LORESERVE = ff00, SHN_HIRESERVE = ffff,
156 * so basically we map 0000..feff -> 0000..feff
157 * ff00..ffff -> (you are a bad boy, dont do it)
158 * 10000..xxxx -> ff00..(xxxx-0x100)
159 */ 152 */
160static inline unsigned int shndx2secindex(unsigned int i) 153#define SPECIAL(i) ((i) - (SHN_HIRESERVE + 1))
161{
162 if (i <= SHN_HIRESERVE)
163 return i;
164 return i - (SHN_HIRESERVE + 1 - SHN_LORESERVE);
165}
166 154
167/* Accessor for sym->st_shndx, hides ugliness of "64k sections" */ 155/* Accessor for sym->st_shndx, hides ugliness of "64k sections" */
168static inline unsigned int get_secindex(const struct elf_info *info, 156static inline unsigned int get_secindex(const struct elf_info *info,
169 const Elf_Sym *sym) 157 const Elf_Sym *sym)
170{ 158{
159 if (is_shndx_special(sym->st_shndx))
160 return SPECIAL(sym->st_shndx);
171 if (sym->st_shndx != SHN_XINDEX) 161 if (sym->st_shndx != SHN_XINDEX)
172 return sym->st_shndx; 162 return sym->st_shndx;
173 return shndx2secindex(info->symtab_shndx_start[sym - 163 return info->symtab_shndx_start[sym - info->symtab_start];
174 info->symtab_start]);
175} 164}
176 165
177/* file2alias.c */ 166/* file2alias.c */
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index 47a1f9ae0ede..0865b3e752be 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -5,4 +5,15 @@
5 */ 5 */
6SECTIONS { 6SECTIONS {
7 /DISCARD/ : { *(.discard) } 7 /DISCARD/ : { *(.discard) }
8
9 __ksymtab : { *(SORT(___ksymtab+*)) }
10 __ksymtab_gpl : { *(SORT(___ksymtab_gpl+*)) }
11 __ksymtab_unused : { *(SORT(___ksymtab_unused+*)) }
12 __ksymtab_unused_gpl : { *(SORT(___ksymtab_unused_gpl+*)) }
13 __ksymtab_gpl_future : { *(SORT(___ksymtab_gpl_future+*)) }
14 __kcrctab : { *(SORT(___kcrctab+*)) }
15 __kcrctab_gpl : { *(SORT(___kcrctab_gpl+*)) }
16 __kcrctab_unused : { *(SORT(___kcrctab_unused+*)) }
17 __kcrctab_unused_gpl : { *(SORT(___kcrctab_unused_gpl+*)) }
18 __kcrctab_gpl_future : { *(SORT(___kcrctab_gpl_future+*)) }
8} 19}