Commit 5b48bb8506c5 ("openvswitch: Fix helper reference leak") fixed a reference leak on helper objects, but inadvertently introduced a leak on the ct template. Previously, ct_info.ct->general.use was initialized to 0 by nf_ct_tmpl_alloc() and only incremented when ovs_ct_copy_action() returned successful. If an error occurred while adding the helper or adding the action to the actions buffer, the __ovs_ct_free_action() cleanup would use nf_ct_put() to free the entry; However, this relies on atomic_dec_and_test(ct_info.ct->general.use). This reference must be incremented first, or nf_ct_put() will never free it. Fix the issue by acquiring a reference to the template immediately after allocation.
Unified · Split
| @@ -698,6 +698,10 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr, · 697 unmodified lines | ||
| 698 | 698 | OVS_NLERR(log, "Failed to allocate conntrack template"); |
| 699 | 699 | return -ENOMEM; |
| 700 | 700 | } |
| 701 | + | |
| 702 | + __set_bit(IPS_CONFIRMED_BIT, &ct_info.ct->status); | |
| 703 | + nf_conntrack_get(&ct_info.ct->ct_general); | |
| 704 | + | |
| 701 | 705 | if (helper) { |
| 702 | 706 | err = ovs_ct_add_helper(&ct_info, helper, key, log); |
| 703 | 707 | if (err) |
| @@ -709,8 +713,6 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr, · 5 unmodified lines | ||
| 709 | 713 | if (err) |
| 710 | 714 | goto err_free_ct; |
| 711 | 715 | |
| 712 | − __set_bit(IPS_CONFIRMED_BIT, &ct_info.ct->status); | |
| 713 | − nf_conntrack_get(&ct_info.ct->ct_general); | |
| 714 | 716 | return 0; |
| 715 | 717 | err_free_ct: |
| 716 | 718 | __ovs_ct_free_action(&ct_info); |