mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-15 01:24:33 +00:00
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: a4b4766c3ceb ("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>
This commit is contained in:
parent
2cdaa3eefe
commit
73db1b8f2b
@ -89,7 +89,11 @@ static inline void __nf_ct_set_timeout(struct nf_conn *ct, u64 timeout)
|
||||
{
|
||||
if (timeout > INT_MAX)
|
||||
timeout = INT_MAX;
|
||||
WRITE_ONCE(ct->timeout, nfct_time_stamp + (u32)timeout);
|
||||
|
||||
if (nf_ct_is_confirmed(ct))
|
||||
WRITE_ONCE(ct->timeout, nfct_time_stamp + (u32)timeout);
|
||||
else
|
||||
ct->timeout = (u32)timeout;
|
||||
}
|
||||
|
||||
int __nf_ct_change_timeout(struct nf_conn *ct, u64 cta_timeout);
|
||||
|
@ -176,7 +176,12 @@ nla_put_failure:
|
||||
static int ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct,
|
||||
bool skip_zero)
|
||||
{
|
||||
long timeout = nf_ct_expires(ct) / HZ;
|
||||
long timeout;
|
||||
|
||||
if (nf_ct_is_confirmed(ct))
|
||||
timeout = nf_ct_expires(ct) / HZ;
|
||||
else
|
||||
timeout = ct->timeout / HZ;
|
||||
|
||||
if (skip_zero && timeout == 0)
|
||||
return 0;
|
||||
@ -2253,9 +2258,6 @@ ctnetlink_create_conntrack(struct net *net,
|
||||
if (!cda[CTA_TIMEOUT])
|
||||
goto err1;
|
||||
|
||||
timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
|
||||
__nf_ct_set_timeout(ct, timeout);
|
||||
|
||||
rcu_read_lock();
|
||||
if (cda[CTA_HELP]) {
|
||||
char *helpname = NULL;
|
||||
@ -2319,6 +2321,9 @@ ctnetlink_create_conntrack(struct net *net,
|
||||
/* we must add conntrack extensions before confirmation. */
|
||||
ct->status |= IPS_CONFIRMED;
|
||||
|
||||
timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
|
||||
__nf_ct_set_timeout(ct, timeout);
|
||||
|
||||
if (cda[CTA_STATUS]) {
|
||||
err = ctnetlink_change_status(ct, cda);
|
||||
if (err < 0)
|
||||
|
Loading…
x
Reference in New Issue
Block a user