diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index 1c9eeb98d826..1c0bee2544d9 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c @@ -338,6 +338,9 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, struct tcf_result cr = {}; int err, balloc = 0; struct tcf_exts e; +#ifdef CONFIG_NET_CLS_ACT + struct tcf_exts old_e = {}; +#endif err = tcf_exts_init(&e, net, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE); if (err < 0) @@ -479,6 +482,14 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, } if (old_r && old_r != r) { +#ifdef CONFIG_NET_CLS_ACT + /* r->exts is not copied from old_r->exts, and + * the following code will clears the old_r, so + * we need to destroy it after update the tp->root, + * to avoid memory leak bug. + */ + old_e = old_r->exts; +#endif err = tcindex_filter_result_init(old_r, cp, net); if (err < 0) { kfree(f); @@ -510,6 +521,9 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, tcf_exts_destroy(&new_filter_result.exts); } +#ifdef CONFIG_NET_CLS_ACT + tcf_exts_destroy(&old_e); +#endif if (oldp) tcf_queue_work(&oldp->rwork, tcindex_partial_destroy_work); return 0;