Commit b3d2c7b8 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
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: default avatarJakub Kicinski <kuba@kernel.org>
parents 647b8dd5 8d6bca15
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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;
	}
+19 −6
Original line number Diff line number Diff line
@@ -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);
@@ -9030,6 +9042,7 @@ static void __net_exit nf_tables_exit_net(struct net *net)

static struct pernet_operations nf_tables_net_ops = {
	.init		= nf_tables_init_net,
	.pre_exit	= nf_tables_pre_exit_net,
	.exit		= nf_tables_exit_net,
};

+10 −2
Original line number Diff line number Diff line
@@ -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 ||
+1 −1
Original line number Diff line number Diff line
@@ -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 {