diff options
-rw-r--r-- | arch/alpha/mm/extable.c | 21 | ||||
-rw-r--r-- | arch/ia64/mm/extable.c | 26 | ||||
-rw-r--r-- | arch/sparc/include/asm/uaccess_32.h | 3 | ||||
-rw-r--r-- | arch/sparc/mm/extable.c | 29 | ||||
-rw-r--r-- | include/linux/module.h | 1 | ||||
-rw-r--r-- | kernel/module.c | 1 | ||||
-rw-r--r-- | lib/extable.c | 21 |
7 files changed, 101 insertions, 1 deletions
diff --git a/arch/alpha/mm/extable.c b/arch/alpha/mm/extable.c index 62dc379d301a..813c9b63c0e1 100644 --- a/arch/alpha/mm/extable.c +++ b/arch/alpha/mm/extable.c | |||
@@ -48,6 +48,27 @@ void sort_extable(struct exception_table_entry *start, | |||
48 | cmp_ex, swap_ex); | 48 | cmp_ex, swap_ex); |
49 | } | 49 | } |
50 | 50 | ||
51 | #ifdef CONFIG_MODULES | ||
52 | /* | ||
53 | * Any entry referring to the module init will be at the beginning or | ||
54 | * the end. | ||
55 | */ | ||
56 | void trim_init_extable(struct module *m) | ||
57 | { | ||
58 | /*trim the beginning*/ | ||
59 | while (m->num_exentries && | ||
60 | within_module_init(ex_to_addr(&m->extable[0]), m)) { | ||
61 | m->extable++; | ||
62 | m->num_exentries--; | ||
63 | } | ||
64 | /*trim the end*/ | ||
65 | while (m->num_exentries && | ||
66 | within_module_init(ex_to_addr(&m->extable[m->num_exentries-1]), | ||
67 | m)) | ||
68 | m->num_exentries--; | ||
69 | } | ||
70 | #endif /* CONFIG_MODULES */ | ||
71 | |||
51 | const struct exception_table_entry * | 72 | const struct exception_table_entry * |
52 | search_extable(const struct exception_table_entry *first, | 73 | search_extable(const struct exception_table_entry *first, |
53 | const struct exception_table_entry *last, | 74 | const struct exception_table_entry *last, |
diff --git a/arch/ia64/mm/extable.c b/arch/ia64/mm/extable.c index 71c50dd8f870..e95d5ad9285d 100644 --- a/arch/ia64/mm/extable.c +++ b/arch/ia64/mm/extable.c | |||
@@ -53,6 +53,32 @@ void sort_extable (struct exception_table_entry *start, | |||
53 | cmp_ex, swap_ex); | 53 | cmp_ex, swap_ex); |
54 | } | 54 | } |
55 | 55 | ||
56 | static inline unsigned long ex_to_addr(const struct exception_table_entry *x) | ||
57 | { | ||
58 | return (unsigned long)&x->insn + x->insn; | ||
59 | } | ||
60 | |||
61 | #ifdef CONFIG_MODULES | ||
62 | /* | ||
63 | * Any entry referring to the module init will be at the beginning or | ||
64 | * the end. | ||
65 | */ | ||
66 | void trim_init_extable(struct module *m) | ||
67 | { | ||
68 | /*trim the beginning*/ | ||
69 | while (m->num_exentries && | ||
70 | within_module_init(ex_to_addr(&m->extable[0]), m)) { | ||
71 | m->extable++; | ||
72 | m->num_exentries--; | ||
73 | } | ||
74 | /*trim the end*/ | ||
75 | while (m->num_exentries && | ||
76 | within_module_init(ex_to_addr(&m->extable[m->num_exentries-1]), | ||
77 | m)) | ||
78 | m->num_exentries--; | ||
79 | } | ||
80 | #endif /* CONFIG_MODULES */ | ||
81 | |||
56 | const struct exception_table_entry * | 82 | const struct exception_table_entry * |
57 | search_extable (const struct exception_table_entry *first, | 83 | search_extable (const struct exception_table_entry *first, |
58 | const struct exception_table_entry *last, | 84 | const struct exception_table_entry *last, |
diff --git a/arch/sparc/include/asm/uaccess_32.h b/arch/sparc/include/asm/uaccess_32.h index 47d5619d43fa..8303ac481034 100644 --- a/arch/sparc/include/asm/uaccess_32.h +++ b/arch/sparc/include/asm/uaccess_32.h | |||
@@ -17,6 +17,9 @@ | |||
17 | 17 | ||
18 | #ifndef __ASSEMBLY__ | 18 | #ifndef __ASSEMBLY__ |
19 | 19 | ||
20 | #define ARCH_HAS_SORT_EXTABLE | ||
21 | #define ARCH_HAS_SEARCH_EXTABLE | ||
22 | |||
20 | /* Sparc is not segmented, however we need to be able to fool access_ok() | 23 | /* Sparc is not segmented, however we need to be able to fool access_ok() |
21 | * when doing system calls from kernel mode legitimately. | 24 | * when doing system calls from kernel mode legitimately. |
22 | * | 25 | * |
diff --git a/arch/sparc/mm/extable.c b/arch/sparc/mm/extable.c index 16cc28935e39..a61c349448e1 100644 --- a/arch/sparc/mm/extable.c +++ b/arch/sparc/mm/extable.c | |||
@@ -28,6 +28,10 @@ search_extable(const struct exception_table_entry *start, | |||
28 | * word 3: last insn address + 4 bytes | 28 | * word 3: last insn address + 4 bytes |
29 | * word 4: fixup code address | 29 | * word 4: fixup code address |
30 | * | 30 | * |
31 | * Deleted entries are encoded as: | ||
32 | * word 1: unused | ||
33 | * word 2: -1 | ||
34 | * | ||
31 | * See asm/uaccess.h for more details. | 35 | * See asm/uaccess.h for more details. |
32 | */ | 36 | */ |
33 | 37 | ||
@@ -39,6 +43,10 @@ search_extable(const struct exception_table_entry *start, | |||
39 | continue; | 43 | continue; |
40 | } | 44 | } |
41 | 45 | ||
46 | /* A deleted entry; see trim_init_extable */ | ||
47 | if (walk->fixup == -1) | ||
48 | continue; | ||
49 | |||
42 | if (walk->insn == value) | 50 | if (walk->insn == value) |
43 | return walk; | 51 | return walk; |
44 | } | 52 | } |
@@ -57,6 +65,27 @@ search_extable(const struct exception_table_entry *start, | |||
57 | return NULL; | 65 | return NULL; |
58 | } | 66 | } |
59 | 67 | ||
68 | #ifdef CONFIG_MODULES | ||
69 | /* We could memmove them around; easier to mark the trimmed ones. */ | ||
70 | void trim_init_extable(struct module *m) | ||
71 | { | ||
72 | unsigned int i; | ||
73 | bool range; | ||
74 | |||
75 | for (i = 0; i < m->num_exentries; i += range ? 2 : 1) { | ||
76 | range = m->extable[i].fixup == 0; | ||
77 | |||
78 | if (within_module_init(m->extable[i].insn, m)) { | ||
79 | m->extable[i].fixup = -1; | ||
80 | if (range) | ||
81 | m->extable[i+1].fixup = -1; | ||
82 | } | ||
83 | if (range) | ||
84 | i++; | ||
85 | } | ||
86 | } | ||
87 | #endif /* CONFIG_MODULES */ | ||
88 | |||
60 | /* Special extable search, which handles ranges. Returns fixup */ | 89 | /* Special extable search, which handles ranges. Returns fixup */ |
61 | unsigned long search_extables_range(unsigned long addr, unsigned long *g2) | 90 | unsigned long search_extables_range(unsigned long addr, unsigned long *g2) |
62 | { | 91 | { |
diff --git a/include/linux/module.h b/include/linux/module.h index a8f2c0aa4c32..a7bc6e7b43a7 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -77,6 +77,7 @@ search_extable(const struct exception_table_entry *first, | |||
77 | void sort_extable(struct exception_table_entry *start, | 77 | void sort_extable(struct exception_table_entry *start, |
78 | struct exception_table_entry *finish); | 78 | struct exception_table_entry *finish); |
79 | void sort_main_extable(void); | 79 | void sort_main_extable(void); |
80 | void trim_init_extable(struct module *m); | ||
80 | 81 | ||
81 | #ifdef MODULE | 82 | #ifdef MODULE |
82 | #define MODULE_GENERIC_TABLE(gtype,name) \ | 83 | #define MODULE_GENERIC_TABLE(gtype,name) \ |
diff --git a/kernel/module.c b/kernel/module.c index 35f7de00bf0d..e4ab36ce7672 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -2455,6 +2455,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, | |||
2455 | mutex_lock(&module_mutex); | 2455 | mutex_lock(&module_mutex); |
2456 | /* Drop initial reference. */ | 2456 | /* Drop initial reference. */ |
2457 | module_put(mod); | 2457 | module_put(mod); |
2458 | trim_init_extable(mod); | ||
2458 | module_free(mod, mod->module_init); | 2459 | module_free(mod, mod->module_init); |
2459 | mod->module_init = NULL; | 2460 | mod->module_init = NULL; |
2460 | mod->init_size = 0; | 2461 | mod->init_size = 0; |
diff --git a/lib/extable.c b/lib/extable.c index 179c08745595..4cac81ec225e 100644 --- a/lib/extable.c +++ b/lib/extable.c | |||
@@ -39,7 +39,26 @@ void sort_extable(struct exception_table_entry *start, | |||
39 | sort(start, finish - start, sizeof(struct exception_table_entry), | 39 | sort(start, finish - start, sizeof(struct exception_table_entry), |
40 | cmp_ex, NULL); | 40 | cmp_ex, NULL); |
41 | } | 41 | } |
42 | #endif | 42 | |
43 | #ifdef CONFIG_MODULES | ||
44 | /* | ||
45 | * If the exception table is sorted, any referring to the module init | ||
46 | * will be at the beginning or the end. | ||
47 | */ | ||
48 | void trim_init_extable(struct module *m) | ||
49 | { | ||
50 | /*trim the beginning*/ | ||
51 | while (m->num_exentries && within_module_init(m->extable[0].insn, m)) { | ||
52 | m->extable++; | ||
53 | m->num_exentries--; | ||
54 | } | ||
55 | /*trim the end*/ | ||
56 | while (m->num_exentries && | ||
57 | within_module_init(m->extable[m->num_exentries-1].insn, m)) | ||
58 | m->num_exentries--; | ||
59 | } | ||
60 | #endif /* CONFIG_MODULES */ | ||
61 | #endif /* !ARCH_HAS_SORT_EXTABLE */ | ||
43 | 62 | ||
44 | #ifndef ARCH_HAS_SEARCH_EXTABLE | 63 | #ifndef ARCH_HAS_SEARCH_EXTABLE |
45 | /* | 64 | /* |