Skip to content

Commit

Permalink
check_unsafe_exec: s/lock_task_sighand/rcu_read_lock/
Browse files Browse the repository at this point in the history
write_lock(&current->fs->lock) guarantees we can't wrongly miss
LSM_UNSAFE_SHARE, this is what we care about. Use rcu_read_lock()
instead of ->siglock to iterate over the sub-threads. We must see
all CLONE_THREAD|CLONE_FS threads which didn't pass exit_fs(), it
takes fs->lock too.

With or without this patch we can miss the freshly cloned thread
and set LSM_UNSAFE_SHARE, we don't care.

Signed-off-by: Oleg Nesterov <[email protected]>
Acked-by: Roland McGrath <[email protected]>
[ Fixed lock/unlock typo  - Hugh ]
Acked-by: Hugh Dickins <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
oleg-nesterov authored and torvalds committed Apr 24, 2009
1 parent 8c652f9 commit 437f7fd
Showing 1 changed file with 2 additions and 4 deletions.
6 changes: 2 additions & 4 deletions fs/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1060,19 +1060,19 @@ EXPORT_SYMBOL(install_exec_creds);
int check_unsafe_exec(struct linux_binprm *bprm)
{
struct task_struct *p = current, *t;
unsigned long flags;
unsigned n_fs;
int res = 0;

bprm->unsafe = tracehook_unsafe_exec(p);

n_fs = 1;
write_lock(&p->fs->lock);
lock_task_sighand(p, &flags);
rcu_read_lock();
for (t = next_thread(p); t != p; t = next_thread(t)) {
if (t->fs == p->fs)
n_fs++;
}
rcu_read_unlock();

if (p->fs->users > n_fs) {
bprm->unsafe |= LSM_UNSAFE_SHARE;
Expand All @@ -1083,8 +1083,6 @@ int check_unsafe_exec(struct linux_binprm *bprm)
res = 1;
}
}

unlock_task_sighand(p, &flags);
write_unlock(&p->fs->lock);

return res;
Expand Down

0 comments on commit 437f7fd

Please sign in to comment.