342-v4.16-netfilter-nf_tables-fix-flowtable-free.patch 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. From: Pablo Neira Ayuso <pablo@netfilter.org>
  2. Date: Mon, 5 Feb 2018 21:44:50 +0100
  3. Subject: [PATCH] netfilter: nf_tables: fix flowtable free
  4. Every flow_offload entry is added into the table twice. Because of this,
  5. rhashtable_free_and_destroy can't be used, since it would call kfree for
  6. each flow_offload object twice.
  7. This patch adds a call to nf_flow_table_iterate_cleanup() to schedule
  8. removal of entries, then there is an explicitly invocation of the
  9. garbage collector to clean up resources.
  10. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
  11. ---
  12. --- a/include/net/netfilter/nf_flow_table.h
  13. +++ b/include/net/netfilter/nf_flow_table.h
  14. @@ -14,6 +14,7 @@ struct nf_flowtable_type {
  15. struct list_head list;
  16. int family;
  17. void (*gc)(struct work_struct *work);
  18. + void (*free)(struct nf_flowtable *ft);
  19. const struct rhashtable_params *params;
  20. nf_hookfn *hook;
  21. struct module *owner;
  22. @@ -98,6 +99,7 @@ int nf_flow_table_iterate(struct nf_flow
  23. void nf_flow_table_cleanup(struct net *net, struct net_device *dev);
  24. +void nf_flow_table_free(struct nf_flowtable *flow_table);
  25. void nf_flow_offload_work_gc(struct work_struct *work);
  26. extern const struct rhashtable_params nf_flow_offload_rhash_params;
  27. --- a/net/ipv4/netfilter/nf_flow_table_ipv4.c
  28. +++ b/net/ipv4/netfilter/nf_flow_table_ipv4.c
  29. @@ -260,6 +260,7 @@ static struct nf_flowtable_type flowtabl
  30. .family = NFPROTO_IPV4,
  31. .params = &nf_flow_offload_rhash_params,
  32. .gc = nf_flow_offload_work_gc,
  33. + .free = nf_flow_table_free,
  34. .hook = nf_flow_offload_ip_hook,
  35. .owner = THIS_MODULE,
  36. };
  37. --- a/net/ipv6/netfilter/nf_flow_table_ipv6.c
  38. +++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c
  39. @@ -254,6 +254,7 @@ static struct nf_flowtable_type flowtabl
  40. .family = NFPROTO_IPV6,
  41. .params = &nf_flow_offload_rhash_params,
  42. .gc = nf_flow_offload_work_gc,
  43. + .free = nf_flow_table_free,
  44. .hook = nf_flow_offload_ipv6_hook,
  45. .owner = THIS_MODULE,
  46. };
  47. --- a/net/netfilter/nf_flow_table.c
  48. +++ b/net/netfilter/nf_flow_table.c
  49. @@ -232,19 +232,16 @@ static inline bool nf_flow_is_dying(cons
  50. return flow->flags & FLOW_OFFLOAD_DYING;
  51. }
  52. -void nf_flow_offload_work_gc(struct work_struct *work)
  53. +static int nf_flow_offload_gc_step(struct nf_flowtable *flow_table)
  54. {
  55. struct flow_offload_tuple_rhash *tuplehash;
  56. - struct nf_flowtable *flow_table;
  57. struct rhashtable_iter hti;
  58. struct flow_offload *flow;
  59. int err;
  60. - flow_table = container_of(work, struct nf_flowtable, gc_work.work);
  61. -
  62. err = rhashtable_walk_init(&flow_table->rhashtable, &hti, GFP_KERNEL);
  63. if (err)
  64. - goto schedule;
  65. + return 0;
  66. rhashtable_walk_start(&hti);
  67. @@ -270,7 +267,16 @@ void nf_flow_offload_work_gc(struct work
  68. out:
  69. rhashtable_walk_stop(&hti);
  70. rhashtable_walk_exit(&hti);
  71. -schedule:
  72. +
  73. + return 1;
  74. +}
  75. +
  76. +void nf_flow_offload_work_gc(struct work_struct *work)
  77. +{
  78. + struct nf_flowtable *flow_table;
  79. +
  80. + flow_table = container_of(work, struct nf_flowtable, gc_work.work);
  81. + nf_flow_offload_gc_step(flow_table);
  82. queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ);
  83. }
  84. EXPORT_SYMBOL_GPL(nf_flow_offload_work_gc);
  85. @@ -449,5 +455,12 @@ void nf_flow_table_cleanup(struct net *n
  86. }
  87. EXPORT_SYMBOL_GPL(nf_flow_table_cleanup);
  88. +void nf_flow_table_free(struct nf_flowtable *flow_table)
  89. +{
  90. + nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL);
  91. + WARN_ON(!nf_flow_offload_gc_step(flow_table));
  92. +}
  93. +EXPORT_SYMBOL_GPL(nf_flow_table_free);
  94. +
  95. MODULE_LICENSE("GPL");
  96. MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
  97. --- a/net/netfilter/nf_flow_table_inet.c
  98. +++ b/net/netfilter/nf_flow_table_inet.c
  99. @@ -24,6 +24,7 @@ static struct nf_flowtable_type flowtabl
  100. .family = NFPROTO_INET,
  101. .params = &nf_flow_offload_rhash_params,
  102. .gc = nf_flow_offload_work_gc,
  103. + .free = nf_flow_table_free,
  104. .hook = nf_flow_offload_inet_hook,
  105. .owner = THIS_MODULE,
  106. };
  107. --- a/net/netfilter/nf_tables_api.c
  108. +++ b/net/netfilter/nf_tables_api.c
  109. @@ -5299,17 +5299,12 @@ err:
  110. nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
  111. }
  112. -static void nft_flowtable_destroy(void *ptr, void *arg)
  113. -{
  114. - kfree(ptr);
  115. -}
  116. -
  117. static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable)
  118. {
  119. cancel_delayed_work_sync(&flowtable->data.gc_work);
  120. kfree(flowtable->name);
  121. - rhashtable_free_and_destroy(&flowtable->data.rhashtable,
  122. - nft_flowtable_destroy, NULL);
  123. + flowtable->data.type->free(&flowtable->data);
  124. + rhashtable_destroy(&flowtable->data.rhashtable);
  125. module_put(flowtable->data.type->owner);
  126. }