audit: Call tty_audit_push_task() outside preempt disabled
While auditing all tasklist_lock read_lock sites I stumbled over the following call chain: audit_prepare_user_tty() read_lock(&tasklist_lock); tty_audit_push_task(); mutex_lock(&buf->mutex); --> buf->mutex is locked with preemption disabled. Solve this by acquiring a reference to the task struct under rcu_read_lock and call tty_audit_push_task outside of the preempt disabled region. Move all code which needs to be protected by sighand lock into tty_audit_push_task() and use lock/unlock_sighand as we do not hold tasklist_lock. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Eric Paris <eparis@redhat.com> Cc: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
@ -467,23 +467,16 @@ static int audit_prepare_user_tty(pid_t pid, uid_t loginuid, u32 sessionid)
|
||||
struct task_struct *tsk;
|
||||
int err;
|
||||
|
||||
read_lock(&tasklist_lock);
|
||||
rcu_read_lock();
|
||||
tsk = find_task_by_vpid(pid);
|
||||
err = -ESRCH;
|
||||
if (!tsk)
|
||||
goto out;
|
||||
err = 0;
|
||||
|
||||
spin_lock_irq(&tsk->sighand->siglock);
|
||||
if (!tsk->signal->audit_tty)
|
||||
err = -EPERM;
|
||||
spin_unlock_irq(&tsk->sighand->siglock);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
tty_audit_push_task(tsk, loginuid, sessionid);
|
||||
out:
|
||||
read_unlock(&tasklist_lock);
|
||||
if (!tsk) {
|
||||
rcu_read_unlock();
|
||||
return -ESRCH;
|
||||
}
|
||||
get_task_struct(tsk);
|
||||
rcu_read_unlock();
|
||||
err = tty_audit_push_task(tsk, loginuid, sessionid);
|
||||
put_task_struct(tsk);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user