As of commit 58e207e4983d ("netfilter: evict stale entries when user reads /proc/net/nf_conntrack"), timeouts are evaluated by casting the difference between a timeout value and the nfct_time_stamp to a signed integer and comparing that to zero. This means that any timeout greater than or equal to (1<<31) will be considered negative, and the conntracking code will think it has immediately expired. Prior to 58e207e4983d, they would have been treated as very large positive timeouts. Using 64-bit will allow the full range of a 32-bit unsigned integer to be used as a positive value without changing any of the logic used to evaluate timeouts. The timeout value input from userspace over the netlink is still 32-bit. Fixes: 58e207e4983d ("netfilter: evict stale entries when user reads /proc/net/nf_conntrack") Signed-off-by: Jay Elliott <jelliott@xxxxxxxxxx> --- include/net/netfilter/nf_conntrack.h | 10 +++++----- net/netfilter/nf_conntrack_netlink.c | 6 ++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 792c3f6..62bfc33 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -71,8 +71,8 @@ struct nf_conn { /* Have we seen traffic both ways yet? (bitset) */ unsigned long status; - /* jiffies32 when this ct is considered dead */ - u32 timeout; + /* jiffies64 when this ct is considered dead */ + u64 timeout; possible_net_t ct_net; @@ -261,19 +261,19 @@ static inline bool nf_is_loopback_packet(const struct sk_buff *skb) return skb->dev && skb->skb_iif && skb->dev->flags & IFF_LOOPBACK; } -#define nfct_time_stamp ((u32)(jiffies)) +#define nfct_time_stamp (get_jiffies_64()) /* jiffies until ct expires, 0 if already expired */ static inline unsigned long nf_ct_expires(const struct nf_conn *ct) { - s32 timeout = ct->timeout - nfct_time_stamp; + s64 timeout = ct->timeout - nfct_time_stamp; return timeout > 0 ? timeout : 0; } static inline bool nf_ct_is_expired(const struct nf_conn *ct) { - return (__s32)(ct->timeout - nfct_time_stamp) <= 0; + return (__s64)(ct->timeout - nfct_time_stamp) <= 0; } /* use after obtaining a reference count */ diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index de4053d..82e3ef6 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1562,7 +1562,7 @@ static int ctnetlink_change_timeout(struct nf_conn *ct, { u_int32_t timeout = ntohl(nla_get_be32(cda[CTA_TIMEOUT])); - ct->timeout = nfct_time_stamp + timeout * HZ; + ct->timeout = nfct_time_stamp + (u_int64_t)timeout * HZ; if (test_bit(IPS_DYING_BIT, &ct->status)) return -ETIME; @@ -1762,6 +1762,7 @@ static int change_seq_adj(struct nf_ct_seqadj *seq, int err = -EINVAL; struct nf_conntrack_helper *helper; struct nf_conn_tstamp *tstamp; + u64 timeout_nla; ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC); if (IS_ERR(ct)) @@ -1770,7 +1771,8 @@ static int change_seq_adj(struct nf_ct_seqadj *seq, if (!cda[CTA_TIMEOUT]) goto err1; - ct->timeout = nfct_time_stamp + ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ; + timeout_nla = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])); + ct->timeout = nfct_time_stamp + timeout_nla * HZ; rcu_read_lock(); if (cda[CTA_HELP]) { -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html