diff options
author | Pavel Emelyanov <xemul@openvz.org> | 2007-10-18 00:22:42 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-10-18 00:22:42 -0400 |
commit | 47e958eac280c263397582d5581e868c3227a1bd (patch) | |
tree | 67fc50a26b7861b3330eae7f1874df851c0ef740 /include/net/sock.h | |
parent | d3904b739928edd83d117f1eb5bfa69f18d6f046 (diff) |
[NET]: Fix the race between sk_filter_(de|at)tach and sk_clone()
The proposed fix is to delay the reference counter decrement
until the quiescent state pass. This will give sk_clone() a
chance to get the reference on the cloned filter.
Regular sk_filter_uncharge can happen from the sk_free() only
and there's no need in delaying the put - the socket is dead
anyway and is to be release itself.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net/sock.h')
-rw-r--r-- | include/net/sock.h | 12 |
1 files changed, 1 insertions, 11 deletions
diff --git a/include/net/sock.h b/include/net/sock.h index b9cfe125c9e6..43fc3fa50d62 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -905,16 +905,6 @@ static inline int sk_filter(struct sock *sk, struct sk_buff *skb) | |||
905 | } | 905 | } |
906 | 906 | ||
907 | /** | 907 | /** |
908 | * sk_filter_rcu_free: Free a socket filter | ||
909 | * @rcu: rcu_head that contains the sk_filter to free | ||
910 | */ | ||
911 | static inline void sk_filter_rcu_free(struct rcu_head *rcu) | ||
912 | { | ||
913 | struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu); | ||
914 | kfree(fp); | ||
915 | } | ||
916 | |||
917 | /** | ||
918 | * sk_filter_release: Release a socket filter | 908 | * sk_filter_release: Release a socket filter |
919 | * @sk: socket | 909 | * @sk: socket |
920 | * @fp: filter to remove | 910 | * @fp: filter to remove |
@@ -925,7 +915,7 @@ static inline void sk_filter_rcu_free(struct rcu_head *rcu) | |||
925 | static inline void sk_filter_release(struct sk_filter *fp) | 915 | static inline void sk_filter_release(struct sk_filter *fp) |
926 | { | 916 | { |
927 | if (atomic_dec_and_test(&fp->refcnt)) | 917 | if (atomic_dec_and_test(&fp->refcnt)) |
928 | call_rcu_bh(&fp->rcu, sk_filter_rcu_free); | 918 | kfree(fp); |
929 | } | 919 | } |
930 | 920 | ||
931 | static inline void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp) | 921 | static inline void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp) |