1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Function to determine if a thread group is single threaded or not
3  *
4  * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells (dhowells@redhat.com)
6  * - Derived from security/selinux/hooks.c
7  */
8 #include <linux/sched/signal.h>
9 #include <linux/sched/task.h>
10 #include <linux/sched/mm.h>
11 
12 /*
13  * Returns true if the task does not share ->mm with another thread/process.
14  */
current_is_single_threaded(void)15 bool current_is_single_threaded(void)
16 {
17 	struct task_struct *task = current;
18 	struct mm_struct *mm = task->mm;
19 	struct task_struct *p, *t;
20 	bool ret;
21 
22 	if (atomic_read(&task->signal->live) != 1)
23 		return false;
24 
25 	if (atomic_read(&mm->mm_users) == 1)
26 		return true;
27 
28 	ret = false;
29 	rcu_read_lock();
30 	for_each_process(p) {
31 		if (unlikely(p->flags & PF_KTHREAD))
32 			continue;
33 		if (unlikely(p == task->group_leader))
34 			continue;
35 
36 		for_each_thread(p, t) {
37 			if (unlikely(t->mm == mm))
38 				goto found;
39 			if (likely(t->mm))
40 				break;
41 			/*
42 			 * t->mm == NULL. Make sure next_thread/next_task
43 			 * will see other CLONE_VM tasks which might be
44 			 * forked before exiting.
45 			 */
46 			smp_rmb();
47 		}
48 	}
49 	ret = true;
50 found:
51 	rcu_read_unlock();
52 
53 	return ret;
54 }
55