diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-11 11:55:49 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-11 11:55:49 -0400 |
| commit | f6f79190866d5b2d06a2114d673f91f54e7c7ce4 (patch) | |
| tree | 025bc2ff00351c71a719cb5bc2aa3f59133400f6 /lib/is_single_threaded.c | |
| parent | 0d03d59d9b31cd1e33b7e46a80b6fef66244b1f2 (diff) | |
| parent | a3c8b97396ef42edfb845788ba6f53b2a93ce980 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: (57 commits)
binfmt_elf: fix PT_INTERP bss handling
TPM: Fixup boot probe timeout for tpm_tis driver
sysfs: Add labeling support for sysfs
LSM/SELinux: inode_{get,set,notify}secctx hooks to access LSM security context information.
VFS: Factor out part of vfs_setxattr so it can be called from the SELinux hook for inode_setsecctx.
KEYS: Add missing linux/tracehook.h #inclusions
KEYS: Fix default security_session_to_parent()
Security/SELinux: includecheck fix kernel/sysctl.c
KEYS: security_cred_alloc_blank() should return int under all circumstances
IMA: open new file for read
KEYS: Add a keyctl to install a process's session keyring on its parent [try #6]
KEYS: Extend TIF_NOTIFY_RESUME to (almost) all architectures [try #6]
KEYS: Do some whitespace cleanups [try #6]
KEYS: Make /proc/keys use keyid not numread as file position [try #6]
KEYS: Add garbage collection for dead, revoked and expired keys. [try #6]
KEYS: Flag dead keys to induce EKEYREVOKED [try #6]
KEYS: Allow keyctl_revoke() on keys that have SETATTR but not WRITE perm [try #6]
KEYS: Deal with dead-type keys appropriately [try #6]
CRED: Add some configurable debugging [try #6]
selinux: Support for the new TUN LSM hooks
...
Diffstat (limited to 'lib/is_single_threaded.c')
| -rw-r--r-- | lib/is_single_threaded.c | 61 |
1 files changed, 37 insertions, 24 deletions
diff --git a/lib/is_single_threaded.c b/lib/is_single_threaded.c index f1ed2fe76c65..bd2bea963364 100644 --- a/lib/is_single_threaded.c +++ b/lib/is_single_threaded.c | |||
| @@ -12,34 +12,47 @@ | |||
| 12 | 12 | ||
| 13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
| 14 | 14 | ||
| 15 | /** | 15 | /* |
| 16 | * is_single_threaded - Determine if a thread group is single-threaded or not | 16 | * Returns true if the task does not share ->mm with another thread/process. |
| 17 | * @p: A task in the thread group in question | ||
| 18 | * | ||
| 19 | * This returns true if the thread group to which a task belongs is single | ||
| 20 | * threaded, false if it is not. | ||
| 21 | */ | 17 | */ |
| 22 | bool is_single_threaded(struct task_struct *p) | 18 | bool current_is_single_threaded(void) |
| 23 | { | 19 | { |
| 24 | struct task_struct *g, *t; | 20 | struct task_struct *task = current; |
| 25 | struct mm_struct *mm = p->mm; | 21 | struct mm_struct *mm = task->mm; |
| 22 | struct task_struct *p, *t; | ||
| 23 | bool ret; | ||
| 26 | 24 | ||
| 27 | if (atomic_read(&p->signal->count) != 1) | 25 | if (atomic_read(&task->signal->live) != 1) |
| 28 | goto no; | 26 | return false; |
| 29 | 27 | ||
| 30 | if (atomic_read(&p->mm->mm_users) != 1) { | 28 | if (atomic_read(&mm->mm_users) == 1) |
| 31 | read_lock(&tasklist_lock); | 29 | return true; |
| 32 | do_each_thread(g, t) { | ||
| 33 | if (t->mm == mm && t != p) | ||
| 34 | goto no_unlock; | ||
| 35 | } while_each_thread(g, t); | ||
| 36 | read_unlock(&tasklist_lock); | ||
| 37 | } | ||
| 38 | 30 | ||
| 39 | return true; | 31 | ret = false; |
| 32 | rcu_read_lock(); | ||
| 33 | for_each_process(p) { | ||
| 34 | if (unlikely(p->flags & PF_KTHREAD)) | ||
| 35 | continue; | ||
| 36 | if (unlikely(p == task->group_leader)) | ||
| 37 | continue; | ||
| 38 | |||
| 39 | t = p; | ||
| 40 | do { | ||
| 41 | if (unlikely(t->mm == mm)) | ||
| 42 | goto found; | ||
| 43 | if (likely(t->mm)) | ||
| 44 | break; | ||
| 45 | /* | ||
| 46 | * t->mm == NULL. Make sure next_thread/next_task | ||
| 47 | * will see other CLONE_VM tasks which might be | ||
| 48 | * forked before exiting. | ||
| 49 | */ | ||
| 50 | smp_rmb(); | ||
| 51 | } while_each_thread(p, t); | ||
| 52 | } | ||
| 53 | ret = true; | ||
| 54 | found: | ||
| 55 | rcu_read_unlock(); | ||
| 40 | 56 | ||
| 41 | no_unlock: | 57 | return ret; |
| 42 | read_unlock(&tasklist_lock); | ||
| 43 | no: | ||
| 44 | return false; | ||
| 45 | } | 58 | } |
