History

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says: ==================== Netfilter/IPVS updates for net-next The following patchset contains Netfilter updates for net-next: 1) Support for rejecting packets from the prerouting chain, from Laura Garcia Liebana. 2) Remove useless assignment in pipapo, from Stefano Brivio. 3) On demand hook registration in IPVS, from Julian Anastasov. 4) Expire IPVS connection from process context to not overload timers, also from Julian. 5) Fallback to conntrack TCP tracker to handle connection reuse in IPVS, from Julian Anastasov. 6) Several patches to support for chain bindings. 7) Expose enum nft_chain_flags through UAPI. 8) Reject unsupported chain flags from the netlink control plane. ====================

David S. Miller committed 6 years ago

Commit e80a07b2 parents 3d07ae5 c1f79a212 files · +428 −89Browse files

Unified · Split

12 files
  1. include/net/ip_vs.h +9 −6
  2. include/net/netfilter/nf_tables.h +16 −7
  3. include/uapi/linux/netfilter/nf_tables.h +14 −0
  4. net/ipv4/netfilter/nf_reject_ipv4.c +21 −0
  5. net/ipv6/netfilter/nf_reject_ipv6.c +26 −0
  6. net/netfilter/ipvs/ip_vs_conn.c +38 −15
  7. net/netfilter/ipvs/ip_vs_core.c +70 −22
  8. net/netfilter/ipvs/ip_vs_ctl.c +25 −4
  9. net/netfilter/nf_tables_api.c +156 −32
  10. net/netfilter/nft_immediate.c +51 −0
  11. net/netfilter/nft_reject.c +2 −1
  12. net/netfilter/nft_set_pipapo.c +0 −2
