mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	x86/unwind/orc: Fix error handling in __unwind_start()
The unwind_state 'error' field is used to inform the reliable unwinding code that the stack trace can't be trusted. Set this field for all errors in __unwind_start(). Also, move the zeroing out of the unwind_state struct to before the ORC table initialization check, to prevent the caller from reading uninitialized data if the ORC table is corrupted. Fixes:af085d9084("stacktrace/x86: add function for detecting reliable stack traces") Fixes:d3a0910401("x86/unwinder/orc: Dont bail on stack overflow") Fixes:98d0c8ebf7("x86/unwind/orc: Prevent unwinding before ORC initialization") Reported-by: Pavel Machek <pavel@denx.de> Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lkml.kernel.org/r/d6ac7215a84ca92b895fdd2e1aa546729417e6e6.1589487277.git.jpoimboe@redhat.com
This commit is contained in:
		
							parent
							
								
									2ef96a5bb1
								
							
						
					
					
						commit
						71c9582528
					
				
					 1 changed files with 9 additions and 7 deletions
				
			
		| 
						 | 
				
			
			@ -617,23 +617,23 @@ EXPORT_SYMBOL_GPL(unwind_next_frame);
 | 
			
		|||
void __unwind_start(struct unwind_state *state, struct task_struct *task,
 | 
			
		||||
		    struct pt_regs *regs, unsigned long *first_frame)
 | 
			
		||||
{
 | 
			
		||||
	if (!orc_init)
 | 
			
		||||
		goto done;
 | 
			
		||||
 | 
			
		||||
	memset(state, 0, sizeof(*state));
 | 
			
		||||
	state->task = task;
 | 
			
		||||
 | 
			
		||||
	if (!orc_init)
 | 
			
		||||
		goto err;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Refuse to unwind the stack of a task while it's executing on another
 | 
			
		||||
	 * CPU.  This check is racy, but that's ok: the unwinder has other
 | 
			
		||||
	 * checks to prevent it from going off the rails.
 | 
			
		||||
	 */
 | 
			
		||||
	if (task_on_another_cpu(task))
 | 
			
		||||
		goto done;
 | 
			
		||||
		goto err;
 | 
			
		||||
 | 
			
		||||
	if (regs) {
 | 
			
		||||
		if (user_mode(regs))
 | 
			
		||||
			goto done;
 | 
			
		||||
			goto the_end;
 | 
			
		||||
 | 
			
		||||
		state->ip = regs->ip;
 | 
			
		||||
		state->sp = regs->sp;
 | 
			
		||||
| 
						 | 
				
			
			@ -666,6 +666,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
 | 
			
		|||
		 * generate some kind of backtrace if this happens.
 | 
			
		||||
		 */
 | 
			
		||||
		void *next_page = (void *)PAGE_ALIGN((unsigned long)state->sp);
 | 
			
		||||
		state->error = true;
 | 
			
		||||
		if (get_stack_info(next_page, state->task, &state->stack_info,
 | 
			
		||||
				   &state->stack_mask))
 | 
			
		||||
			return;
 | 
			
		||||
| 
						 | 
				
			
			@ -691,8 +692,9 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
 | 
			
		|||
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
done:
 | 
			
		||||
err:
 | 
			
		||||
	state->error = true;
 | 
			
		||||
the_end:
 | 
			
		||||
	state->stack_info.type = STACK_TYPE_UNKNOWN;
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(__unwind_start);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue