There's a debug option called CONFIG_DEBUG_STACKOVERFLOW which might help you catch stack overflows before they bite you and crash your kernel.
However, this is implemented in an arch-specific way inside the interrupt handling. As v4.6, the architectures that support this are:
$ git grep "select HAVE_DEBUG_STACKOVERFLOW" v4.6
v4.6:arch/arc/Kconfig: select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/blackfin/Kconfig: select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/frv/Kconfig: select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/m32r/Kconfig: select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/metag/Kconfig: select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/mips/Kconfig: select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/mn10300/Kconfig: select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/openrisc/Kconfig: select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/parisc/Kconfig: select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/powerpc/Kconfig: select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/tile/Kconfig: select HAVE_DEBUG_STACKOVERFLOW
v4.6:arch/x86/Kconfig: select HAVE_DEBUG_STACKOVERFLOW
Notably, ARM is not on that list.
It is interesting to see how simple it is to check the current stack depth:
/* Debugging check for stack overflow: is there less than 1KB free? */
static int check_stack_overflow(void)
{
long sp;
__asm__ __volatile__("andl %%esp,%0" :
"=r" (sp) : "0" (THREAD_SIZE - 1));
return sp < (sizeof(struct thread_info) + STACK_WARN);
}
Now, regarding your question about recursion: it is a poor design in kernel development, for precisely the issue you are facing. In kernel land, the stack is fixed and won't grow. Recursion is usually stack-hungry and will lead you to stack overflowing easily.
Keep in mind that theoretically you can always convert a recursive algorithm to an iterative one, as explained here: Can every recursion be converted into iteration?