Skip to content

Commit c461721

Browse files
Florian Westphalummakynes
authored andcommitted
netfilter: conntrack: do not auto-delete clash entries on reply
Its possible that we have more than one packet with the same ct tuple simultaneously, e.g. when an application emits n packets on same UDP socket from multiple threads. NAT rules might be applied to those packets. With the right set of rules, n packets will be mapped to m destinations, where at least two packets end up with the same destination. When this happens, the existing clash resolution may merge the skb that is processed after the first has been received with the identical tuple already in hash table. However, its possible that this identical tuple is a NAT_CLASH tuple. In that case the second skb will be sent, but no reply can be received since the reply that is processed first removes the NAT_CLASH tuple. Do not auto-delete, this gives a 1 second window for replies to be passed back to originator. Packets that are coming later (udp stream case) will not be affected: they match the original ct entry, not a NAT_CLASH one. Also prevent NAT_CLASH entries from getting offloaded. Fixes: 6a757c0 ("netfilter: conntrack: allow insertion of clashing entries") Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 67afbda commit c461721

File tree

2 files changed

+11
-17
lines changed

2 files changed

+11
-17
lines changed

net/netfilter/nf_conntrack_proto_udp.c

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -81,18 +81,6 @@ static bool udp_error(struct sk_buff *skb,
8181
return false;
8282
}
8383

84-
static void nf_conntrack_udp_refresh_unreplied(struct nf_conn *ct,
85-
struct sk_buff *skb,
86-
enum ip_conntrack_info ctinfo,
87-
u32 extra_jiffies)
88-
{
89-
if (unlikely(ctinfo == IP_CT_ESTABLISHED_REPLY &&
90-
ct->status & IPS_NAT_CLASH))
91-
nf_ct_kill(ct);
92-
else
93-
nf_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies);
94-
}
95-
9684
/* Returns verdict for packet, and may modify conntracktype */
9785
int nf_conntrack_udp_packet(struct nf_conn *ct,
9886
struct sk_buff *skb,
@@ -124,12 +112,15 @@ int nf_conntrack_udp_packet(struct nf_conn *ct,
124112

125113
nf_ct_refresh_acct(ct, ctinfo, skb, extra);
126114

115+
/* never set ASSURED for IPS_NAT_CLASH, they time out soon */
116+
if (unlikely((ct->status & IPS_NAT_CLASH)))
117+
return NF_ACCEPT;
118+
127119
/* Also, more likely to be important, and not a probe */
128120
if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
129121
nf_conntrack_event_cache(IPCT_ASSURED, ct);
130122
} else {
131-
nf_conntrack_udp_refresh_unreplied(ct, skb, ctinfo,
132-
timeouts[UDP_CT_UNREPLIED]);
123+
nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[UDP_CT_UNREPLIED]);
133124
}
134125
return NF_ACCEPT;
135126
}
@@ -206,12 +197,15 @@ int nf_conntrack_udplite_packet(struct nf_conn *ct,
206197
if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
207198
nf_ct_refresh_acct(ct, ctinfo, skb,
208199
timeouts[UDP_CT_REPLIED]);
200+
201+
if (unlikely((ct->status & IPS_NAT_CLASH)))
202+
return NF_ACCEPT;
203+
209204
/* Also, more likely to be important, and not a probe */
210205
if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
211206
nf_conntrack_event_cache(IPCT_ASSURED, ct);
212207
} else {
213-
nf_conntrack_udp_refresh_unreplied(ct, skb, ctinfo,
214-
timeouts[UDP_CT_UNREPLIED]);
208+
nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[UDP_CT_UNREPLIED]);
215209
}
216210
return NF_ACCEPT;
217211
}

net/netfilter/nft_flow_offload.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
102102
}
103103

104104
if (nf_ct_ext_exist(ct, NF_CT_EXT_HELPER) ||
105-
ct->status & IPS_SEQ_ADJUST)
105+
ct->status & (IPS_SEQ_ADJUST | IPS_NAT_CLASH))
106106
goto out;
107107

108108
if (!nf_ct_is_confirmed(ct))

0 commit comments

Comments
 (0)