From 01cd267bff52619a53fa05c930ea5ed53493d21a Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 8 May 2018 10:05:38 +0200 Subject: netfilter: fix fallout from xt/nf osf separation Stephen Rothwell says: today's linux-next build (x86_64 allmodconfig) produced this warning: ./usr/include/linux/netfilter/nf_osf.h:25: found __[us]{8,16,32,64} type without #include Fix that up and also move kernel-private struct out of uapi (it was not exposed in any released kernel version). tested via allmodconfig build + make headers_check. Reported-by: Stephen Rothwell Fixes: bfb15f2a95cb ("netfilter: extract Passive OS fingerprint infrastructure from xt_osf") Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/nf_osf.h | 6 ++++++ include/uapi/linux/netfilter/nf_osf.h | 8 ++------ 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/linux/netfilter/nf_osf.h b/include/linux/netfilter/nf_osf.h index a2b39602e87d..0e114c492fb8 100644 --- a/include/linux/netfilter/nf_osf.h +++ b/include/linux/netfilter/nf_osf.h @@ -21,6 +21,12 @@ enum osf_fmatch_states { FMATCH_OPT_WRONG, }; +struct nf_osf_finger { + struct rcu_head rcu_head; + struct list_head finger_entry; + struct nf_osf_user_finger finger; +}; + bool nf_osf_match(const struct sk_buff *skb, u_int8_t family, int hooknum, struct net_device *in, struct net_device *out, const struct nf_osf_info *info, struct net *net, diff --git a/include/uapi/linux/netfilter/nf_osf.h b/include/uapi/linux/netfilter/nf_osf.h index 45376eae31ef..8f2f2f403183 100644 --- a/include/uapi/linux/netfilter/nf_osf.h +++ b/include/uapi/linux/netfilter/nf_osf.h @@ -1,6 +1,8 @@ #ifndef _NF_OSF_H #define _NF_OSF_H +#include + #define MAXGENRELEN 32 #define NF_OSF_GENRE (1 << 0) @@ -57,12 +59,6 @@ struct nf_osf_user_finger { struct nf_osf_opt opt[MAX_IPOPTLEN]; }; -struct nf_osf_finger { - struct rcu_head rcu_head; - struct list_head finger_entry; - struct nf_osf_user_finger finger; -}; - struct nf_osf_nlmsg { struct nf_osf_user_finger f; struct iphdr ip; -- cgit v1.2.3 From b9ccc07e3f31ad8073697982bac014fbceef7ecb Mon Sep 17 00:00:00 2001 From: Laura Garcia Liebana Date: Fri, 11 May 2018 00:14:48 +0200 Subject: netfilter: nft_hash: add map lookups for hashing operations This patch creates new attributes to accept a map as argument and then perform the lookup with the generated hash accordingly. Both current hash functions are supported: Jenkins and Symmetric Hash. Signed-off-by: Laura Garcia Liebana Signed-off-by: Pablo Neira Ayuso --- include/uapi/linux/netfilter/nf_tables.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index ce031cf72288..9c71f024f9cc 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -856,6 +856,8 @@ enum nft_hash_types { * @NFTA_HASH_SEED: seed value (NLA_U32) * @NFTA_HASH_OFFSET: add this offset value to hash result (NLA_U32) * @NFTA_HASH_TYPE: hash operation (NLA_U32: nft_hash_types) + * @NFTA_HASH_SET_NAME: name of the map to lookup (NLA_STRING) + * @NFTA_HASH_SET_ID: id of the map (NLA_U32) */ enum nft_hash_attributes { NFTA_HASH_UNSPEC, @@ -866,6 +868,8 @@ enum nft_hash_attributes { NFTA_HASH_SEED, NFTA_HASH_OFFSET, NFTA_HASH_TYPE, + NFTA_HASH_SET_NAME, + NFTA_HASH_SET_ID, __NFTA_HASH_MAX, }; #define NFTA_HASH_MAX (__NFTA_HASH_MAX - 1) -- cgit v1.2.3 From 1f55236bd8dde69d1860a30c50793fb28d8405ae Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 14 May 2018 23:46:53 +0200 Subject: netfilter: nf_nat: move common nat code to nat core Copy-pasted, both l3 helpers almost use same code here. Split out the common part into an 'inet' helper. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_nat_core.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include') diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h index 235bd0e9a5aa..0d84dd29108d 100644 --- a/include/net/netfilter/nf_nat_core.h +++ b/include/net/netfilter/nf_nat_core.h @@ -11,6 +11,13 @@ unsigned int nf_nat_packet(struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned int hooknum, struct sk_buff *skb); +unsigned int +nf_nat_inet_fn(void *priv, struct sk_buff *skb, + const struct nf_hook_state *state, + unsigned int (*do_chain)(void *priv, + struct sk_buff *skb, + const struct nf_hook_state *state)); + int nf_xfrm_me_harder(struct net *net, struct sk_buff *skb, unsigned int family); static inline int nf_nat_initialized(struct nf_conn *ct, -- cgit v1.2.3 From 4e25ceb80b585891c5e2a6edfa481bc4709e9544 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 14 May 2018 23:46:55 +0200 Subject: netfilter: nf_tables: allow chain type to override hook register Will be used in followup patch when nat types no longer use nf_register_net_hook() but will instead register with the nat core. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_tables.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 435c9e3b9181..a94fd0c730d6 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -880,8 +880,8 @@ enum nft_chain_types { * @owner: module owner * @hook_mask: mask of valid hooks * @hooks: array of hook functions - * @init: chain initialization function - * @free: chain release function + * @ops_register: base chain register function + * @ops_unregister: base chain unregister function */ struct nft_chain_type { const char *name; @@ -890,8 +890,8 @@ struct nft_chain_type { struct module *owner; unsigned int hook_mask; nf_hookfn *hooks[NF_MAX_HOOKS]; - int (*init)(struct nft_ctx *ctx); - void (*free)(struct nft_ctx *ctx); + int (*ops_register)(struct net *net, const struct nf_hook_ops *ops); + void (*ops_unregister)(struct net *net, const struct nf_hook_ops *ops); }; int nft_chain_validate_dependency(const struct nft_chain *chain, -- cgit v1.2.3 From 1cd472bf036ca038e783ef5f058f54e45b7e8180 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 14 May 2018 23:46:57 +0200 Subject: netfilter: nf_nat: add nat hook register functions to nf_nat This adds the infrastructure to register nat hooks with the nat core instead of the netfilter core. nat hooks are used to configure nat bindings. Such hooks are registered from ip(6)table_nat or by the nftables core when a nat chain is added. After next patch, nat hooks will be registered with nf_nat instead of netfilter core. This allows to use many nat lookup functions at the same time while doing the real packet rewrite (nat transformation) in one place. This change doesn't convert the intended users yet to ease review. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_nat.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index da3d601cadee..a17eb2f8d40e 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h @@ -75,4 +75,8 @@ static inline bool nf_nat_oif_changed(unsigned int hooknum, #endif } +int nf_nat_register_fn(struct net *net, const struct nf_hook_ops *ops, + const struct nf_hook_ops *nat_ops, unsigned int ops_count); +void nf_nat_unregister_fn(struct net *net, const struct nf_hook_ops *ops, + unsigned int ops_count); #endif -- cgit v1.2.3 From 9971a514ed2697e542f3984a6162eac54bb1da98 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 14 May 2018 23:46:58 +0200 Subject: netfilter: nf_nat: add nat type hooks to nat core Currently the packet rewrite and instantiation of nat NULL bindings happens from the protocol specific nat backend. Invocation occurs either via ip(6)table_nat or the nf_tables nat chain type. Invocation looks like this (simplified): NF_HOOK() | `---iptable_nat | `---> nf_nat_l3proto_ipv4 -> nf_nat_packet | new packet? pass skb though iptables nat chain | `---> iptable_nat: ipt_do_table In nft case, this looks the same (nft_chain_nat_ipv4 instead of iptable_nat). This is a problem for two reasons: 1. Can't use iptables nat and nf_tables nat at the same time, as the first user adds a nat binding (nf_nat_l3proto_ipv4 adds a NULL binding if do_table() did not find a matching nat rule so we can detect post-nat tuple collisions). 2. If you use e.g. nft_masq, snat, redir, etc. uses must also register an empty base chain so that the nat core gets called fro NF_HOOK() to do the reverse translation, which is neither obvious nor user friendly. After this change, the base hook gets registered not from iptable_nat or nftables nat hooks, but from the l3 nat core. iptables/nft nat base hooks get registered with the nat core instead: NF_HOOK() | `---> nf_nat_l3proto_ipv4 -> nf_nat_packet | new packet? pass skb through iptables/nftables nat chains | +-> iptables_nat: ipt_do_table +-> nft nat chain x `-> nft nat chain y The nat core deals with null bindings and reverse translation. When no mapping exists, it calls the registered nat lookup hooks until one creates a new mapping. If both iptables and nftables nat hooks exist, the first matching one is used (i.e., higher priority wins). Also, nft users do not need to create empty nat hooks anymore, nat core always registers the base hooks that take care of reverse/reply translation. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_nat_core.h | 5 +--- include/net/netfilter/nf_nat_l3proto.h | 52 +++------------------------------- 2 files changed, 5 insertions(+), 52 deletions(-) (limited to 'include') diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h index 0d84dd29108d..c78e9be14b3d 100644 --- a/include/net/netfilter/nf_nat_core.h +++ b/include/net/netfilter/nf_nat_core.h @@ -13,10 +13,7 @@ unsigned int nf_nat_packet(struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned int nf_nat_inet_fn(void *priv, struct sk_buff *skb, - const struct nf_hook_state *state, - unsigned int (*do_chain)(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state)); + const struct nf_hook_state *state); int nf_xfrm_me_harder(struct net *net, struct sk_buff *skb, unsigned int family); diff --git a/include/net/netfilter/nf_nat_l3proto.h b/include/net/netfilter/nf_nat_l3proto.h index 8bad2560576f..d300b8f03972 100644 --- a/include/net/netfilter/nf_nat_l3proto.h +++ b/include/net/netfilter/nf_nat_l3proto.h @@ -44,58 +44,14 @@ int nf_nat_icmp_reply_translation(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned int hooknum); -unsigned int nf_nat_ipv4_in(void *priv, struct sk_buff *skb, - const struct nf_hook_state *state, - unsigned int (*do_chain)(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state)); - -unsigned int nf_nat_ipv4_out(void *priv, struct sk_buff *skb, - const struct nf_hook_state *state, - unsigned int (*do_chain)(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state)); - -unsigned int nf_nat_ipv4_local_fn(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state, - unsigned int (*do_chain)(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state)); - -unsigned int nf_nat_ipv4_fn(void *priv, struct sk_buff *skb, - const struct nf_hook_state *state, - unsigned int (*do_chain)(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state)); - int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned int hooknum, unsigned int hdrlen); -unsigned int nf_nat_ipv6_in(void *priv, struct sk_buff *skb, - const struct nf_hook_state *state, - unsigned int (*do_chain)(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state)); - -unsigned int nf_nat_ipv6_out(void *priv, struct sk_buff *skb, - const struct nf_hook_state *state, - unsigned int (*do_chain)(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state)); - -unsigned int nf_nat_ipv6_local_fn(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state, - unsigned int (*do_chain)(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state)); +int nf_nat_l3proto_ipv4_register_fn(struct net *net, const struct nf_hook_ops *ops); +void nf_nat_l3proto_ipv4_unregister_fn(struct net *net, const struct nf_hook_ops *ops); -unsigned int nf_nat_ipv6_fn(void *priv, struct sk_buff *skb, - const struct nf_hook_state *state, - unsigned int (*do_chain)(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state)); +int nf_nat_l3proto_ipv6_register_fn(struct net *net, const struct nf_hook_ops *ops); +void nf_nat_l3proto_ipv6_unregister_fn(struct net *net, const struct nf_hook_ops *ops); #endif /* _NF_NAT_L3PROTO_H */ -- cgit v1.2.3 From a37061a678cab6d164f2989dd6f3b65f730289c7 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 14 May 2018 23:46:59 +0200 Subject: netfilter: lift one-nat-hook-only restriction This reverts commit f92b40a8b2645 ("netfilter: core: only allow one nat hook per hook point"), this limitation is no longer needed. The nat core now invokes these functions and makes sure that hook evaluation stops after a mapping is created and a null binding is created otherwise. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 85a1a0b32c66..72f5871b9a0a 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -67,7 +67,6 @@ struct nf_hook_ops { struct net_device *dev; void *priv; u_int8_t pf; - bool nat_hook; unsigned int hooknum; /* Hooks are ordered in ascending priority. */ int priority; -- cgit v1.2.3 From 1f4b24397d3e164dde7026b91056e67304724fb6 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 23 May 2018 09:17:12 +0200 Subject: netfilter: add struct nf_ct_hook and use it Move the nf_ct_destroy indirection to the struct nf_ct_hook. Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 72f5871b9a0a..75ded6f6eebe 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -373,13 +373,18 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) extern void (*ip_ct_attach)(struct sk_buff *, const struct sk_buff *) __rcu; void nf_ct_attach(struct sk_buff *, const struct sk_buff *); -extern void (*nf_ct_destroy)(struct nf_conntrack *) __rcu; #else static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {} #endif struct nf_conn; enum ip_conntrack_info; + +struct nf_ct_hook { + void (*destroy)(struct nf_conntrack *); +}; +extern struct nf_ct_hook __rcu *nf_ct_hook; + struct nlattr; struct nfnl_ct_hook { -- cgit v1.2.3 From 2c205dd3981f79cef097207ba9c61c2260812f39 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 23 May 2018 09:17:19 +0200 Subject: netfilter: add struct nf_nat_hook and use it Move decode_session() and parse_nat_setup_hook() indirections to struct nf_nat_hook structure. Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter.h | 21 ++++++++++++++++----- include/net/netfilter/nf_nat_core.h | 7 ------- 2 files changed, 16 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 75ded6f6eebe..e8d09dc028f6 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -320,18 +320,29 @@ int nf_route(struct net *net, struct dst_entry **dst, struct flowi *fl, int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry); #include -extern void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *); + +struct nf_conn; +enum nf_nat_manip_type; +struct nlattr; + +struct nf_nat_hook { + int (*parse_nat_setup)(struct nf_conn *ct, enum nf_nat_manip_type manip, + const struct nlattr *attr); + void (*decode_session)(struct sk_buff *skb, struct flowi *fl); +}; + +extern struct nf_nat_hook __rcu *nf_nat_hook; static inline void nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) { #ifdef CONFIG_NF_NAT_NEEDED - void (*decodefn)(struct sk_buff *, struct flowi *); + struct nf_nat_hook *nat_hook; rcu_read_lock(); - decodefn = rcu_dereference(nf_nat_decode_session_hook); - if (decodefn) - decodefn(skb, fl); + nat_hook = rcu_dereference(nf_nat_hook); + if (nat_hook->decode_session) + nat_hook->decode_session(skb, fl); rcu_read_unlock(); #endif } diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h index c78e9be14b3d..dc7cd0440229 100644 --- a/include/net/netfilter/nf_nat_core.h +++ b/include/net/netfilter/nf_nat_core.h @@ -26,11 +26,4 @@ static inline int nf_nat_initialized(struct nf_conn *ct, return ct->status & IPS_DST_NAT_DONE; } -struct nlattr; - -extern int -(*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct, - enum nf_nat_manip_type manip, - const struct nlattr *attr); - #endif /* _NF_NAT_CORE_H */ -- cgit v1.2.3 From 368982cd7d1bd41cd39049c794990aca3770db44 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 23 May 2018 09:17:24 +0200 Subject: netfilter: nfnetlink_queue: resolve clash for unconfirmed conntracks In nfqueue, two consecutive skbuffs may race to create the conntrack entry. Hence, the one that loses the race gets dropped due to clash in the insertion into the hashes from the nf_conntrack_confirm() path. This patch adds a new nf_conntrack_update() function which searches for possible clashes and resolve them. NAT mangling for the packet losing race is corrected by using the conntrack information that won race. In order to avoid direct module dependencies with conntrack and NAT, the nf_ct_hook and nf_nat_hook structures are used for this purpose. Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index e8d09dc028f6..04551af2ff23 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -324,11 +324,15 @@ int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry); struct nf_conn; enum nf_nat_manip_type; struct nlattr; +enum ip_conntrack_dir; struct nf_nat_hook { int (*parse_nat_setup)(struct nf_conn *ct, enum nf_nat_manip_type manip, const struct nlattr *attr); void (*decode_session)(struct sk_buff *skb, struct flowi *fl); + unsigned int (*manip_pkt)(struct sk_buff *skb, struct nf_conn *ct, + enum nf_nat_manip_type mtype, + enum ip_conntrack_dir dir); }; extern struct nf_nat_hook __rcu *nf_nat_hook; @@ -392,6 +396,7 @@ struct nf_conn; enum ip_conntrack_info; struct nf_ct_hook { + int (*update)(struct net *net, struct sk_buff *skb); void (*destroy)(struct nf_conntrack *); }; extern struct nf_ct_hook __rcu *nf_ct_hook; -- cgit v1.2.3 From 0c6bca747111dee19aa48c8f73d77fc85fcb8dd0 Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Tue, 15 May 2018 21:23:31 +0900 Subject: netfilter: nf_tables: remove nft_af_info. The struct nft_af_info was removed. Signed-off-by: Taehee Yoo Signed-off-by: Pablo Neira Ayuso --- include/net/netns/nftables.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/net/netns/nftables.h b/include/net/netns/nftables.h index 48134353411d..29c3851b486a 100644 --- a/include/net/netns/nftables.h +++ b/include/net/netns/nftables.h @@ -4,8 +4,6 @@ #include -struct nft_af_info; - struct netns_nftables { struct list_head tables; struct list_head commit_list; -- cgit v1.2.3