mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-03 18:20:25 +02:00 
			
		
		
		
	ptrace: Document that wait_task_inactive can't fail
After ptrace_freeze_traced succeeds it is known that the tracee has a __state value of __TASK_TRACED and that no __ptrace_unlink will happen because the tracer is waiting for the tracee, and the tracee is in ptrace_stop. The function ptrace_freeze_traced can succeed at any point after ptrace_stop has set TASK_TRACED and dropped siglock. The read_lock on tasklist_lock only excludes ptrace_attach. This means that the !current->ptrace which executes under a read_lock of tasklist_lock will never see a ptrace_freeze_trace as the tracer must have gone away before the tasklist_lock was taken and ptrace_attach can not occur until the read_lock is dropped. As ptrace_freeze_traced depends upon ptrace_attach running before it can run that excludes ptrace_freeze_traced until __state is set to TASK_RUNNING. This means that task_is_traced will fail in ptrace_freeze_attach and ptrace_freeze_attached will fail. On the current->ptrace branch of ptrace_stop which will be reached any time after ptrace_freeze_traced has succeed it is known that __state is __TASK_TRACED and schedule() will be called with that state. Use a WARN_ON_ONCE to document that wait_task_inactive(TASK_TRACED) should never fail. Remove the stale comment about may_ptrace_stop. Strictly speaking this is not true because if PREEMPT_RT is enabled wait_task_inactive can fail because __state can be changed. I don't see this as a problem as the ptrace code is currently broken on PREMPT_RT, and this is one of the issues. Failing and warning when the assumptions of the code are broken is good. Tested-by: Kees Cook <keescook@chromium.org> Reviewed-by: Oleg Nesterov <oleg@redhat.com> Link: https://lkml.kernel.org/r/20220505182645.497868-8-ebiederm@xmission.com Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
This commit is contained in:
		
							parent
							
								
									6a2d90ba02
								
							
						
					
					
						commit
						7b0fe1367e
					
				
					 1 changed files with 3 additions and 11 deletions
				
			
		| 
						 | 
					@ -266,17 +266,9 @@ static int ptrace_check_attach(struct task_struct *child, bool ignore_state)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	read_unlock(&tasklist_lock);
 | 
						read_unlock(&tasklist_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!ret && !ignore_state) {
 | 
						if (!ret && !ignore_state &&
 | 
				
			||||||
		if (!wait_task_inactive(child, __TASK_TRACED)) {
 | 
						    WARN_ON_ONCE(!wait_task_inactive(child, __TASK_TRACED)))
 | 
				
			||||||
			/*
 | 
							ret = -ESRCH;
 | 
				
			||||||
			 * This can only happen if may_ptrace_stop() fails and
 | 
					 | 
				
			||||||
			 * ptrace_stop() changes ->state back to TASK_RUNNING,
 | 
					 | 
				
			||||||
			 * so we should not worry about leaking __TASK_TRACED.
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
			WARN_ON(READ_ONCE(child->__state) == __TASK_TRACED);
 | 
					 | 
				
			||||||
			ret = -ESRCH;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue