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
874 struct ip_vs_stats tot_stats; /* Statistics & est. */874 struct ip_vs_stats tot_stats; /* Statistics & est. */
875 875
876 int num_services; /* no of virtual services */876 int num_services; /* no of virtual services */
877 int num_services6; /* IPv6 virtual services */
877 878
878 /* Trash for destinations */879 /* Trash for destinations */
879 struct list_head dest_trash;880 struct list_head dest_trash;
@@ -960,6 +961,7 @@ struct netns_ipvs { · 80 unmodified lines
960 * are not supported when synchronization is enabled.961 * are not supported when synchronization is enabled.
961 */962 */
962 unsigned int mixed_address_family_dests;963 unsigned int mixed_address_family_dests;
964 unsigned int hooks_afmask; /* &1=AF_INET, &2=AF_INET6 */
963};965};
964 966
965#define DEFAULT_SYNC_THRESHOLD 3967#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
1624}1626}
1625#endif /* CONFIG_IP_VS_NFCT */1627#endif /* CONFIG_IP_VS_NFCT */
1626 1628
1627/* Really using conntrack? */1629/* Using old conntrack that can not be redirected to another real server? */
1628static inline bool ip_vs_conn_uses_conntrack(struct ip_vs_conn *cp,1630static inline bool ip_vs_conn_uses_old_conntrack(struct ip_vs_conn *cp,
1629 struct sk_buff *skb)1631 struct sk_buff *skb)
1630{1632{
1631#ifdef CONFIG_IP_VS_NFCT1633#ifdef CONFIG_IP_VS_NFCT
1632 enum ip_conntrack_info ctinfo;1634 enum ip_conntrack_info ctinfo;
1633 struct nf_conn *ct;1635 struct nf_conn *ct;
1634 1636
1635 if (!(cp->flags & IP_VS_CONN_F_NFCT))
1636 return false;
1637 ct = nf_ct_get(skb, &ctinfo);1637 ct = nf_ct_get(skb, &ctinfo);
1638 if (ct)1638 if (ct && nf_ct_is_confirmed(ct))
1639 return true;1639 return true;
1640#endif1640#endif
1641 return false;1641 return false;
@@ -1670,6 +1670,9 @@ static inline void ip_vs_unregister_conntrack(struct ip_vs_service *svc) · 28 unmodified lines
1670#endif1670#endif
1671}1671}
1672 1672
1673int ip_vs_register_hooks(struct netns_ipvs *ipvs, unsigned int af);
1674void ip_vs_unregister_hooks(struct netns_ipvs *ipvs, unsigned int af);
1675
1673static inline int1676static inline int
1674ip_vs_dest_conn_overhead(struct ip_vs_dest *dest)1677ip_vs_dest_conn_overhead(struct ip_vs_dest *dest)
1675{1678{
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
899 return (void *)&rule->data[rule->dlen];899 return (void *)&rule->data[rule->dlen];
900}900}
901 901
902void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule);
903
902static inline void nft_set_elem_update_expr(const struct nft_set_ext *ext,904static inline void nft_set_elem_update_expr(const struct nft_set_ext *ext,
903 struct nft_regs *regs,905 struct nft_regs *regs,
904 const struct nft_pktinfo *pkt)906 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
921 (expr) != (last); \923 (expr) != (last); \
922 (expr) = nft_expr_next(expr))924 (expr) = nft_expr_next(expr))
923 925
924enum nft_chain_flags {
925 NFT_BASE_CHAIN = 0x1,
926 NFT_CHAIN_HW_OFFLOAD = 0x2,
927};
928
929#define NFT_CHAIN_POLICY_UNSET U8_MAX926#define NFT_CHAIN_POLICY_UNSET U8_MAX
930 927
931/**928/**
@@ -949,7 +946,8 @@ struct nft_chain { · 17 unmodified lines
949 struct nft_table *table;946 struct nft_table *table;
950 u64 handle;947 u64 handle;
951 u32 use;948 u32 use;
952 u8 flags:6,949 u8 flags:5,
950 bound:1,
953 genmask:2;951 genmask:2;
954 char *name;952 char *name;
955 953
@@ -994,6 +992,14 @@ int nft_chain_validate_dependency(const struct nft_chain *chain, · 38 unmodified lines
994int nft_chain_validate_hooks(const struct nft_chain *chain,992int nft_chain_validate_hooks(const struct nft_chain *chain,
995 unsigned int hook_flags);993 unsigned int hook_flags);
996 994
995static inline bool nft_chain_is_bound(struct nft_chain *chain)
996{
997 return (chain->flags & NFT_CHAIN_BINDING) && chain->bound;
998}
999
1000void nft_chain_del(struct nft_chain *chain);
1001void nf_tables_chain_destroy(struct nft_ctx *ctx);
1002
997struct nft_stats {1003struct nft_stats {
998 u64 bytes;1004 u64 bytes;
999 u64 pkts;1005 u64 pkts;
@@ -1036,7 +1042,7 @@ static inline struct nft_base_chain *nft_base_chain(const struct nft_chain *chai · 36 unmodified lines
1036 1042
1037static inline bool nft_is_base_chain(const struct nft_chain *chain)1043static inline bool nft_is_base_chain(const struct nft_chain *chain)
1038{1044{
1039 return chain->flags & NFT_BASE_CHAIN;1045 return chain->flags & NFT_CHAIN_BASE;
1040}1046}
1041 1047
1042int __nft_release_basechain(struct nft_ctx *ctx);1048int __nft_release_basechain(struct nft_ctx *ctx);
@@ -1433,6 +1439,7 @@ struct nft_trans_chain { · 390 unmodified lines
1433 char *name;1439 char *name;
1434 struct nft_stats __percpu *stats;1440 struct nft_stats __percpu *stats;
1435 u8 policy;1441 u8 policy;
1442 u32 chain_id;
1436};1443};
1437 1444
1438#define nft_trans_chain_update(trans) \1445#define nft_trans_chain_update(trans) \
@@ -1443,6 +1450,8 @@ struct nft_trans_chain { · 4 unmodified lines
1443 (((struct nft_trans_chain *)trans->data)->stats)1450 (((struct nft_trans_chain *)trans->data)->stats)
1444#define nft_trans_chain_policy(trans) \1451#define nft_trans_chain_policy(trans) \
1445 (((struct nft_trans_chain *)trans->data)->policy)1452 (((struct nft_trans_chain *)trans->data)->policy)
1453#define nft_trans_chain_id(trans) \
1454 (((struct nft_trans_chain *)trans->data)->chain_id)
1446 1455
1447struct nft_trans_table {1456struct nft_trans_table {
1448 bool update;1457 bool update;
include/uapi/linux/netfilter/nf_tables.h+14−0
@@ -184,6 +184,15 @@ enum nft_table_attributes { · 183 unmodified lines
184};184};
185#define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1)185#define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1)
186 186
187enum 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
187/**196/**
188 * enum nft_chain_attributes - nf_tables chain netlink attributes197 * enum nft_chain_attributes - nf_tables chain netlink attributes
189 *198 *
@@ -196,6 +205,7 @@ enum nft_table_attributes { · 6 unmodified lines
196 * @NFTA_CHAIN_TYPE: type name of the string (NLA_NUL_STRING)205 * @NFTA_CHAIN_TYPE: type name of the string (NLA_NUL_STRING)
197 * @NFTA_CHAIN_COUNTERS: counter specification of the chain (NLA_NESTED: nft_counter_attributes)206 * @NFTA_CHAIN_COUNTERS: counter specification of the chain (NLA_NESTED: nft_counter_attributes)
198 * @NFTA_CHAIN_FLAGS: chain flags207 * @NFTA_CHAIN_FLAGS: chain flags
208 * @NFTA_CHAIN_ID: uniquely identifies a chain in a transaction (NLA_U32)
199 */209 */
200enum nft_chain_attributes {210enum nft_chain_attributes {
201 NFTA_CHAIN_UNSPEC,211 NFTA_CHAIN_UNSPEC,
@@ -209,6 +219,7 @@ enum nft_chain_attributes { · 7 unmodified lines
209 NFTA_CHAIN_COUNTERS,219 NFTA_CHAIN_COUNTERS,
210 NFTA_CHAIN_PAD,220 NFTA_CHAIN_PAD,
211 NFTA_CHAIN_FLAGS,221 NFTA_CHAIN_FLAGS,
222 NFTA_CHAIN_ID,
212 __NFTA_CHAIN_MAX223 __NFTA_CHAIN_MAX
213};224};
214#define NFTA_CHAIN_MAX (__NFTA_CHAIN_MAX - 1)225#define NFTA_CHAIN_MAX (__NFTA_CHAIN_MAX - 1)
@@ -238,6 +249,7 @@ enum nft_rule_attributes { · 23 unmodified lines
238 NFTA_RULE_PAD,249 NFTA_RULE_PAD,
239 NFTA_RULE_ID,250 NFTA_RULE_ID,
240 NFTA_RULE_POSITION_ID,251 NFTA_RULE_POSITION_ID,
252 NFTA_RULE_CHAIN_ID,
241 __NFTA_RULE_MAX253 __NFTA_RULE_MAX
242};254};
243#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)255#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)
@@ -468,11 +480,13 @@ enum nft_data_attributes { · 224 unmodified lines
468 *480 *
469 * @NFTA_VERDICT_CODE: nf_tables verdict (NLA_U32: enum nft_verdicts)481 * @NFTA_VERDICT_CODE: nf_tables verdict (NLA_U32: enum nft_verdicts)
470 * @NFTA_VERDICT_CHAIN: jump target chain name (NLA_STRING)482 * @NFTA_VERDICT_CHAIN: jump target chain name (NLA_STRING)
483 * @NFTA_VERDICT_CHAIN_ID: jump target chain ID (NLA_U32)
471 */484 */
472enum nft_verdict_attributes {485enum nft_verdict_attributes {
473 NFTA_VERDICT_UNSPEC,486 NFTA_VERDICT_UNSPEC,
474 NFTA_VERDICT_CODE,487 NFTA_VERDICT_CODE,
475 NFTA_VERDICT_CHAIN,488 NFTA_VERDICT_CHAIN,
489 NFTA_VERDICT_CHAIN_ID,
476 __NFTA_VERDICT_MAX490 __NFTA_VERDICT_MAX
477};491};
478#define NFTA_VERDICT_MAX (__NFTA_VERDICT_MAX - 1)492#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
96}96}
97EXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_put);97EXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_put);
98 98
99static 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
99/* Send RST reply */114/* Send RST reply */
100void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)115void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
101{116{
@@ -109,6 +124,9 @@ void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook) · 7 unmodified lines
109 if (!oth)124 if (!oth)
110 return;125 return;
111 126
127 if (hook == NF_INET_PRE_ROUTING && nf_reject_fill_skb_dst(oldskb))
128 return;
129
112 if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))130 if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
113 return;131 return;
114 132
@@ -175,6 +193,9 @@ void nf_send_unreach(struct sk_buff *skb_in, int code, int hook) · 60 unmodified lines
175 if (iph->frag_off & htons(IP_OFFSET))193 if (iph->frag_off & htons(IP_OFFSET))
176 return;194 return;
177 195
196 if (hook == NF_INET_PRE_ROUTING && nf_reject_fill_skb_dst(skb_in))
197 return;
198
178 if (skb_csum_unnecessary(skb_in) || !nf_reject_verify_csum(proto)) {199 if (skb_csum_unnecessary(skb_in) || !nf_reject_verify_csum(proto)) {
179 icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);200 icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
180 return;201 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
126}126}
127EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_put);127EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_put);
128 128
129static 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
129void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)144void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
130{145{
131 struct net_device *br_indev __maybe_unused;146 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
154 fl6.daddr = oip6h->saddr;169 fl6.daddr = oip6h->saddr;
155 fl6.fl6_sport = otcph->dest;170 fl6.fl6_sport = otcph->dest;
156 fl6.fl6_dport = otcph->source;171 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
157 fl6.flowi6_oif = l3mdev_master_ifindex(skb_dst(oldskb)->dev);180 fl6.flowi6_oif = l3mdev_master_ifindex(skb_dst(oldskb)->dev);
158 fl6.flowi6_mark = IP6_REPLY_MARK(net, oldskb->mark);181 fl6.flowi6_mark = IP6_REPLY_MARK(net, oldskb->mark);
159 security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));182 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
245 if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL)268 if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL)
246 skb_in->dev = net->loopback_dev;269 skb_in->dev = net->loopback_dev;
247 270
271 if (hooknum == NF_INET_PRE_ROUTING && nf_reject6_fill_skb_dst(skb_in))
272 return;
273
248 icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0);274 icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0);
249}275}
250EXPORT_SYMBOL_GPL(nf_send_unreach6);276EXPORT_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
807 kmem_cache_free(ip_vs_conn_cachep, cp);807 kmem_cache_free(ip_vs_conn_cachep, cp);
808}808}
809 809
810/* Try to delete connection while not holding reference */
811static 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 */
822static 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
810static void ip_vs_conn_expire(struct timer_list *t)835static void ip_vs_conn_expire(struct timer_list *t)
811{836{
812 struct ip_vs_conn *cp = from_timer(cp, t, timer);837 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
827 852
828 /* does anybody control me? */853 /* does anybody control me? */
829 if (ct) {854 if (ct) {
855 bool has_ref = !cp->timeout && __ip_vs_conn_get(ct);
856
830 ip_vs_control_del(cp);857 ip_vs_control_del(cp);
831 /* Drop CTL or non-assured TPL if not used anymore */858 /* 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) &&
833 (!(ct->flags & IP_VS_CONN_F_TEMPLATE) ||860 (!(ct->flags & IP_VS_CONN_F_TEMPLATE) ||
834 !(ct->state & IP_VS_CTPL_S_ASSURED))) {861 !(ct->state & IP_VS_CTPL_S_ASSURED))) {
835 IP_VS_DBG(4, "drop controlling connection\n");862 IP_VS_DBG(4, "drop controlling connection\n");
836 ct->timeout = 0;863 ip_vs_conn_del_put(ct);
837 ip_vs_conn_expire_now(ct);864 } else if (has_ref) {
865 __ip_vs_conn_put(ct);
838 }866 }
839 }867 }
840 868
@@ -1317,8 +1345,7 @@ try_drop: · 476 unmodified lines
1317 1345
1318drop:1346drop:
1319 IP_VS_DBG(4, "drop connection\n");1347 IP_VS_DBG(4, "drop connection\n");
1320 cp->timeout = 0;1348 ip_vs_conn_del(cp);
1321 ip_vs_conn_expire_now(cp);
1322 }1349 }
1323 cond_resched_rcu();1350 cond_resched_rcu();
1324 }1351 }
@@ -1341,19 +1368,15 @@ flush_again: · 16 unmodified lines
1341 hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[idx], c_list) {1368 hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[idx], c_list) {
1342 if (cp->ipvs != ipvs)1369 if (cp->ipvs != ipvs)
1343 continue;1370 continue;
1344 /* As timers are expired in LIFO order, restart1371 if (atomic_read(&cp->n_control))
1345 * the timer of controlling connection first, so1372 continue;
1346 * that it is expired after us.
1347 */
1348 cp_c = cp->control;1373 cp_c = cp->control;
1349 /* cp->control is valid only with reference to cp */1374 IP_VS_DBG(4, "del connection\n");
1350 if (cp_c && __ip_vs_conn_get(cp)) {1375 ip_vs_conn_del(cp);
1376 if (cp_c && !atomic_read(&cp_c->n_control)) {
1351 IP_VS_DBG(4, "del controlling connection\n");1377 IP_VS_DBG(4, "del controlling connection\n");
1352 ip_vs_conn_expire_now(cp_c);1378 ip_vs_conn_del(cp_c);
1353 __ip_vs_conn_put(cp);
1354 }1379 }
1355 IP_VS_DBG(4, "del connection\n");
1356 ip_vs_conn_expire_now(cp);
1357 }1380 }
1358 cond_resched_rcu();1381 cond_resched_rcu();
1359 }1382 }
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
2066 2066
2067 conn_reuse_mode = sysctl_conn_reuse_mode(ipvs);2067 conn_reuse_mode = sysctl_conn_reuse_mode(ipvs);
2068 if (conn_reuse_mode && !iph.fragoffs && is_new_conn(skb, &iph) && cp) {2068 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;
2070 2070
2071 if (unlikely(sysctl_expire_nodest_conn(ipvs)) && cp->dest &&2071 if (unlikely(sysctl_expire_nodest_conn(ipvs)) && cp->dest &&
2072 unlikely(!atomic_read(&cp->dest->weight))) {2072 unlikely(!atomic_read(&cp->dest->weight))) {
2073 resched = true;2073 resched = true;
2074 uses_ct = ip_vs_conn_uses_conntrack(cp, skb);2074 old_ct = ip_vs_conn_uses_old_conntrack(cp, skb);
2075 } else if (is_new_conn_expected(cp, conn_reuse_mode)) {2075 } 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);
2077 if (!atomic_read(&cp->n_control)) {2077 if (!atomic_read(&cp->n_control)) {
2078 resched = true;2078 resched = true;
2079 } else {2079 } else {
@@ -2081,15 +2081,17 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int · 1 unmodified line
2081 * that uses conntrack while it is still2081 * that uses conntrack while it is still
2082 * referenced by controlled connection(s).2082 * referenced by controlled connection(s).
2083 */2083 */
2084 resched = !uses_ct;2084 resched = !old_ct;
2085 }2085 }
2086 }2086 }
2087 2087
2088 if (resched) {2088 if (resched) {
2089 if (!old_ct)
2090 cp->flags &= ~IP_VS_CONN_F_NFCT;
2089 if (!atomic_read(&cp->n_control))2091 if (!atomic_read(&cp->n_control))
2090 ip_vs_conn_expire_now(cp);2092 ip_vs_conn_expire_now(cp);
2091 __ip_vs_conn_put(cp);2093 __ip_vs_conn_put(cp);
2092 if (uses_ct)2094 if (old_ct)
2093 return NF_DROP;2095 return NF_DROP;
2094 cp = NULL;2096 cp = NULL;
2095 }2097 }
@@ -2256,7 +2258,7 @@ ip_vs_forward_icmp_v6(void *priv, struct sk_buff *skb, · 160 unmodified lines
2256#endif2258#endif
2257 2259
2258 2260
2259static const struct nf_hook_ops ip_vs_ops[] = {2261static const struct nf_hook_ops ip_vs_ops4[] = {
2260 /* After packet filtering, change source only for VS/NAT */2262 /* After packet filtering, change source only for VS/NAT */
2261 {2263 {
2262 .hook = ip_vs_reply4,2264 .hook = ip_vs_reply4,
@@ -2302,7 +2304,10 @@ static const struct nf_hook_ops ip_vs_ops[] = { · 39 unmodified lines
2302 .hooknum = NF_INET_FORWARD,2304 .hooknum = NF_INET_FORWARD,
2303 .priority = 100,2305 .priority = 100,
2304 },2306 },
2307};
2308
2305#ifdef CONFIG_IP_VS_IPV62309#ifdef CONFIG_IP_VS_IPV6
2310static const struct nf_hook_ops ip_vs_ops6[] = {
2306 /* After packet filtering, change source only for VS/NAT */2311 /* After packet filtering, change source only for VS/NAT */
2307 {2312 {
2308 .hook = ip_vs_reply6,2313 .hook = ip_vs_reply6,
@@ -2348,8 +2353,64 @@ static const struct nf_hook_ops ip_vs_ops[] = { · 39 unmodified lines
2348 .hooknum = NF_INET_FORWARD,2353 .hooknum = NF_INET_FORWARD,
2349 .priority = 100,2354 .priority = 100,
2350 },2355 },
2351#endif
2352};2356};
2357#endif
2358
2359int 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
2388void 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
2353/*2414/*
2354 * Initialize IP Virtual Server netns mem.2415 * Initialize IP Virtual Server netns mem.
2355 */2416 */
@@ -2425,19 +2486,6 @@ static void __net_exit __ip_vs_cleanup_batch(struct list_head *net_list) · 69 unmodified lines
2425 }2486 }
2426}2487}
2427 2488
2428static 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
2437hook_fail:
2438 return ret;
2439}
2440
2441static void __net_exit __ip_vs_dev_cleanup_batch(struct list_head *net_list)2489static void __net_exit __ip_vs_dev_cleanup_batch(struct list_head *net_list)
2442{2490{
2443 struct netns_ipvs *ipvs;2491 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
2446 EnterFunction(2);2494 EnterFunction(2);
2447 list_for_each_entry(net, net_list, exit_list) {2495 list_for_each_entry(net, net_list, exit_list) {
2448 ipvs = net_ipvs(net);2496 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);
2450 ipvs->enable = 0; /* Disable packet reception */2499 ipvs->enable = 0; /* Disable packet reception */
2451 smp_wmb();2500 smp_wmb();
2452 ip_vs_sync_net_cleanup(ipvs);2501 ip_vs_sync_net_cleanup(ipvs);
@@ -2462,7 +2511,6 @@ static struct pernet_operations ipvs_core_ops = { · 9 unmodified lines
2462};2511};
2463 2512
2464static struct pernet_operations ipvs_core_dev_ops = {2513static struct pernet_operations ipvs_core_dev_ops = {
2465 .init = __ip_vs_dev_init,
2466 .exit_batch = __ip_vs_dev_cleanup_batch,2514 .exit_batch = __ip_vs_dev_cleanup_batch,
2467};2515};
2468 2516
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
224 update_defense_level(ipvs);224 update_defense_level(ipvs);
225 if (atomic_read(&ipvs->dropentry))225 if (atomic_read(&ipvs->dropentry))
226 ip_vs_random_dropentry(ipvs);226 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);
228}229}
229#endif230#endif
230 231
@@ -1272,6 +1273,7 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u, · 1041 unmodified lines
1272 struct ip_vs_scheduler *sched = NULL;1273 struct ip_vs_scheduler *sched = NULL;
1273 struct ip_vs_pe *pe = NULL;1274 struct ip_vs_pe *pe = NULL;
1274 struct ip_vs_service *svc = NULL;1275 struct ip_vs_service *svc = NULL;
1276 int ret_hooks = -1;
1275 1277
1276 /* increase the module use count */1278 /* increase the module use count */
1277 if (!ip_vs_use_count_inc())1279 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
1313 }1315 }
1314#endif1316#endif
1315 1317
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
1316 svc = kzalloc(sizeof(struct ip_vs_service), GFP_KERNEL);1326 svc = kzalloc(sizeof(struct ip_vs_service), GFP_KERNEL);
1317 if (svc == NULL) {1327 if (svc == NULL) {
1318 IP_VS_DBG(1, "%s(): no memory\n", __func__);1328 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
1374 /* Count only IPv4 services for old get/setsockopt interface */1384 /* Count only IPv4 services for old get/setsockopt interface */
1375 if (svc->af == AF_INET)1385 if (svc->af == AF_INET)
1376 ipvs->num_services++;1386 ipvs->num_services++;
1387 else if (svc->af == AF_INET6)
1388 ipvs->num_services6++;
1377 1389
1378 /* Hash the service into the service table */1390 /* Hash the service into the service table */
1379 ip_vs_svc_hash(svc);1391 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
1385 1397
1386 1398
1387 out_err:1399 out_err:
1400 if (ret_hooks >= 0)
1401 ip_vs_unregister_hooks(ipvs, u->af);
1388 if (svc != NULL) {1402 if (svc != NULL) {
1389 ip_vs_unbind_scheduler(svc, sched);1403 ip_vs_unbind_scheduler(svc, sched);
1390 ip_vs_service_free(svc);1404 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
1500 struct ip_vs_pe *old_pe;1514 struct ip_vs_pe *old_pe;
1501 struct netns_ipvs *ipvs = svc->ipvs;1515 struct netns_ipvs *ipvs = svc->ipvs;
1502 1516
1503 /* Count only IPv4 services for old get/setsockopt interface */1517 if (svc->af == AF_INET) {
1504 if (svc->af == AF_INET)
1505 ipvs->num_services--;1518 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 }
1506 1526
1507 ip_vs_stop_estimator(svc->ipvs, &svc->stats);1527 ip_vs_stop_estimator(svc->ipvs, &svc->stats);
1508 1528
@@ -4063,7 +4083,8 @@ static int __net_init ip_vs_control_net_init_sysctl(struct netns_ipvs *ipvs) · 2554 unmodified lines
4063 ipvs->sysctl_tbl = tbl;4083 ipvs->sysctl_tbl = tbl;
4064 /* Schedule defense work */4084 /* Schedule defense work */
4065 INIT_DELAYED_WORK(&ipvs->defense_work, defense_work_handler);4085 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);
4067 4088
4068 return 0;4089 return 0;
4069}4090}
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
280 if (trans == NULL)280 if (trans == NULL)
281 return ERR_PTR(-ENOMEM);281 return ERR_PTR(-ENOMEM);
282 282
283 if (msg_type == NFT_MSG_NEWCHAIN)283 if (msg_type == NFT_MSG_NEWCHAIN) {
284 nft_activate_next(ctx->net, ctx->chain);284 nft_activate_next(ctx->net, ctx->chain);
285 285
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
286 list_add_tail(&trans->list, &ctx->net->nft.commit_list);292 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
287 return trans;293 return trans;
288}294}
@@ -1050,6 +1056,9 @@ static int nft_flush_table(struct nft_ctx *ctx) · 761 unmodified lines
1050 if (!nft_is_active_next(ctx->net, chain))1056 if (!nft_is_active_next(ctx->net, chain))
1051 continue;1057 continue;
1052 1058
1059 if (nft_chain_is_bound(chain))
1060 continue;
1061
1053 ctx->chain = chain;1062 ctx->chain = chain;
1054 1063
1055 err = nft_delrule_by_chain(ctx);1064 err = nft_delrule_by_chain(ctx);
@@ -1092,6 +1101,9 @@ static int nft_flush_table(struct nft_ctx *ctx) · 36 unmodified lines
1092 if (!nft_is_active_next(ctx->net, chain))1101 if (!nft_is_active_next(ctx->net, chain))
1093 continue;1102 continue;
1094 1103
1104 if (nft_chain_is_bound(chain))
1105 continue;
1106
1095 ctx->chain = chain;1107 ctx->chain = chain;
1096 1108
1097 err = nft_delchain(ctx);1109 err = nft_delchain(ctx);
@@ -1274,6 +1286,7 @@ static const struct nla_policy nft_chain_policy[NFTA_CHAIN_MAX + 1] = { · 176 unmodified lines
1274 .len = NFT_MODULE_AUTOLOAD_LIMIT },1286 .len = NFT_MODULE_AUTOLOAD_LIMIT },
1275 [NFTA_CHAIN_COUNTERS] = { .type = NLA_NESTED },1287 [NFTA_CHAIN_COUNTERS] = { .type = NLA_NESTED },
1276 [NFTA_CHAIN_FLAGS] = { .type = NLA_U32 },1288 [NFTA_CHAIN_FLAGS] = { .type = NLA_U32 },
1289 [NFTA_CHAIN_ID] = { .type = NLA_U32 },
1277};1290};
1278 1291
1279static const struct nla_policy nft_hook_policy[NFTA_HOOK_MAX + 1] = {1292static 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
1406 lockdep_commit_lock_is_held(net));1419 lockdep_commit_lock_is_held(net));
1407 if (nft_dump_stats(skb, stats))1420 if (nft_dump_stats(skb, stats))
1408 goto nla_put_failure;1421 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;
1414 }1422 }
1415 1423
1424 if (chain->flags &&
1425 nla_put_be32(skb, NFTA_CHAIN_FLAGS, htonl(chain->flags)))
1426 goto nla_put_failure;
1427
1416 if (nla_put_be32(skb, NFTA_CHAIN_USE, htonl(chain->use)))1428 if (nla_put_be32(skb, NFTA_CHAIN_USE, htonl(chain->use)))
1417 goto nla_put_failure;1429 goto nla_put_failure;
1418 1430
@@ -1614,7 +1626,7 @@ static void nf_tables_chain_free_chain_rules(struct nft_chain *chain) · 195 unmodified lines
1614 kvfree(chain->rules_next);1626 kvfree(chain->rules_next);
1615}1627}
1616 1628
1617static void nf_tables_chain_destroy(struct nft_ctx *ctx)1629void nf_tables_chain_destroy(struct nft_ctx *ctx)
1618{1630{
1619 struct nft_chain *chain = ctx->chain;1631 struct nft_chain *chain = ctx->chain;
1620 struct nft_hook *hook, *next;1632 struct nft_hook *hook, *next;
@@ -1896,7 +1908,7 @@ static int nft_basechain_init(struct nft_base_chain *basechain, u8 family, · 275 unmodified lines
1896 nft_basechain_hook_init(&basechain->ops, family, hook, chain);1908 nft_basechain_hook_init(&basechain->ops, family, hook, chain);
1897 }1909 }
1898 1910
1899 chain->flags |= NFT_BASE_CHAIN | flags;1911 chain->flags |= NFT_CHAIN_BASE | flags;
1900 basechain->policy = NF_ACCEPT;1912 basechain->policy = NF_ACCEPT;
1901 if (chain->flags & NFT_CHAIN_HW_OFFLOAD &&1913 if (chain->flags & NFT_CHAIN_HW_OFFLOAD &&
1902 nft_chain_offload_priority(basechain) < 0)1914 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
1907 return 0;1919 return 0;
1908}1920}
1909 1921
1922static 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
1936static u64 chain_id;
1937
1910static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,1938static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
1911 u8 policy, u32 flags)1939 u8 policy, u32 flags)
1912{1940{
@@ -1915,6 +1943,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, · 2 unmodified lines
1915 struct nft_base_chain *basechain;1943 struct nft_base_chain *basechain;
1916 struct nft_stats __percpu *stats;1944 struct nft_stats __percpu *stats;
1917 struct net *net = ctx->net;1945 struct net *net = ctx->net;
1946 char name[NFT_NAME_MAXLEN];
1918 struct nft_trans *trans;1947 struct nft_trans *trans;
1919 struct nft_chain *chain;1948 struct nft_chain *chain;
1920 struct nft_rule **rules;1949 struct nft_rule **rules;
@@ -1926,6 +1955,9 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, · 5 unmodified lines
1926 if (nla[NFTA_CHAIN_HOOK]) {1955 if (nla[NFTA_CHAIN_HOOK]) {
1927 struct nft_chain_hook hook;1956 struct nft_chain_hook hook;
1928 1957
1958 if (flags & NFT_CHAIN_BINDING)
1959 return -EOPNOTSUPP;
1960
1929 err = nft_chain_parse_hook(net, nla, &hook, family, true);1961 err = nft_chain_parse_hook(net, nla, &hook, family, true);
1930 if (err < 0)1962 if (err < 0)
1931 return err;1963 return err;
@@ -1955,16 +1987,33 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, · 23 unmodified lines
1955 return err;1987 return err;
1956 }1988 }
1957 } else {1989 } else {
1990 if (flags & NFT_CHAIN_BASE)
1991 return -EINVAL;
1992 if (flags & NFT_CHAIN_HW_OFFLOAD)
1993 return -EOPNOTSUPP;
1994
1958 chain = kzalloc(sizeof(*chain), GFP_KERNEL);1995 chain = kzalloc(sizeof(*chain), GFP_KERNEL);
1959 if (chain == NULL)1996 if (chain == NULL)
1960 return -ENOMEM;1997 return -ENOMEM;
1998
1999 chain->flags = flags;
1961 }2000 }
1962 ctx->chain = chain;2001 ctx->chain = chain;
1963 2002
1964 INIT_LIST_HEAD(&chain->rules);2003 INIT_LIST_HEAD(&chain->rules);
1965 chain->handle = nf_tables_alloc_handle(table);2004 chain->handle = nf_tables_alloc_handle(table);
1966 chain->table = table;2005 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
1968 if (!chain->name) {2017 if (!chain->name) {
1969 err = -ENOMEM;2018 err = -ENOMEM;
1970 goto err1;2019 goto err1;
@@ -1984,16 +2033,9 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, · 13 unmodified lines
1984 if (err < 0)2033 if (err < 0)
1985 goto err1;2034 goto err1;
1986 2035
1987 err = rhltable_insert_key(&table->chains_ht, chain->name,
1988 &chain->rhlhead, nft_chain_ht_params);
1989 if (err)
1990 goto err2;
1991
1992 trans = nft_trans_chain_add(ctx, NFT_MSG_NEWCHAIN);2036 trans = nft_trans_chain_add(ctx, NFT_MSG_NEWCHAIN);
1993 if (IS_ERR(trans)) {2037 if (IS_ERR(trans)) {
1994 err = PTR_ERR(trans);2038 err = PTR_ERR(trans);
1995 rhltable_remove(&table->chains_ht, &chain->rhlhead,
1996 nft_chain_ht_params);
1997 goto err2;2039 goto err2;
1998 }2040 }
1999 2041
@@ -2001,8 +2043,13 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, · 1 unmodified line
2001 if (nft_is_base_chain(chain))2043 if (nft_is_base_chain(chain))
2002 nft_trans_chain_policy(trans) = policy;2044 nft_trans_chain_policy(trans) = policy;
2003 2045
2046 err = nft_chain_add(table, chain);
2047 if (err < 0) {
2048 nft_trans_destroy(trans);
2049 goto err2;
2050 }
2051
2004 table->use++;2052 table->use++;
2005 list_add_tail_rcu(&chain->list, &table->chains);
2006 2053
2007 return 0;2054 return 0;
2008err2:2055err2:
@@ -2146,6 +2193,22 @@ err: · 137 unmodified lines
2146 return err;2193 return err;
2147}2194}
2148 2195
2196static 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
2149static int nf_tables_newchain(struct net *net, struct sock *nlsk,2212static int nf_tables_newchain(struct net *net, struct sock *nlsk,
2150 struct sk_buff *skb, const struct nlmsghdr *nlh,2213 struct sk_buff *skb, const struct nlmsghdr *nlh,
2151 const struct nlattr * const nla[],2214 const struct nlattr * const nla[],
@@ -2154,9 +2217,9 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, · 2 unmodified lines
2154 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);2217 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
2155 u8 genmask = nft_genmask_next(net);2218 u8 genmask = nft_genmask_next(net);
2156 int family = nfmsg->nfgen_family;2219 int family = nfmsg->nfgen_family;
2220 struct nft_chain *chain = NULL;
2157 const struct nlattr *attr;2221 const struct nlattr *attr;
2158 struct nft_table *table;2222 struct nft_table *table;
2159 struct nft_chain *chain;
2160 u8 policy = NF_ACCEPT;2223 u8 policy = NF_ACCEPT;
2161 struct nft_ctx ctx;2224 struct nft_ctx ctx;
2162 u64 handle = 0;2225 u64 handle = 0;
@@ -2181,7 +2244,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, · 18 unmodified lines
2181 return PTR_ERR(chain);2244 return PTR_ERR(chain);
2182 }2245 }
2183 attr = nla[NFTA_CHAIN_HANDLE];2246 attr = nla[NFTA_CHAIN_HANDLE];
2184 } else {2247 } else if (nla[NFTA_CHAIN_NAME]) {
2185 chain = nft_chain_lookup(net, table, attr, genmask);2248 chain = nft_chain_lookup(net, table, attr, genmask);
2186 if (IS_ERR(chain)) {2249 if (IS_ERR(chain)) {
2187 if (PTR_ERR(chain) != -ENOENT) {2250 if (PTR_ERR(chain) != -ENOENT) {
@@ -2190,6 +2253,8 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, · 2 unmodified lines
2190 }2253 }
2191 chain = NULL;2254 chain = NULL;
2192 }2255 }
2256 } else if (!nla[NFTA_CHAIN_ID]) {
2257 return -EINVAL;
2193 }2258 }
2194 2259
2195 if (nla[NFTA_CHAIN_POLICY]) {2260 if (nla[NFTA_CHAIN_POLICY]) {
@@ -2220,6 +2285,9 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, · 24 unmodified lines
2220 else if (chain)2285 else if (chain)
2221 flags = chain->flags;2286 flags = chain->flags;
2222 2287
2288 if (flags & ~NFT_CHAIN_FLAGS)
2289 return -EOPNOTSUPP;
2290
2223 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);2291 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
2224 2292
2225 if (chain != NULL) {2293 if (chain != NULL) {
@@ -2230,7 +2298,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, · 4 unmodified lines
2230 if (nlh->nlmsg_flags & NLM_F_REPLACE)2298 if (nlh->nlmsg_flags & NLM_F_REPLACE)
2231 return -EOPNOTSUPP;2299 return -EOPNOTSUPP;
2232 2300
2233 flags |= chain->flags & NFT_BASE_CHAIN;2301 flags |= chain->flags & NFT_CHAIN_BASE;
2234 return nf_tables_updchain(&ctx, genmask, policy, flags);2302 return nf_tables_updchain(&ctx, genmask, policy, flags);
2235 }2303 }
2236 2304
@@ -2624,6 +2692,7 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = { · 387 unmodified lines
2624 .len = NFT_USERDATA_MAXLEN },2692 .len = NFT_USERDATA_MAXLEN },
2625 [NFTA_RULE_ID] = { .type = NLA_U32 },2693 [NFTA_RULE_ID] = { .type = NLA_U32 },
2626 [NFTA_RULE_POSITION_ID] = { .type = NLA_U32 },2694 [NFTA_RULE_POSITION_ID] = { .type = NLA_U32 },
2695 [NFTA_RULE_CHAIN_ID] = { .type = NLA_U32 },
2627};2696};
2628 2697
2629static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,2698static 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
2938 kfree(rule);3007 kfree(rule);
2939}3008}
2940 3009
2941static void nf_tables_rule_release(const struct nft_ctx *ctx,3010void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule)
2942 struct nft_rule *rule)
2943{3011{
2944 nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE);3012 nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE);
2945 nf_tables_rule_destroy(ctx, rule);3013 nf_tables_rule_destroy(ctx, rule);
@@ -3030,10 +3098,24 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, · 84 unmodified lines
3030 return PTR_ERR(table);3098 return PTR_ERR(table);
3031 }3099 }
3032 3100
3033 chain = nft_chain_lookup(net, table, nla[NFTA_RULE_CHAIN], genmask);3101 if (nla[NFTA_RULE_CHAIN]) {
3034 if (IS_ERR(chain)) {3102 chain = nft_chain_lookup(net, table, nla[NFTA_RULE_CHAIN],
3035 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);3103 genmask);
3036 return PTR_ERR(chain);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;
3037 }3119 }
3038 3120
3039 if (nla[NFTA_RULE_HANDLE]) {3121 if (nla[NFTA_RULE_HANDLE]) {
@@ -3245,6 +3327,8 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk, · 205 unmodified lines
3245 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);3327 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);
3246 return PTR_ERR(chain);3328 return PTR_ERR(chain);
3247 }3329 }
3330 if (nft_chain_is_bound(chain))
3331 return -EOPNOTSUPP;
3248 }3332 }
3249 3333
3250 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);3334 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
5281 */5365 */
5282void nft_data_hold(const struct nft_data *data, enum nft_data_types type)5366void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
5283{5367{
5368 struct nft_chain *chain;
5369 struct nft_rule *rule;
5370
5284 if (type == NFT_DATA_VERDICT) {5371 if (type == NFT_DATA_VERDICT) {
5285 switch (data->verdict.code) {5372 switch (data->verdict.code) {
5286 case NFT_JUMP:5373 case NFT_JUMP:
5287 case NFT_GOTO:5374 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);
5289 break;5386 break;
5290 }5387 }
5291 }5388 }
@@ -7425,7 +7522,7 @@ static void nft_obj_del(struct nft_object *obj) · 2133 unmodified lines
7425 list_del_rcu(&obj->list);7522 list_del_rcu(&obj->list);
7426}7523}
7427 7524
7428static void nft_chain_del(struct nft_chain *chain)7525void nft_chain_del(struct nft_chain *chain)
7429{7526{
7430 struct nft_table *table = chain->table;7527 struct nft_table *table = chain->table;
7431 7528
@@ -7776,6 +7873,10 @@ static int __nf_tables_abort(struct net *net, bool autoload) · 344 unmodified lines
7776 kfree(nft_trans_chain_name(trans));7873 kfree(nft_trans_chain_name(trans));
7777 nft_trans_destroy(trans);7874 nft_trans_destroy(trans);
7778 } else {7875 } else {
7876 if (nft_chain_is_bound(trans->ctx.chain)) {
7877 nft_trans_destroy(trans);
7878 break;
7879 }
7779 trans->ctx.table->use--;7880 trans->ctx.table->use--;
7780 nft_chain_del(trans->ctx.chain);7881 nft_chain_del(trans->ctx.chain);
7781 nf_tables_unregister_hook(trans->ctx.net,7882 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
8205 [NFTA_VERDICT_CODE] = { .type = NLA_U32 },8306 [NFTA_VERDICT_CODE] = { .type = NLA_U32 },
8206 [NFTA_VERDICT_CHAIN] = { .type = NLA_STRING,8307 [NFTA_VERDICT_CHAIN] = { .type = NLA_STRING,
8207 .len = NFT_CHAIN_MAXNAMELEN - 1 },8308 .len = NFT_CHAIN_MAXNAMELEN - 1 },
8309 [NFTA_VERDICT_CHAIN_ID] = { .type = NLA_U32 },
8208};8310};
8209 8311
8210static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,8312static 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
8241 break;8343 break;
8242 case NFT_JUMP:8344 case NFT_JUMP:
8243 case NFT_GOTO:8345 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 {
8245 return -EINVAL;8356 return -EINVAL;
8246 chain = nft_chain_lookup(ctx->net, ctx->table,8357 }
8247 tb[NFTA_VERDICT_CHAIN], genmask);8358
8248 if (IS_ERR(chain))8359 if (IS_ERR(chain))
8249 return PTR_ERR(chain);8360 return PTR_ERR(chain);
8250 if (nft_is_base_chain(chain))8361 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
8262 8373
8263static void nft_verdict_uninit(const struct nft_data *data)8374static void nft_verdict_uninit(const struct nft_data *data)
8264{8375{
8376 struct nft_chain *chain;
8377 struct nft_rule *rule;
8378
8265 switch (data->verdict.code) {8379 switch (data->verdict.code) {
8266 case NFT_JUMP:8380 case NFT_JUMP:
8267 case NFT_GOTO:8381 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);
8269 break;8393 break;
8270 }8394 }
8271}8395}
net/netfilter/nft_immediate.c+51−0
@@ -54,6 +54,23 @@ static int nft_immediate_init(const struct nft_ctx *ctx, · 53 unmodified lines
54 if (err < 0)54 if (err < 0)
55 goto err1;55 goto err1;
56 56
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
57 return 0;74 return 0;
58 75
59err1:76err1:
@@ -81,6 +98,39 @@ static void nft_immediate_deactivate(const struct nft_ctx *ctx, · 21 unmodified lines
81 return nft_data_release(&priv->data, nft_dreg_to_type(priv->dreg));98 return nft_data_release(&priv->data, nft_dreg_to_type(priv->dreg));
82}99}
83 100
101static 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
84static int nft_immediate_dump(struct sk_buff *skb, const struct nft_expr *expr)134static int nft_immediate_dump(struct sk_buff *skb, const struct nft_expr *expr)
85{135{
86 const struct nft_immediate_expr *priv = nft_expr_priv(expr);136 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
170 .init = nft_immediate_init,220 .init = nft_immediate_init,
171 .activate = nft_immediate_activate,221 .activate = nft_immediate_activate,
172 .deactivate = nft_immediate_deactivate,222 .deactivate = nft_immediate_deactivate,
223 .destroy = nft_immediate_destroy,
173 .dump = nft_immediate_dump,224 .dump = nft_immediate_dump,
174 .validate = nft_immediate_validate,225 .validate = nft_immediate_validate,
175 .offload = nft_immediate_offload,226 .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
30 return nft_chain_validate_hooks(ctx->chain,30 return nft_chain_validate_hooks(ctx->chain,
31 (1 << NF_INET_LOCAL_IN) |31 (1 << NF_INET_LOCAL_IN) |
32 (1 << NF_INET_FORWARD) |32 (1 << NF_INET_FORWARD) |
33 (1 << NF_INET_LOCAL_OUT));33 (1 << NF_INET_LOCAL_OUT) |
34 (1 << NF_INET_PRE_ROUTING));
34}35}
35EXPORT_SYMBOL_GPL(nft_reject_validate);36EXPORT_SYMBOL_GPL(nft_reject_validate);
36 37
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
1249 if (err)1249 if (err)
1250 return err;1250 return err;
1251 1251
1252 this_cpu_write(nft_pipapo_scratch_index, false);
1253
1254 m->bsize_max = bsize_max;1252 m->bsize_max = bsize_max;
1255 } else {1253 } else {
1256 put_cpu_ptr(m->scratch);1254 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