Netfilter/IPVS fixes for net
Subsystems (4)
Pablo Neira Ayuso
maintainercover Netfilter/IPVS fixes for net
Hi David,
The following patchset contains Netfilter updates for your net tree, they are:
1) Fix missing initialization of the range structure (allocated in the stack) in nft_masq_{ipv4, ipv6}_eval, from Daniel Borkmann.
2) Make sure the data we receive from userspace contains the req_version structure, otherwise return an error incomplete on truncated input. From Dan Carpenter.
3) Fix handling og skb->sk which may cause incorrect handling of connections from a local process. Via Simon Horman, patch from Calvin Owens.
4) Fix wrong netns in nft_compat when setting target and match params structure.
5) Relax chain type validation in nft_compat that was recently included, this broke the matches that need to be run from the route chain type. Now iptables-test.py automated regression tests report success again and we avoid the only possible problematic case, which is the use of nat targets out of nat chain type.
6) Use match->table to validate the tablename, instead of the match->name. Again patch for nft_compat.
7) Restore the synchronous release of objects from the commit and abort path in nf_tables. This is causing two major problems: splats when using nft_compat, given that matches and targets may sleep and call_rcu is invoked from softirq context. Moreover Patrick reported possible event notification reordering when rules refer to anonymous sets.
8) Fix race condition in between packets that are being confirmed by conntrack and the ctnetlink flush operation. This happens since the removal of the central spinlock. Thanks to Jesper D. Brouer to looking into this.
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git
Thanks!
----------------------------------------------------------------
The following changes since commit d52fdbb735c36a209f36a628d40ca9185b349ba7:
smc91x: retrieve IRQ and trigger flags in a modern way (2014-11-01 17:04:20 -0400)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git master
for you to fetch changes up to 5195c14c8b27cc0b18220ddbf0e5ad3328a04187:
netfilter: conntrack: fix race in __nf_conntrack_confirm against get_next_corpse (2014-11-14 17:43:05 +0100)
----------------------------------------------------------------
Calvin Owens (1):
ipvs: Keep skb->sk when allocating headroom on tunnel xmit
Dan Carpenter (1):
netfilter: ipset: small potential read beyond the end of buffer
Daniel Borkmann (1):
netfilter: nft_masq: fix uninitialized range in nft_masq_{ipv4, ipv6}_eval
Pablo Neira Ayuso (4):
netfilter: nft_compat: use current net namespace
netfilter: nft_compat: relax chain type validation
netfilter: nft_compat: use the match->table to validate dependencies
netfilter: nf_tables: restore synchronous object release from commit/abort
bill bonaparte (1):
netfilter: conntrack: fix race in __nf_conntrack_confirm against get_next_corpse
include/net/netfilter/nf_tables.h | 2 -- net/ipv4/netfilter/nft_masq_ipv4.c | 1 + net/ipv6/netfilter/nft_masq_ipv6.c | 1 + net/netfilter/ipset/ip_set_core.c | 6 ++++++ net/netfilter/ipvs/ip_vs_xmit.c | 2 ++ net/netfilter/nf_conntrack_core.c | 14 +++++++------ net/netfilter/nf_tables_api.c | 24 ++++++++-------------- net/netfilter/nft_compat.c | 40 ++++++------------------------------ 8 files changed, 32 insertions(+), 58 deletions(-)
Pablo Neira Ayuso
maintainercover Netfilter/IPVS fixes for net
Hi David,
The following patchset contains Netfilter updates for your net tree, they are:
1) Fix missing initialization of the range structure (allocated in the stack) in nft_masq_{ipv4, ipv6}_eval, from Daniel Borkmann.
2) Make sure the data we receive from userspace contains the req_version structure, otherwise return an error incomplete on truncated input. From Dan Carpenter.
3) Fix handling og skb->sk which may cause incorrect handling of connections from a local process. Via Simon Horman, patch from Calvin Owens.
4) Fix wrong netns in nft_compat when setting target and match params structure.
5) Relax chain type validation in nft_compat that was recently included, this broke the matches that need to be run from the route chain type. Now iptables-test.py automated regression tests report success again and we avoid the only possible problematic case, which is the use of nat targets out of nat chain type.
6) Use match->table to validate the tablename, instead of the match->name. Again patch for nft_compat.
7) Restore the synchronous release of objects from the commit and abort path in nf_tables. This is causing two major problems: splats when using nft_compat, given that matches and targets may sleep and call_rcu is invoked from softirq context. Moreover Patrick reported possible event notification reordering when rules refer to anonymous sets.
8) Fix race condition in between packets that are being confirmed by conntrack and the ctnetlink flush operation. This happens since the removal of the central spinlock. Thanks to Jesper D. Brouer to looking into this.
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git
Thanks!
----------------------------------------------------------------
The following changes since commit d52fdbb735c36a209f36a628d40ca9185b349ba7:
smc91x: retrieve IRQ and trigger flags in a modern way (2014-11-01 17:04:20 -0400)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git master
for you to fetch changes up to 5195c14c8b27cc0b18220ddbf0e5ad3328a04187:
netfilter: conntrack: fix race in __nf_conntrack_confirm against get_next_corpse (2014-11-14 17:43:05 +0100)
----------------------------------------------------------------
Calvin Owens (1):
ipvs: Keep skb->sk when allocating headroom on tunnel xmit
Dan Carpenter (1):
netfilter: ipset: small potential read beyond the end of buffer
Daniel Borkmann (1):
netfilter: nft_masq: fix uninitialized range in nft_masq_{ipv4, ipv6}_eval
Pablo Neira Ayuso (4):
netfilter: nft_compat: use current net namespace
netfilter: nft_compat: relax chain type validation
netfilter: nft_compat: use the match->table to validate dependencies
netfilter: nf_tables: restore synchronous object release from commit/abort
bill bonaparte (1):
netfilter: conntrack: fix race in __nf_conntrack_confirm against get_next_corpse
include/net/netfilter/nf_tables.h | 2 -- net/ipv4/netfilter/nft_masq_ipv4.c | 1 + net/ipv6/netfilter/nft_masq_ipv6.c | 1 + net/netfilter/ipset/ip_set_core.c | 6 ++++++ net/netfilter/ipvs/ip_vs_xmit.c | 2 ++ net/netfilter/nf_conntrack_core.c | 14 +++++++------ net/netfilter/nf_tables_api.c | 24 ++++++++-------------- net/netfilter/nft_compat.c | 40 ++++++------------------------------ 8 files changed, 32 insertions(+), 58 deletions(-)
Pablo Neira Ayuso
maintainerPATCH 1/8 netfilter: nft_masq: fix uninitialized range in nft_masq_{ipv4, ipv6}_eval
In reply to Pablo Neira AyusoFrom: Daniel Borkmann <[email protected]>
When transferring from the original range in nf_nat_masquerade_{ipv4,ipv6}() we copy over values from stack in from min_proto/max_proto due to uninitialized range variable in both, nft_masq_{ipv4,ipv6}_eval. As we only initialize flags at this time from nft_masq struct, just zero out the rest.
--- net/ipv4/netfilter/nft_masq_ipv4.c | 1 + net/ipv6/netfilter/nft_masq_ipv6.c | 1 + 2 files changed, 2 insertions(+)
net/ipv4/netfilter/nft_masq_ipv4.c +1 -0
@@ -24,6 +24,7 @@ static void nft_masq_ipv4_eval(const struct nft_expr *expr,struct nf_nat_range range;unsigned int verdict; +memset (&range,0 ,sizeof (range)); range.flags = priv->flags; verdict = nf_nat_masquerade_ipv4(pkt->skb, pkt->ops->hooknum,
net/ipv6/netfilter/nft_masq_ipv6.c +1 -0
@@ -25,6 +25,7 @@ static void nft_masq_ipv6_eval(const struct nft_expr *expr,struct nf_nat_range range;unsigned int verdict; +memset (&range,0 ,sizeof (range)); range.flags = priv->flags; verdict =nf_nat_masquerade_ipv6 (pkt->skb, &range, pkt->out);
Signature · 1 line
1.7.10.4
Pablo Neira Ayuso
maintainerPATCH 2/8 netfilter: ipset: small potential read beyond the end of buffer
In reply to Pablo Neira AyusoFrom: Dan Carpenter <[email protected]>
We could be reading 8 bytes into a 4 byte buffer here. It seems harmless but adding a check is the right thing to do and it silences a static checker warning.
--- net/netfilter/ipset/ip_set_core.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/netfilter/ipset/ip_set_core.c +6 -0
@@ -1863,6 +1863,12 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)if (*op <IP_SET_OP_VERSION ) {/* Check the version at the beginning of operations */ struct ip_set_req_version *req_version = data; + +if (*len <sizeof (struct ip_set_req_version )) { + ret = -EINVAL ; + goto done; + } +if (req_version->version !=IPSET_PROTOCOL ) { ret = -EPROTO ; goto done;
Signature · 1 line
1.7.10.4
Pablo Neira Ayuso
maintainerPATCH 3/8 ipvs: Keep skb->sk when allocating headroom on tunnel xmit
In reply to Pablo Neira AyusoFrom: Calvin Owens <[email protected]>
ip_vs_prepare_tunneled_skb() ignores ->sk when allocating a new skb, either unconditionally setting ->sk to NULL or allowing the uninitialized ->sk from a newly allocated skb to leak through to the caller.
This patch properly copies ->sk and increments its reference count.
--- net/netfilter/ipvs/ip_vs_xmit.c | 2 ++ 1 file changed, 2 insertions(+)
net/netfilter/ipvs/ip_vs_xmit.c +2 -0
@@ -846,6 +846,8 @@ ip_vs_prepare_tunneled_skb(struct sk_buff *skb, int skb_af, new_skb =skb_realloc_headroom (skb, max_headroom);if (!new_skb) goto error; +if (skb->sk) +skb_set_owner_w (new_skb, skb->sk);consume_skb (skb); skb = new_skb; }
Signature · 1 line
1.7.10.4
Pablo Neira Ayuso
maintainerPATCH 4/8 netfilter: nft_compat: use current net namespace
In reply to Pablo Neira AyusoInstead of init_net when using xtables over nftables compat.
--- net/netfilter/nft_compat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/netfilter/nft_compat.c +2 -2
@@ -117,7 +117,7 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par, struct xt_target *target, void *info, union nft_entry *entry, u8 proto, bool inv) { - par->net = &init_net; + par->net = ctx->net; par->table = ctx->table->name;switch (ctx->afi->family) {case AF_INET :
@@ -324,7 +324,7 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx, struct xt_match *match, void *info, union nft_entry *entry, u8 proto, bool inv) { - par->net = &init_net; + par->net = ctx->net; par->table = ctx->table->name;switch (ctx->afi->family) {case AF_INET :
Signature · 1 line
1.7.10.4
Pablo Neira Ayuso
maintainerPATCH 5/8 netfilter: nft_compat: relax chain type validation
In reply to Pablo Neira AyusoCheck for nat chain dependency only, which is the one that can actually crash the kernel. Don't care if mangle, filter and security specific match and targets are used out of their scope, they are harmless.
This restores iptables-compat with mangle specific match/target when used out of the OUTPUT chain, that are actually emulated through filter chains, which broke when performing strict validation.
--- net/netfilter/nft_compat.c | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-)
net/netfilter/nft_compat.c +2 -30
@@ -21,45 +21,17 @@#include <linux/netfilter_ipv6/ip6_tables.h> #include <net/netfilter/nf_tables.h> -static const struct { -const char *name; -u8 type; -} table_to_chaintype[] = { - {"filter" ,NFT_CHAIN_T_DEFAULT }, - {"raw" ,NFT_CHAIN_T_DEFAULT }, - {"security" ,NFT_CHAIN_T_DEFAULT }, - {"mangle" ,NFT_CHAIN_T_ROUTE }, - {"nat" ,NFT_CHAIN_T_NAT }, - { }, -}; - -static int nft_compat_table_to_chaintype (const char *table) -{ -int i; - -for (i =0 ; table_to_chaintype[i].name !=NULL ; i++) { -if (strcmp (table_to_chaintype[i].name, table) ==0 ) -return table_to_chaintype[i].type; - } - -return -1 ; -} -static int nft_compat_chain_validate_dependency (const char *tablename,const struct nft_chain *chain) { -enum nft_chain_type type;const struct nft_base_chain *basechain;if (!tablename || !(chain->flags &NFT_BASE_CHAIN ))return 0 ; - type =nft_compat_table_to_chaintype (tablename); -if (type <0 ) -return -EINVAL ; - basechain =nft_base_chain (chain); -if (basechain->type->type != type) +if (strcmp (tablename,"nat" ) ==0 && + basechain->type->type !=NFT_CHAIN_T_NAT )return -EINVAL ;return 0 ;
Signature · 1 line
1.7.10.4
Pablo Neira Ayuso
maintainerPATCH 6/8 netfilter: nft_compat: use the match->table to validate dependencies
In reply to Pablo Neira AyusoInstead of the match->name, which is of course not relevant.
--- net/netfilter/nft_compat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/netfilter/nft_compat.c +2 -2
@@ -346,7 +346,7 @@ nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,union nft_entry e = {};int ret; - ret =nft_compat_chain_validate_dependency (match->name, ctx->chain); + ret =nft_compat_chain_validate_dependency (match->table, ctx->chain);if (ret <0 ) goto err;
@@ -420,7 +420,7 @@ static int nft_match_validate(const struct nft_ctx *ctx,if (!(hook_mask & match->hooks))return -EINVAL ; - ret =nft_compat_chain_validate_dependency (match->name, + ret =nft_compat_chain_validate_dependency (match->table, ctx->chain);if (ret <0 )return ret;
Signature · 1 line
1.7.10.4
Pablo Neira Ayuso
maintainerPATCH 7/8 netfilter: nf_tables: restore synchronous object release from commit/abort
In reply to Pablo Neira AyusoThe existing xtables matches and targets, when used from nft_compat, may sleep from the destroy path, ie. when removing rules. Since the objects are released via call_rcu from softirq context, this results in lockdep splats and possible lockups that may be hard to reproduce.
Patrick also indicated that delayed object release via call_rcu can cause us problems in the ordering of event notifications when anonymous sets are in place.
So, this patch restores the synchronous object release from the commit and abort paths. This includes a call to synchronize_rcu() to make sure that no packets are walking on the objects that are going to be released. This is slowier though, but it's simple and it resolves the aforementioned problems.
This is a partial revert of c7c32e7 ("netfilter: nf_tables: defer all object release via rcu") that was introduced in 3.16 to speed up interaction with userspace.
--- include/net/netfilter/nf_tables.h | 2 -- net/netfilter/nf_tables_api.c | 24 ++++++++---------------- 2 files changed, 8 insertions(+), 18 deletions(-)
include/net/netfilter/nf_tables.h +0 -2
@@ -396,14 +396,12 @@ struct nft_rule {/** * struct nft_trans - nf_tables object update in transaction * -* @rcu_head: rcu head to defer release of transaction data * @list: used internally * @msg_type: message type * @ctx: transaction context * @data: internal information related to the transaction */ struct nft_trans { -struct rcu_head rcu_head;struct list_head list;int msg_type;struct nft_ctx ctx;
net/netfilter/nf_tables_api.c +8 -16
@@ -3484,13 +3484,8 @@ static void nft_chain_commit_update(struct nft_trans *trans) } } -/* Schedule objects for release via rcu to make sure no packets are accesing -* removed rules. -*/ -static void nf_tables_commit_release_rcu (struct rcu_head *rt) +static void nf_tables_commit_release (struct nft_trans *trans) { - struct nft_trans *trans = container_of(rt, struct nft_trans, rcu_head); -switch (trans->msg_type) {case NFT_MSG_DELTABLE :nf_tables_table_destroy (&trans->ctx);
@@ -3612,10 +3607,11 @@ static int nf_tables_commit(struct sk_buff *skb) } } +synchronize_rcu (); +list_for_each_entry_safe (trans, next, &net->nft.commit_list, list) {list_del (&trans->list); - trans->ctx.nla =NULL ; -call_rcu (&trans->rcu_head, nf_tables_commit_release_rcu); +nf_tables_commit_release (trans); }nf_tables_gen_notify (net, skb,NFT_MSG_NEWGEN );
@@ -3623,13 +3619,8 @@ static int nf_tables_commit(struct sk_buff *skb)return 0 ; } -/* Schedule objects for release via rcu to make sure no packets are accesing -* aborted rules. -*/ -static void nf_tables_abort_release_rcu (struct rcu_head *rt) +static void nf_tables_abort_release (struct nft_trans *trans) { - struct nft_trans *trans = container_of(rt, struct nft_trans, rcu_head); -switch (trans->msg_type) {case NFT_MSG_NEWTABLE :nf_tables_table_destroy (&trans->ctx);
@@ -3725,11 +3716,12 @@ static int nf_tables_abort(struct sk_buff *skb) } } +synchronize_rcu (); +list_for_each_entry_safe_reverse (trans, next, &net->nft.commit_list, list) {list_del (&trans->list); - trans->ctx.nla =NULL ; -call_rcu (&trans->rcu_head, nf_tables_abort_release_rcu); +nf_tables_abort_release (trans); }return 0 ;
Signature · 1 line
1.7.10.4
Pablo Neira Ayuso
maintainerPATCH 8/8 netfilter: conntrack: fix race in __nf_conntrack_confirm against get_next_corpse
In reply to Pablo Neira AyusoFrom: bill bonaparte <[email protected]>
After removal of the central spinlock nf_conntrack_lock, in commit 93bb0ceb75be2 ("netfilter: conntrack: remove central spinlock nf_conntrack_lock"), it is possible to race against get_next_corpse().
The race is against the get_next_corpse() cleanup on the "unconfirmed" list (a per-cpu list with seperate locking), which set the DYING bit.
Fix this race, in __nf_conntrack_confirm(), by removing the CT from unconfirmed list before checking the DYING bit. In case race occured, re-add the CT to the dying list.
While at this, fix coding style of the comment that has been updated.
--- net/netfilter/nf_conntrack_core.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
net/netfilter/nf_conntrack_core.c +8 -6
@@ -611,12 +611,16 @@ __nf_conntrack_confirm(struct sk_buff *skb)*/ NF_CT_ASSERT (!nf_ct_is_confirmed (ct));pr_debug ("Confirming conntrack %p\n" , ct); -/* We have to check the DYING flag inside the lock to prevent -a race against nf_ct_get_next_corpse() possibly called from -user context, else we insert an already 'dead' hash, blocking -further use of that particular connection -JM */ + +/* We have to check the DYING flag after unlink to prevent +* a race against nf_ct_get_next_corpse() possibly called from +* user context, else we insert an already 'dead' hash, blocking +* further use of that particular connection -JM. +*/ +nf_ct_del_from_dying_or_unconfirmed_list (ct);if (unlikely (nf_ct_is_dying (ct))) { +nf_ct_add_to_dying_list (ct);nf_conntrack_double_unlock (hash, reply_hash);local_bh_enable ();return NF_ACCEPT ;
@@ -636,8 +640,6 @@ __nf_conntrack_confirm(struct sk_buff *skb) zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h))) goto out; -nf_ct_del_from_dying_or_unconfirmed_list (ct); -/* Timer relative to confirmation time, not original setting time, otherwise we'd get timer wrap in weird delay cases. */
Signature · 1 line
1.7.10.4
David Miller
maintainerFrom: Pablo Neira Ayuso <[email protected]>
Date: Fri, 14 Nov 2014 17:58:40 +0100
Quoted 2 lines
The following patchset contains Netfilter updates for your net tree, they are:
...
Quoted 3 lines
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git
Pulled, thanks a lot Pablo!