Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf

Pablo Neira Ayuso says:

====================
Netfilter fixes for net

1) Fix combination of --reap and --update in xt_recent that triggers
   UAF, from Jozsef Kadlecsik.

2) Fix current year in nft_meta selftest, from Fabian Frederick.

3) Fix possible UAF in the netns destroy path of nftables.

4) Fix incorrect checksum calculation when mangling ports in flowtable,
   from Sven Auhagen.

* git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf:
  netfilter: flowtable: fix tcp and udp header checksum update
  netfilter: nftables: fix possible UAF over chains from packet path in netns
  selftests: netfilter: fix current year
  netfilter: xt_recent: Fix attempt to update deleted entry
====================

Link: https://lore.kernel.org/r/20210205001727.2125-1-pablo@netfilter.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2021-02-04 21:36:59 -08:00
commit b3d2c7b876
4 changed files with 32 additions and 11 deletions

View file

@ -399,7 +399,7 @@ static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff,
return -1;
tcph = (void *)(skb_network_header(skb) + thoff);
inet_proto_csum_replace2(&tcph->check, skb, port, new_port, true);
inet_proto_csum_replace2(&tcph->check, skb, port, new_port, false);
return 0;
}
@ -415,7 +415,7 @@ static int nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff,
udph = (void *)(skb_network_header(skb) + thoff);
if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) {
inet_proto_csum_replace2(&udph->check, skb, port,
new_port, true);
new_port, false);
if (!udph->check)
udph->check = CSUM_MANGLED_0;
}

View file

@ -8949,6 +8949,17 @@ int __nft_release_basechain(struct nft_ctx *ctx)
}
EXPORT_SYMBOL_GPL(__nft_release_basechain);
static void __nft_release_hooks(struct net *net)
{
struct nft_table *table;
struct nft_chain *chain;
list_for_each_entry(table, &net->nft.tables, list) {
list_for_each_entry(chain, &table->chains, list)
nf_tables_unregister_hook(net, table, chain);
}
}
static void __nft_release_tables(struct net *net)
{
struct nft_flowtable *flowtable, *nf;
@ -8964,10 +8975,6 @@ static void __nft_release_tables(struct net *net)
list_for_each_entry_safe(table, nt, &net->nft.tables, list) {
ctx.family = table->family;
list_for_each_entry(chain, &table->chains, list)
nf_tables_unregister_hook(net, table, chain);
/* No packets are walking on these chains anymore. */
ctx.table = table;
list_for_each_entry(chain, &table->chains, list) {
ctx.chain = chain;
@ -9016,6 +9023,11 @@ static int __net_init nf_tables_init_net(struct net *net)
return 0;
}
static void __net_exit nf_tables_pre_exit_net(struct net *net)
{
__nft_release_hooks(net);
}
static void __net_exit nf_tables_exit_net(struct net *net)
{
mutex_lock(&net->nft.commit_mutex);
@ -9029,8 +9041,9 @@ static void __net_exit nf_tables_exit_net(struct net *net)
}
static struct pernet_operations nf_tables_net_ops = {
.init = nf_tables_init_net,
.exit = nf_tables_exit_net,
.init = nf_tables_init_net,
.pre_exit = nf_tables_pre_exit_net,
.exit = nf_tables_exit_net,
};
static int __init nf_tables_module_init(void)

View file

@ -152,7 +152,8 @@ static void recent_entry_remove(struct recent_table *t, struct recent_entry *e)
/*
* Drop entries with timestamps older then 'time'.
*/
static void recent_entry_reap(struct recent_table *t, unsigned long time)
static void recent_entry_reap(struct recent_table *t, unsigned long time,
struct recent_entry *working, bool update)
{
struct recent_entry *e;
@ -161,6 +162,12 @@ static void recent_entry_reap(struct recent_table *t, unsigned long time)
*/
e = list_entry(t->lru_list.next, struct recent_entry, lru_list);
/*
* Do not reap the entry which are going to be updated.
*/
if (e == working && update)
return;
/*
* The last time stamp is the most recent.
*/
@ -303,7 +310,8 @@ recent_mt(const struct sk_buff *skb, struct xt_action_param *par)
/* info->seconds must be non-zero */
if (info->check_set & XT_RECENT_REAP)
recent_entry_reap(t, time);
recent_entry_reap(t, time, e,
info->check_set & XT_RECENT_UPDATE && ret);
}
if (info->check_set & XT_RECENT_SET ||

View file

@ -23,7 +23,7 @@ ip -net "$ns0" addr add 127.0.0.1 dev lo
trap cleanup EXIT
currentyear=$(date +%G)
currentyear=$(date +%Y)
lastyear=$((currentyear-1))
ip netns exec "$ns0" nft -f /dev/stdin <<EOF
table inet filter {