Re: [PATCH v3] riscv: stacktrace: fix stack-out-of-bounds in walk_stackframe()

kernel test robot <[email protected]>
Newsgroups org.infradead.lists.linux-riscv,dev.linux.lists.oe-kbuild-all,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Hi Jiakai,

kernel test robot noticed the following build errors:

[auto build test ERROR on linus/master]
[also build test ERROR on v7.2-rc7 next-20260811]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Jiakai-Xu/riscv-stacktrace-fix-stack-out-of-bounds-in-walk_stackframe/20260812-091247
base:   linus/master
patch link:    https://lore.kernel.org/r/20260625123906.211981-1-xujiakai2025%40iscas.ac.cn
patch subject: [PATCH v3] riscv: stacktrace: fix stack-out-of-bounds in walk_stackframe()
config: riscv-randconfig-002-20260812 (https://download.01.org/0day-ci/archive/20260813/[email protected]/config)
compiler: riscv64-linux-gcc (GCC) 8.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260813/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All errors (new ones prefixed by >>):

   In file included from include/linux/export.h:5,
                    from arch/riscv/kernel/stacktrace.c:7:
   arch/riscv/kernel/stacktrace.c: In function 'walk_stackframe':
>> arch/riscv/kernel/stacktrace.c:82:39: error: 'irq_stack_ptr' undeclared (first use in this function); did you mean 'irq_stat'?
      high = (unsigned long)this_cpu_read(irq_stack_ptr) +
                                          ^~~~~~~~~~~~~
   include/linux/compiler.h:239:40: note: in definition of macro 'TYPEOF_UNQUAL'
    # define TYPEOF_UNQUAL(exp) __typeof__(exp)
                                           ^~~
   include/linux/percpu-defs.h:499:29: note: in expansion of macro '__pcpu_size_call_return'
    #define this_cpu_read(pcp)  __pcpu_size_call_return(this_cpu_read_, pcp)
                                ^~~~~~~~~~~~~~~~~~~~~~~
   arch/riscv/kernel/stacktrace.c:82:25: note: in expansion of macro 'this_cpu_read'
      high = (unsigned long)this_cpu_read(irq_stack_ptr) +
                            ^~~~~~~~~~~~~
   arch/riscv/kernel/stacktrace.c:82:39: note: each undeclared identifier is reported only once for each function it appears in
      high = (unsigned long)this_cpu_read(irq_stack_ptr) +
                                          ^~~~~~~~~~~~~
   include/linux/compiler.h:239:40: note: in definition of macro 'TYPEOF_UNQUAL'
    # define TYPEOF_UNQUAL(exp) __typeof__(exp)
                                           ^~~
   include/linux/percpu-defs.h:499:29: note: in expansion of macro '__pcpu_size_call_return'
    #define this_cpu_read(pcp)  __pcpu_size_call_return(this_cpu_read_, pcp)
                                ^~~~~~~~~~~~~~~~~~~~~~~
   arch/riscv/kernel/stacktrace.c:82:25: note: in expansion of macro 'this_cpu_read'
      high = (unsigned long)this_cpu_read(irq_stack_ptr) +
                            ^~~~~~~~~~~~~


vim +82 arch/riscv/kernel/stacktrace.c

   > 7	#include <linux/export.h>
     8	#include <linux/kallsyms.h>
     9	#include <linux/sched.h>
    10	#include <linux/sched/debug.h>
    11	#include <linux/sched/task_stack.h>
    12	#include <linux/stacktrace.h>
    13	#include <linux/ftrace.h>
    14	
    15	#include <asm/stacktrace.h>
    16	
    17	#ifdef CONFIG_FRAME_POINTER
    18	
    19	/*
    20	 * This disables KASAN checking when reading a value from another task's stack,
    21	 * since the other task could be running on another CPU and could have poisoned
    22	 * the stack in the meantime.
    23	 */
    24	#define READ_ONCE_TASK_STACK(task, x)			\
    25	({							\
    26		unsigned long val;				\
    27		unsigned long addr = x;				\
    28		if ((task) == current)				\
    29			val = READ_ONCE(addr);			\
    30		else						\
    31			val = READ_ONCE_NOCHECK(addr);		\
    32		val;						\
    33	})
    34	
    35	extern asmlinkage void handle_exception(void);
    36	extern unsigned long ret_from_exception_end;
    37	
    38	#ifdef CONFIG_IRQ_STACKS
    39	DECLARE_PER_CPU(ulong *, irq_stack_ptr);
    40	#endif
    41	
    42	static inline int fp_is_valid(unsigned long fp, unsigned long sp,
    43				      unsigned long high)
    44	{
    45		unsigned long low;
    46	
    47		low = sp + sizeof(struct stackframe);
    48	
    49		return !(fp < low || fp > high || fp & 0x07);
    50	}
    51	
    52	void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
    53				     bool (*fn)(void *, unsigned long), void *arg)
    54	{
    55		unsigned long fp, sp, pc, high;
    56		int graph_idx = 0;
    57		int level = 0;
    58	
    59		if (regs) {
    60			fp = frame_pointer(regs);
    61			sp = user_stack_pointer(regs);
    62			pc = instruction_pointer(regs);
    63		} else if (task == NULL || task == current) {
    64			fp = (unsigned long)__builtin_frame_address(0);
    65			sp = current_stack_pointer;
    66			pc = (unsigned long)walk_stackframe;
    67			level = -1;
    68		} else {
    69			/* task blocked in __switch_to */
    70			fp = task->thread.s[0];
    71			sp = task->thread.sp;
    72			pc = task->thread.ra;
    73		}
    74	
    75		if (!task)
    76			task = current;
    77	
    78		if (sp >= (unsigned long)task_stack_page(task) &&
    79		    sp < (unsigned long)task_stack_page(task) + THREAD_SIZE) {
    80			high = (unsigned long)task_pt_regs(task);
    81		} else if (IS_ENABLED(CONFIG_IRQ_STACKS)) {
  > 82			high = (unsigned long)this_cpu_read(irq_stack_ptr) +
    83			       IRQ_STACK_SIZE;
    84		} else {
    85			high = (unsigned long)task_pt_regs(task);
    86		}
    87	
    88		for (;;) {
    89			struct stackframe *frame;
    90	
    91			if (unlikely(!__kernel_text_address(pc) || (level++ >= 0 && !fn(arg, pc))))
    92				break;
    93	
    94			if (unlikely(!fp_is_valid(fp, sp, high)))
    95				break;
    96	
    97			/* Unwind stack frame */
    98			frame = (struct stackframe *)fp - 1;
    99			sp = fp;
   100			if (regs && (regs->epc == pc) && fp_is_valid(frame->ra, sp, high)) {
   101				/* We hit function where ra is not saved on the stack */
   102				fp = frame->ra;
   103				pc = regs->ra;
   104			} else {
   105				fp = READ_ONCE_TASK_STACK(task, frame->fp);
   106				pc = READ_ONCE_TASK_STACK(task, frame->ra);
   107				pc = ftrace_graph_ret_addr(task, &graph_idx, pc,
   108							   &frame->ra);
   109				if (pc >= (unsigned long)handle_exception &&
   110				    pc < (unsigned long)&ret_from_exception_end) {
   111					if (unlikely(!fn(arg, pc)))
   112						break;
   113	
   114					pc = ((struct pt_regs *)sp)->epc;
   115					fp = ((struct pt_regs *)sp)->s0;
   116				}
   117			}
   118	
   119		}
   120	}
   121	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.