]> git.ipfire.org Git - thirdparty/ipset.git/commitdiff
Limit the maximal range of consecutive elements to add/delete fix
authorJozsef Kadlecsik <kadlec@netfilter.org>
Fri, 16 Jul 2021 12:36:45 +0000 (14:36 +0200)
committerJozsef Kadlecsik <kadlec@netfilter.org>
Fri, 16 Jul 2021 12:36:45 +0000 (14:36 +0200)
Avoid possible number overflows when calculating the number of
consecutive elements. Also, compute properly the consecutive
elements in the case of hash:net* types.

Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
kernel/net/netfilter/ipset/ip_set_hash_ip.c
kernel/net/netfilter/ipset/ip_set_hash_ipmark.c
kernel/net/netfilter/ipset/ip_set_hash_ipport.c
kernel/net/netfilter/ipset/ip_set_hash_ipportip.c
kernel/net/netfilter/ipset/ip_set_hash_ipportnet.c
kernel/net/netfilter/ipset/ip_set_hash_net.c
kernel/net/netfilter/ipset/ip_set_hash_netiface.c
kernel/net/netfilter/ipset/ip_set_hash_netnet.c
kernel/net/netfilter/ipset/ip_set_hash_netport.c
kernel/net/netfilter/ipset/ip_set_hash_netportnet.c

index a3559d7d3a4fe686cc5350012b2e1be2c5b020e4..789b28a4ff9bcae86a56c23697af4852453eef25 100644 (file)
@@ -133,8 +133,11 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
                        return ret;
-               if (ip > ip_to)
+               if (ip > ip_to) {
+                       if (ip_to == 0)
+                               return -IPSET_ERR_HASH_ELEM;
                        swap(ip, ip_to);
+               }
        } else if (tb[IPSET_ATTR_CIDR]) {
                u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 
@@ -145,7 +148,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
 
        hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
 
-       if ((ip_to - ip + 1)/hosts > IPSET_MAX_RANGE)
+       if (((u64)ip_to - ip + 1)/hosts > IPSET_MAX_RANGE)
                return -ERANGE;
 
        if (retried) {
index 698da284e9da9d7d83d2e5c4f3055145b2e02aec..7e7eedef45621251ef569344f189ecac8bea5883 100644 (file)
@@ -123,6 +123,8 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
 
        e.mark = ntohl(nla_get_be32(tb[IPSET_ATTR_MARK]));
        e.mark &= h->markmask;
+       if (e.mark == 0 && e.ip == 0)
+               return -IPSET_ERR_HASH_ELEM;
 
        if (adt == IPSET_TEST ||
            !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR])) {
@@ -135,8 +137,11 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
                        return ret;
-               if (ip > ip_to)
+               if (ip > ip_to) {
+                       if (e.mark == 0 && ip_to == 0)
+                               return -IPSET_ERR_HASH_ELEM;
                        swap(ip, ip_to);
+               }
        } else if (tb[IPSET_ATTR_CIDR]) {
                u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 
@@ -145,7 +150,7 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
                ip_set_mask_from_to(ip, ip_to, cidr);
        }
 
-       if ((ip_to - ip + 1) > IPSET_MAX_RANGE)
+       if (((u64)ip_to - ip + 1) > IPSET_MAX_RANGE)
                return -ERANGE;
 
        if (retried)
index 36ffc3b8d84f1c4abd1ad5f33fed89c314d68605..09837c30412a1b7ed503fee8df6f95731740cfa6 100644 (file)
@@ -174,7 +174,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
                        swap(port, port_to);
        }
 