include/net/ip_vs.h+9−6
@@ -874,6 +874,7 @@ struct netns_ipvs { · 873 unmodified lines
874874 struct ip_vs_stats tot_stats; /* Statistics & est. */
875875
876876 int num_services; /* no of virtual services */
877+ int num_services6; /* IPv6 virtual services */
877878
878879 /* Trash for destinations */
879880 struct list_head dest_trash;
@@ -960,6 +961,7 @@ struct netns_ipvs { · 80 unmodified lines
960961 * are not supported when synchronization is enabled.
961962 */
962963 unsigned int mixed_address_family_dests;
964+ unsigned int hooks_afmask; /* &1=AF_INET, &2=AF_INET6 */
963965 };
964966
965967 #define DEFAULT_SYNC_THRESHOLD 3
@@ -1624,18 +1626,16 @@ static inline void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp) · 658 unmodified lines
16241626 }
16251627 #endif /* CONFIG_IP_VS_NFCT */
16261628
1627−/* Really using conntrack? */
1628−static inline bool ip_vs_conn_uses_conntrack(struct ip_vs_conn *cp,
1629− struct sk_buff *skb)
1629+/* Using old conntrack that can not be redirected to another real server? */
1630+static inline bool ip_vs_conn_uses_old_conntrack(struct ip_vs_conn *cp,
1631+ struct sk_buff *skb)
16301632 {
16311633 #ifdef CONFIG_IP_VS_NFCT
16321634 enum ip_conntrack_info ctinfo;
16331635 struct nf_conn *ct;
16341636
1635− if (!(cp->flags & IP_VS_CONN_F_NFCT))
1636− return false;
16371637 ct = nf_ct_get(skb, &ctinfo);
1638− if (ct)
1638+ if (ct && nf_ct_is_confirmed(ct))
16391639 return true;
16401640 #endif
16411641 return false;
@@ -1670,6 +1670,9 @@ static inline void ip_vs_unregister_conntrack(struct ip_vs_service *svc) · 28 unmodified lines
16701670 #endif
16711671 }
16721672
1673+int ip_vs_register_hooks(struct netns_ipvs *ipvs, unsigned int af);
1674+void ip_vs_unregister_hooks(struct netns_ipvs *ipvs, unsigned int af);
1675+
16731676 static inline int
16741677 ip_vs_dest_conn_overhead(struct ip_vs_dest *dest)
16751678 {
include/net/netfilter/nf_tables.h+16−7
@@ -899,6 +899,8 @@ static inline struct nft_userdata *nft_userdata(const struct nft_rule *rule) · 898 unmodified lines
899899 return (void *)&rule->data[rule->dlen];
900900 }
901901
902+void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule);
903+
902904 static inline void nft_set_elem_update_expr(const struct nft_set_ext *ext,
903905 struct nft_regs *regs,
904906 const struct nft_pktinfo *pkt)
@@ -921,11 +923,6 @@ static inline void nft_set_elem_update_expr(const struct nft_set_ext *ext, · 16 unmodified lines
921923 (expr) != (last); \
922924 (expr) = nft_expr_next(expr))
923925
924−enum nft_chain_flags {
925− NFT_BASE_CHAIN = 0x1,
926− NFT_CHAIN_HW_OFFLOAD = 0x2,
927−};
928−
929926 #define NFT_CHAIN_POLICY_UNSET U8_MAX
930927
931928 /**
@@ -949,7 +946,8 @@ struct nft_chain { · 17 unmodified lines
949946 struct nft_table *table;
950947 u64 handle;
951948 u32 use;
952− u8 flags:6,
949+ u8 flags:5,
950+ bound:1,
953951 genmask:2;
954952 char *name;
955953
@@ -994,6 +992,14 @@ int nft_chain_validate_dependency(const struct nft_chain *chain, · 38 unmodified lines
994992 int nft_chain_validate_hooks(const struct nft_chain *chain,
995993 unsigned int hook_flags);
996994
995+static inline bool nft_chain_is_bound(struct nft_chain *chain)
996+{
997+ return (chain->flags & NFT_CHAIN_BINDING) && chain->bound;
998+}
999+
1000+void nft_chain_del(struct nft_chain *chain);
1001+void nf_tables_chain_destroy(struct nft_ctx *ctx);
1002+
9971003 struct nft_stats {
9981004 u64 bytes;
9991005 u64 pkts;
@@ -1036,7 +1042,7 @@ static inline struct nft_base_chain *nft_base_chain(const struct nft_chain *chai · 36 unmodified lines
10361042
10371043 static inline bool nft_is_base_chain(const struct nft_chain *chain)
10381044 {
1039− return chain->flags & NFT_BASE_CHAIN;
1045+ return chain->flags & NFT_CHAIN_BASE;
10401046 }
10411047
10421048 int __nft_release_basechain(struct nft_ctx *ctx);
@@ -1433,6 +1439,7 @@ struct nft_trans_chain { · 390 unmodified lines
14331439 char *name;
14341440 struct nft_stats __percpu *stats;
14351441 u8 policy;
1442+ u32 chain_id;
14361443 };
14371444
14381445 #define nft_trans_chain_update(trans) \
@@ -1443,6 +1450,8 @@ struct nft_trans_chain { · 4 unmodified lines
14431450 (((struct nft_trans_chain *)trans->data)->stats)
14441451 #define nft_trans_chain_policy(trans) \
14451452 (((struct nft_trans_chain *)trans->data)->policy)
1453+#define nft_trans_chain_id(trans) \
1454+ (((struct nft_trans_chain *)trans->data)->chain_id)
14461455
14471456 struct nft_trans_table {
14481457 bool update;
include/uapi/linux/netfilter/nf_tables.h+14−0
@@ -184,6 +184,15 @@ enum nft_table_attributes { · 183 unmodified lines
184184 };
185185 #define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1)
186186
187+enum nft_chain_flags {
188+ NFT_CHAIN_BASE = (1 << 0),
189+ NFT_CHAIN_HW_OFFLOAD = (1 << 1),
190+ NFT_CHAIN_BINDING = (1 << 2),
191+};
192+#define NFT_CHAIN_FLAGS (NFT_CHAIN_BASE | \
193+ NFT_CHAIN_HW_OFFLOAD | \
194+ NFT_CHAIN_BINDING)
195+
187196 /**
188197 * enum nft_chain_attributes - nf_tables chain netlink attributes
189198 *
@@ -196,6 +205,7 @@ enum nft_table_attributes { · 6 unmodified lines
196205 * @NFTA_CHAIN_TYPE: type name of the string (NLA_NUL_STRING)
197206 * @NFTA_CHAIN_COUNTERS: counter specification of the chain (NLA_NESTED: nft_counter_attributes)
198207 * @NFTA_CHAIN_FLAGS: chain flags
208+ * @NFTA_CHAIN_ID: uniquely identifies a chain in a transaction (NLA_U32)
199209 */
200210 enum nft_chain_attributes {
201211 NFTA_CHAIN_UNSPEC,
@@ -209,6 +219,7 @@ enum nft_chain_attributes { · 7 unmodified lines
209219 NFTA_CHAIN_COUNTERS,
210220 NFTA_CHAIN_PAD,
211221 NFTA_CHAIN_FLAGS,
222+ NFTA_CHAIN_ID,
212223 __NFTA_CHAIN_MAX
213224 };
214225 #define NFTA_CHAIN_MAX (__NFTA_CHAIN_MAX - 1)
@@ -238,6 +249,7 @@ enum nft_rule_attributes { · 23 unmodified lines
238249 NFTA_RULE_PAD,
239250 NFTA_RULE_ID,
240251 NFTA_RULE_POSITION_ID,
252+ NFTA_RULE_CHAIN_ID,
241253 __NFTA_RULE_MAX
242254 };
243255 #define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)
@@ -468,11 +480,13 @@ enum nft_data_attributes { · 224 unmodified lines
468480 *
469481 * @NFTA_VERDICT_CODE: nf_tables verdict (NLA_U32: enum nft_verdicts)
470482 * @NFTA_VERDICT_CHAIN: jump target chain name (NLA_STRING)
483+ * @NFTA_VERDICT_CHAIN_ID: jump target chain ID (NLA_U32)
471484 */
472485 enum nft_verdict_attributes {
473486 NFTA_VERDICT_UNSPEC,
474487 NFTA_VERDICT_CODE,
475488 NFTA_VERDICT_CHAIN,
489+ NFTA_VERDICT_CHAIN_ID,
476490 __NFTA_VERDICT_MAX
477491 };
478492 #define NFTA_VERDICT_MAX (__NFTA_VERDICT_MAX - 1)
net/ipv4/netfilter/nf_reject_ipv4.c+21−0
@@ -96,6 +96,21 @@ void nf_reject_ip_tcphdr_put(struct sk_buff *nskb, const struct sk_buff *oldskb, · 95 unmodified lines
9696 }
9797 EXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_put);
9898
99+static int nf_reject_fill_skb_dst(struct sk_buff *skb_in)
100+{
101+ struct dst_entry *dst = NULL;
102+ struct flowi fl;
103+
104+ memset(&fl, 0, sizeof(struct flowi));
105+ fl.u.ip4.daddr = ip_hdr(skb_in)->saddr;
106+ nf_ip_route(dev_net(skb_in->dev), &dst, &fl, false);
107+ if (!dst)
108+ return -1;
109+
110+ skb_dst_set(skb_in, dst);
111+ return 0;
112+}
113+
99114 /* Send RST reply */
100115 void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
101116 {
@@ -109,6 +124,9 @@ void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook) · 7 unmodified lines
109124 if (!oth)
110125 return;
111126
127+ if (hook == NF_INET_PRE_ROUTING && nf_reject_fill_skb_dst(oldskb))
128+ return;
129+
112130 if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
113131 return;
114132
@@ -175,6 +193,9 @@ void nf_send_unreach(struct sk_buff *skb_in, int code, int hook) · 60 unmodified lines
175193 if (iph->frag_off & htons(IP_OFFSET))
176194 return;
177195
196+ if (hook == NF_INET_PRE_ROUTING && nf_reject_fill_skb_dst(skb_in))
197+ return;
198+
178199 if (skb_csum_unnecessary(skb_in) || !nf_reject_verify_csum(proto)) {
179200 icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
180201 return;
net/ipv6/netfilter/nf_reject_ipv6.c+26−0
@@ -126,6 +126,21 @@ void nf_reject_ip6_tcphdr_put(struct sk_buff *nskb, · 125 unmodified lines
126126 }
127127 EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_put);
128128
129+static int nf_reject6_fill_skb_dst(struct sk_buff *skb_in)
130+{
131+ struct dst_entry *dst = NULL;
132+ struct flowi fl;
133+
134+ memset(&fl, 0, sizeof(struct flowi));
135+ fl.u.ip6.daddr = ipv6_hdr(skb_in)->saddr;
136+ nf_ip6_route(dev_net(skb_in->dev), &dst, &fl, false);
137+ if (!dst)
138+ return -1;
139+
140+ skb_dst_set(skb_in, dst);
141+ return 0;
142+}
143+
129144 void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
130145 {
131146 struct net_device *br_indev __maybe_unused;
@@ -154,6 +169,14 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) · 22 unmodified lines
154169 fl6.daddr = oip6h->saddr;
155170 fl6.fl6_sport = otcph->dest;
156171 fl6.fl6_dport = otcph->source;
172+
173+ if (hook == NF_INET_PRE_ROUTING) {
174+ nf_ip6_route(net, &dst, flowi6_to_flowi(&fl6), false);
175+ if (!dst)
176+ return;
177+ skb_dst_set(oldskb, dst);
178+ }
179+
157180 fl6.flowi6_oif = l3mdev_master_ifindex(skb_dst(oldskb)->dev);
158181 fl6.flowi6_mark = IP6_REPLY_MARK(net, oldskb->mark);
159182 security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));
@@ -245,6 +268,9 @@ void nf_send_unreach6(struct net *net, struct sk_buff *skb_in, · 85 unmodified lines
245268 if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL)
246269 skb_in->dev = net->loopback_dev;
247270
271+ if (hooknum == NF_INET_PRE_ROUTING && nf_reject6_fill_skb_dst(skb_in))
272+ return;
273+
248274 icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0);
249275 }
250276 EXPORT_SYMBOL_GPL(nf_send_unreach6);
net/netfilter/ipvs/ip_vs_conn.c+38−15
@@ -807,6 +807,31 @@ static void ip_vs_conn_rcu_free(struct rcu_head *head) · 806 unmodified lines
807807 kmem_cache_free(ip_vs_conn_cachep, cp);
808808 }
809809
810+/* Try to delete connection while not holding reference */
811+static void ip_vs_conn_del(struct ip_vs_conn *cp)
812+{
813+ if (del_timer(&cp->timer)) {
814+ /* Drop cp->control chain too */
815+ if (cp->control)
816+ cp->timeout = 0;
817+ ip_vs_conn_expire(&cp->timer);
818+ }
819+}
820+
821+/* Try to delete connection while holding reference */
822+static void ip_vs_conn_del_put(struct ip_vs_conn *cp)
823+{
824+ if (del_timer(&cp->timer)) {
825+ /* Drop cp->control chain too */
826+ if (cp->control)
827+ cp->timeout = 0;
828+ __ip_vs_conn_put(cp);
829+ ip_vs_conn_expire(&cp->timer);
830+ } else {
831+ __ip_vs_conn_put(cp);
832+ }
833+}
834+
810835 static void ip_vs_conn_expire(struct timer_list *t)
811836 {
812837 struct ip_vs_conn *cp = from_timer(cp, t, timer);
@@ -827,14 +852,17 @@ static void ip_vs_conn_expire(struct timer_list *t) · 14 unmodified lines
827852
828853 /* does anybody control me? */
829854 if (ct) {
855+ bool has_ref = !cp->timeout && __ip_vs_conn_get(ct);
856+
830857 ip_vs_control_del(cp);
831858 /* Drop CTL or non-assured TPL if not used anymore */
832− if (!cp->timeout && !atomic_read(&ct->n_control) &&
859+ if (has_ref && !atomic_read(&ct->n_control) &&
833860 (!(ct->flags & IP_VS_CONN_F_TEMPLATE) ||
834861 !(ct->state & IP_VS_CTPL_S_ASSURED))) {
835862 IP_VS_DBG(4, "drop controlling connection\n");
836− ct->timeout = 0;
837− ip_vs_conn_expire_now(ct);
863+ ip_vs_conn_del_put(ct);
864+ } else if (has_ref) {
865+ __ip_vs_conn_put(ct);
838866 }
839867 }
840868
@@ -1317,8 +1345,7 @@ try_drop: · 476 unmodified lines
13171345
13181346 drop:
13191347 IP_VS_DBG(4, "drop connection\n");
1320− cp->timeout = 0;
1321− ip_vs_conn_expire_now(cp);
1348+ ip_vs_conn_del(cp);
13221349 }
13231350 cond_resched_rcu();
13241351 }
@@ -1341,19 +1368,15 @@ flush_again: · 16 unmodified lines
13411368 hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[idx], c_list) {
13421369 if (cp->ipvs != ipvs)
13431370 continue;
1344− /* As timers are expired in LIFO order, restart
1345− * the timer of controlling connection first, so
1346− * that it is expired after us.
1347− */
1371+ if (atomic_read(&cp->n_control))
1372+ continue;
13481373 cp_c = cp->control;
1349− /* cp->control is valid only with reference to cp */
1350− if (cp_c && __ip_vs_conn_get(cp)) {
1374+ IP_VS_DBG(4, "del connection\n");
1375+ ip_vs_conn_del(cp);
1376+ if (cp_c && !atomic_read(&cp_c->n_control)) {
13511377 IP_VS_DBG(4, "del controlling connection\n");
1352− ip_vs_conn_expire_now(cp_c);
1353− __ip_vs_conn_put(cp);
1378+ ip_vs_conn_del(cp_c);
13541379 }
1355− IP_VS_DBG(4, "del connection\n");
1356− ip_vs_conn_expire_now(cp);
13571380 }
13581381 cond_resched_rcu();
13591382 }
net/netfilter/ipvs/ip_vs_core.c+70−22
@@ -2066,14 +2066,14 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int · 2065 unmodified lines
20662066
20672067 conn_reuse_mode = sysctl_conn_reuse_mode(ipvs);
20682068 if (conn_reuse_mode && !iph.fragoffs && is_new_conn(skb, &iph) && cp) {
2069− bool uses_ct = false, resched = false;
2069+ bool old_ct = false, resched = false;
20702070
20712071 if (unlikely(sysctl_expire_nodest_conn(ipvs)) && cp->dest &&
20722072 unlikely(!atomic_read(&cp->dest->weight))) {
20732073 resched = true;
2074− uses_ct = ip_vs_conn_uses_conntrack(cp, skb);
2074+ old_ct = ip_vs_conn_uses_old_conntrack(cp, skb);
20752075 } else if (is_new_conn_expected(cp, conn_reuse_mode)) {
2076− uses_ct = ip_vs_conn_uses_conntrack(cp, skb);
2076+ old_ct = ip_vs_conn_uses_old_conntrack(cp, skb);
20772077 if (!atomic_read(&cp->n_control)) {
20782078 resched = true;
20792079 } else {
@@ -2081,15 +2081,17 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int · 1 unmodified line
20812081 * that uses conntrack while it is still
20822082 * referenced by controlled connection(s).
20832083 */
2084− resched = !uses_ct;
2084+ resched = !old_ct;
20852085 }
20862086 }
20872087
20882088 if (resched) {
2089+ if (!old_ct)
2090+ cp->flags &= ~IP_VS_CONN_F_NFCT;
20892091 if (!atomic_read(&cp->n_control))
20902092 ip_vs_conn_expire_now(cp);
20912093 __ip_vs_conn_put(cp);
2092− if (uses_ct)
2094+ if (old_ct)
20932095 return NF_DROP;
20942096 cp = NULL;
20952097 }
@@ -2256,7 +2258,7 @@ ip_vs_forward_icmp_v6(void *priv, struct sk_buff *skb, · 160 unmodified lines
22562258 #endif
22572259
22582260
2259−static const struct nf_hook_ops ip_vs_ops[] = {
2261+static const struct nf_hook_ops ip_vs_ops4[] = {
22602262 /* After packet filtering, change source only for VS/NAT */
22612263 {
22622264 .hook = ip_vs_reply4,
@@ -2302,7 +2304,10 @@ static const struct nf_hook_ops ip_vs_ops[] = { · 39 unmodified lines
23022304 .hooknum = NF_INET_FORWARD,
23032305 .priority = 100,
23042306 },
2307+};
2308+
23052309 #ifdef CONFIG_IP_VS_IPV6
2310+static const struct nf_hook_ops ip_vs_ops6[] = {
23062311 /* After packet filtering, change source only for VS/NAT */
23072312 {
23082313 .hook = ip_vs_reply6,
@@ -2348,8 +2353,64 @@ static const struct nf_hook_ops ip_vs_ops[] = { · 39 unmodified lines
23482353 .hooknum = NF_INET_FORWARD,
23492354 .priority = 100,
23502355 },
2351−#endif
23522356 };
2357+#endif
2358+
2359+int ip_vs_register_hooks(struct netns_ipvs *ipvs, unsigned int af)
2360+{
2361+ const struct nf_hook_ops *ops;
2362+ unsigned int count;
2363+ unsigned int afmask;
2364+ int ret = 0;
2365+
2366+ if (af == AF_INET6) {
2367+#ifdef CONFIG_IP_VS_IPV6
2368+ ops = ip_vs_ops6;
2369+ count = ARRAY_SIZE(ip_vs_ops6);
2370+ afmask = 2;
2371+#else
2372+ return -EINVAL;
2373+#endif
2374+ } else {
2375+ ops = ip_vs_ops4;
2376+ count = ARRAY_SIZE(ip_vs_ops4);
2377+ afmask = 1;
2378+ }
2379+
2380+ if (!(ipvs->hooks_afmask & afmask)) {
2381+ ret = nf_register_net_hooks(ipvs->net, ops, count);
2382+ if (ret >= 0)
2383+ ipvs->hooks_afmask |= afmask;
2384+ }
2385+ return ret;
2386+}
2387+
2388+void ip_vs_unregister_hooks(struct netns_ipvs *ipvs, unsigned int af)
2389+{
2390+ const struct nf_hook_ops *ops;
2391+ unsigned int count;
2392+ unsigned int afmask;
2393+
2394+ if (af == AF_INET6) {
2395+#ifdef CONFIG_IP_VS_IPV6
2396+ ops = ip_vs_ops6;
2397+ count = ARRAY_SIZE(ip_vs_ops6);
2398+ afmask = 2;
2399+#else
2400+ return;
2401+#endif
2402+ } else {
2403+ ops = ip_vs_ops4;
2404+ count = ARRAY_SIZE(ip_vs_ops4);
2405+ afmask = 1;
2406+ }
2407+
2408+ if (ipvs->hooks_afmask & afmask) {
2409+ nf_unregister_net_hooks(ipvs->net, ops, count);
2410+ ipvs->hooks_afmask &= ~afmask;
2411+ }
2412+}
2413+
23532414 /*
23542415 * Initialize IP Virtual Server netns mem.
23552416 */
@@ -2425,19 +2486,6 @@ static void __net_exit __ip_vs_cleanup_batch(struct list_head *net_list) · 69 unmodified lines
24252486 }
24262487 }
24272488
2428−static int __net_init __ip_vs_dev_init(struct net *net)
2429−{
2430− int ret;
2431−
2432− ret = nf_register_net_hooks(net, ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
2433− if (ret < 0)
2434− goto hook_fail;
2435− return 0;
2436−
2437−hook_fail:
2438− return ret;
2439−}
2440−
24412489 static void __net_exit __ip_vs_dev_cleanup_batch(struct list_head *net_list)
24422490 {
24432491 struct netns_ipvs *ipvs;
@@ -2446,7 +2494,8 @@ static void __net_exit __ip_vs_dev_cleanup_batch(struct list_head *net_list) · 2 unmodified lines
24462494 EnterFunction(2);
24472495 list_for_each_entry(net, net_list, exit_list) {
24482496 ipvs = net_ipvs(net);
2449− nf_unregister_net_hooks(net, ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
2497+ ip_vs_unregister_hooks(ipvs, AF_INET);
2498+ ip_vs_unregister_hooks(ipvs, AF_INET6);
24502499 ipvs->enable = 0; /* Disable packet reception */
24512500 smp_wmb();
24522501 ip_vs_sync_net_cleanup(ipvs);
@@ -2462,7 +2511,6 @@ static struct pernet_operations ipvs_core_ops = { · 9 unmodified lines
24622511 };
24632512
24642513 static struct pernet_operations ipvs_core_dev_ops = {
2465− .init = __ip_vs_dev_init,
24662514 .exit_batch = __ip_vs_dev_cleanup_batch,
24672515 };
24682516
net/netfilter/ipvs/ip_vs_ctl.c+25−4
@@ -224,7 +224,8 @@ static void defense_work_handler(struct work_struct *work) · 223 unmodified lines
224224 update_defense_level(ipvs);
225225 if (atomic_read(&ipvs->dropentry))
226226 ip_vs_random_dropentry(ipvs);
227− schedule_delayed_work(&ipvs->defense_work, DEFENSE_TIMER_PERIOD);
227+ queue_delayed_work(system_long_wq, &ipvs->defense_work,
228+ DEFENSE_TIMER_PERIOD);
228229 }
229230 #endif
230231
@@ -1272,6 +1273,7 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u, · 1041 unmodified lines
12721273 struct ip_vs_scheduler *sched = NULL;
12731274 struct ip_vs_pe *pe = NULL;
12741275 struct ip_vs_service *svc = NULL;
1276+ int ret_hooks = -1;
12751277
12761278 /* increase the module use count */
12771279 if (!ip_vs_use_count_inc())
@@ -1313,6 +1315,14 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u, · 35 unmodified lines
13131315 }
13141316 #endif
13151317
1318+ if ((u->af == AF_INET && !ipvs->num_services) ||
1319+ (u->af == AF_INET6 && !ipvs->num_services6)) {
1320+ ret = ip_vs_register_hooks(ipvs, u->af);
1321+ if (ret < 0)
1322+ goto out_err;
1323+ ret_hooks = ret;
1324+ }
1325+
13161326 svc = kzalloc(sizeof(struct ip_vs_service), GFP_KERNEL);
13171327 if (svc == NULL) {
13181328 IP_VS_DBG(1, "%s(): no memory\n", __func__);
@@ -1374,6 +1384,8 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u, · 55 unmodified lines
13741384 /* Count only IPv4 services for old get/setsockopt interface */
13751385 if (svc->af == AF_INET)
13761386 ipvs->num_services++;
1387+ else if (svc->af == AF_INET6)
1388+ ipvs->num_services6++;
13771389
13781390 /* Hash the service into the service table */
13791391 ip_vs_svc_hash(svc);
@@ -1385,6 +1397,8 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u, · 5 unmodified lines
13851397
13861398
13871399 out_err:
1400+ if (ret_hooks >= 0)
1401+ ip_vs_unregister_hooks(ipvs, u->af);
13881402 if (svc != NULL) {
13891403 ip_vs_unbind_scheduler(svc, sched);
13901404 ip_vs_service_free(svc);
@@ -1500,9 +1514,15 @@ static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup) · 109 unmodified lines
15001514 struct ip_vs_pe *old_pe;
15011515 struct netns_ipvs *ipvs = svc->ipvs;
15021516
1503− /* Count only IPv4 services for old get/setsockopt interface */
1504− if (svc->af == AF_INET)
1517+ if (svc->af == AF_INET) {
15051518 ipvs->num_services--;
1519+ if (!ipvs->num_services)
1520+ ip_vs_unregister_hooks(ipvs, svc->af);
1521+ } else if (svc->af == AF_INET6) {
1522+ ipvs->num_services6--;
1523+ if (!ipvs->num_services6)
1524+ ip_vs_unregister_hooks(ipvs, svc->af);
1525+ }
15061526
15071527 ip_vs_stop_estimator(svc->ipvs, &svc->stats);
15081528
@@ -4063,7 +4083,8 @@ static int __net_init ip_vs_control_net_init_sysctl(struct netns_ipvs *ipvs) · 2554 unmodified lines
40634083 ipvs->sysctl_tbl = tbl;
40644084 /* Schedule defense work */
40654085 INIT_DELAYED_WORK(&ipvs->defense_work, defense_work_handler);
4066− schedule_delayed_work(&ipvs->defense_work, DEFENSE_TIMER_PERIOD);
4086+ queue_delayed_work(system_long_wq, &ipvs->defense_work,
4087+ DEFENSE_TIMER_PERIOD);
40674088
40684089 return 0;
40694090 }
net/netfilter/nf_tables_api.c+156−32
@@ -280,9 +280,15 @@ static struct nft_trans *nft_trans_chain_add(struct nft_ctx *ctx, int msg_type) · 279 unmodified lines
280280 if (trans == NULL)
281281 return ERR_PTR(-ENOMEM);
282282
283− if (msg_type == NFT_MSG_NEWCHAIN)
283+ if (msg_type == NFT_MSG_NEWCHAIN) {
284284 nft_activate_next(ctx->net, ctx->chain);
285285
286+ if (ctx->nla[NFTA_CHAIN_ID]) {
287+ nft_trans_chain_id(trans) =
288+ ntohl(nla_get_be32(ctx->nla[NFTA_CHAIN_ID]));
289+ }
290+ }
291+
286292 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
287293 return trans;
288294 }
@@ -1050,6 +1056,9 @@ static int nft_flush_table(struct nft_ctx *ctx) · 761 unmodified lines
10501056 if (!nft_is_active_next(ctx->net, chain))
10511057 continue;
10521058
1059+ if (nft_chain_is_bound(chain))
1060+ continue;
1061+
10531062 ctx->chain = chain;
10541063
10551064 err = nft_delrule_by_chain(ctx);
@@ -1092,6 +1101,9 @@ static int nft_flush_table(struct nft_ctx *ctx) · 36 unmodified lines
10921101 if (!nft_is_active_next(ctx->net, chain))
10931102 continue;
10941103
1104+ if (nft_chain_is_bound(chain))
1105+ continue;
1106+
10951107 ctx->chain = chain;
10961108
10971109 err = nft_delchain(ctx);
@@ -1274,6 +1286,7 @@ static const struct nla_policy nft_chain_policy[NFTA_CHAIN_MAX + 1] = { · 176 unmodified lines
12741286 .len = NFT_MODULE_AUTOLOAD_LIMIT },
12751287 [NFTA_CHAIN_COUNTERS] = { .type = NLA_NESTED },
12761288 [NFTA_CHAIN_FLAGS] = { .type = NLA_U32 },
1289+ [NFTA_CHAIN_ID] = { .type = NLA_U32 },
12771290 };
12781291
12791292 static const struct nla_policy nft_hook_policy[NFTA_HOOK_MAX + 1] = {
@@ -1406,13 +1419,12 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net, · 126 unmodified lines
14061419 lockdep_commit_lock_is_held(net));
14071420 if (nft_dump_stats(skb, stats))
14081421 goto nla_put_failure;
1409−
1410− if ((chain->flags & NFT_CHAIN_HW_OFFLOAD) &&
1411− nla_put_be32(skb, NFTA_CHAIN_FLAGS,
1412− htonl(NFT_CHAIN_HW_OFFLOAD)))
1413− goto nla_put_failure;
14141422 }
14151423
1424+ if (chain->flags &&
1425+ nla_put_be32(skb, NFTA_CHAIN_FLAGS, htonl(chain->flags)))
1426+ goto nla_put_failure;
1427+
14161428 if (nla_put_be32(skb, NFTA_CHAIN_USE, htonl(chain->use)))
14171429 goto nla_put_failure;
14181430
@@ -1614,7 +1626,7 @@ static void nf_tables_chain_free_chain_rules(struct nft_chain *chain) · 195 unmodified lines
16141626 kvfree(chain->rules_next);
16151627 }
16161628
1617−static void nf_tables_chain_destroy(struct nft_ctx *ctx)
1629+void nf_tables_chain_destroy(struct nft_ctx *ctx)
16181630 {
16191631 struct nft_chain *chain = ctx->chain;
16201632 struct nft_hook *hook, *next;
@@ -1896,7 +1908,7 @@ static int nft_basechain_init(struct nft_base_chain *basechain, u8 family, · 275 unmodified lines
18961908 nft_basechain_hook_init(&basechain->ops, family, hook, chain);
18971909 }
18981910
1899− chain->flags |= NFT_BASE_CHAIN | flags;
1911+ chain->flags |= NFT_CHAIN_BASE | flags;
19001912 basechain->policy = NF_ACCEPT;
19011913 if (chain->flags & NFT_CHAIN_HW_OFFLOAD &&
19021914 nft_chain_offload_priority(basechain) < 0)
@@ -1907,6 +1919,22 @@ static int nft_basechain_init(struct nft_base_chain *basechain, u8 family, · 4 unmodified lines
19071919 return 0;
19081920 }
19091921
1922+static int nft_chain_add(struct nft_table *table, struct nft_chain *chain)
1923+{
1924+ int err;
1925+
1926+ err = rhltable_insert_key(&table->chains_ht, chain->name,
1927+ &chain->rhlhead, nft_chain_ht_params);
1928+ if (err)
1929+ return err;
1930+
1931+ list_add_tail_rcu(&chain->list, &table->chains);
1932+
1933+ return 0;
1934+}
1935+
1936+static u64 chain_id;
1937+
19101938 static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
19111939 u8 policy, u32 flags)
19121940 {
@@ -1915,6 +1943,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, · 2 unmodified lines
19151943 struct nft_base_chain *basechain;
19161944 struct nft_stats __percpu *stats;
19171945 struct net *net = ctx->net;
1946+ char name[NFT_NAME_MAXLEN];
19181947 struct nft_trans *trans;
19191948 struct nft_chain *chain;
19201949 struct nft_rule **rules;
@@ -1926,6 +1955,9 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, · 5 unmodified lines
19261955 if (nla[NFTA_CHAIN_HOOK]) {
19271956 struct nft_chain_hook hook;
19281957
1958+ if (flags & NFT_CHAIN_BINDING)
1959+ return -EOPNOTSUPP;
1960+
19291961 err = nft_chain_parse_hook(net, nla, &hook, family, true);
19301962 if (err < 0)
19311963 return err;
@@ -1955,16 +1987,33 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, · 23 unmodified lines
19551987 return err;
19561988 }
19571989 } else {
1990+ if (flags & NFT_CHAIN_BASE)
1991+ return -EINVAL;
1992+ if (flags & NFT_CHAIN_HW_OFFLOAD)
1993+ return -EOPNOTSUPP;
1994+
19581995 chain = kzalloc(sizeof(*chain), GFP_KERNEL);
19591996 if (chain == NULL)
19601997 return -ENOMEM;
1998+
1999+ chain->flags = flags;
19612000 }
19622001 ctx->chain = chain;
19632002
19642003 INIT_LIST_HEAD(&chain->rules);
19652004 chain->handle = nf_tables_alloc_handle(table);
19662005 chain->table = table;
1967− chain->name = nla_strdup(nla[NFTA_CHAIN_NAME], GFP_KERNEL);
2006+
2007+ if (nla[NFTA_CHAIN_NAME]) {
2008+ chain->name = nla_strdup(nla[NFTA_CHAIN_NAME], GFP_KERNEL);
2009+ } else {
2010+ if (!(flags & NFT_CHAIN_BINDING))
2011+ return -EINVAL;
2012+
2013+ snprintf(name, sizeof(name), "__chain%llu", ++chain_id);
2014+ chain->name = kstrdup(name, GFP_KERNEL);
2015+ }
2016+
19682017 if (!chain->name) {
19692018 err = -ENOMEM;
19702019 goto err1;
@@ -1984,16 +2033,9 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, · 13 unmodified lines
19842033 if (err < 0)
19852034 goto err1;
19862035
1987− err = rhltable_insert_key(&table->chains_ht, chain->name,
1988− &chain->rhlhead, nft_chain_ht_params);
1989− if (err)
1990− goto err2;
1991−
19922036 trans = nft_trans_chain_add(ctx, NFT_MSG_NEWCHAIN);
19932037 if (IS_ERR(trans)) {
19942038 err = PTR_ERR(trans);
1995− rhltable_remove(&table->chains_ht, &chain->rhlhead,
1996− nft_chain_ht_params);
19972039 goto err2;
19982040 }
19992041
@@ -2001,8 +2043,13 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, · 1 unmodified line
20012043 if (nft_is_base_chain(chain))
20022044 nft_trans_chain_policy(trans) = policy;
20032045
2046+ err = nft_chain_add(table, chain);
2047+ if (err < 0) {
2048+ nft_trans_destroy(trans);
2049+ goto err2;
2050+ }
2051+
20042052 table->use++;
2005− list_add_tail_rcu(&chain->list, &table->chains);
20062053
20072054 return 0;
20082055 err2:
@@ -2146,6 +2193,22 @@ err: · 137 unmodified lines
21462193 return err;
21472194 }
21482195
2196+static struct nft_chain *nft_chain_lookup_byid(const struct net *net,
2197+ const struct nlattr *nla)
2198+{
2199+ u32 id = ntohl(nla_get_be32(nla));
2200+ struct nft_trans *trans;
2201+
2202+ list_for_each_entry(trans, &net->nft.commit_list, list) {
2203+ struct nft_chain *chain = trans->ctx.chain;
2204+
2205+ if (trans->msg_type == NFT_MSG_NEWCHAIN &&
2206+ id == nft_trans_chain_id(trans))
2207+ return chain;
2208+ }
2209+ return ERR_PTR(-ENOENT);
2210+}
2211+
21492212 static int nf_tables_newchain(struct net *net, struct sock *nlsk,
21502213 struct sk_buff *skb, const struct nlmsghdr *nlh,
21512214 const struct nlattr * const nla[],
@@ -2154,9 +2217,9 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, · 2 unmodified lines
21542217 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
21552218 u8 genmask = nft_genmask_next(net);
21562219 int family = nfmsg->nfgen_family;
2220+ struct nft_chain *chain = NULL;
21572221 const struct nlattr *attr;
21582222 struct nft_table *table;
2159− struct nft_chain *chain;
21602223 u8 policy = NF_ACCEPT;
21612224 struct nft_ctx ctx;
21622225 u64 handle = 0;
@@ -2181,7 +2244,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, · 18 unmodified lines
21812244 return PTR_ERR(chain);
21822245 }
21832246 attr = nla[NFTA_CHAIN_HANDLE];
2184− } else {
2247+ } else if (nla[NFTA_CHAIN_NAME]) {
21852248 chain = nft_chain_lookup(net, table, attr, genmask);
21862249 if (IS_ERR(chain)) {
21872250 if (PTR_ERR(chain) != -ENOENT) {
@@ -2190,6 +2253,8 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, · 2 unmodified lines
21902253 }
21912254 chain = NULL;
21922255 }
2256+ } else if (!nla[NFTA_CHAIN_ID]) {
2257+ return -EINVAL;
21932258 }
21942259
21952260 if (nla[NFTA_CHAIN_POLICY]) {
@@ -2220,6 +2285,9 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, · 24 unmodified lines
22202285 else if (chain)
22212286 flags = chain->flags;
22222287
2288+ if (flags & ~NFT_CHAIN_FLAGS)
2289+ return -EOPNOTSUPP;
2290+
22232291 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
22242292
22252293 if (chain != NULL) {
@@ -2230,7 +2298,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, · 4 unmodified lines
22302298 if (nlh->nlmsg_flags & NLM_F_REPLACE)
22312299 return -EOPNOTSUPP;
22322300
2233− flags |= chain->flags & NFT_BASE_CHAIN;
2301+ flags |= chain->flags & NFT_CHAIN_BASE;
22342302 return nf_tables_updchain(&ctx, genmask, policy, flags);
22352303 }
22362304
@@ -2624,6 +2692,7 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = { · 387 unmodified lines
26242692 .len = NFT_USERDATA_MAXLEN },
26252693 [NFTA_RULE_ID] = { .type = NLA_U32 },
26262694 [NFTA_RULE_POSITION_ID] = { .type = NLA_U32 },
2695+ [NFTA_RULE_CHAIN_ID] = { .type = NLA_U32 },
26272696 };
26282697
26292698 static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,
@@ -2938,8 +3007,7 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx, · 308 unmodified lines
29383007 kfree(rule);
29393008 }
29403009
2941−static void nf_tables_rule_release(const struct nft_ctx *ctx,
2942− struct nft_rule *rule)
3010+void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule)
29433011 {
29443012 nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE);
29453013 nf_tables_rule_destroy(ctx, rule);
@@ -3030,10 +3098,24 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, · 84 unmodified lines
30303098 return PTR_ERR(table);
30313099 }
30323100
3033− chain = nft_chain_lookup(net, table, nla[NFTA_RULE_CHAIN], genmask);
3034− if (IS_ERR(chain)) {
3035− NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);
3036− return PTR_ERR(chain);
3101+ if (nla[NFTA_RULE_CHAIN]) {
3102+ chain = nft_chain_lookup(net, table, nla[NFTA_RULE_CHAIN],
3103+ genmask);
3104+ if (IS_ERR(chain)) {
3105+ NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);
3106+ return PTR_ERR(chain);
3107+ }
3108+ if (nft_chain_is_bound(chain))
3109+ return -EOPNOTSUPP;
3110+
3111+ } else if (nla[NFTA_RULE_CHAIN_ID]) {
3112+ chain = nft_chain_lookup_byid(net, nla[NFTA_RULE_CHAIN_ID]);
3113+ if (IS_ERR(chain)) {
3114+ NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN_ID]);
3115+ return PTR_ERR(chain);
3116+ }
3117+ } else {
3118+ return -EINVAL;
30373119 }
30383120
30393121 if (nla[NFTA_RULE_HANDLE]) {
@@ -3245,6 +3327,8 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk, · 205 unmodified lines
32453327 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);
32463328 return PTR_ERR(chain);
32473329 }
3330+ if (nft_chain_is_bound(chain))
3331+ return -EOPNOTSUPP;
32483332 }
32493333
32503334 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
@@ -5281,11 +5365,24 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk, · 2030 unmodified lines
52815365 */
52825366 void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
52835367 {
5368+ struct nft_chain *chain;
5369+ struct nft_rule *rule;
5370+
52845371 if (type == NFT_DATA_VERDICT) {
52855372 switch (data->verdict.code) {
52865373 case NFT_JUMP:
52875374 case NFT_GOTO:
5288− data->verdict.chain->use++;
5375+ chain = data->verdict.chain;
5376+ chain->use++;
5377+
5378+ if (!nft_chain_is_bound(chain))
5379+ break;
5380+
5381+ chain->table->use++;
5382+ list_for_each_entry(rule, &chain->rules, list)
5383+ chain->use++;
5384+
5385+ nft_chain_add(chain->table, chain);
52895386 break;
52905387 }
52915388 }
@@ -7425,7 +7522,7 @@ static void nft_obj_del(struct nft_object *obj) · 2133 unmodified lines
74257522 list_del_rcu(&obj->list);
74267523 }
74277524
7428−static void nft_chain_del(struct nft_chain *chain)
7525+void nft_chain_del(struct nft_chain *chain)
74297526 {
74307527 struct nft_table *table = chain->table;
74317528
@@ -7776,6 +7873,10 @@ static int __nf_tables_abort(struct net *net, bool autoload) · 344 unmodified lines
77767873 kfree(nft_trans_chain_name(trans));
77777874 nft_trans_destroy(trans);
77787875 } else {
7876+ if (nft_chain_is_bound(trans->ctx.chain)) {
7877+ nft_trans_destroy(trans);
7878+ break;
7879+ }
77797880 trans->ctx.table->use--;
77807881 nft_chain_del(trans->ctx.chain);
77817882 nf_tables_unregister_hook(trans->ctx.net,
@@ -8205,6 +8306,7 @@ static const struct nla_policy nft_verdict_policy[NFTA_VERDICT_MAX + 1] = { · 423 unmodified lines
82058306 [NFTA_VERDICT_CODE] = { .type = NLA_U32 },
82068307 [NFTA_VERDICT_CHAIN] = { .type = NLA_STRING,
82078308 .len = NFT_CHAIN_MAXNAMELEN - 1 },
8309+ [NFTA_VERDICT_CHAIN_ID] = { .type = NLA_U32 },
82088310 };
82098311
82108312 static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
@@ -8241,10 +8343,19 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data, · 30 unmodified lines
82418343 break;
82428344 case NFT_JUMP:
82438345 case NFT_GOTO:
8244− if (!tb[NFTA_VERDICT_CHAIN])
8346+ if (tb[NFTA_VERDICT_CHAIN]) {
8347+ chain = nft_chain_lookup(ctx->net, ctx->table,
8348+ tb[NFTA_VERDICT_CHAIN],
8349+ genmask);
8350+ } else if (tb[NFTA_VERDICT_CHAIN_ID]) {
8351+ chain = nft_chain_lookup_byid(ctx->net,
8352+ tb[NFTA_VERDICT_CHAIN_ID]);
8353+ if (IS_ERR(chain))
8354+ return PTR_ERR(chain);
8355+ } else {
82458356 return -EINVAL;
8246− chain = nft_chain_lookup(ctx->net, ctx->table,
8247− tb[NFTA_VERDICT_CHAIN], genmask);
8357+ }
8358+
82488359 if (IS_ERR(chain))
82498360 return PTR_ERR(chain);
82508361 if (nft_is_base_chain(chain))
@@ -8262,10 +8373,23 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data, · 11 unmodified lines
82628373
82638374 static void nft_verdict_uninit(const struct nft_data *data)
82648375 {
8376+ struct nft_chain *chain;
8377+ struct nft_rule *rule;
8378+
82658379 switch (data->verdict.code) {
82668380 case NFT_JUMP:
82678381 case NFT_GOTO:
8268− data->verdict.chain->use--;
8382+ chain = data->verdict.chain;
8383+ chain->use--;
8384+
8385+ if (!nft_chain_is_bound(chain))
8386+ break;
8387+
8388+ chain->table->use--;
8389+ list_for_each_entry(rule, &chain->rules, list)
8390+ chain->use--;
8391+
8392+ nft_chain_del(chain);
82698393 break;
82708394 }
82718395 }
net/netfilter/nft_immediate.c+51−0
@@ -54,6 +54,23 @@ static int nft_immediate_init(const struct nft_ctx *ctx, · 53 unmodified lines
5454 if (err < 0)
5555 goto err1;
5656
57+ if (priv->dreg == NFT_REG_VERDICT) {
58+ struct nft_chain *chain = priv->data.verdict.chain;
59+
60+ switch (priv->data.verdict.code) {
61+ case NFT_JUMP:
62+ case NFT_GOTO:
63+ if (nft_chain_is_bound(chain)) {
64+ err = -EBUSY;
65+ goto err1;
66+ }
67+ chain->bound = true;
68+ break;
69+ default:
70+ break;
71+ }
72+ }
73+
5774 return 0;
5875
5976 err1:
@@ -81,6 +98,39 @@ static void nft_immediate_deactivate(const struct nft_ctx *ctx, · 21 unmodified lines
8198 return nft_data_release(&priv->data, nft_dreg_to_type(priv->dreg));
8299 }
83100
101+static void nft_immediate_destroy(const struct nft_ctx *ctx,
102+ const struct nft_expr *expr)
103+{
104+ const struct nft_immediate_expr *priv = nft_expr_priv(expr);
105+ const struct nft_data *data = &priv->data;
106+ struct nft_ctx chain_ctx;
107+ struct nft_chain *chain;
108+ struct nft_rule *rule;
109+
110+ if (priv->dreg != NFT_REG_VERDICT)
111+ return;
112+
113+ switch (data->verdict.code) {
114+ case NFT_JUMP:
115+ case NFT_GOTO:
116+ chain = data->verdict.chain;
117+
118+ if (!nft_chain_is_bound(chain))
119+ break;
120+
121+ chain_ctx = *ctx;
122+ chain_ctx.chain = chain;
123+
124+ list_for_each_entry(rule, &chain->rules, list)
125+ nf_tables_rule_release(&chain_ctx, rule);
126+
127+ nf_tables_chain_destroy(&chain_ctx);
128+ break;
129+ default:
130+ break;
131+ }
132+}
133+
84134 static int nft_immediate_dump(struct sk_buff *skb, const struct nft_expr *expr)
85135 {
86136 const struct nft_immediate_expr *priv = nft_expr_priv(expr);
@@ -170,6 +220,7 @@ static const struct nft_expr_ops nft_imm_ops = { · 83 unmodified lines
170220 .init = nft_immediate_init,
171221 .activate = nft_immediate_activate,
172222 .deactivate = nft_immediate_deactivate,
223+ .destroy = nft_immediate_destroy,
173224 .dump = nft_immediate_dump,
174225 .validate = nft_immediate_validate,
175226 .offload = nft_immediate_offload,
net/netfilter/nft_reject.c+2−1
@@ -30,7 +30,8 @@ int nft_reject_validate(const struct nft_ctx *ctx, · 29 unmodified lines
3030 return nft_chain_validate_hooks(ctx->chain,
3131 (1 << NF_INET_LOCAL_IN) |
3232 (1 << NF_INET_FORWARD) |
33− (1 << NF_INET_LOCAL_OUT));
33+ (1 << NF_INET_LOCAL_OUT) |
34+ (1 << NF_INET_PRE_ROUTING));
3435 }
3536 EXPORT_SYMBOL_GPL(nft_reject_validate);
3637
net/netfilter/nft_set_pipapo.c+0−2
@@ -1249,8 +1249,6 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set, · 1248 unmodified lines
12491249 if (err)
12501250 return err;
12511251
1252− this_cpu_write(nft_pipapo_scratch_index, false);
1253−
12541252 m->bsize_max = bsize_max;
12551253 } else {
12561254 put_cpu_ptr(m->scratch);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t