Skip to content

Commit

Permalink
asm-generic: Refactor dereference_[kernel]_function_descriptor()
Browse files Browse the repository at this point in the history
dereference_function_descriptor() and
dereference_kernel_function_descriptor() are identical on the
three architectures implementing them.

Make them common and put them out-of-line in kernel/extable.c
which is one of the users and has similar type of functions.

Signed-off-by: Christophe Leroy <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
Reviewed-by: Arnd Bergmann <[email protected]>
Acked-by: Helge Deller <[email protected]>
Signed-off-by: Michael Ellerman <[email protected]>
Link: https://lore.kernel.org/r/449db09b2eba57f4ab05f80102a67d8675bc8bcd.1644928018.git.christophe.leroy@csgroup.eu
  • Loading branch information
chleroy authored and mpe committed Feb 16, 2022
1 parent 0dc690e commit e1478d8
Show file tree
Hide file tree
Showing 6 changed files with 24 additions and 73 deletions.
19 changes: 0 additions & 19 deletions arch/ia64/include/asm/sections.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,4 @@ extern char __start_gate_brl_fsys_bubble_down_patchlist[], __end_gate_brl_fsys_b
extern char __start_unwind[], __end_unwind[];
extern char __start_ivt_text[], __end_ivt_text[];

#undef dereference_function_descriptor
static inline void *dereference_function_descriptor(void *ptr)
{
struct fdesc *desc = ptr;
void *p;

if (!get_kernel_nofault(p, (void *)&desc->addr))
ptr = p;
return ptr;
}

#undef dereference_kernel_function_descriptor
static inline void *dereference_kernel_function_descriptor(void *ptr)
{
if (ptr < (void *)__start_opd || ptr >= (void *)__end_opd)
return ptr;
return dereference_function_descriptor(ptr);
}

#endif /* _ASM_IA64_SECTIONS_H */
9 changes: 0 additions & 9 deletions arch/parisc/include/asm/sections.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,4 @@ typedef Elf64_Fdesc func_desc_t;

extern char __alt_instructions[], __alt_instructions_end[];

#ifdef CONFIG_64BIT

#undef dereference_function_descriptor
void *dereference_function_descriptor(void *);

#undef dereference_kernel_function_descriptor
void *dereference_kernel_function_descriptor(void *);
#endif

#endif
21 changes: 0 additions & 21 deletions arch/parisc/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,27 +263,6 @@ __get_wchan(struct task_struct *p)
return 0;
}

#ifdef CONFIG_64BIT
void *dereference_function_descriptor(void *ptr)
{
Elf64_Fdesc *desc = ptr;
void *p;

if (!get_kernel_nofault(p, (void *)&desc->addr))
ptr = p;
return ptr;
}

void *dereference_kernel_function_descriptor(void *ptr)
{
if (ptr < (void *)__start_opd ||
ptr >= (void *)__end_opd)
return ptr;

return dereference_function_descriptor(ptr);
}
#endif

static inline unsigned long brk_rnd(void)
{
return (get_random_int() & BRK_RND_MASK) << PAGE_SHIFT;
Expand Down
23 changes: 0 additions & 23 deletions arch/powerpc/include/asm/sections.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,29 +58,6 @@ static inline int overlaps_kernel_text(unsigned long start, unsigned long end)
(unsigned long)_stext < end;
}

#ifdef PPC64_ELF_ABI_v1

#undef dereference_function_descriptor
static inline void *dereference_function_descriptor(void *ptr)
{
struct func_desc *desc = ptr;
void *p;

if (!get_kernel_nofault(p, (void *)&desc->addr))
ptr = p;
return ptr;
}

#undef dereference_kernel_function_descriptor
static inline void *dereference_kernel_function_descriptor(void *ptr)
{
if (ptr < (void *)__start_opd || ptr >= (void *)__end_opd)
return ptr;

return dereference_function_descriptor(ptr);
}
#endif /* PPC64_ELF_ABI_v1 */

#endif

#endif /* __KERNEL__ */
Expand Down
2 changes: 2 additions & 0 deletions include/asm-generic/sections.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ extern __visible const void __nosave_begin, __nosave_end;

/* Function descriptor handling (if any). Override in asm/sections.h */
#ifdef CONFIG_HAVE_FUNCTION_DESCRIPTORS
void *dereference_function_descriptor(void *ptr);
void *dereference_kernel_function_descriptor(void *ptr);
#else
#define dereference_function_descriptor(p) ((void *)(p))
#define dereference_kernel_function_descriptor(p) ((void *)(p))
Expand Down
23 changes: 22 additions & 1 deletion kernel/extable.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM.
*/
#include <linux/elf.h>
#include <linux/ftrace.h>
#include <linux/memory.h>
#include <linux/extable.h>
Expand Down Expand Up @@ -132,12 +133,32 @@ int kernel_text_address(unsigned long addr)
}

/*
* On some architectures (PPC64, IA64) function pointers
* On some architectures (PPC64, IA64, PARISC) function pointers
* are actually only tokens to some data that then holds the
* real function address. As a result, to find if a function
* pointer is part of the kernel text, we need to do some
* special dereferencing first.
*/
#ifdef CONFIG_HAVE_FUNCTION_DESCRIPTORS
void *dereference_function_descriptor(void *ptr)
{
func_desc_t *desc = ptr;
void *p;

if (!get_kernel_nofault(p, (void *)&desc->addr))
ptr = p;
return ptr;
}

void *dereference_kernel_function_descriptor(void *ptr)
{
if (ptr < (void *)__start_opd || ptr >= (void *)__end_opd)
return ptr;

return dereference_function_descriptor(ptr);
}
#endif

int func_ptr_is_kernel_text(void *ptr)
{
unsigned long addr;
Expand Down

0 comments on commit e1478d8

Please sign in to comment.