-       if ((ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE)
+       if (((u64)ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE)
                return -ERANGE;
 
        if (retried)
index 0728b38d6a8f3d159a12961c3226f6de32635687..0be8f5337042d201c41308f0a79136fc0d49bd18 100644 (file)
@@ -181,7 +181,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
                        swap(port, port_to);
        }
 
-       if ((ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE)
+       if (((u64)ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE)
                return -ERANGE;
 
        if (retried)
index 94dde4714bbc89a114c8dcf4a5d55ffbee0e9be9..273e0c12b174ceddda703de4790287b822e2fbc5 100644 (file)
@@ -247,7 +247,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
                ip_set_mask_from_to(ip, ip_to, cidr);
        }
 
-       if ((ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE)
+       if (((u64)ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE)
                return -ERANGE;
 
        port_to = port = ntohs(e.port);
index c2819c6f657620c72b2b4b82cf4efdaca0b441d2..5dfd0eddab714e4f98172cdc74fd68d70fe46bd7 100644 (file)
@@ -141,7 +141,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_net4_elem e = { .cidr = HOST_MASK };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
-       u32 ip = 0, ip_to = 0;
+       u32 ip = 0, ip_to = 0, ipn, n = 0;
        int ret;
 
        if (tb[IPSET_ATTR_LINENO])
@@ -189,8 +189,15 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (ip + UINT_MAX == ip_to)
                        return -IPSET_ERR_HASH_RANGE;
        }
-       if ((ip_to - ip + 1)/(1<<(32 - e.cidr)) > IPSET_MAX_RANGE)
+       ipn = ip;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr);
+               n++;
+       } while (ipn++ < ip_to);
+
+       if (n > IPSET_MAX_RANGE)
                return -ERANGE;
+
        if (retried)
                ip = ntohl(h->next.ip);
        do {
index 4bebf2adbcdf7c509e08bd4ea8bc9c35d4da61ad..b25400a2c1785a2159216193db3b2425c7047de3 100644 (file)
@@ -203,7 +203,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
-       u32 ip = 0, ip_to = 0;
+       u32 ip = 0, ip_to = 0, ipn, n = 0;
        int ret;
 
        if (tb[IPSET_ATTR_LINENO])
@@ -257,7 +257,13 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
        } else {
                ip_set_mask_from_to(ip, ip_to, e.cidr);
        }
-       if ((ip_to - ip + 1)/(1<<(32 - e.cidr)) > IPSET_MAX_RANGE)
+       ipn = ip;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr);
+               n++;
+       } while (ipn++ < ip_to);
+
+       if (n > IPSET_MAX_RANGE)
                return -ERANGE;
 
        if (retried)
index 4ca005dd1251f7806a56c511e8422439f6aa271b..3d09eefe998a7f82f9549d141daeb13e311f3486 100644 (file)
@@ -168,7 +168,8 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
        struct hash_netnet4_elem e = { };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
        u32 ip = 0, ip_to = 0;
-       u32 ip2 = 0, ip2_from = 0, ip2_to = 0;
+       u32 ip2 = 0, ip2_from = 0, ip2_to = 0, ipn;
+       u64 n = 0, m = 0;
        int ret;
 
        if (tb[IPSET_ATTR_LINENO])
@@ -244,8 +245,18 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
        } else {
                ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]);
        }
-       if ((ip_to - ip + 1)/(1<<(32 - e.cidr[0]))*
-           (ip2_to - ip2_from + 1)/(1<<(32 - e.cidr[1])) > IPSET_MAX_RANGE)
+       ipn = ip;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr[0]);
+               n++;
+       } while (ipn++ < ip_to);
+       ipn = ip2_from;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip2_to, &e.cidr[1]);
+               m++;
+       } while (ipn++ < ip2_to);
+
+       if (n*m > IPSET_MAX_RANGE)
                return -ERANGE;
 
        if (retried) {
index 2b0a1ebcbf01ed1ee67ec17116c7b3fceccdcb7f..cf703249d83c75e8254e7b4bbe8bde906968f619 100644 (file)
@@ -159,7 +159,8 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_netport4_elem e = { .cidr = HOST_MASK - 1 };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
-       u32 port, port_to, p = 0, ip = 0, ip_to = 0;
+       u32 port, port_to, p = 0, ip = 0, ip_to = 0, ipn;
+       u64 n = 0;
        bool with_ports = false;
        u8 cidr;
        int ret;
@@ -236,6 +237,14 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
        } else {
                ip_set_mask_from_to(ip, ip_to, e.cidr + 1);
        }
+       ipn = ip;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip_to, &cidr);
+               n++;
+       } while (ipn++ < ip_to);
+
+       if (n*(port_to - port + 1) > IPSET_MAX_RANGE)
+               return -ERANGE;
 
        if (retried) {
                ip = ntohl(h->next.ip);
index 0bf866d4d27b60480e83c359be5c6515488d10cb..57be10286b6a3f83b9044785f978c123d18d9216 100644 (file)
@@ -183,7 +183,8 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
        struct hash_netportnet4_elem e = { };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
        u32 ip = 0, ip_to = 0, p = 0, port, port_to;
-       u32 ip2_from = 0, ip2_to = 0, ip2;
+       u32 ip2_from = 0, ip2_to = 0, ip2, ipn;
+       u64 n = 0, m = 0;
        bool with_ports = false;
        int ret;
 
@@ -285,9 +286,18 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
        } else {
                ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]);
        }
-       if ((ip_to - ip + 1)/(1<<(32 - e.cidr[0]))*
-           (ip2_to - ip2_from + 1)/(1<<(32 - e.cidr[1])) *
-           (port_to - port + 1) > IPSET_MAX_RANGE)
+       ipn = ip;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr[0]);
+               n++;
+       } while (ipn++ < ip_to);
+       ipn = ip2_from;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip2_to, &e.cidr[1]);
+               m++;
+       } while (ipn++ < ip2_to);
+
+       if (n*m*(port_to - port + 1) > IPSET_MAX_RANGE)
                return -ERANGE;
 
        if (retried) {