Skip to content

Commit 5ec8ca2

Browse files
author
Florian Westphal
committed
netfilter: nf_nat: remove bogus direction check
Jakub reports spurious failures of the 'conntrack_reverse_clash.sh' selftest. A bogus test makes nat core resort to port rewrite even though there is no need for this. When the test is made, nf_nat_used_tuple() would already have caused us to return if no other CPU had added a colliding entry. Moreover, nf_nat_used_tuple() would have ignored the colliding entry if their origin tuples had been the same. All that is left to check is if the colliding entry in the hash table is subject to NAT, and, if its not, if our entry matches in the reverse direction, e.g. hash table has addr1:1234 -> addr2:80, and we want to commit addr2:80 -> addr1:1234. Because we already checked that neither the new nor the committed entry is subject to NAT we only have to check origin vs. reply tuple: for non-nat entries, the reply tuple is always the inverted original. Just in case there are more problems extend the error reporting in the selftest while at it and dump conntrack table/stats on error. Reported-by: Jakub Kicinski <kuba@kernel.org> Closes: https://lore.kernel.org/netdev/20251206175135.4a56591b@kernel.org/ Fixes: d8f84a9 ("netfilter: nf_nat: don't try nat source port reallocation for reverse dir clash") Signed-off-by: Florian Westphal <fw@strlen.de>
1 parent 99c6931 commit 5ec8ca2

File tree

3 files changed

+12
-17
lines changed

3 files changed

+12
-17
lines changed

net/netfilter/nf_nat_core.c

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -294,25 +294,13 @@ nf_nat_used_tuple_new(const struct nf_conntrack_tuple *tuple,
294294

295295
ct = nf_ct_tuplehash_to_ctrack(thash);
296296

297-
/* NB: IP_CT_DIR_ORIGINAL should be impossible because
298-
* nf_nat_used_tuple() handles origin collisions.
299-
*
300-
* Handle remote chance other CPU confirmed its ct right after.
301-
*/
302-
if (thash->tuple.dst.dir != IP_CT_DIR_REPLY)
303-
goto out;
304-
305297
/* clashing connection subject to NAT? Retry with new tuple. */
306298
if (READ_ONCE(ct->status) & uses_nat)
307299
goto out;
308300

309301
if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
310-
&ignored_ct->tuplehash[IP_CT_DIR_REPLY].tuple) &&
311-
nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple,
312-
&ignored_ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple)) {
302+
&ignored_ct->tuplehash[IP_CT_DIR_REPLY].tuple))
313303
taken = false;
314-
goto out;
315-
}
316304
out:
317305
nf_ct_put(ct);
318306
return taken;

tools/testing/selftests/net/netfilter/conntrack_reverse_clash.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,14 @@ static void die(const char *e)
3333
exit(111);
3434
}
3535

36-
static void die_port(uint16_t got, uint16_t want)
36+
static void die_port(const struct sockaddr_in *sin, uint16_t want)
3737
{
38-
fprintf(stderr, "Port number changed, wanted %d got %d\n", want, ntohs(got));
38+
uint16_t got = ntohs(sin->sin_port);
39+
char str[INET_ADDRSTRLEN];
40+
41+
inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str));
42+
43+
fprintf(stderr, "Port number changed, wanted %d got %d from %s\n", want, got, str);
3944
exit(1);
4045
}
4146

@@ -100,7 +105,7 @@ int main(int argc, char *argv[])
100105
die("child recvfrom");
101106

102107
if (peer.sin_port != htons(PORT))
103-
die_port(peer.sin_port, PORT);
108+
die_port(&peer, PORT);
104109
} else {
105110
if (sendto(s2, buf, LEN, 0, (struct sockaddr *)&sa1, sizeof(sa1)) != LEN)
106111
continue;
@@ -109,7 +114,7 @@ int main(int argc, char *argv[])
109114
die("parent recvfrom");
110115

111116
if (peer.sin_port != htons((PORT + 1)))
112-
die_port(peer.sin_port, PORT + 1);
117+
die_port(&peer, PORT + 1);
113118
}
114119
}
115120

tools/testing/selftests/net/netfilter/conntrack_reverse_clash.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ if ip netns exec "$ns0" ./conntrack_reverse_clash; then
4545
echo "PASS: No SNAT performed for null bindings"
4646
else
4747
echo "ERROR: SNAT performed without any matching snat rule"
48+
ip netns exec "$ns0" conntrack -L
49+
ip netns exec "$ns0" conntrack -S
4850
exit 1
4951
fi
5052

0 commit comments

Comments
 (0)