diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c index a58dfebb5512326db7065a433c37676c99820407..7106f3456439468772189ce8053efe598ab8101b 100644 --- a/drivers/net/team/team_mode_loadbalance.c +++ b/drivers/net/team/team_mode_loadbalance.c @@ -293,11 +293,15 @@ static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx) __fprog_destroy(lb_priv->ex->orig_fprog); orig_fp = rcu_dereference_protected(lb_priv->fp, lockdep_is_held(&team->lock)); - sk_unattached_filter_destroy(orig_fp); } rcu_assign_pointer(lb_priv->fp, fp); lb_priv->ex->orig_fprog = fprog; + + if (orig_fp) { + synchronize_rcu(); + sk_unattached_filter_destroy(orig_fp); + } return 0; } diff --git a/net/core/filter.c b/net/core/filter.c index f3b2d5e9fe5f0126f060b30e5b9fab9899f3d9b3..42c1944b0c631843b8588b8b062bcfbd5e0e5567 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -841,6 +841,12 @@ static void sk_release_orig_filter(struct sk_filter *fp) } } +static void __sk_filter_release(struct sk_filter *fp) +{ + sk_release_orig_filter(fp); + sk_filter_free(fp); +} + /** * sk_filter_release_rcu - Release a socket filter by rcu_head * @rcu: rcu_head that contains the sk_filter to free @@ -849,8 +855,7 @@ static void sk_filter_release_rcu(struct rcu_head *rcu) { struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu); - sk_release_orig_filter(fp); - sk_filter_free(fp); + __sk_filter_release(fp); } /** @@ -1050,7 +1055,7 @@ EXPORT_SYMBOL_GPL(sk_unattached_filter_create); void sk_unattached_filter_destroy(struct sk_filter *fp) { - sk_filter_release(fp); + __sk_filter_release(fp); } EXPORT_SYMBOL_GPL(sk_unattached_filter_destroy);