Commit 898ae76a authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
Florian Westphal says:

====================
netfilter: updates for net

1) Fix refcount leaks in nf_conncount, from Fernando Fernandez Mancera.
   This addresses a recent regression that came in the last -next
   pull request.

2) Fix a null dereference in route error handling in IPVS, from Slavin
   Liu.  This is an ancient issue dating back to 5.1 days.

3) Always set ifindex in route tuple in the flowtable output path, from
   Lorenzo Bianconi.  This bug came in with the recent output path refactoring.

4) Prefer 'exit $ksft_xfail' over 'exit $ksft_skip' when we fail to
   trigger a nat race condition to exercise the clash resolution path in
   selftest infra, $ksft_skip should be reserved for missing tooling,
   From myself.

* tag 'nf-25-12-10' of https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf:
  selftests: netfilter: prefer xfail in case race wasn't triggered
  netfilter: always set route tuple out ifindex
  ipvs: fix ipv4 null-ptr-deref in route error path
  netfilter: nf_conncount: fix leaked ct in error paths
====================

Link: https://patch.msgid.link/20251210110754.22620-1-fw@strlen.de


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 237c1e15 b8a81b0c
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -408,6 +408,9 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
	return -1;

err_unreach:
	if (!skb->dev)
		skb->dev = skb_dst(skb)->dev;

	dst_link_failure(skb);
	return -1;
}
+14 −11
Original line number Diff line number Diff line
@@ -172,14 +172,14 @@ static int __nf_conncount_add(struct net *net,
	struct nf_conn *found_ct;
	unsigned int collect = 0;
	bool refcounted = false;
	int err = 0;

	if (!get_ct_or_tuple_from_skb(net, skb, l3num, &ct, &tuple, &zone, &refcounted))
		return -ENOENT;

	if (ct && nf_ct_is_confirmed(ct)) {
		if (refcounted)
			nf_ct_put(ct);
		return -EEXIST;
		err = -EEXIST;
		goto out_put;
	}

	if ((u32)jiffies == list->last_gc)
@@ -231,12 +231,16 @@ static int __nf_conncount_add(struct net *net,
	}

add_new_node:
	if (WARN_ON_ONCE(list->count > INT_MAX))
		return -EOVERFLOW;
	if (WARN_ON_ONCE(list->count > INT_MAX)) {
		err = -EOVERFLOW;
		goto out_put;
	}

	conn = kmem_cache_alloc(conncount_conn_cachep, GFP_ATOMIC);
	if (conn == NULL)
		return -ENOMEM;
	if (conn == NULL) {
		err = -ENOMEM;
		goto out_put;
	}

	conn->tuple = tuple;
	conn->zone = *zone;
@@ -249,7 +253,7 @@ static int __nf_conncount_add(struct net *net,
out_put:
	if (refcounted)
		nf_ct_put(ct);
	return 0;
	return err;
}

int nf_conncount_add_skb(struct net *net,
@@ -456,11 +460,10 @@ insert_tree(struct net *net,

		rb_link_node_rcu(&rbconn->node, parent, rbnode);
		rb_insert_color(&rbconn->node, root);

		if (refcounted)
			nf_ct_put(ct);
	}
out_unlock:
	if (refcounted)
		nf_ct_put(ct);
	spin_unlock_bh(&nf_conncount_locks[hash]);
	return count;
}
+3 −1
Original line number Diff line number Diff line
@@ -250,6 +250,9 @@ static void nft_dev_forward_path(const struct nft_pktinfo *pkt,
	if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0)
		nft_dev_path_info(&stack, &info, ha, &ft->data);

	if (info.outdev)
		route->tuple[dir].out.ifindex = info.outdev->ifindex;

	if (!info.indev || !nft_flowtable_find_dev(info.indev, ft))
		return;

@@ -269,7 +272,6 @@ static void nft_dev_forward_path(const struct nft_pktinfo *pkt,

	route->tuple[!dir].in.num_encaps = info.num_encaps;
	route->tuple[!dir].in.ingress_vlans = info.ingress_vlans;
	route->tuple[dir].out.ifindex = info.outdev->ifindex;

	if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) {
		memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN);
+4 −5
Original line number Diff line number Diff line
@@ -116,7 +116,7 @@ run_one_clash_test()
	# not a failure: clash resolution logic did not trigger.
	# With right timing, xmit completed sequentially and
	# no parallel insertion occurs.
	return $ksft_skip
	return $ksft_xfail
}

run_clash_test()
@@ -133,12 +133,12 @@ run_clash_test()
		if [ $rv -eq 0 ];then
			echo "PASS: clash resolution test for $daddr:$dport on attempt $i"
			return 0
		elif [ $rv -eq $ksft_skip ]; then
		elif [ $rv -eq $ksft_xfail ]; then
			softerr=1
		fi
	done

	[ $softerr -eq 1 ] && echo "SKIP: clash resolution for $daddr:$dport did not trigger"
	[ $softerr -eq 1 ] && echo "XFAIL: clash resolution for $daddr:$dport did not trigger"
}

ip link add veth0 netns "$nsclient1" type veth peer name veth0 netns "$nsrouter"
@@ -167,8 +167,7 @@ load_simple_ruleset "$nsclient2"
run_clash_test "$nsclient2" "$nsclient2" 127.0.0.1 9001

if [ $clash_resolution_active -eq 0 ];then
	[ "$ret" -eq 0 ] && ret=$ksft_skip
	echo "SKIP: Clash resolution did not trigger"
	[ "$ret" -eq 0 ] && ret=$ksft_xfail
fi

exit $ret