Commit b3d2c7b8 authored by Jakub Kicinski's avatar Jakub Kicinski

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.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 647b8dd5 8d6bca15
...@@ -399,7 +399,7 @@ static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff, ...@@ -399,7 +399,7 @@ static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff,
return -1; return -1;
tcph = (void *)(skb_network_header(skb) + thoff); 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; return 0;
} }
...@@ -415,7 +415,7 @@ static int nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff, ...@@ -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); udph = (void *)(skb_network_header(skb) + thoff);
if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) {
inet_proto_csum_replace2(&udph->check, skb, port, inet_proto_csum_replace2(&udph->check, skb, port,
new_port, true); new_port, false);
if (!udph->check) if (!udph->check)
udph->check = CSUM_MANGLED_0; udph->check = CSUM_MANGLED_0;
} }
......
...@@ -8949,6 +8949,17 @@ int __nft_release_basechain(struct nft_ctx *ctx) ...@@ -8949,6 +8949,17 @@ int __nft_release_basechain(struct nft_ctx *ctx)
} }
EXPORT_SYMBOL_GPL(__nft_release_basechain); 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) static void __nft_release_tables(struct net *net)
{ {
struct nft_flowtable *flowtable, *nf; struct nft_flowtable *flowtable, *nf;
...@@ -8964,10 +8975,6 @@ static void __nft_release_tables(struct net *net) ...@@ -8964,10 +8975,6 @@ static void __nft_release_tables(struct net *net)
list_for_each_entry_safe(table, nt, &net->nft.tables, list) { list_for_each_entry_safe(table, nt, &net->nft.tables, list) {
ctx.family = table->family; 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; ctx.table = table;
list_for_each_entry(chain, &table->chains, list) { list_for_each_entry(chain, &table->chains, list) {
ctx.chain = chain; ctx.chain = chain;
...@@ -9016,6 +9023,11 @@ static int __net_init nf_tables_init_net(struct net *net) ...@@ -9016,6 +9023,11 @@ static int __net_init nf_tables_init_net(struct net *net)
return 0; 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) static void __net_exit nf_tables_exit_net(struct net *net)
{ {
mutex_lock(&net->nft.commit_mutex); mutex_lock(&net->nft.commit_mutex);
...@@ -9029,8 +9041,9 @@ static void __net_exit nf_tables_exit_net(struct net *net) ...@@ -9029,8 +9041,9 @@ static void __net_exit nf_tables_exit_net(struct net *net)
} }
static struct pernet_operations nf_tables_net_ops = { static struct pernet_operations nf_tables_net_ops = {
.init = nf_tables_init_net, .init = nf_tables_init_net,
.exit = nf_tables_exit_net, .pre_exit = nf_tables_pre_exit_net,
.exit = nf_tables_exit_net,
}; };
static int __init nf_tables_module_init(void) static int __init nf_tables_module_init(void)
......
...@@ -152,7 +152,8 @@ static void recent_entry_remove(struct recent_table *t, struct recent_entry *e) ...@@ -152,7 +152,8 @@ static void recent_entry_remove(struct recent_table *t, struct recent_entry *e)
/* /*
* Drop entries with timestamps older then 'time'. * 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; struct recent_entry *e;
...@@ -161,6 +162,12 @@ static void recent_entry_reap(struct recent_table *t, unsigned long time) ...@@ -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); 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. * The last time stamp is the most recent.
*/ */
...@@ -303,7 +310,8 @@ recent_mt(const struct sk_buff *skb, struct xt_action_param *par) ...@@ -303,7 +310,8 @@ recent_mt(const struct sk_buff *skb, struct xt_action_param *par)
/* info->seconds must be non-zero */ /* info->seconds must be non-zero */
if (info->check_set & XT_RECENT_REAP) 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 || if (info->check_set & XT_RECENT_SET ||
......
...@@ -23,7 +23,7 @@ ip -net "$ns0" addr add 127.0.0.1 dev lo ...@@ -23,7 +23,7 @@ ip -net "$ns0" addr add 127.0.0.1 dev lo
trap cleanup EXIT trap cleanup EXIT
currentyear=$(date +%G) currentyear=$(date +%Y)
lastyear=$((currentyear-1)) lastyear=$((currentyear-1))
ip netns exec "$ns0" nft -f /dev/stdin <<EOF ip netns exec "$ns0" nft -f /dev/stdin <<EOF
table inet filter { table inet filter {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment