diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2009-12-09 09:19:41 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-10-30 08:45:42 -0400 |
commit | ab263f47c9781a644de8b28013434b645082922e (patch) | |
tree | bae72a448f5d5f37fb5c762a4c336fe731523dfd /kernel/audit.c | |
parent | 207032051a5ed38df332729ba42e98e9a1e60434 (diff) |
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>
Diffstat (limited to 'kernel/audit.c')
-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 57f4038694d1..77770a034d59 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) | |||
873 | case AUDIT_TTY_GET: { | 873 | case AUDIT_TTY_GET: { |
874 | struct audit_tty_status s; | 874 | struct audit_tty_status s; |
875 | struct task_struct *tsk; | 875 | struct task_struct *tsk; |
876 | unsigned long flags; | ||
876 | 877 | ||
877 | read_lock(&tasklist_lock); | 878 | rcu_read_lock(); |
878 | tsk = find_task_by_vpid(pid); | 879 | tsk = find_task_by_vpid(pid); |
879 | if (!tsk) | 880 | if (tsk && lock_task_sighand(tsk, &flags)) { |
880 | err = -ESRCH; | ||
881 | else { | ||
882 | spin_lock_irq(&tsk->sighand->siglock); | ||
883 | s.enabled = tsk->signal->audit_tty != 0; | 881 | s.enabled = tsk->signal->audit_tty != 0; |
884 | spin_unlock_irq(&tsk->sighand->siglock); | 882 | unlock_task_sighand(tsk, &flags); |
885 | } | 883 | } else |
886 | read_unlock(&tasklist_lock); | 884 | err = -ESRCH; |
885 | rcu_read_unlock(); | ||
887 | 886 | ||
888 | if (!err) | 887 | if (!err) |
889 | audit_send_reply(NETLINK_CB(skb).pid, seq, | 888 | audit_send_reply(NETLINK_CB(skb).pid, seq, |
@@ -893,22 +892,21 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
893 | case AUDIT_TTY_SET: { | 892 | case AUDIT_TTY_SET: { |
894 | struct audit_tty_status *s; | 893 | struct audit_tty_status *s; |
895 | struct task_struct *tsk; | 894 | struct task_struct *tsk; |
895 | unsigned long flags; | ||
896 | 896 | ||
897 | if (nlh->nlmsg_len < sizeof(struct audit_tty_status)) | 897 | if (nlh->nlmsg_len < sizeof(struct audit_tty_status)) |
898 | return -EINVAL; | 898 | return -EINVAL; |
899 | s = data; | 899 | s = data; |
900 | if (s->enabled != 0 && s->enabled != 1) | 900 | if (s->enabled != 0 && s->enabled != 1) |
901 | return -EINVAL; | 901 | return -EINVAL; |
902 | read_lock(&tasklist_lock); | 902 | rcu_read_lock(); |
903 | tsk = find_task_by_vpid(pid); | 903 | tsk = find_task_by_vpid(pid); |
904 | if (!tsk) | 904 | if (tsk && lock_task_sighand(tsk, &flags)) { |
905 | err = -ESRCH; | ||
906 | else { | ||
907 | spin_lock_irq(&tsk->sighand->siglock); | ||
908 | tsk->signal->audit_tty = s->enabled != 0; | 905 | tsk->signal->audit_tty = s->enabled != 0; |
909 | spin_unlock_irq(&tsk->sighand->siglock); | 906 | unlock_task_sighand(tsk, &flags); |
910 | } | 907 | } else |
911 | read_unlock(&tasklist_lock); | 908 | err = -ESRCH; |
909 | rcu_read_unlock(); | ||
912 | break; | 910 | break; |
913 | } | 911 | } |
914 | default: | 912 | default: |