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 <[email protected]>
---
 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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to