From: Pablo Neira Ayuso <pablo@netfilter.org> Date: 2017-08-24 14:43:43
Hi David,
The following patchset contains Netfilter fixes for your net tree,
they are:
1) Fix use after free of struct proc_dir_entry in ipt_CLUSTERIP, patch
from Sabrina Dubroca.
2) Fix spurious EINVAL errors from iptables over nft compatibility layer.
3) Reload pointer to ip header only if there is non-terminal verdict,
ie. XT_CONTINUE, otherwise invalid memory access may happen, patch
from Taehee Yoo.
4) Fix interaction between SYNPROXY and NAT, SYNPROXY adds sequence
adjustment already, however from nf_nat_setup() assumes there's not.
Patch from Xin Long.
5) Fix burst arithmetics in nft_limit as Joe Stringer mentioned during
NFWS in Faro. Patch from Andy Zhou.
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git
Thanks a lot!
----------------------------------------------------------------
The following changes since commit 073dd5ad34b1d3aaadaa7e5e8cbe576d9545f163:
netfilter: fix netfilter_net_init() return (2017-07-18 14:50:28 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git HEAD
for you to fetch changes up to c26844eda9d4fdbd266660e3b3de2d0270e3a1ed:
netfilter: nf_tables: Fix nft limit burst handling (2017-08-24 16:23:17 +0200)
----------------------------------------------------------------
Pablo Neira Ayuso (1):
netfilter: nft_compat: check extension hook mask only if set
Sabrina Dubroca (1):
netfilter: ipt_CLUSTERIP: fix use-after-free of proc entry
Taehee Yoo (1):
netfilter: x_tables: Fix use-after-free in ipt_do_table.
Xin Long (1):
netfilter: check for seqadj ext existence before adding it in nf_nat_setup_info
andy zhou (1):
netfilter: nf_tables: Fix nft limit burst handling
net/ipv4/netfilter/arp_tables.c | 10 +++++-----
net/ipv4/netfilter/ip_tables.c | 9 +++++----
net/ipv4/netfilter/ipt_CLUSTERIP.c | 4 +++-
net/netfilter/nf_nat_core.c | 2 +-
net/netfilter/nft_compat.c | 4 ++--
net/netfilter/nft_limit.c | 25 ++++++++++++++-----------
6 files changed, 30 insertions(+), 24 deletions(-)
From: Pablo Neira Ayuso <pablo@netfilter.org> Date: 2017-08-24 14:43:27
From: Sabrina Dubroca <sd@queasysnail.net>
When we delete a netns with a CLUSTERIP rule, clusterip_net_exit() is
called first, removing /proc/net/ipt_CLUSTERIP.
Then clusterip_config_entry_put() is called from clusterip_tg_destroy(),
and tries to remove its entry under /proc/net/ipt_CLUSTERIP/.
Fix this by checking that the parent directory of the entry to remove
hasn't already been deleted.
The following triggers a KASAN splat (stealing the reproducer from
202f59afd441, thanks to Jianlin Shi and Xin Long):
ip netns add test
ip link add veth0_in type veth peer name veth0_out
ip link set veth0_in netns test
ip netns exec test ip link set lo up
ip netns exec test ip link set veth0_in up
ip netns exec test iptables -I INPUT -d 1.2.3.4 -i veth0_in -j \
CLUSTERIP --new --clustermac 89:d4:47:eb:9a:fa --total-nodes 3 \
--local-node 1 --hashmode sourceip-sourceport
ip netns del test
Fixes: ce4ff76c15a8 ("netfilter: ipt_CLUSTERIP: make proc directory per net namespace")
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Reviewed-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/ipv4/netfilter/ipt_CLUSTERIP.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
From: Pablo Neira Ayuso <pablo@netfilter.org> Date: 2017-08-24 14:43:28
If the x_tables extension comes with no hook mask, skip this validation.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nft_compat.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
From: Pablo Neira Ayuso <pablo@netfilter.org> Date: 2017-08-24 14:43:29
From: Taehee Yoo <ap420073@gmail.com>
If verdict is NF_STOLEN in the SYNPROXY target,
the skb is consumed.
However, ipt_do_table() always tries to get ip header from the skb.
So that, KASAN triggers the use-after-free message.
We can reproduce this message using below command.
# iptables -I INPUT -p tcp -j SYNPROXY --mss 1460
[ 193.542265] BUG: KASAN: use-after-free in ipt_do_table+0x1405/0x1c10
[ ... ]
[ 193.578603] Call Trace:
[ 193.581590] <IRQ>
[ 193.584107] dump_stack+0x68/0xa0
[ 193.588168] print_address_description+0x78/0x290
[ 193.593828] ? ipt_do_table+0x1405/0x1c10
[ 193.598690] kasan_report+0x230/0x340
[ 193.603194] __asan_report_load2_noabort+0x19/0x20
[ 193.608950] ipt_do_table+0x1405/0x1c10
[ 193.613591] ? rcu_read_lock_held+0xae/0xd0
[ 193.618631] ? ip_route_input_rcu+0x27d7/0x4270
[ 193.624348] ? ipt_do_table+0xb68/0x1c10
[ 193.629124] ? do_add_counters+0x620/0x620
[ 193.634234] ? iptable_filter_net_init+0x60/0x60
[ ... ]
After this patch, only when verdict is XT_CONTINUE,
ipt_do_table() tries to get ip header.
Also arpt_do_table() is modified because it has same bug.
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/ipv4/netfilter/arp_tables.c | 10 +++++-----
net/ipv4/netfilter/ip_tables.c | 9 +++++----
2 files changed, 10 insertions(+), 9 deletions(-)
From: Pablo Neira Ayuso <pablo@netfilter.org> Date: 2017-08-24 14:43:48
From: Xin Long <lucien.xin@gmail.com>
Commit 4440a2ab3b9f ("netfilter: synproxy: Check oom when adding synproxy
and seqadj ct extensions") wanted to drop the packet when it fails to add
seqadj ext due to no memory by checking if nfct_seqadj_ext_add returns
NULL.
But that nfct_seqadj_ext_add returns NULL can also happen when seqadj ext
already exists in a nf_conn. It will cause that userspace protocol doesn't
work when both dnat and snat are configured.
Li Shuang found this issue in the case:
Topo:
ftp client router ftp server
10.167.131.2 <-> 10.167.131.254 10.167.141.254 <-> 10.167.141.1
Rules:
# iptables -t nat -A PREROUTING -i eth1 -p tcp -m tcp --dport 21 -j \
DNAT --to-destination 10.167.141.1
# iptables -t nat -A POSTROUTING -o eth2 -p tcp -m tcp --dport 21 -j \
SNAT --to-source 10.167.141.254
In router, when both dnat and snat are added, nf_nat_setup_info will be
called twice. The packet can be dropped at the 2nd time for DNAT due to
seqadj ext is already added at the 1st time for SNAT.
This patch is to fix it by checking for seqadj ext existence before adding
it, so that the packet will not be dropped if seqadj ext already exists.
Note that as Florian mentioned, as a long term, we should review ext_add()
behaviour, it's better to return a pointer to the existing ext instead.
Fixes: 4440a2ab3b9f ("netfilter: synproxy: Check oom when adding synproxy and seqadj ct extensions")
Reported-by: Li Shuang <redacted>
Acked-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_nat_core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: Pablo Neira Ayuso <pablo@netfilter.org> Date: 2017-08-24 14:43:49
From: andy zhou <redacted>
Current implementation treats the burst configuration the same as
rate configuration. This can cause the per packet cost to be lower
than configured. In effect, this bug causes the token bucket to be
refilled at a higher rate than what user has specified.
This patch changes the implementation so that the token bucket size
is controlled by "rate + burst", while maintain the token bucket
refill rate the same as user specified.
Fixes: 96518518cc41 ("netfilter: add nftables")
Signed-off-by: Andy Zhou <redacted>
Acked-by: Joe Stringer <redacted>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nft_limit.c | 25 ++++++++++++++-----------
1 file changed, 14 insertions(+), 11 deletions(-)
@@ -65,19 +65,23 @@ static int nft_limit_init(struct nft_limit *limit,limit->nsecs=unit*NSEC_PER_SEC;if(limit->rate==0||limit->nsecs<unit)return-EOVERFLOW;-limit->tokens=limit->tokens_max=limit->nsecs;--if(tb[NFTA_LIMIT_BURST]){-u64rate;+if(tb[NFTA_LIMIT_BURST])limit->burst=ntohl(nla_get_be32(tb[NFTA_LIMIT_BURST]));+else+limit->burst=0;++if(limit->rate+limit->burst<limit->rate)+return-EOVERFLOW;-rate=limit->rate+limit->burst;-if(rate<limit->rate)-return-EOVERFLOW;+/* The token bucket size limits the number of tokens can be+*accumulated.tokens_maxspecifiesthebucketsize.+*tokens_max=unit*(rate+burst)/rate.+*/+limit->tokens=div_u64(limit->nsecs*(limit->rate+limit->burst),+limit->rate);+limit->tokens_max=limit->tokens;-limit->rate=rate;-}if(tb[NFTA_LIMIT_FLAGS]){u32flags=ntohl(nla_get_be32(tb[NFTA_LIMIT_FLAGS]));