aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/alpha/mm/extable.c21
-rw-r--r--arch/ia64/mm/extable.c26
-rw-r--r--arch/sparc/include/asm/uaccess_32.h3
-rw-r--r--arch/sparc/mm/extable.c29
-rw-r--r--include/linux/module.h1
-rw-r--r--kernel/module.c1
-rw-r--r--lib/extable.c21
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 */
56void 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
51const struct exception_table_entry * 72const struct exception_table_entry *
52search_extable(const struct exception_table_entry *first, 73search_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
56static 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 */
66void 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
56const struct exception_table_entry * 82const struct exception_table_entry *
57search_extable (const struct exception_table_entry *first, 83search_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. */
70void 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 */
61unsigned long search_extables_range(unsigned long addr, unsigned long *g2) 90unsigned 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,
77void sort_extable(struct exception_table_entry *start, 77void sort_extable(struct exception_table_entry *start,
78 struct exception_table_entry *finish); 78 struct exception_table_entry *finish);
79void sort_main_extable(void); 79void sort_main_extable(void);
80void 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 */
48void 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/*