diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-09-27 02:07:30 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-09-28 00:30:44 -0400 |
commit | f91ff5b9ff529be8aac2039af63b2c8ea6cd6ebe (patch) | |
tree | 21af332c509f7ba24699e7a6784f60b48f1baa45 | |
parent | 7fa7cb7109d07c29ab28bb877bc7049a0150dbe5 (diff) |
net: sk_{detach|attach}_filter() rcu fixes
sk_attach_filter() and sk_detach_filter() are run with socket locked.
Use the appropriate rcu_dereference_protected() instead of blocking BH,
and rcu_dereference_bh().
There is no point adding BH prevention and memory barrier.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/core/filter.c | 10 |
1 files changed, 4 insertions, 6 deletions
diff --git a/net/core/filter.c b/net/core/filter.c index 52b051f82a01..7adf50352918 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -638,10 +638,9 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) | |||
638 | return err; | 638 | return err; |
639 | } | 639 | } |
640 | 640 | ||
641 | rcu_read_lock_bh(); | 641 | old_fp = rcu_dereference_protected(sk->sk_filter, |
642 | old_fp = rcu_dereference_bh(sk->sk_filter); | 642 | sock_owned_by_user(sk)); |
643 | rcu_assign_pointer(sk->sk_filter, fp); | 643 | rcu_assign_pointer(sk->sk_filter, fp); |
644 | rcu_read_unlock_bh(); | ||
645 | 644 | ||
646 | if (old_fp) | 645 | if (old_fp) |
647 | sk_filter_delayed_uncharge(sk, old_fp); | 646 | sk_filter_delayed_uncharge(sk, old_fp); |
@@ -654,14 +653,13 @@ int sk_detach_filter(struct sock *sk) | |||
654 | int ret = -ENOENT; | 653 | int ret = -ENOENT; |
655 | struct sk_filter *filter; | 654 | struct sk_filter *filter; |
656 | 655 | ||
657 | rcu_read_lock_bh(); | 656 | filter = rcu_dereference_protected(sk->sk_filter, |
658 | filter = rcu_dereference_bh(sk->sk_filter); | 657 | sock_owned_by_user(sk)); |
659 | if (filter) { | 658 | if (filter) { |
660 | rcu_assign_pointer(sk->sk_filter, NULL); | 659 | rcu_assign_pointer(sk->sk_filter, NULL); |
661 | sk_filter_delayed_uncharge(sk, filter); | 660 | sk_filter_delayed_uncharge(sk, filter); |
662 | ret = 0; | 661 | ret = 0; |
663 | } | 662 | } |
664 | rcu_read_unlock_bh(); | ||
665 | return ret; | 663 | return ret; |
666 | } | 664 | } |
667 | EXPORT_SYMBOL_GPL(sk_detach_filter); | 665 | EXPORT_SYMBOL_GPL(sk_detach_filter); |