Walks the stack when copy_{to,from}_user address is in the stack to ensure that the object being copied is entirely within a single stack frame.
Substatially similar to the x86 implementation except using the back chain to traverse the stack and identify stack frame boundaries. Signed-off-by: Nicholas Miehlbradt <nicho...@linux.ibm.com> --- arch/powerpc/Kconfig | 1 + arch/powerpc/include/asm/thread_info.h | 38 ++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 2ca5418457ed..4c59d139ea83 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -198,6 +198,7 @@ config PPC select HAVE_ARCH_KASAN_VMALLOC if HAVE_ARCH_KASAN select HAVE_ARCH_KFENCE if ARCH_SUPPORTS_DEBUG_PAGEALLOC select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET + select HAVE_ARCH_WITHIN_STACK_FRAMES if PPC64 select HAVE_ARCH_KGDB select HAVE_ARCH_MMAP_RND_BITS select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index af58f1ed3952..efdf39e07884 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h @@ -186,6 +186,44 @@ static inline bool test_thread_local_flags(unsigned int flags) #define is_elf2_task() (0) #endif +#ifdef CONFIG_PPC64 + +#ifdef CONFIG_PPC64_ELF_ABI_V1 +#define PARAMETER_SAVE_OFFSET 48 +#else +#define PARAMETER_SAVE_OFFSET 32 +#endif + +/* + * Walks up the stack frames to make sure that the specified object is + * entirely contained by a single stack frame. + * + * Returns: + * GOOD_FRAME if within a frame + * BAD_STACK if placed across a frame boundary (or outside stack) + */ +static inline int arch_within_stack_frames(const void * const stack, + const void * const stackend, + const void *obj, unsigned long len) +{ + const void *frame; + const void *oldframe; + + oldframe = (const void *)current_stack_pointer; + frame = *(const void * const *)oldframe; + + while (stack <= frame && frame < stackend) { + if (obj + len <= frame) + return obj >= oldframe + PARAMETER_SAVE_OFFSET ? + GOOD_FRAME : BAD_STACK; + oldframe = frame; + frame = *(const void * const *)oldframe; + } + + return BAD_STACK; +} +#endif /* CONFIG_PPC64 */ + #endif /* !__ASSEMBLY__ */ #endif /* __KERNEL__ */ -- 2.34.1