Skip to content

Commit 73db1b8

Browse files
Tzung-Bi Shihummakynes
authored andcommitted
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 <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 2cdaa3e commit 73db1b8

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
@@ -89,7 +89,11 @@ static inline void __nf_ct_set_timeout(struct nf_conn *ct, u64 timeout)
8989
{
9090
if (timeout > INT_MAX)
9191
timeout = INT_MAX;
92-
WRITE_ONCE(ct->timeout, nfct_time_stamp + (u32)timeout);
92+
93+
if (nf_ct_is_confirmed(ct))
94+
WRITE_ONCE(ct->timeout, nfct_time_stamp + (u32)timeout);
95+
else
96+
ct->timeout = (u32)timeout;
9397
}
9498

9599
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;
@@ -2319,6 +2321,9 @@ ctnetlink_create_conntrack(struct net *net,
23192321
/* we must add conntrack extensions before confirmation. */
23202322
ct->status |= IPS_CONFIRMED;
23212323

2324+
timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
2325+
__nf_ct_set_timeout(ct, timeout);
2326+
23222327
if (cda[CTA_STATUS]) {
23232328
err = ctnetlink_change_status(ct, cda);
23242329
if (err < 0)

0 commit comments

Comments
 (0)