Skip to content

Commit 05445b5

Browse files
committed
netfilter: conntrack: fix wrong ct->timeout value
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2189550 Upstream Status: commit 73db1b8 commit 73db1b8 Author: Tzung-Bi Shih <tzungbi@kernel.org> Date: Wed Apr 19 13:15:26 2023 +0800 netfilter: conntrack: fix wrong ct->timeout value (struct nf_conn)->timeout is an interval before the conntrack confirmed. After confirmed, it becomes a timestamp. It is observed that timeout of an unconfirmed conntrack: - Set by calling ctnetlink_change_timeout(). As a result, `nfct_time_stamp` was wrongly added to `ct->timeout` twice. - Get by calling ctnetlink_dump_timeout(). As a result, `nfct_time_stamp` was wrongly subtracted. Call Trace: <TASK> dump_stack_lvl ctnetlink_dump_timeout __ctnetlink_glue_build ctnetlink_glue_build __nfqnl_enqueue_packet nf_queue nf_hook_slow ip_mc_output ? __pfx_ip_finish_output ip_send_skb ? __pfx_dst_output udp_send_skb udp_sendmsg ? __pfx_ip_generic_getfrag sock_sendmsg Separate the 2 cases in: - Setting `ct->timeout` in __nf_ct_set_timeout(). - Getting `ct->timeout` in ctnetlink_dump_timeout(). Pablo appends: Update ctnetlink to set up the timeout _after_ the IPS_CONFIRMED flag is set on, otherwise conntrack creation via ctnetlink breaks. Note that the problem described in this patch occurs since the introduction of the nfnetlink_queue conntrack support, select a sufficiently old Fixes: tag for -stable kernel to pick up this fix. Fixes: a4b4766 ("netfilter: nfnetlink_queue: rename related to nfqueue attaching conntrack info") Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fwestpha@redhat.com>
1 parent d17406d commit 05445b5

File tree

2 files changed

+14
-5
lines changed

2 files changed

+14
-5
lines changed

include/net/netfilter/nf_conntrack_core.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,11 @@ static inline void __nf_ct_set_timeout(struct nf_conn *ct, u64 timeout)
9494
{
9595
if (timeout > INT_MAX)
9696
timeout = INT_MAX;
97-
WRITE_ONCE(ct->timeout, nfct_time_stamp + (u32)timeout);
97+
98+
if (nf_ct_is_confirmed(ct))
99+
WRITE_ONCE(ct->timeout, nfct_time_stamp + (u32)timeout);
100+
else
101+
ct->timeout = (u32)timeout;
98102
}
99103

100104
int __nf_ct_change_timeout(struct nf_conn *ct, u64 cta_timeout);

net/netfilter/nf_conntrack_netlink.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,12 @@ static int ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *ct)
176176
static int ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct,
177177
bool skip_zero)
178178
{
179-
long timeout = nf_ct_expires(ct) / HZ;
179+
long timeout;
180+
181+
if (nf_ct_is_confirmed(ct))
182+
timeout = nf_ct_expires(ct) / HZ;
183+
else
184+
timeout = ct->timeout / HZ;
180185

181186
if (skip_zero && timeout == 0)
182187
return 0;
@@ -2253,9 +2258,6 @@ ctnetlink_create_conntrack(struct net *net,
22532258
if (!cda[CTA_TIMEOUT])
22542259
goto err1;
22552260

2256-
timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
2257-
__nf_ct_set_timeout(ct, timeout);
2258-
22592261
rcu_read_lock();
22602262
if (cda[CTA_HELP]) {
22612263
char *helpname = NULL;
@@ -2324,6 +2326,9 @@ ctnetlink_create_conntrack(struct net *net,
23242326
/* we must add conntrack extensions before confirmation. */
23252327
ct->status |= IPS_CONFIRMED;
23262328

2329+
timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
2330+
__nf_ct_set_timeout(ct, timeout);
2331+
23272332
if (cda[CTA_STATUS]) {
23282333
err = ctnetlink_change_status(ct, cda);
23292334
if (err < 0)

0 commit comments

Comments
 (0)