aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/core/filter.c23
1 files changed, 11 insertions, 12 deletions
diff --git a/net/core/filter.c b/net/core/filter.c
index 2be1830d3c35..54dddc92452d 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -398,7 +398,7 @@ int sk_chk_filter(struct sock_filter *filter, int flen)
398 */ 398 */
399int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) 399int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
400{ 400{
401 struct sk_filter *fp; 401 struct sk_filter *fp, *old_fp;
402 unsigned int fsize = sizeof(struct sock_filter) * fprog->len; 402 unsigned int fsize = sizeof(struct sock_filter) * fprog->len;
403 int err; 403 int err;
404 404
@@ -418,19 +418,18 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
418 fp->len = fprog->len; 418 fp->len = fprog->len;
419 419
420 err = sk_chk_filter(fp->insns, fp->len); 420 err = sk_chk_filter(fp->insns, fp->len);
421 if (!err) { 421 if (err) {
422 struct sk_filter *old_fp; 422 sk_filter_uncharge(sk, fp);
423 423 return err;
424 rcu_read_lock_bh();
425 old_fp = rcu_dereference(sk->sk_filter);
426 rcu_assign_pointer(sk->sk_filter, fp);
427 rcu_read_unlock_bh();
428 fp = old_fp;
429 } 424 }
430 425
431 if (fp) 426 rcu_read_lock_bh();
432 sk_filter_uncharge(sk, fp); 427 old_fp = rcu_dereference(sk->sk_filter);
433 return err; 428 rcu_assign_pointer(sk->sk_filter, fp);
429 rcu_read_unlock_bh();
430
431 sk_filter_uncharge(sk, old_fp);
432 return 0;
434} 433}
435 434
436int sk_detach_filter(struct sock *sk) 435int sk_detach_filter(struct sock *sk)