Netfilter/IPVS updates for net-next
Subsystems (5)
Pablo Neira Ayuso
maintainercover Netfilter/IPVS updates for net-next
Hi David,
The following patchset contains Netfilter/IPVS updates for your net-next tree, the most relevant things in this batch are:
1) Compile masquerade infrastructure into NAT module, from Florian Westphal. Same thing with the redirection support.
2) Abort transaction if early initialization of the commit phase fails. Also from Florian.
3) Get rid of synchronize_rcu() by using rule array in nf_tables, from Florian.
4) Abort nf_tables batch if fatal signal is pending, from Florian.
5) Use .call_rcu nfnetlink from nf_tables to make dumps fully lockless. From Florian Westphal.
6) Support to match transparent sockets from nf_tables, from Máté Eckl.
7) Audit support for nf_tables, from Phil Sutter.
8) Validate chain dependencies from commit phase, fall back to fine grain validation only in case of errors.
9) Attach dst to skbuff from netfilter flowtable packet path, from Jason A. Donenfeld.
10) Use artificial maximum attribute cap to remove VLA from nfnetlink. Patch from Kees Cook.
11) Add extension to allow to forward packets through neighbour layer.
12) Add IPv6 conntrack helper support to IPVS, from Julian Anastasov.
13) Add IPv6 FTP conntrack support to IPVS, from Julian Anastasov.
Plus patches including small incremental improvements.
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git
Thanks.
----------------------------------------------------------------
The following changes since commit 5b79c2af667c0e2684f2a6dbf6439074b78f490c:
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net (2018-05-26 19:46:15 -0400)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git HEAD
for you to fetch changes up to d12e12299a6915fc10131602cca41170e46ae755:
ipvs: add ipv6 support to ftp (2018-06-01 14:01:54 +0200)
----------------------------------------------------------------
Florian Westphal (8):
netfilter: nat: merge ipv4/ipv6 masquerade code into main nat module
netfilter: nat: merge nf_nat_redirect into nf_nat
netfilter: nfnetlink: allow commit to fail
netfilter: nf_tables: remove synchronize_rcu in commit phase
netfilter: nft_compat: use call_rcu for nfnl_compat_get
netfilter: nf_tables: fix endian mismatch in return type
netfilter: nf_tables: fail batch if fatal signal is pending
netfilter: nf_tables: use call_rcu in netlink dumps
Jason A. Donenfeld (1):
netfilter: nf_flow_table: attach dst to skbs
Julian Anastasov (2):
ipvs: add full ipv6 support to nfct
ipvs: add ipv6 support to ftp
Kees Cook (1):
netfilter: nfnetlink: Remove VLA usage
Máté Eckl (2):
netfilter: add includes to nf_socket.h
netfilter: nf_tables: add support for native socket matching
Pablo Neira Ayuso (2):
netfilter: nf_tables: fix chain dependency validation
netfilter: nft_fwd_netdev: allow to forward packets via neighbour layer
Phil Sutter (1):
netfilter: nf_tables: Add audit support to log statement
Taehee Yoo (1):
netfilter: nf_tables: remove unused variables
Wei Yongjun (1):
netfilter: nat: make symbol nat_hook static
kbuild test robot (1):
netfilter: fix ptr_ret.cocci warnings
include/linux/netfilter/nfnetlink.h | 1 + include/net/ip_vs.h | 10 +- include/net/netfilter/nf_socket.h | 6 +- include/net/netfilter/nf_tables.h | 7 + include/net/netfilter/nf_tables_core.h | 8 + include/net/netns/nftables.h | 1 + include/uapi/linux/netfilter/nf_tables.h | 34 ++ net/ipv4/netfilter/Kconfig | 5 +- net/ipv4/netfilter/Makefile | 4 +- net/ipv4/netfilter/nf_nat_masquerade_ipv4.c | 4 - net/ipv6/netfilter/Kconfig | 5 +- net/ipv6/netfilter/Makefile | 2 +- net/ipv6/netfilter/nf_nat_masquerade_ipv6.c | 4 - net/netfilter/Kconfig | 15 +- net/netfilter/Makefile | 3 +- net/netfilter/ipvs/ip_vs_app.c | 24 +- net/netfilter/ipvs/ip_vs_ftp.c | 467 +++++++++++++++++---------- net/netfilter/ipvs/ip_vs_nfct.c | 101 +++--- net/netfilter/ipvs/ip_vs_proto_sctp.c | 4 +- net/netfilter/ipvs/ip_vs_proto_tcp.c | 4 +- net/netfilter/ipvs/ip_vs_proto_udp.c | 4 +- net/netfilter/nf_flow_table_ip.c | 6 +- net/netfilter/nf_nat_core.c | 2 +- net/netfilter/nf_nat_redirect.c | 4 - net/netfilter/nf_tables_api.c | 469 +++++++++++++++++++++++----- net/netfilter/nf_tables_core.c | 40 +-- net/netfilter/nfnetlink.c | 44 ++- net/netfilter/nft_compat.c | 29 +- net/netfilter/nft_fwd_netdev.c | 146 ++++++++- net/netfilter/nft_hash.c | 10 +- net/netfilter/nft_immediate.c | 27 +- net/netfilter/nft_log.c | 92 +++++- net/netfilter/nft_lookup.c | 47 +++ net/netfilter/nft_numgen.c | 5 +- net/netfilter/nft_socket.c | 143 +++++++++ 35 files changed, 1372 insertions(+), 405 deletions(-) create mode 100644 net/netfilter/nft_socket.c
Pablo Neira Ayuso
maintainerPATCH 1/20 netfilter: add includes to nf_socket.h
From: Máté Eckl <[email protected]>
These have to be included always when nf_socket.h is included.
--- include/net/netfilter/nf_socket.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
include/net/netfilter/nf_socket.h +2 -4
@@ -2,10 +2,8 @@#ifndef _NF_SOCK_H_#define _NF_SOCK_H_ -struct net_device ; -struct sk_buff ; -struct sock ; -struct net ; +#include <net/sock.h> +#include <net/inet_timewait_sock.h> static inline bool nf_sk_is_transparent (struct sock *sk) {
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 2/20 netfilter: nat: merge ipv4/ipv6 masquerade code into main nat module
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
Instead of using extra modules for these, turn the config options into an implicit dependency that adds masq feature to the protocol specific nf_nat module.
before:
text data bss dec hex filename
2001 860 4 2865 b31 net/ipv4/netfilter/nf_nat_masquerade_ipv4.ko 5579 780 2 6361 18d9 net/ipv4/netfilter/nf_nat_ipv4.ko 2860 836 8 3704 e78 net/ipv6/netfilter/nf_nat_masquerade_ipv6.ko 6648 780 2 7430 1d06 net/ipv6/netfilter/nf_nat_ipv6.ko
after:
text data bss dec hex filename
7245 872 8 8125 1fbd net/ipv4/netfilter/nf_nat_ipv4.ko 9165 848 12 10025 2729 net/ipv6/netfilter/nf_nat_ipv6.ko
--- net/ipv4/netfilter/Kconfig | 5 +---- net/ipv4/netfilter/Makefile | 4 +--- net/ipv4/netfilter/nf_nat_masquerade_ipv4.c | 4 ---- net/ipv6/netfilter/Kconfig | 5 +---- net/ipv6/netfilter/Makefile | 2 +- net/ipv6/netfilter/nf_nat_masquerade_ipv6.c | 4 ---- 6 files changed, 4 insertions(+), 20 deletions(-)
net/ipv4/netfilter/Kconfig +1 -4
@@ -129,10 +129,7 @@ config NFT_CHAIN_NAT_IPV4 source and destination ports. config NF_NAT_MASQUERADE_IPV4 - tristate "IPv4 masquerade support" - help - This is the kernel functionality to provide NAT in the masquerade - flavour (automatic source address selection). + bool config NFT_MASQ_IPV4 tristate "IPv4 masquerading support for nf_tables"
net/ipv4/netfilter/Makefile +1 -3
@@ -10,6 +10,7 @@ nf_conntrack_ipv4-y := nf_conntrack_l3proto_ipv4.o nf_conntrack_proto_icmp.o obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o nf_nat_ipv4-y := nf_nat_l3proto_ipv4.o nf_nat_proto_icmp.o +nf_nat_ipv4-$(CONFIG_NF_NAT_MASQUERADE_IPV4) += nf_nat_masquerade_ipv4.o obj-$(CONFIG_NF_NAT_IPV4) += nf_nat_ipv4.o # defrag
@@ -32,9 +33,6 @@ nf_nat_snmp_basic-y := nf_nat_snmp_basic.asn1.o nf_nat_snmp_basic_main.o $(obj)/nf_nat_snmp_basic_main.o: $(obj)/nf_nat_snmp_basic.asn1.h obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o -obj-$(CONFIG_NF_NAT_MASQUERADE_IPV4) += nf_nat_masquerade_ipv4.o - - # NAT protocols (nf_nat) obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
net/ipv4/netfilter/nf_nat_masquerade_ipv4.c +0 -4
@@ -7,7 +7,6 @@*/ #include <linux/types.h> -#include <linux/module.h> #include <linux/atomic.h> #include <linux/inetdevice.h> #include <linux/ip.h>
@@ -157,6 +156,3 @@ void nf_nat_masquerade_ipv4_unregister_notifier(void)unregister_inetaddr_notifier (&masq_inet_notifier); }EXPORT_SYMBOL_GPL (nf_nat_masquerade_ipv4_unregister_notifier); - -MODULE_LICENSE ("GPL" ); -MODULE_AUTHOR ("Rusty Russell <[email protected]>" );
net/ipv6/netfilter/Kconfig +1 -4
@@ -136,10 +136,7 @@ config NF_NAT_IPV6 if NF_NAT_IPV6 config NF_NAT_MASQUERADE_IPV6 - tristate "IPv6 masquerade support" - help - This is the kernel functionality to provide NAT in the masquerade - flavour (automatic source address selection) for IPv6. + bool endif # NF_NAT_IPV6
net/ipv6/netfilter/Makefile +1 -1
@@ -18,8 +18,8 @@ nf_conntrack_ipv6-y := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o nf_nat_ipv6-y := nf_nat_l3proto_ipv6.o nf_nat_proto_icmpv6.o +nf_nat_ipv6-$(CONFIG_NF_NAT_MASQUERADE_IPV6) += nf_nat_masquerade_ipv6.o obj-$(CONFIG_NF_NAT_IPV6) += nf_nat_ipv6.o -obj-$(CONFIG_NF_NAT_MASQUERADE_IPV6) += nf_nat_masquerade_ipv6.o # defrag nf_defrag_ipv6-y := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o
net/ipv6/netfilter/nf_nat_masquerade_ipv6.c +0 -4
@@ -10,7 +10,6 @@*/ #include <linux/kernel.h> -#include <linux/module.h> #include <linux/atomic.h> #include <linux/netdevice.h> #include <linux/ipv6.h>
@@ -186,6 +185,3 @@ void nf_nat_masquerade_ipv6_unregister_notifier(void)unregister_netdevice_notifier (&masq_dev_notifier); }EXPORT_SYMBOL_GPL (nf_nat_masquerade_ipv6_unregister_notifier); - -MODULE_LICENSE ("GPL" ); -MODULE_AUTHOR ("Patrick McHardy <[email protected]>" );
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 3/20 netfilter: nat: merge nf_nat_redirect into nf_nat
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
Similar to previous patch, this time, merge redirect+nat. The redirect module is just 2k in size, get rid of it and make redirect part available from the nat core.
before:
text data bss dec hex filename
19461 1484 4138 25083 61fb net/netfilter/nf_nat.ko
1236 792 0 2028 7ec net/netfilter/nf_nat_redirect.ko
after:
20340 1508 4138 25986 6582 net/netfilter/nf_nat.ko
--- net/netfilter/Kconfig | 6 +----- net/netfilter/Makefile | 2 +- net/netfilter/nf_nat_redirect.c | 4 ---- 3 files changed, 2 insertions(+), 10 deletions(-)
net/netfilter/Kconfig +1 -5
@@ -433,11 +433,7 @@ config NF_NAT_TFTP default NF_NAT && NF_CONNTRACK_TFTP config NF_NAT_REDIRECT - tristate "IPv4/IPv6 redirect support" - depends on NF_NAT - help - This is the kernel functionality to redirect packets to local - machine through NAT. + bool config NETFILTER_SYNPROXY tristate
net/netfilter/Makefile +1 -1
@@ -55,7 +55,7 @@ obj-$(CONFIG_NF_LOG_COMMON) += nf_log_common.o obj-$(CONFIG_NF_LOG_NETDEV) += nf_log_netdev.o obj-$(CONFIG_NF_NAT) += nf_nat.o -obj-$(CONFIG_NF_NAT_REDIRECT) += nf_nat_redirect.o +nf_nat-$(CONFIG_NF_NAT_REDIRECT) += nf_nat_redirect.o # NAT helpers obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o
net/netfilter/nf_nat_redirect.c +0 -4
@@ -15,7 +15,6 @@#include <linux/inetdevice.h> #include <linux/ip.h> #include <linux/kernel.h> -#include <linux/module.h> #include <linux/netdevice.h> #include <linux/netfilter.h> #include <linux/types.h>
@@ -124,6 +123,3 @@ nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range,return nf_nat_setup_info (ct, &newrange,NF_NAT_MANIP_DST ); }EXPORT_SYMBOL_GPL (nf_nat_redirect_ipv6); - -MODULE_LICENSE ("GPL" ); -MODULE_AUTHOR ("Patrick McHardy <[email protected]>" );
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 4/20 netfilter: nfnetlink: allow commit to fail
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
->commit() cannot fail at the moment.
Followup-patch adds kmalloc calls in the commit phase, so we'll need to be able to handle errors.
Make it so that -EGAIN causes a full replay, and make other errors cause the transaction to fail.
Failing is ok from a consistency point of view as long as we perform all actions that could return an error before we increment the generation counter and the base seq.
--- net/netfilter/nfnetlink.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
net/netfilter/nfnetlink.c +8 -1
@@ -441,7 +441,14 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,kfree_skb (skb); goto replay; }else if (status ==NFNL_BATCH_DONE ) { - ss->commit (net, oskb); + err = ss->commit (net, oskb); +if (err == -EAGAIN ) { + status |=NFNL_BATCH_REPLAY ; + goto done; + }else if (err) { + ss->abort (net, oskb); +netlink_ack (oskb,nlmsg_hdr (oskb), err,NULL ); + } }else { ss->abort (net, oskb); }
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 5/20 netfilter: nf_tables: remove synchronize_rcu in commit phase
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
synchronize_rcu() is expensive.
The commit phase currently enforces an unconditional synchronize_rcu() after incrementing the generation counter.
This is to make sure that a packet always sees a consistent chain, either nft_do_chain is still using old generation (it will skip the newly added rules), or the new one (it will skip old ones that might still be linked into the list).
We could just remove the synchronize_rcu(), it would not cause a crash but it could cause us to evaluate a rule that was removed and new rule for the same packet, instead of either-or.
To resolve this, add rule pointer array holding two generations, the current one and the future generation.
In commit phase, allocate the rule blob and populate it with the rules that will be active in the new generation.
Then, make this rule blob public, replacing the old generation pointer.
Then the generation counter can be incremented.
nft_do_chain() will either continue to use the current generation (in case loop was invoked right before increment), or the new one.
--- include/net/netfilter/nf_tables.h | 5 + net/netfilter/nf_tables_api.c | 204 ++++++++++++++++++++++++++++++++++++-- net/netfilter/nf_tables_core.c | 24 +++-- 3 files changed, 215 insertions(+), 18 deletions(-)
include/net/netfilter/nf_tables.h +5 -0
@@ -858,6 +858,8 @@ enum nft_chain_flags {* @name: name of the chain */ struct nft_chain { +struct nft_rule *__rcu *rules_gen_0; +struct nft_rule *__rcu *rules_gen_1;struct list_head rules;struct list_head list;struct nft_table *table;
@@ -867,6 +869,9 @@ struct nft_chain { u8 flags:6, genmask:2;char *name; + +/* Only used during control plane commit phase: */ +struct nft_rule **rules_next; };enum nft_chain_types {
net/netfilter/nf_tables_api.c +197 -7
248 lines not on this page · raw message
net/netfilter/nf_tables_core.c +13 -11
@@ -133,7 +133,7 @@ static noinline void nft_update_chain_stats(const struct nft_chain *chain,struct nft_jumpstack {const struct nft_chain *chain; -const struct nft_rule *rule; +struct nft_rule *const *rules; };unsigned int
@@ -141,27 +141,29 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv) {const struct nft_chain *chain = priv, *basechain = chain;const struct net *net =nft_net (pkt); +struct nft_rule *const *rules;const struct nft_rule *rule;const struct nft_expr *expr, *last;struct nft_regs regs;unsigned int stackptr =0 ;struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE ]; -unsigned int gencursor =nft_genmask_cur (net); +bool genbit =READ_ONCE (net->nft.gencursor);struct nft_traceinfo info; info.trace = false;if (static_branch_unlikely (&nft_trace_enabled))nft_trace_init (&info, pkt, ®s.verdict, basechain); do_chain: - rule = list_entry(&chain->rules, struct nft_rule, list); +if (genbit) + rules =rcu_dereference (chain->rules_gen_1); +else + rules =rcu_dereference (chain->rules_gen_0); + next_rule: + rule = *rules; regs.verdict.code =NFT_CONTINUE ; -list_for_each_entry_continue_rcu (rule, &chain->rules, list) { - -/* This rule is not active, skip. */ -if (unlikely (rule->genmask & gencursor)) -continue ; - +for (; *rules ; rules++) { + rule = *rules;nft_rule_for_each_expr (expr, last, rule) {if (expr->ops == &nft_cmp_fast_ops)nft_cmp_fast_eval (expr, ®s);
@@ -199,7 +201,7 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)case NFT_JUMP :BUG_ON (stackptr >=NFT_JUMP_STACK_SIZE ); jumpstack[stackptr].chain = chain; - jumpstack[stackptr].rule = rule; + jumpstack[stackptr].rules = rules +1 ; stackptr++;/* fall through */ case NFT_GOTO :
@@ -221,7 +223,7 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)if (stackptr >0 ) { stackptr--; chain = jumpstack[stackptr].chain; - rule = jumpstack[stackptr].rule; + rules = jumpstack[stackptr].rules; goto next_rule; }
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 6/20 netfilter: nat: make symbol nat_hook static
In reply to Pablo Neira AyusoFrom: Wei Yongjun <[email protected]>
Fixes the following sparse warning:
net/netfilter/nf_nat_core.c:1039:20: warning:
symbol 'nat_hook' was not declared. Should it be static?
--- net/netfilter/nf_nat_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/nf_nat_core.c +1 -1
@@ -1036,7 +1036,7 @@ static struct pernet_operations nat_net_ops = { .size = sizeof(struct nat_net), }; -struct nf_nat_hook nat_hook = { +static struct nf_nat_hook nat_hook = { .parse_nat_setup = nfnetlink_parse_nat_setup, #ifdef CONFIG_XFRM .decode_session = __nf_nat_decode_session,
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 7/20 netfilter: nft_compat: use call_rcu for nfnl_compat_get
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
Just use .call_rcu instead. We can drop the rcu read lock after obtaining a reference and re-acquire on return.
--- net/netfilter/nft_compat.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-)
net/netfilter/nft_compat.c +18 -11
@@ -611,10 +611,10 @@ nfnl_compat_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,return -1 ; } -static int nfnl_compat_get (struct net *net,struct sock *nfnl, -struct sk_buff *skb,const struct nlmsghdr *nlh, -const struct nlattr *const tb[], -struct netlink_ext_ack *extack) +static int nfnl_compat_get_rcu (struct net *net,struct sock *nfnl, +struct sk_buff *skb,const struct nlmsghdr *nlh, +const struct nlattr *const tb[], +struct netlink_ext_ack *extack) {int ret =0 , target;struct nfgenmsg *nfmsg;
@@ -653,16 +653,21 @@ static int nfnl_compat_get(struct net *net, struct sock *nfnl,return -EINVAL ; } +if (!try_module_get (THIS_MODULE )) +return -EINVAL ; + +rcu_read_unlock ();try_then_request_module (xt_find_revision (nfmsg->nfgen_family, name, rev, target, &ret), fmt, name); -if (ret <0 ) -return ret; + goto out_put; skb2 =nlmsg_new (NLMSG_DEFAULT_SIZE ,GFP_KERNEL ); -if (skb2 ==NULL ) -return -ENOMEM ; +if (skb2 ==NULL ) { + ret = -ENOMEM ; + goto out_put; + }/* include the best revision for this extension in the message */ if (nfnl_compat_fill_info(skb2, NETLINK_CB(skb).portid,
@@ -672,14 +677,16 @@ static int nfnl_compat_get(struct net *net, struct sock *nfnl, nfmsg->nfgen_family, name, ret, target) <= 0) {kfree_skb (skb2); -return -ENOSPC ; + goto out_put; } ret =netlink_unicast (nfnl, skb2,NETLINK_CB (skb).portid,MSG_DONTWAIT );if (ret >0 ) ret =0 ; - +out_put: +rcu_read_lock (); +module_put (THIS_MODULE );return ret == -EAGAIN ? -ENOBUFS : ret; }
@@ -691,7 +698,7 @@ static const struct nla_policy nfnl_compat_policy_get[NFTA_COMPAT_MAX+1] = { };static const struct nfnl_callback nfnl_nft_compat_cb[NFNL_MSG_COMPAT_MAX ] = { - [NFNL_MSG_COMPAT_GET ] = { .call = nfnl_compat_get, + [NFNL_MSG_COMPAT_GET ] = { .call_rcu = nfnl_compat_get_rcu, .attr_count =NFTA_COMPAT_MAX , .policy = nfnl_compat_policy_get }, };
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 8/20 netfilter: nf_tables: fix endian mismatch in return type
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
harmless, but it avoids sparse warnings:
nf_tables_api.c:2813:16: warning: incorrect type in return expression (different base types) nf_tables_api.c:2863:47: warning: incorrect type in argument 3 (different base types) nf_tables_api.c:3524:47: warning: incorrect type in argument 3 (different base types) nf_tables_api.c:3538:55: warning: incorrect type in argument 3 (different base types)
--- net/netfilter/nf_tables_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/nf_tables_api.c +1 -1
@@ -2830,7 +2830,7 @@ static int nf_msecs_to_jiffies64(const struct nlattr *nla, u64 *result)return 0 ; } -static u64 nf_jiffies64_to_msecs (u64 input) +static __be64 nf_jiffies64_to_msecs (u64 input) {u64 ms =jiffies64_to_nsecs (input);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 9/20 netfilter: nf_tables: fail batch if fatal signal is pending
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
abort batch processing and return so task can exit faster. Otherwise even SIGKILL has no immediate effect.
--- net/netfilter/nfnetlink.c | 8 ++++++++ 1 file changed, 8 insertions(+)
net/netfilter/nfnetlink.c +8 -0
@@ -25,6 +25,7 @@#include <linux/uaccess.h> #include <net/sock.h> #include <linux/init.h> +#include <linux/sched/signal.h> #include <net/netlink.h> #include <linux/netfilter/nfnetlink.h>
@@ -330,6 +331,13 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,while (skb->len >=nlmsg_total_size (0 )) {int msglen, type; +if (fatal_signal_pending (current)) { +nfnl_err_reset (&err_list); + err = -EINTR ; + status =NFNL_BATCH_FAILURE ; + goto done; + } +memset (&extack,0 ,sizeof (extack)); nlh =nlmsg_hdr (skb); err =0 ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 10/20 netfilter: nf_tables: use call_rcu in netlink dumps
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
We can make all dumps and lookups lockless.
Dumps currently only hold the nfnl mutex on the dump request itself. Dumps can span multiple syscalls, dump continuation doesn't acquire the nfnl mutex anywhere, i.e. the dump callbacks in nf_tables already use rcu and never rely on nfnl mutex being held.
So, just switch all dumpers to rcu.
This requires taking a module reference before dropping the rcu lock so rmmod is blocked, we also need to hold module reference over the entire dump operation sequence. netlink already supports this via the .module member in the netlink_dump_control struct.
For the non-dump case (i.e. lookup of a specific tables, chains, etc), we need to swtich to _rcu list iteration primitive and make sure we use GFP_ATOMIC.
This patch also adds the new nft_netlink_dump_start_rcu() helper that takes care of the get_ref, drop-rcu-lock,start dump, get-rcu-lock,put-ref sequence.
The helper will be reused for all dumps.
Rationale in all dump requests is:
- use the nft_netlink_dump_start_rcu helper added in first patch
- use GFP_ATOMIC and rcu list iteration
- switch to .call_rcu
... thus making all dumps in nf_tables not depend on the nfnl mutex anymore.
In the nf_tables_getgen: This callback just fetches the current base sequence, there is no need to serialize this with nfnl nft mutex.
--- net/netfilter/nf_tables_api.c | 111 +++++++++++++++++++++++++++--------------- 1 file changed, 72 insertions(+), 39 deletions(-)
net/netfilter/nf_tables_api.c +72 -39
@@ -373,7 +373,7 @@ static struct nft_table *nft_table_lookup(const struct net *net,if (nla ==NULL )return ERR_PTR (-EINVAL ); -list_for_each_entry (table, &net->nft.tables, list) { +list_for_each_entry_rcu (table, &net->nft.tables, list) {if (!nla_strcmp (nla, table->name) && table->family == family &&nft_active_genmask (table, genmask))
@@ -546,6 +546,24 @@ static int nf_tables_dump_tables(struct sk_buff *skb,return skb->len; } +static int nft_netlink_dump_start_rcu (struct sock *nlsk,struct sk_buff *skb, +const struct nlmsghdr *nlh, +struct netlink_dump_control *c) +{ +int err; + +if (!try_module_get (THIS_MODULE )) +return -EINVAL ; + +rcu_read_unlock (); + err =netlink_dump_start (nlsk, skb, nlh, c); +rcu_read_lock (); +module_put (THIS_MODULE ); + +return err; +} + +/* called with rcu_read_lock held */ static int nf_tables_gettable(struct net *net, struct sock *nlsk, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const nla[],
@@ -561,8 +579,10 @@ static int nf_tables_gettable(struct net *net, struct sock *nlsk,if (nlh->nlmsg_flags &NLM_F_DUMP ) {struct netlink_dump_control c = { .dump = nf_tables_dump_tables, + .module =THIS_MODULE , }; -return netlink_dump_start (nlsk, skb, nlh, &c); + +return nft_netlink_dump_start_rcu (nlsk, skb, nlh, &c); } table =nft_table_lookup (net, nla[NFTA_TABLE_NAME ], family, genmask);
@@ -571,7 +591,7 @@ static int nf_tables_gettable(struct net *net, struct sock *nlsk,return PTR_ERR (table); } - skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_KERNEL ); + skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_ATOMIC );if (!skb2)return -ENOMEM ;
@@ -933,7 +953,7 @@ static struct nft_chain *nft_chain_lookup(const struct nft_table *table,if (nla ==NULL )return ERR_PTR (-EINVAL ); -list_for_each_entry (chain, &table->chains, list) { +list_for_each_entry_rcu (chain, &table->chains, list) {if (!nla_strcmp (nla, chain->name) &&nft_active_genmask (chain, genmask))return chain;
@@ -1135,6 +1155,7 @@ static int nf_tables_dump_chains(struct sk_buff *skb,return skb->len; } +/* called with rcu_read_lock held */ static int nf_tables_getchain(struct net *net, struct sock *nlsk, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const nla[],
@@ -1151,8 +1172,10 @@ static int nf_tables_getchain(struct net *net, struct sock *nlsk,if (nlh->nlmsg_flags &NLM_F_DUMP ) {struct netlink_dump_control c = { .dump = nf_tables_dump_chains, + .module =THIS_MODULE , }; -return netlink_dump_start (nlsk, skb, nlh, &c); + +return nft_netlink_dump_start_rcu (nlsk, skb, nlh, &c); } table =nft_table_lookup (net, nla[NFTA_CHAIN_TABLE ], family, genmask);
@@ -1167,7 +1190,7 @@ static int nf_tables_getchain(struct net *net, struct sock *nlsk,return PTR_ERR (chain); } - skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_KERNEL ); + skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_ATOMIC );if (!skb2)return -ENOMEM ;
@@ -1969,7 +1992,7 @@ static struct nft_rule *__nft_rule_lookup(const struct nft_chain *chain,struct nft_rule *rule;// FIXME: this sucks -list_for_each_entry (rule, &chain->rules, list) { +list_for_each_entry_rcu (rule, &chain->rules, list) {if (handle == rule->handle)return rule; }
@@ -2165,6 +2188,7 @@ static int nf_tables_dump_rules_done(struct netlink_callback *cb)return 0 ; } +/* called with rcu_read_lock held */ static int nf_tables_getrule(struct net *net, struct sock *nlsk, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const nla[],
@@ -2183,18 +2207,19 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk,struct netlink_dump_control c = { .dump = nf_tables_dump_rules, .done = nf_tables_dump_rules_done, + .module =THIS_MODULE , };if (nla[NFTA_RULE_TABLE ] || nla[NFTA_RULE_CHAIN ]) {struct nft_rule_dump_ctx *ctx; - ctx =kzalloc (sizeof (*ctx),GFP_KERNEL ); + ctx =kzalloc (sizeof (*ctx),GFP_ATOMIC );if (!ctx)return -ENOMEM ;if (nla[NFTA_RULE_TABLE ]) { ctx->table =nla_strdup (nla[NFTA_RULE_TABLE ], -GFP_KERNEL ); +GFP_ATOMIC );if (!ctx->table) {kfree (ctx);return -ENOMEM ;
@@ -2202,7 +2227,7 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk, }if (nla[NFTA_RULE_CHAIN ]) { ctx->chain =nla_strdup (nla[NFTA_RULE_CHAIN ], -GFP_KERNEL ); +GFP_ATOMIC );if (!ctx->chain) {kfree (ctx->table);kfree (ctx);
@@ -2212,7 +2237,7 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk, c.data = ctx; } -return netlink_dump_start (nlsk, skb, nlh, &c); +return nft_netlink_dump_start_rcu (nlsk, skb, nlh, &c); } table =nft_table_lookup (net, nla[NFTA_RULE_TABLE ], family, genmask);
@@ -2233,7 +2258,7 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk,return PTR_ERR (rule); } - skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_KERNEL ); + skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_ATOMIC );if (!skb2)return -ENOMEM ;
@@ -2704,7 +2729,7 @@ static struct nft_set *nft_set_lookup(const struct nft_table *table,if (nla ==NULL )return ERR_PTR (-EINVAL ); -list_for_each_entry (set, &table->sets, list) { +list_for_each_entry_rcu (set, &table->sets, list) {if (!nla_strcmp (nla, set->name) &&nft_active_genmask (set, genmask))return set;
@@ -3009,6 +3034,7 @@ static int nf_tables_dump_sets_done(struct netlink_callback *cb)return 0 ; } +/* called with rcu_read_lock held */ static int nf_tables_getset(struct net *net, struct sock *nlsk, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const nla[],
@@ -3031,17 +3057,18 @@ static int nf_tables_getset(struct net *net, struct sock *nlsk,struct netlink_dump_control c = { .dump = nf_tables_dump_sets, .done = nf_tables_dump_sets_done, + .module =THIS_MODULE , };struct nft_ctx *ctx_dump; - ctx_dump =kmalloc (sizeof (*ctx_dump),GFP_KERNEL ); + ctx_dump =kmalloc (sizeof (*ctx_dump),GFP_ATOMIC );if (ctx_dump ==NULL )return -ENOMEM ; *ctx_dump = ctx; c.data = ctx_dump; -return netlink_dump_start (nlsk, skb, nlh, &c); +return nft_netlink_dump_start_rcu (nlsk, skb, nlh, &c); }/* Only accept unspec with dump */
@@ -3054,7 +3081,7 @@ static int nf_tables_getset(struct net *net, struct sock *nlsk,if (IS_ERR (set))return PTR_ERR (set); - skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_KERNEL ); + skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_ATOMIC );if (skb2 ==NULL )return -ENOMEM ;
@@ -3795,7 +3822,7 @@ static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set, ext =nft_set_elem_ext (set, &elem); err = -ENOMEM ; - skb =nlmsg_new (NLMSG_GOODSIZE ,GFP_KERNEL ); + skb =nlmsg_new (NLMSG_GOODSIZE ,GFP_ATOMIC );if (skb ==NULL ) goto err1;
@@ -3817,6 +3844,7 @@ static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set,return err == -EAGAIN ? -ENOBUFS : err; } +/* called with rcu_read_lock held */ static int nf_tables_getsetelem(struct net *net, struct sock *nlsk, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const nla[],
@@ -3841,10 +3869,11 @@ static int nf_tables_getsetelem(struct net *net, struct sock *nlsk,struct netlink_dump_control c = { .dump = nf_tables_dump_set, .done = nf_tables_dump_set_done, + .module =THIS_MODULE , };struct nft_set_dump_ctx *dump_ctx; - dump_ctx =kmalloc (sizeof (*dump_ctx),GFP_KERNEL ); + dump_ctx =kmalloc (sizeof (*dump_ctx),GFP_ATOMIC );if (!dump_ctx)return -ENOMEM ;
@@ -3852,7 +3881,7 @@ static int nf_tables_getsetelem(struct net *net, struct sock *nlsk, dump_ctx->ctx = ctx; c.data = dump_ctx; -return netlink_dump_start (nlsk, skb, nlh, &c); +return nft_netlink_dump_start_rcu (nlsk, skb, nlh, &c); }if (!nla[NFTA_SET_ELEM_LIST_ELEMENTS ])
@@ -4475,7 +4504,7 @@ struct nft_object *nft_obj_lookup(const struct nft_table *table, {struct nft_object *obj; -list_for_each_entry (obj, &table->objects, list) { +list_for_each_entry_rcu (obj, &table->objects, list) {if (!nla_strcmp (nla, obj->name) && objtype == obj->ops->type->type &&nft_active_genmask (obj, genmask))
@@ -4805,12 +4834,12 @@ nft_obj_filter_alloc(const struct nlattr * const nla[]) {struct nft_obj_filter *filter; - filter =kzalloc (sizeof (*filter),GFP_KERNEL ); + filter =kzalloc (sizeof (*filter),GFP_ATOMIC );if (!filter)return ERR_PTR (-ENOMEM );if (nla[NFTA_OBJ_TABLE ]) { - filter->table =nla_strdup (nla[NFTA_OBJ_TABLE ],GFP_KERNEL ); + filter->table =nla_strdup (nla[NFTA_OBJ_TABLE ],GFP_ATOMIC );if (!filter->table) {kfree (filter);return ERR_PTR (-ENOMEM );
@@ -4822,6 +4851,7 @@ nft_obj_filter_alloc(const struct nlattr * const nla[])return filter; } +/* called with rcu_read_lock held */ static int nf_tables_getobj(struct net *net, struct sock *nlsk, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const nla[],
@@ -4841,6 +4871,7 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk,struct netlink_dump_control c = { .dump = nf_tables_dump_obj, .done = nf_tables_dump_obj_done, + .module =THIS_MODULE , }; if (nla[NFTA_OBJ_TABLE] ||
@@ -4853,7 +4884,7 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk, c.data = filter; } -return netlink_dump_start (nlsk, skb, nlh, &c); +return nft_netlink_dump_start_rcu (nlsk, skb, nlh, &c); } if (!nla[NFTA_OBJ_NAME] ||
@@ -4873,7 +4904,7 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk,return PTR_ERR (obj); } - skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_KERNEL ); + skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_ATOMIC );if (!skb2)return -ENOMEM ;
@@ -5018,7 +5049,7 @@ struct nft_flowtable *nft_flowtable_lookup(const struct nft_table *table, {struct nft_flowtable *flowtable; -list_for_each_entry (flowtable, &table->flowtables, list) { +list_for_each_entry_rcu (flowtable, &table->flowtables, list) {if (!nla_strcmp (nla, flowtable->name) &&nft_active_genmask (flowtable, genmask))return flowtable;
@@ -5479,13 +5510,13 @@ nft_flowtable_filter_alloc(const struct nlattr * const nla[]) {struct nft_flowtable_filter *filter; - filter =kzalloc (sizeof (*filter),GFP_KERNEL ); + filter =kzalloc (sizeof (*filter),GFP_ATOMIC );if (!filter)return ERR_PTR (-ENOMEM );if (nla[NFTA_FLOWTABLE_TABLE ]) { filter->table =nla_strdup (nla[NFTA_FLOWTABLE_TABLE ], -GFP_KERNEL ); +GFP_ATOMIC );if (!filter->table) {kfree (filter);return ERR_PTR (-ENOMEM );
@@ -5494,6 +5525,7 @@ nft_flowtable_filter_alloc(const struct nlattr * const nla[])return filter; } +/* called with rcu_read_lock held */ static int nf_tables_getflowtable(struct net *net, struct sock *nlsk, struct sk_buff *skb, const struct nlmsghdr *nlh,
@@ -5512,6 +5544,7 @@ static int nf_tables_getflowtable(struct net *net, struct sock *nlsk,struct netlink_dump_control c = { .dump = nf_tables_dump_flowtable, .done = nf_tables_dump_flowtable_done, + .module =THIS_MODULE , };if (nla[NFTA_FLOWTABLE_TABLE ]) {
@@ -5523,7 +5556,7 @@ static int nf_tables_getflowtable(struct net *net, struct sock *nlsk, c.data = filter; } -return netlink_dump_start (nlsk, skb, nlh, &c); +return nft_netlink_dump_start_rcu (nlsk, skb, nlh, &c); }if (!nla[NFTA_FLOWTABLE_NAME ])
@@ -5539,7 +5572,7 @@ static int nf_tables_getflowtable(struct net *net, struct sock *nlsk,if (IS_ERR (flowtable))return PTR_ERR (flowtable); - skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_KERNEL ); + skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_ATOMIC );if (!skb2)return -ENOMEM ;
@@ -5703,7 +5736,7 @@ static int nf_tables_getgen(struct net *net, struct sock *nlsk,struct sk_buff *skb2;int err; - skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_KERNEL ); + skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_ATOMIC );if (skb2 ==NULL )return -ENOMEM ;
@@ -5725,7 +5758,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { .policy = nft_table_policy, }, [NFT_MSG_GETTABLE] = { - .call = nf_tables_gettable, + .call_rcu = nf_tables_gettable, .attr_count = NFTA_TABLE_MAX, .policy = nft_table_policy, },
@@ -5740,7 +5773,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { .policy = nft_chain_policy, }, [NFT_MSG_GETCHAIN] = { - .call = nf_tables_getchain, + .call_rcu = nf_tables_getchain, .attr_count = NFTA_CHAIN_MAX, .policy = nft_chain_policy, },
@@ -5755,7 +5788,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { .policy = nft_rule_policy, }, [NFT_MSG_GETRULE] = { - .call = nf_tables_getrule, + .call_rcu = nf_tables_getrule, .attr_count = NFTA_RULE_MAX, .policy = nft_rule_policy, },
@@ -5770,7 +5803,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { .policy = nft_set_policy, }, [NFT_MSG_GETSET] = { - .call = nf_tables_getset, + .call_rcu = nf_tables_getset, .attr_count = NFTA_SET_MAX, .policy = nft_set_policy, },
@@ -5785,7 +5818,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { .policy = nft_set_elem_list_policy, }, [NFT_MSG_GETSETELEM] = { - .call = nf_tables_getsetelem, + .call_rcu = nf_tables_getsetelem, .attr_count = NFTA_SET_ELEM_LIST_MAX, .policy = nft_set_elem_list_policy, },
@@ -5795,7 +5828,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { .policy = nft_set_elem_list_policy, }, [NFT_MSG_GETGEN] = { - .call = nf_tables_getgen, + .call_rcu = nf_tables_getgen, }, [NFT_MSG_NEWOBJ] = { .call_batch = nf_tables_newobj,
@@ -5803,7 +5836,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { .policy = nft_obj_policy, }, [NFT_MSG_GETOBJ] = { - .call = nf_tables_getobj, + .call_rcu = nf_tables_getobj, .attr_count = NFTA_OBJ_MAX, .policy = nft_obj_policy, },
@@ -5813,7 +5846,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { .policy = nft_obj_policy, }, [NFT_MSG_GETOBJ_RESET] = { - .call = nf_tables_getobj, + .call_rcu = nf_tables_getobj, .attr_count = NFTA_OBJ_MAX, .policy = nft_obj_policy, },
@@ -5823,7 +5856,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { .policy = nft_flowtable_policy, }, [NFT_MSG_GETFLOWTABLE] = { - .call = nf_tables_getflowtable, + .call_rcu = nf_tables_getflowtable, .attr_count = NFTA_FLOWTABLE_MAX, .policy = nft_flowtable_policy, },
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 11/20 netfilter: nf_tables: remove unused variables
In reply to Pablo Neira AyusoFrom: Taehee Yoo <[email protected]>
The comment and trace_loginfo are not used anymore.
--- net/netfilter/nf_tables_core.c | 16 ---------------- 1 file changed, 16 deletions(-)
net/netfilter/nf_tables_core.c +0 -16
@@ -23,22 +23,6 @@#include <net/netfilter/nf_tables.h> #include <net/netfilter/nf_log.h> -static const char *const comments[__NFT_TRACETYPE_MAX] = { - [NFT_TRACETYPE_POLICY ] ="policy" , - [NFT_TRACETYPE_RETURN ] ="return" , - [NFT_TRACETYPE_RULE ] ="rule" , -}; - -static const struct nf_loginfo trace_loginfo = { - .type =NF_LOG_TYPE_LOG , - .u = { - .log = { - .level =LOGLEVEL_WARNING , - .logflags =NF_LOG_DEFAULT_MASK , - }, - }, -}; - static noinline void __nft_trace_packet(struct nft_traceinfo *info,const struct nft_chain *chain,enum nft_trace_types type)
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 12/20 netfilter: fix ptr_ret.cocci warnings
In reply to Pablo Neira AyusoFrom: kbuild test robot <[email protected]>
net/netfilter/nft_numgen.c:117:1-3: WARNING: PTR_ERR_OR_ZERO can be used net/netfilter/nft_hash.c:180:1-3: WARNING: PTR_ERR_OR_ZERO can be used net/netfilter/nft_hash.c:223:1-3: WARNING: PTR_ERR_OR_ZERO can be used
Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR
Generated by: scripts/coccinelle/api/ptr_ret.cocci
--- net/netfilter/nft_hash.c | 10 ++-------- net/netfilter/nft_numgen.c | 5 +---- 2 files changed, 3 insertions(+), 12 deletions(-)
net/netfilter/nft_hash.c +2 -8
@@ -177,10 +177,7 @@ static int nft_jhash_map_init(const struct nft_ctx *ctx, priv->map =nft_set_lookup_global (ctx->net, ctx->table, tb[NFTA_HASH_SET_NAME ], tb[NFTA_HASH_SET_ID ], genmask); -if (IS_ERR (priv->map)) -return PTR_ERR (priv->map); - -return 0 ; +return PTR_ERR_OR_ZERO (priv->map); } static int nft_symhash_init(const struct nft_ctx *ctx,
@@ -220,10 +217,7 @@ static int nft_symhash_map_init(const struct nft_ctx *ctx, priv->map =nft_set_lookup_global (ctx->net, ctx->table, tb[NFTA_HASH_SET_NAME ], tb[NFTA_HASH_SET_ID ], genmask); -if (IS_ERR (priv->map)) -return PTR_ERR (priv->map); - -return 0 ; +return PTR_ERR_OR_ZERO (priv->map); } static int nft_jhash_dump(struct sk_buff *skb,
net/netfilter/nft_numgen.c +1 -4
@@ -114,10 +114,7 @@ static int nft_ng_inc_map_init(const struct nft_ctx *ctx, tb[NFTA_NG_SET_NAME ], tb[NFTA_NG_SET_ID], genmask); -if (IS_ERR (priv->map)) -return PTR_ERR (priv->map); - -return 0 ; +return PTR_ERR_OR_ZERO (priv->map); } static int nft_ng_dump(struct sk_buff *skb, enum nft_registers dreg,
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 13/20 netfilter: nf_tables: add support for native socket matching
In reply to Pablo Neira AyusoFrom: Máté Eckl <[email protected]>
Now it can only match the transparent flag of an ip/ipv6 socket.
--- include/uapi/linux/netfilter/nf_tables.h | 25 ++++++ net/netfilter/Kconfig | 9 ++ net/netfilter/Makefile | 1 + net/netfilter/nft_socket.c | 143 +++++++++++++++++++++++++++++++ 4 files changed, 178 insertions(+) create mode 100644 net/netfilter/nft_socket.c
include/uapi/linux/netfilter/nf_tables.h +25 -0
@@ -905,6 +905,31 @@ enum nft_rt_attributes {#define NFTA_RT_MAX (__NFTA_RT_MAX - 1)/** +* enum nft_socket_attributes - nf_tables socket expression netlink attributes +* +* @NFTA_SOCKET_KEY: socket key to match +* @NFTA_SOCKET_DREG: destination register +*/ +enum nft_socket_attributes { +NFTA_SOCKET_UNSPEC , +NFTA_SOCKET_KEY , +NFTA_SOCKET_DREG , + __NFTA_SOCKET_MAX +}; +#define NFTA_SOCKET_MAX (__NFTA_SOCKET_MAX - 1) + +/* +* enum nft_socket_keys - nf_tables socket expression keys +* +* @NFT_SOCKET_TRANSPARENT: Value of the IP(V6)_TRANSPARENT socket option_ +*/ +enum nft_socket_keys { +NFT_SOCKET_TRANSPARENT , + __NFT_SOCKET_MAX +}; +#define NFT_SOCKET_MAX (__NFT_SOCKET_MAX - 1) + +/** * enum nft_ct_keys - nf_tables ct expression keys * * @NFT_CT_STATE: conntrack state (bitmask of enum ip_conntrack_info)
net/netfilter/Kconfig +9 -0
@@ -613,6 +613,15 @@ config NFT_FIB_INET The lookup will be delegated to the IPv4 or IPv6 FIB depending on the protocol of the packet. +config NFT_SOCKET + tristate "Netfilter nf_tables socket match support" + depends on IPV6 || IPV6=n + select NF_SOCKET_IPV4 + select NF_SOCKET_IPV6 if IPV6 + help + This option allows matching for the presence or absence of a + corresponding socket and its attributes. + if NF_TABLES_NETDEV config NF_DUP_NETDEV
net/netfilter/Makefile +1 -0
@@ -102,6 +102,7 @@ obj-$(CONFIG_NFT_FIB) += nft_fib.o obj-$(CONFIG_NFT_FIB_INET) += nft_fib_inet.o obj-$(CONFIG_NFT_FIB_NETDEV) += nft_fib_netdev.o obj-$(CONFIG_NF_OSF) += nf_osf.o +obj-$(CONFIG_NFT_SOCKET) += nft_socket.o # nf_tables netdev obj-$(CONFIG_NFT_DUP_NETDEV) += nft_dup_netdev.o
net/netfilter/nft_socket.c new file +143 -0
143 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 14/20 netfilter: nf_tables: Add audit support to log statement
In reply to Pablo Neira AyusoFrom: Phil Sutter <[email protected]>
This extends log statement to support the behaviour achieved with AUDIT target in iptables.
Audit logging is enabled via a pseudo log level 8. In this case any other settings like log prefix are ignored since audit log format is fixed.
--- include/uapi/linux/netfilter/nf_tables.h | 5 ++ net/netfilter/nft_log.c | 92 +++++++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 1 deletion(-)
include/uapi/linux/netfilter/nf_tables.h +5 -0
@@ -1081,6 +1081,11 @@ enum nft_log_attributes {#define NFTA_LOG_MAX (__NFTA_LOG_MAX - 1)/** +* LOGLEVEL_AUDIT - a pseudo log level enabling audit logging +*/ +#define LOGLEVEL_AUDIT 8 + +/** * enum nft_queue_attributes - nf_tables queue expression netlink attributes * * @NFTA_QUEUE_NUM: netlink queue to send messages to (NLA_U16)
net/netfilter/nft_log.c +91 -1
134 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 15/20 netfilter: nf_tables: fix chain dependency validation
In reply to Pablo Neira AyusoThe following ruleset:
add table ip filter
add chain ip filter input { type filter hook input priority 4; } add chain ip filter ap
add rule ip filter input jump ap
add rule ip filter ap masquerade
results in a panic, because the masquerade extension should be rejected from the filter chain. The existing validation is missing a chain dependency check when the rule is added to the non-base chain.
This patch fixes the problem by walking down the rules from the basechains, searching for either immediate or lookup expressions, then jumping to non-base chains and again walking down the rules to perform the expression validation, so we make sure the full ruleset graph is validated. This is done only once from the commit phase, in case of problem, we abort the transaction and perform fine grain validation for error reporting. This patch requires 003087911af2 ("netfilter:
nfnetlink: allow commit to fail") to achieve this behaviour.
This patch also adds a cleanup callback to nfnl batch interface to reset the validate state from the exit path.
As a result of this patch, nf_tables_check_loops() doesn't use ->validate to check for loops, instead it just checks for immediate expressions.
--- include/linux/netfilter/nfnetlink.h | 1 + include/net/netfilter/nf_tables.h | 2 + include/net/netfilter/nf_tables_core.h | 8 ++ include/net/netns/nftables.h | 1 + net/netfilter/nf_tables_api.c | 152 ++++++++++++++++++++++++++++----- net/netfilter/nfnetlink.c | 2 + net/netfilter/nft_immediate.c | 27 ++++-- net/netfilter/nft_lookup.c | 47 ++++++++++ 8 files changed, 208 insertions(+), 32 deletions(-)
include/linux/netfilter/nfnetlink.h +1 -0
@@ -31,6 +31,7 @@ struct nfnetlink_subsystem {const struct nfnl_callback *cb;/* callback for individual types */ int (*commit)(struct net *net,struct sk_buff *skb);int (*abort)(struct net *net,struct sk_buff *skb); +void (*cleanup)(struct net *net);bool (*valid_genid)(struct net *net,u32 genid); };
include/net/netfilter/nf_tables.h +2 -0
@@ -874,6 +874,8 @@ struct nft_chain {struct nft_rule **rules_next; }; +int nft_chain_validate (const struct nft_ctx *ctx,const struct nft_chain *chain); +enum nft_chain_types {NFT_CHAIN_T_DEFAULT =0 ,NFT_CHAIN_T_ROUTE ,
include/net/netfilter/nf_tables_core.h +8 -0
@@ -2,6 +2,8 @@#ifndef _NET_NF_TABLES_CORE_H#define _NET_NF_TABLES_CORE_H +#include <net/netfilter/nf_tables.h> +extern struct nft_expr_type nft_imm_type;extern struct nft_expr_type nft_cmp_type;extern struct nft_expr_type nft_lookup_type;
@@ -23,6 +25,12 @@ struct nft_cmp_fast_expr {u8 len; }; +struct nft_immediate_expr { +struct nft_data data; +enum nft_registers dreg:8 ; +u8 dlen; +}; +/* Calculate the mask for the nft_cmp_fast expression. On big endian the * mask needs to include the *upper* bytes when interpreting that data as * something smaller than the full u32, therefore a cpu_to_le32 is done.
include/net/netns/nftables.h +1 -0
@@ -9,6 +9,7 @@ struct netns_nftables {struct list_head commit_list;unsigned int base_seq;u8 gencursor; + u8 validate_state; };#endif
net/netfilter/nf_tables_api.c +129 -23
245 lines not on this page · raw message
net/netfilter/nfnetlink.c +2 -0
@@ -460,6 +460,8 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh, }else { ss->abort (net, oskb); } +if (ss->cleanup) + ss->cleanup (net);nfnl_err_deliver (&err_list, oskb);nfnl_unlock (subsys_id);
net/netfilter/nft_immediate.c +18 -9
@@ -17,12 +17,6 @@#include <net/netfilter/nf_tables_core.h> #include <net/netfilter/nf_tables.h> -struct nft_immediate_expr { -struct nft_data data; -enum nft_registers dreg:8 ; -u8 dlen; -}; -static void nft_immediate_eval (const struct nft_expr *expr,struct nft_regs *regs,const struct nft_pktinfo *pkt)
@@ -101,12 +95,27 @@ static int nft_immediate_dump(struct sk_buff *skb, const struct nft_expr *expr)static int nft_immediate_validate (const struct nft_ctx *ctx,const struct nft_expr *expr, -const struct nft_data **data) +const struct nft_data **d) {const struct nft_immediate_expr *priv =nft_expr_priv (expr); +const struct nft_data *data; +int err; -if (priv->dreg ==NFT_REG_VERDICT ) - *data = &priv->data; +if (priv->dreg !=NFT_REG_VERDICT ) +return 0 ; + + data = &priv->data; + +switch (data->verdict.code) { +case NFT_JUMP : +case NFT_GOTO : + err =nft_chain_validate (ctx, data->verdict.chain); +if (err <0 ) +return err; +break ; +default : +break ; + }return 0 ; }
net/netfilter/nft_lookup.c +47 -0
59 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 16/20 netfilter: nf_flow_table: attach dst to skbs
In reply to Pablo Neira AyusoFrom: "Jason A. Donenfeld" <[email protected]>
Some drivers, such as vxlan and wireguard, use the skb's dst in order to determine things like PMTU. They therefore loose functionality when flow offloading is enabled. So, we ensure the skb has it before xmit'ing it in the offloading path.
--- net/netfilter/nf_flow_table_ip.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
net/netfilter/nf_flow_table_ip.c +4 -2
@@ -220,7 +220,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,enum flow_offload_tuple_dir dir;struct flow_offload *flow;struct net_device *outdev; -const struct rtable *rt; +struct rtable *rt;unsigned int thoff;struct iphdr *iph;__be32 nexthop;
@@ -241,7 +241,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, dir = tuplehash->tuple.dir; flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); - rt = (const struct rtable *)flow->tuplehash[dir].tuple.dst_cache; + rt = (struct rtable *)flow->tuplehash[dir].tuple.dst_cache;if (unlikely (nf_flow_exceeds_mtu (skb, flow->tuplehash[dir].tuple.mtu)) && (ip_hdr (skb)->frag_off &htons (IP_DF )) !=0 )
@@ -264,6 +264,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, skb->dev = outdev; nexthop =rt_nexthop (rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); +skb_dst_set_noref (skb, &rt->dst);neigh_xmit (NEIGH_ARP_TABLE , outdev, &nexthop, skb);return NF_STOLEN ;
@@ -480,6 +481,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, skb->dev = outdev; nexthop =rt6_nexthop (rt, &flow->tuplehash[!dir].tuple.src_v6); +skb_dst_set_noref (skb, &rt->dst);neigh_xmit (NEIGH_ND_TABLE , outdev, nexthop, skb);return NF_STOLEN ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 17/20 netfilter: nfnetlink: Remove VLA usage
In reply to Pablo Neira AyusoFrom: Kees Cook <[email protected]>
In the quest to remove all stack VLA usage from the kernel[1], this allocates the maximum size expected for all possible attrs and adds sanity-checks at both registration and usage to make sure nothing gets out of sync.
[1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com
--- net/netfilter/nfnetlink.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-)
net/netfilter/nfnetlink.c +23 -2
@@ -38,6 +38,8 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER);rcu_dereference_protected (table[(id)].subsys, \ lockdep_nfnl_is_held((id))) +#define NFNL_MAX_ATTR_COUNT 32 + static struct { struct mutex mutex; const struct nfnetlink_subsystem __rcu *subsys;
@@ -77,6 +79,13 @@ EXPORT_SYMBOL_GPL(lockdep_nfnl_is_held);int nfnetlink_subsys_register (const struct nfnetlink_subsystem *n) { +u8 cb_id; + +/* Sanity-check attr_count size to avoid stack buffer overflow. */ +for (cb_id =0 ; cb_id < n->cb_count; cb_id++) +if (WARN_ON (n->cb[cb_id].attr_count >NFNL_MAX_ATTR_COUNT )) +return -EINVAL ; +nfnl_lock (n->subsys_id);if (table[n->subsys_id].subsys) {nfnl_unlock (n->subsys_id);
@@ -186,11 +195,17 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, {int min_len =nlmsg_total_size (sizeof (struct nfgenmsg ));u8 cb_id =NFNL_MSG_TYPE (nlh->nlmsg_type); -struct nlattr *cda[ss->cb[cb_id].attr_count +1 ]; +struct nlattr *cda[NFNL_MAX_ATTR_COUNT +1 ];struct nlattr *attr = (void *)nlh + min_len;int attrlen = nlh->nlmsg_len - min_len;__u8 subsys_id =NFNL_SUBSYS_ID (type); +/* Sanity-check NFNL_MAX_ATTR_COUNT */ +if (ss->cb[cb_id].attr_count >NFNL_MAX_ATTR_COUNT ) { +rcu_read_unlock (); +return -ENOMEM ; + } + err =nla_parse (cda, ss->cb[cb_id].attr_count, attr, attrlen, ss->cb[cb_id].policy, extack);if (err <0 ) {
@@ -387,10 +402,16 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh, {int min_len =nlmsg_total_size (sizeof (struct nfgenmsg ));u8 cb_id =NFNL_MSG_TYPE (nlh->nlmsg_type); -struct nlattr *cda[ss->cb[cb_id].attr_count +1 ]; +struct nlattr *cda[NFNL_MAX_ATTR_COUNT +1 ];struct nlattr *attr = (void *)nlh + min_len;int attrlen = nlh->nlmsg_len - min_len; +/* Sanity-check NFTA_MAX_ATTR */ +if (ss->cb[cb_id].attr_count >NFNL_MAX_ATTR_COUNT ) { + err = -ENOMEM ; + goto ack; + } + err =nla_parse (cda, ss->cb[cb_id].attr_count, attr, attrlen, ss->cb[cb_id].policy,NULL );if (err <0 )
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 18/20 netfilter: nft_fwd_netdev: allow to forward packets via neighbour layer
In reply to Pablo Neira AyusoThis allows us to forward packets from the netdev family via neighbour layer, so you don't need an explicit link-layer destination when using this expression from rules. The ttl/hop_limit field is decremented.
--- include/uapi/linux/netfilter/nf_tables.h | 4 + net/netfilter/nft_fwd_netdev.c | 146 ++++++++++++++++++++++++++++++- 2 files changed, 149 insertions(+), 1 deletion(-)
include/uapi/linux/netfilter/nf_tables.h +4 -0
@@ -1260,10 +1260,14 @@ enum nft_dup_attributes {* enum nft_fwd_attributes - nf_tables fwd expression netlink attributes * * @NFTA_FWD_SREG_DEV: source register of output interface (NLA_U32: nft_register) +* @NFTA_FWD_SREG_ADDR: source register of destination address (NLA_U32: nft_register) +* @NFTA_FWD_NFPROTO: layer 3 family of source register address (NLA_U32: enum nfproto) */ enum nft_fwd_attributes {NFTA_FWD_UNSPEC ,NFTA_FWD_SREG_DEV , +NFTA_FWD_SREG_ADDR , +NFTA_FWD_NFPROTO , __NFTA_FWD_MAX };#define NFTA_FWD_MAX (__NFTA_FWD_MAX - 1)
net/netfilter/nft_fwd_netdev.c +145 -1
176 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 19/20 ipvs: add full ipv6 support to nfct
In reply to Pablo Neira AyusoFrom: Julian Anastasov <[email protected]>
Prepare NFCT to support IPv6 for FTP:
- Do not restrict the expectation callback to PF_INET
- Split the debug messages, so that the 160-byte limitation in IP_VS_DBG_BUF is not exceeded when printing many IPv6 addresses. This means no more than 3 addresses in one message, i.e. 1 tuple with 2 addresses or 1 connection with 3 addresses.
--- net/netfilter/ipvs/ip_vs_nfct.c | 101 +++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 52 deletions(-)
net/netfilter/ipvs/ip_vs_nfct.c +49 -52
@@ -67,15 +67,20 @@#include <net/netfilter/nf_conntrack_zones.h> -#define FMT_TUPLE "%pI4:%u->%pI4:%u/%u" -#define ARG_TUPLE (T ) &(T)->src.u3.ip, ntohs((T)->src.u.all), \ - &(T)->dst.u3.ip, ntohs((T)->dst.u.all), \ +#define FMT_TUPLE "%s:%u->%s:%u/%u" +#define ARG_TUPLE (T ) IP_VS_DBG_ADDR((T)->src.l3num, &(T)->src.u3), \ + ntohs((T)->src.u.all), \ + IP_VS_DBG_ADDR((T)->src.l3num, &(T)->dst.u3), \ + ntohs((T)->dst.u.all), \ (T)->dst.protonum -#define FMT_CONN "%pI4:%u->%pI4:%u->%pI4:%u/%u:%u" -#define ARG_CONN (C ) &((C)->caddr.ip), ntohs((C)->cport), \ - &((C)->vaddr.ip), ntohs((C)->vport), \ - &((C)->daddr.ip), ntohs((C)->dport), \ +#define FMT_CONN "%s:%u->%s:%u->%s:%u/%u:%u" +#define ARG_CONN (C ) IP_VS_DBG_ADDR((C)->af, &((C)->caddr)), \ + ntohs((C)->cport), \ + IP_VS_DBG_ADDR((C)->af, &((C)->vaddr)), \ + ntohs((C)->vport), \ + IP_VS_DBG_ADDR((C)->daf, &((C)->daddr)), \ + ntohs((C)->dport), \ (C)->protocol, (C)->statevoid
@@ -127,13 +132,17 @@ ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin) new_tuple.dst.protonum != IPPROTO_ICMPV6) new_tuple.dst.u.tcp.port = cp->vport; } -IP_VS_DBG (7 ,"%s: Updating conntrack ct=%p, status=0x%lX, " -"ctinfo=%d, old reply=" FMT_TUPLE -", new reply=" FMT_TUPLE ", cp=" FMT_CONN "\n" , - __func__, ct, ct->status, ctinfo, -ARG_TUPLE (&ct->tuplehash[IP_CT_DIR_REPLY ].tuple), -ARG_TUPLE (&new_tuple),ARG_CONN (cp)); +IP_VS_DBG_BUF (7 ,"%s: Updating conntrack ct=%p, status=0x%lX, " +"ctinfo=%d, old reply=" FMT_TUPLE "\n" , + __func__, ct, ct->status, ctinfo, +ARG_TUPLE (&ct->tuplehash[IP_CT_DIR_REPLY ].tuple)); +IP_VS_DBG_BUF (7 ,"%s: Updating conntrack ct=%p, status=0x%lX, " +"ctinfo=%d, new reply=" FMT_TUPLE "\n" , + __func__, ct, ct->status, ctinfo, +ARG_TUPLE (&new_tuple));nf_conntrack_alter_reply (ct, &new_tuple); +IP_VS_DBG_BUF (7 ,"%s: Updated conntrack ct=%p for cp=" FMT_CONN "\n" , + __func__, ct,ARG_CONN (cp)); }int ip_vs_confirm_conntrack (struct sk_buff *skb)
@@ -152,9 +161,6 @@ static void ip_vs_nfct_expect_callback(struct nf_conn *ct,struct ip_vs_conn_param p;struct net *net =nf_ct_net (ct); -if (exp->tuple.src.l3num !=PF_INET ) -return ; -/* * We assume that no NF locks are held before this callback. * ip_vs_conn_out_get and ip_vs_conn_in_get should match their
@@ -171,19 +177,15 @@ static void ip_vs_nfct_expect_callback(struct nf_conn *ct, cp =ip_vs_conn_out_get (&p);if (cp) {/* Change reply CLIENT->RS to CLIENT->VS */ +IP_VS_DBG_BUF (7 ,"%s: for ct=%p, status=0x%lX found inout cp=" +FMT_CONN "\n" , + __func__, ct, ct->status,ARG_CONN (cp)); new_reply = ct->tuplehash[IP_CT_DIR_REPLY ].tuple; -IP_VS_DBG (7 ,"%s: ct=%p, status=0x%lX, tuples=" FMT_TUPLE ", " -FMT_TUPLE ", found inout cp=" FMT_CONN "\n" , - __func__, ct, ct->status, -ARG_TUPLE (orig),ARG_TUPLE (&new_reply), -ARG_CONN (cp)); +IP_VS_DBG_BUF (7 ,"%s: ct=%p before alter: reply tuple=" +FMT_TUPLE "\n" , + __func__, ct,ARG_TUPLE (&new_reply)); new_reply.dst.u3 = cp->vaddr; new_reply.dst.u.tcp.port = cp->vport; -IP_VS_DBG (7 ,"%s: ct=%p, new tuples=" FMT_TUPLE ", " FMT_TUPLE -", inout cp=" FMT_CONN "\n" , - __func__, ct, -ARG_TUPLE (orig),ARG_TUPLE (&new_reply), -ARG_CONN (cp)); goto alter; }
@@ -191,25 +193,21 @@ static void ip_vs_nfct_expect_callback(struct nf_conn *ct, cp =ip_vs_conn_in_get (&p);if (cp) {/* Change reply VS->CLIENT to RS->CLIENT */ +IP_VS_DBG_BUF (7 ,"%s: for ct=%p, status=0x%lX found outin cp=" +FMT_CONN "\n" , + __func__, ct, ct->status,ARG_CONN (cp)); new_reply = ct->tuplehash[IP_CT_DIR_REPLY ].tuple; -IP_VS_DBG (7 ,"%s: ct=%p, status=0x%lX, tuples=" FMT_TUPLE ", " -FMT_TUPLE ", found outin cp=" FMT_CONN "\n" , - __func__, ct, ct->status, -ARG_TUPLE (orig),ARG_TUPLE (&new_reply), -ARG_CONN (cp)); +IP_VS_DBG_BUF (7 ,"%s: ct=%p before alter: reply tuple=" +FMT_TUPLE "\n" , + __func__, ct,ARG_TUPLE (&new_reply)); new_reply.src.u3 = cp->daddr; new_reply.src.u.tcp.port = cp->dport; -IP_VS_DBG (7 ,"%s: ct=%p, new tuples=" FMT_TUPLE ", " -FMT_TUPLE ", outin cp=" FMT_CONN "\n" , - __func__, ct, -ARG_TUPLE (orig),ARG_TUPLE (&new_reply), -ARG_CONN (cp)); goto alter; } -IP_VS_DBG (7 ,"%s: ct=%p, status=0x%lX, tuple=" FMT_TUPLE -" - unknown expect\n" , - __func__, ct, ct->status,ARG_TUPLE (orig)); +IP_VS_DBG_BUF (7 ,"%s: ct=%p, status=0x%lX, tuple=" FMT_TUPLE +" - unknown expect\n" , + __func__, ct, ct->status,ARG_TUPLE (orig));return ; alter:
@@ -247,8 +245,8 @@ void ip_vs_nfct_expect_related(struct sk_buff *skb, struct nf_conn *ct, exp->expectfn = ip_vs_nfct_expect_callback; -IP_VS_DBG (7 ,"%s: ct=%p, expect tuple=" FMT_TUPLE "\n" , - __func__, ct,ARG_TUPLE (&exp->tuple)); +IP_VS_DBG_BUF (7 ,"%s: ct=%p, expect tuple=" FMT_TUPLE "\n" , + __func__, ct,ARG_TUPLE (&exp->tuple));nf_ct_expect_related (exp);nf_ct_expect_put (exp); }
@@ -274,26 +272,25 @@ void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp) tuple.dst.u3 = cp->vaddr; tuple.dst.u.all = cp->vport; -IP_VS_DBG (7 ,"%s: dropping conntrack with tuple=" FMT_TUPLE -" for conn " FMT_CONN "\n" , - __func__,ARG_TUPLE (&tuple),ARG_CONN (cp)); +IP_VS_DBG_BUF (7 ,"%s: dropping conntrack for conn " FMT_CONN "\n" , + __func__,ARG_CONN (cp)); h =nf_conntrack_find_get (cp->ipvs->net, &nf_ct_zone_dflt, &tuple);if (h) { ct =nf_ct_tuplehash_to_ctrack (h);if (nf_ct_kill (ct)) { -IP_VS_DBG (7 ,"%s: ct=%p, deleted conntrack for tuple=" -FMT_TUPLE "\n" , - __func__, ct,ARG_TUPLE (&tuple)); +IP_VS_DBG_BUF (7 ,"%s: ct=%p deleted for tuple=" +FMT_TUPLE "\n" , + __func__, ct,ARG_TUPLE (&tuple)); }else { -IP_VS_DBG (7 ,"%s: ct=%p, no conntrack timer for tuple=" -FMT_TUPLE "\n" , - __func__, ct,ARG_TUPLE (&tuple)); +IP_VS_DBG_BUF (7 ,"%s: ct=%p, no conntrack for tuple=" +FMT_TUPLE "\n" , + __func__, ct,ARG_TUPLE (&tuple)); }nf_ct_put (ct); }else { -IP_VS_DBG (7 ,"%s: no conntrack for tuple=" FMT_TUPLE "\n" , - __func__,ARG_TUPLE (&tuple)); +IP_VS_DBG_BUF (7 ,"%s: no conntrack for tuple=" FMT_TUPLE "\n" , + __func__,ARG_TUPLE (&tuple)); } }
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 20/20 ipvs: add ipv6 support to ftp
In reply to Pablo Neira AyusoFrom: Julian Anastasov <[email protected]>
Add support for FTP commands with extended format (RFC 2428):
- FTP EPRT: IPv4 and IPv6, active mode, similar to PORT
- FTP EPSV: IPv4 and IPv6, passive mode, similar to PASV. EPSV response usually contains only port but we allow real server to provide different address
We restrict control and data connection to be from same address family.
Allow the "(" and ")" to be optional in PASV response.
Also, add ipvsh argument to the pkt_in/pkt_out handlers to better access the payload after transport header.
--- include/net/ip_vs.h | 10 +- net/netfilter/ipvs/ip_vs_app.c | 24 +- net/netfilter/ipvs/ip_vs_ftp.c | 467 ++++++++++++++++++++++------------ net/netfilter/ipvs/ip_vs_proto_sctp.c | 4 +- net/netfilter/ipvs/ip_vs_proto_tcp.c | 4 +- net/netfilter/ipvs/ip_vs_proto_udp.c | 4 +- 6 files changed, 331 insertions(+), 182 deletions(-)
include/net/ip_vs.h +6 -4
@@ -763,14 +763,14 @@ struct ip_vs_app {* 2=Mangled but checksum was not updated */ int (*pkt_out)(struct ip_vs_app *,struct ip_vs_conn *, -struct sk_buff *,int *diff); +struct sk_buff *,int *diff,struct ip_vs_iphdr *ipvsh);/* input hook: Process packet in outin direction, diff set for TCP. * Return: 0=Error, 1=Payload Not Mangled/Mangled but checksum is ok, * 2=Mangled but checksum was not updated */ int (*pkt_in)(struct ip_vs_app *,struct ip_vs_conn *, -struct sk_buff *,int *diff); +struct sk_buff *,int *diff,struct ip_vs_iphdr *ipvsh);/* ip_vs_app initializer */ int (*init_conn)(struct ip_vs_app *,struct ip_vs_conn *);
@@ -1328,8 +1328,10 @@ int register_ip_vs_app_inc(struct netns_ipvs *ipvs, struct ip_vs_app *app, __u16int ip_vs_app_inc_get (struct ip_vs_app *inc);void ip_vs_app_inc_put (struct ip_vs_app *inc); -int ip_vs_app_pkt_out (struct ip_vs_conn *,struct sk_buff *skb); -int ip_vs_app_pkt_in (struct ip_vs_conn *,struct sk_buff *skb); +int ip_vs_app_pkt_out (struct ip_vs_conn *,struct sk_buff *skb, +struct ip_vs_iphdr *ipvsh); +int ip_vs_app_pkt_in (struct ip_vs_conn *,struct sk_buff *skb, +struct ip_vs_iphdr *ipvsh);int register_ip_vs_pe (struct ip_vs_pe *pe);int unregister_ip_vs_pe (struct ip_vs_pe *pe);
net/netfilter/ipvs/ip_vs_app.c +14 -10
@@ -355,7 +355,8 @@ static inline void vs_seq_update(struct ip_vs_conn *cp, struct ip_vs_seq *vseq, }static inline int app_tcp_pkt_out (struct ip_vs_conn *cp,struct sk_buff *skb, -struct ip_vs_app *app) +struct ip_vs_app *app, +struct ip_vs_iphdr *ipvsh) {int diff;const unsigned int tcp_offset =ip_hdrlen (skb);
@@ -386,7 +387,7 @@ static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb,if (app->pkt_out ==NULL )return 1 ; -if (!app->pkt_out (app, cp, skb, &diff)) +if (!app->pkt_out (app, cp, skb, &diff, ipvsh))return 0 ;/*
@@ -404,7 +405,8 @@ static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb,* called by ipvs packet handler, assumes previously checked cp!=NULL * returns false if it can't handle packet (oom) */ -int ip_vs_app_pkt_out (struct ip_vs_conn *cp,struct sk_buff *skb) +int ip_vs_app_pkt_out (struct ip_vs_conn *cp,struct sk_buff *skb, +struct ip_vs_iphdr *ipvsh) {struct ip_vs_app *app;
@@ -417,7 +419,7 @@ int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb)/* TCP is complicated */ if (cp->protocol ==IPPROTO_TCP ) -return app_tcp_pkt_out (cp, skb, app); +return app_tcp_pkt_out (cp, skb, app, ipvsh);/* * Call private output hook function
@@ -425,12 +427,13 @@ int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb)if (app->pkt_out ==NULL )return 1 ; -return app->pkt_out (app, cp, skb,NULL ); +return app->pkt_out (app, cp, skb,NULL , ipvsh); }static inline int app_tcp_pkt_in (struct ip_vs_conn *cp,struct sk_buff *skb, -struct ip_vs_app *app) +struct ip_vs_app *app, +struct ip_vs_iphdr *ipvsh) {int diff;const unsigned int tcp_offset =ip_hdrlen (skb);
@@ -461,7 +464,7 @@ static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb,if (app->pkt_in ==NULL )return 1 ; -if (!app->pkt_in (app, cp, skb, &diff)) +if (!app->pkt_in (app, cp, skb, &diff, ipvsh))return 0 ;/*
@@ -479,7 +482,8 @@ static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb,* called by ipvs packet handler, assumes previously checked cp!=NULL. * returns false if can't handle packet (oom). */ -int ip_vs_app_pkt_in (struct ip_vs_conn *cp,struct sk_buff *skb) +int ip_vs_app_pkt_in (struct ip_vs_conn *cp,struct sk_buff *skb, +struct ip_vs_iphdr *ipvsh) {struct ip_vs_app *app;
@@ -492,7 +496,7 @@ int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb)/* TCP is complicated */ if (cp->protocol ==IPPROTO_TCP ) -return app_tcp_pkt_in (cp, skb, app); +return app_tcp_pkt_in (cp, skb, app, ipvsh);/* * Call private input hook function
@@ -500,7 +504,7 @@ int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb)if (app->pkt_in ==NULL )return 1 ; -return app->pkt_in (app, cp, skb,NULL ); +return app->pkt_in (app, cp, skb,NULL , ipvsh); }
net/netfilter/ipvs/ip_vs_ftp.c +305 -162
618 lines not on this page · raw message
net/netfilter/ipvs/ip_vs_proto_sctp.c +2 -2
@@ -109,7 +109,7 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,return 0 ;/* Call application helper if needed */ - ret =ip_vs_app_pkt_out (cp, skb); + ret =ip_vs_app_pkt_out (cp, skb, iph);if (ret ==0 )return 0 ;/* ret=2: csum update is needed after payload mangling */
@@ -156,7 +156,7 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,return 0 ;/* Call application helper if needed */ - ret =ip_vs_app_pkt_in (cp, skb); + ret =ip_vs_app_pkt_in (cp, skb, iph);if (ret ==0 )return 0 ;/* ret=2: csum update is needed after payload mangling */
net/netfilter/ipvs/ip_vs_proto_tcp.c +2 -2
@@ -170,7 +170,7 @@ tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,return 0 ;/* Call application helper if needed */ -if (!(ret =ip_vs_app_pkt_out (cp, skb))) +if (!(ret =ip_vs_app_pkt_out (cp, skb, iph)))return 0 ;/* ret=2: csum update is needed after payload mangling */ if (ret ==1 )
@@ -251,7 +251,7 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,* Attempt ip_vs_app call. * It will fix ip_vs_conn and iph ack_seq stuff */ -if (!(ret =ip_vs_app_pkt_in (cp, skb))) +if (!(ret =ip_vs_app_pkt_in (cp, skb, iph)))return 0 ;/* ret=2: csum update is needed after payload mangling */ if (ret ==1 )
net/netfilter/ipvs/ip_vs_proto_udp.c +2 -2
@@ -162,7 +162,7 @@ udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,/* * Call application helper if needed */ -if (!(ret =ip_vs_app_pkt_out (cp, skb))) +if (!(ret =ip_vs_app_pkt_out (cp, skb, iph)))return 0 ;/* ret=2: csum update is needed after payload mangling */ if (ret ==1 )
@@ -246,7 +246,7 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,* Attempt ip_vs_app call. * It will fix ip_vs_conn */ -if (!(ret =ip_vs_app_pkt_in (cp, skb))) +if (!(ret =ip_vs_app_pkt_in (cp, skb, iph)))return 0 ;/* ret=2: csum update is needed after payload mangling */ if (ret ==1 )
Signature · 1 line
2.11.0
David Miller
maintainerFrom: Pablo Neira Ayuso <[email protected]>
Date: Sat, 2 Jun 2018 02:22:39 +0200
Quoted 2 lines
The following patchset contains Netfilter/IPVS updates for your net-next tree, the most relevant things in this batch are:
...
Quoted 3 lines
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git
Pulled, thanks.