diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2009-12-09 14:19:41 +0000 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-10-30 08:45:42 -0400 |
commit | ab263f47c9781a644de8b28013434b645082922e (patch) | |
tree | bae72a448f5d5f37fb5c762a4c336fe731523dfd | |
parent | 207032051a5ed38df332729ba42e98e9a1e60434 (diff) | |
download | linux-3.10-ab263f47c9781a644de8b28013434b645082922e.tar.gz linux-3.10-ab263f47c9781a644de8b28013434b645082922e.tar.bz2 linux-3.10-ab263f47c9781a644de8b28013434b645082922e.zip |
audit: Use rcu for task lookup protection
Protect the task lookups in audit_receive_msg() with rcu_read_lock()
instead of tasklist_lock and use lock/unlock_sighand to protect
against the exit race.
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>
-rw-r--r-- | kernel/audit.c | 30 |
1 files changed, 14 insertions, 16 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index 57f4038694d..77770a034d5 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -873,17 +873,16 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) case AUDIT_TTY_GET: { struct audit_tty_status s; struct task_struct *tsk; + unsigned long flags; - read_lock(&tasklist_lock); + rcu_read_lock(); tsk = find_task_by_vpid(pid); - if (!tsk) - err = -ESRCH; - else { - spin_lock_irq(&tsk->sighand->siglock); + if (tsk && lock_task_sighand(tsk, &flags)) { s.enabled = tsk->signal->audit_tty != 0; - spin_unlock_irq(&tsk->sighand->siglock); - } - read_unlock(&tasklist_lock); + unlock_task_sighand(tsk, &flags); + } else + err = -ESRCH; + rcu_read_unlock(); if (!err) audit_send_reply(NETLINK_CB(skb).pid, seq, @@ -893,22 +892,21 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) case AUDIT_TTY_SET: { struct audit_tty_status *s; struct task_struct *tsk; + unsigned long flags; if (nlh->nlmsg_len < sizeof(struct audit_tty_status)) return -EINVAL; s = data; if (s->enabled != 0 && s->enabled != 1) return -EINVAL; - read_lock(&tasklist_lock); + rcu_read_lock(); tsk = find_task_by_vpid(pid); - if (!tsk) - err = -ESRCH; - else { - spin_lock_irq(&tsk->sighand->siglock); + if (tsk && lock_task_sighand(tsk, &flags)) { tsk->signal->audit_tty = s->enabled != 0; - spin_unlock_irq(&tsk->sighand->siglock); - } - read_unlock(&tasklist_lock); + unlock_task_sighand(tsk, &flags); + } else + err = -ESRCH; + rcu_read_unlock(); break; } default: |