summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2009-12-09 14:33:48 +0100
committerThomas Gleixner <tglx@linutronix.de>2010-02-21 20:20:07 +0100
commit378cc63c24b6c9b9269c05475fbefeb8335790b3 (patch)
treebb7c70e1192199236d448e3e1760a978f73ea15d
parent4c9a0a35cd3c2984a3c58bc22c7214472d01c9c9 (diff)
downloadlwn-378cc63c24b6c9b9269c05475fbefeb8335790b3.tar.gz
lwn-378cc63c24b6c9b9269c05475fbefeb8335790b3.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>
-rw-r--r--kernel/audit.c30
1 files changed, 14 insertions, 16 deletions
diff --git a/kernel/audit.c b/kernel/audit.c
index bf307ddf7d03..8ccf8d5a874c 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -880,17 +880,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,
@@ -900,22 +899,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: