Merge branch 'next' into for-linus
This commit is contained in:
@@ -653,6 +653,21 @@ config DEBUG_NOTIFIERS
|
||||
This is a relatively cheap check but if you care about maximum
|
||||
performance, say N.
|
||||
|
||||
config DEBUG_CREDENTIALS
|
||||
bool "Debug credential management"
|
||||
depends on DEBUG_KERNEL
|
||||
help
|
||||
Enable this to turn on some debug checking for credential
|
||||
management. The additional code keeps track of the number of
|
||||
pointers from task_structs to any given cred struct, and checks to
|
||||
see that this number never exceeds the usage count of the cred
|
||||
struct.
|
||||
|
||||
Furthermore, if SELinux is enabled, this also checks that the
|
||||
security pointer in the cred struct is never seen to be invalid.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
#
|
||||
# Select this config option from the architecture Kconfig, if it
|
||||
# it is preferred to always offer frame pointers as a config
|
||||
|
@@ -12,34 +12,47 @@
|
||||
|
||||
#include <linux/sched.h>
|
||||
|
||||
/**
|
||||
* is_single_threaded - Determine if a thread group is single-threaded or not
|
||||
* @p: A task in the thread group in question
|
||||
*
|
||||
* This returns true if the thread group to which a task belongs is single
|
||||
* threaded, false if it is not.
|
||||
/*
|
||||
* Returns true if the task does not share ->mm with another thread/process.
|
||||
*/
|
||||
bool is_single_threaded(struct task_struct *p)
|
||||
bool current_is_single_threaded(void)
|
||||
{
|
||||
struct task_struct *g, *t;
|
||||
struct mm_struct *mm = p->mm;
|
||||
struct task_struct *task = current;
|
||||
struct mm_struct *mm = task->mm;
|
||||
struct task_struct *p, *t;
|
||||
bool ret;
|
||||
|
||||
if (atomic_read(&p->signal->count) != 1)
|
||||
goto no;
|
||||
if (atomic_read(&task->signal->live) != 1)
|
||||
return false;
|
||||
|
||||
if (atomic_read(&p->mm->mm_users) != 1) {
|
||||
read_lock(&tasklist_lock);
|
||||
do_each_thread(g, t) {
|
||||
if (t->mm == mm && t != p)
|
||||
goto no_unlock;
|
||||
} while_each_thread(g, t);
|
||||
read_unlock(&tasklist_lock);
|
||||
if (atomic_read(&mm->mm_users) == 1)
|
||||
return true;
|
||||
|
||||
ret = false;
|
||||
rcu_read_lock();
|
||||
for_each_process(p) {
|
||||
if (unlikely(p->flags & PF_KTHREAD))
|
||||
continue;
|
||||
if (unlikely(p == task->group_leader))
|
||||
continue;
|
||||
|
||||
t = p;
|
||||
do {
|
||||
if (unlikely(t->mm == mm))
|
||||
goto found;
|
||||
if (likely(t->mm))
|
||||
break;
|
||||
/*
|
||||
* t->mm == NULL. Make sure next_thread/next_task
|
||||
* will see other CLONE_VM tasks which might be
|
||||
* forked before exiting.
|
||||
*/
|
||||
smp_rmb();
|
||||
} while_each_thread(p, t);
|
||||
}
|
||||
ret = true;
|
||||
found:
|
||||
rcu_read_unlock();
|
||||
|
||||
return true;
|
||||
|
||||
no_unlock:
|
||||
read_unlock(&tasklist_lock);
|
||||
no:
|
||||
return false;
|
||||
return ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user