@@ -29,7 +29,9 @@ SECTIONS
. = ALIGN(16);
/* Linkage tables */
.opd : {
+ __start_opd = .;
*(.opd)
+ __end_opd = .;
} PROVIDE (__gp = .);
.plt : {
*(.plt)
@@ -6,7 +6,10 @@
#ifdef CONFIG_64BIT
#undef dereference_function_descriptor
+#undef dereference_kernel_function_descriptor
+
void *dereference_function_descriptor(void *);
+void *dereference_kernel_function_descriptor(void *);
#endif
#endif
@@ -954,3 +954,17 @@ void module_arch_cleanup(struct module *mod)
{
deregister_unwind_table(mod);
}
+
+#ifdef CONFIG_64BIT
+unsigned long dereference_module_function_descriptor(struct module *mod,
+ unsigned long addr)
+{
+ void *opd_sz = mod->arch.fdesc_offset +
+ mod->arch.fdesc_max * sizeof(Elf64_Fdesc);
+
+ if (addr < mod->arch.fdesc_offset || opd_sz < addr)
+ return addr;
+
+ return dereference_function_descriptor(addr);
+}
+#endif
@@ -267,6 +267,8 @@ get_wchan(struct task_struct *p)
}
#ifdef CONFIG_64BIT
+extern char __start_opd[], __end_opd[];
+
void *dereference_function_descriptor(void *ptr)
{
Elf64_Fdesc *desc = ptr;
@@ -276,6 +278,14 @@ void *dereference_function_descriptor(void *ptr)
ptr = p;
return ptr;
}
+
+void *dereference_kernel_function_descriptor(void *ptr)
+{
+ if (ptr < (void *)__start_opd || (void *)__end_opd < ptr)
+ return ptr;
+
+ return dereference_function_descriptor(ptr);
+}
#endif
static inline unsigned long brk_rnd(void)
@@ -99,7 +99,9 @@ SECTIONS
. = ALIGN(16);
/* Linkage tables */
.opd : {
+ __start_opd = .;
*(.opd)
+ __end_opd = .;
} PROVIDE (__gp = .);
.plt : {
*(.plt)
We are moving towards separate kernel and module function descriptor dereference callbacks. This patch enables it for parisc64. For pointers that belong to the kernel - Added __start_opd and __end_opd pointers, to track the kernel .opd section address range; - Added dereference_kernel_function_descriptor(). Now we will dereference only function pointers that are within [__start_opd, __end_opd]; For pointers that belong to a module - Added dereference_module_function_descriptor() to handle module function descriptor dereference. Now we will dereference only pointers that are within [module->opd.start, module->opd.end]. Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> --- arch/parisc/boot/compressed/vmlinux.lds.S | 2 ++ arch/parisc/include/asm/sections.h | 3 +++ arch/parisc/kernel/module.c | 14 ++++++++++++++ arch/parisc/kernel/process.c | 10 ++++++++++ arch/parisc/kernel/vmlinux.lds.S | 2 ++ 5 files changed, 31 insertions(+)