net: sk_{detach|attach}_filter() rcu fixes
authorEric Dumazet <eric.dumazet@gmail.com>
Mon, 27 Sep 2010 06:07:30 +0000 (06:07 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 28 Sep 2010 04:30:44 +0000 (21:30 -0700)
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>
net/core/filter.c

index 52b051f82a016e37c792efc8bc30dca3d71fd537..7adf50352918713af197b55283faf6b105087f4e 100644 (file)
@@ -638,10 +638,9 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
                return err;
        }
 
-       rcu_read_lock_bh();
-       old_fp = rcu_dereference_bh(sk->sk_filter);
+       old_fp = rcu_dereference_protected(sk->sk_filter,
+                                          sock_owned_by_user(sk));
        rcu_assign_pointer(sk->sk_filter, fp);
-       rcu_read_unlock_bh();
 
        if (old_fp)
                sk_filter_delayed_uncharge(sk, old_fp);
@@ -654,14 +653,13 @@ int sk_detach_filter(struct sock *sk)
        int ret = -ENOENT;
        struct sk_filter *filter;
 
-       rcu_read_lock_bh();
-       filter = rcu_dereference_bh(sk->sk_filter);
+       filter = rcu_dereference_protected(sk->sk_filter,
+                                          sock_owned_by_user(sk));
        if (filter) {
                rcu_assign_pointer(sk->sk_filter, NULL);
                sk_filter_delayed_uncharge(sk, filter);
                ret = 0;
        }
-       rcu_read_unlock_bh();
        return ret;
 }
 EXPORT_SYMBOL_GPL(sk_detach_filter);