瀏覽代碼

netfilter: conntrack: clamp timeouts to INT_MAX

When the conntracking code multiplies a timeout by HZ, it can overflow
from positive to negative; this causes it to instantly expire.  To
protect against this the multiplication is done in 64-bit so we can
prevent it from exceeding INT_MAX.

Signed-off-by: Jay Elliott <jelliott@arista.com>
Acked-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Jay Elliott 7 年之前
父節點
當前提交
8b1836c4b6
共有 1 個文件被更改,包括 9 次插入3 次删除
  1. 9 3
      net/netfilter/nf_conntrack_netlink.c

+ 9 - 3
net/netfilter/nf_conntrack_netlink.c

@@ -1566,9 +1566,11 @@ static int ctnetlink_change_helper(struct nf_conn *ct,
 static int ctnetlink_change_timeout(struct nf_conn *ct,
 static int ctnetlink_change_timeout(struct nf_conn *ct,
 				    const struct nlattr * const cda[])
 				    const struct nlattr * const cda[])
 {
 {
-	u_int32_t timeout = ntohl(nla_get_be32(cda[CTA_TIMEOUT]));
+	u64 timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
 
 
-	ct->timeout = nfct_time_stamp + timeout * HZ;
+	if (timeout > INT_MAX)
+		timeout = INT_MAX;
+	ct->timeout = nfct_time_stamp + (u32)timeout;
 
 
 	if (test_bit(IPS_DYING_BIT, &ct->status))
 	if (test_bit(IPS_DYING_BIT, &ct->status))
 		return -ETIME;
 		return -ETIME;
@@ -1768,6 +1770,7 @@ ctnetlink_create_conntrack(struct net *net,
 	int err = -EINVAL;
 	int err = -EINVAL;
 	struct nf_conntrack_helper *helper;
 	struct nf_conntrack_helper *helper;
 	struct nf_conn_tstamp *tstamp;
 	struct nf_conn_tstamp *tstamp;
+	u64 timeout;
 
 
 	ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC);
 	ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC);
 	if (IS_ERR(ct))
 	if (IS_ERR(ct))
@@ -1776,7 +1779,10 @@ ctnetlink_create_conntrack(struct net *net,
 	if (!cda[CTA_TIMEOUT])
 	if (!cda[CTA_TIMEOUT])
 		goto err1;
 		goto err1;
 
 
-	ct->timeout = nfct_time_stamp + ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
+	timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
+	if (timeout > INT_MAX)
+		timeout = INT_MAX;
+	ct->timeout = (u32)timeout + nfct_time_stamp;
 
 
 	rcu_read_lock();
 	rcu_read_lock();
  	if (cda[CTA_HELP]) {
  	if (cda[CTA_HELP]) {