mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 16:54:21 +00:00 
			
		
		
		
	mm/oom_kill: fix the wrong task->mm == mm checks in oom_kill_process()
Both "child->mm == mm" and "p->mm != mm" checks in oom_kill_process() are wrong. task->mm can be NULL if the task is the exited group leader. This means in particular that "kill sharing same memory" loop can miss a process with a zombie leader which uses the same ->mm. Note: the process_has_mm(child, p->mm) check is still not 100% correct, p->mm can be NULL too. This is minor, but probably deserves a fix or a comment anyway. [akpm@linux-foundation.org: document process_shares_mm() a bit] Signed-off-by: Oleg Nesterov <oleg@redhat.com> Acked-by: David Rientjes <rientjes@google.com> Acked-by: Michal Hocko <mhocko@suse.com> Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Cc: Kyle Walker <kwalker@redhat.com> Cc: Stanislav Kozina <skozina@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									c319025a6c
								
							
						
					
					
						commit
						4d7b3394f7
					
				
					 1 changed files with 20 additions and 2 deletions
				
			
		|  | @ -474,6 +474,24 @@ void oom_killer_enable(void) | |||
| 	oom_killer_disabled = false; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * task->mm can be NULL if the task is the exited group leader.  So to | ||||
|  * determine whether the task is using a particular mm, we examine all the | ||||
|  * task's threads: if one of those is using this mm then this task was also | ||||
|  * using it. | ||||
|  */ | ||||
| static bool process_shares_mm(struct task_struct *p, struct mm_struct *mm) | ||||
| { | ||||
| 	struct task_struct *t; | ||||
| 
 | ||||
| 	for_each_thread(p, t) { | ||||
| 		struct mm_struct *t_mm = READ_ONCE(t->mm); | ||||
| 		if (t_mm) | ||||
| 			return t_mm == mm; | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| #define K(x) ((x) << (PAGE_SHIFT-10)) | ||||
| /*
 | ||||
|  * Must be called while holding a reference to p, which will be released upon | ||||
|  | @ -521,7 +539,7 @@ void oom_kill_process(struct oom_control *oc, struct task_struct *p, | |||
| 		list_for_each_entry(child, &t->children, sibling) { | ||||
| 			unsigned int child_points; | ||||
| 
 | ||||
| 			if (child->mm == p->mm) | ||||
| 			if (process_shares_mm(child, p->mm)) | ||||
| 				continue; | ||||
| 			/*
 | ||||
| 			 * oom_badness() returns 0 if the thread is unkillable | ||||
|  | @ -575,7 +593,7 @@ void oom_kill_process(struct oom_control *oc, struct task_struct *p, | |||
| 	 */ | ||||
| 	rcu_read_lock(); | ||||
| 	for_each_process(p) { | ||||
| 		if (p->mm != mm) | ||||
| 		if (!process_shares_mm(p, mm)) | ||||
| 			continue; | ||||
| 		if (same_thread_group(p, victim)) | ||||
| 			continue; | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Oleg Nesterov
						Oleg Nesterov