]> git.ipfire.org Git - thirdparty/ipset.git/commitdiff
Limit the maximal range of consecutive elements to add/delete
authorJozsef Kadlecsik <kadlec@netfilter.org>
Wed, 14 Jul 2021 10:37:07 +0000 (12:37 +0200)
committerJozsef Kadlecsik <kadlec@netfilter.org>
Wed, 14 Jul 2021 10:40:49 +0000 (12:40 +0200)
The range size of consecutive elements were not limited. Thus one
could define a huge range which may result soft lockup errors due
to the long execution time. Now the range size is limited to 2^20
entries. Reported by Brad Spengler.

Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
kernel/include/linux/netfilter/ipset/ip_set.h
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_netportnet.c
lib/errcode.c

index 554f90fab7e53cc0bd34df9df679faef585cd624..3a6963cd5261ca4d1c9758c7cfb9e3684dfcae3d 100644 (file)
@@ -199,6 +199,9 @@ struct ip_set_region {
        u32 elements;           /* Number of elements vs timeout */
 };
 
+/* Max range where every element is added/deleted in one step */
+#define IPSET_MAX_RANGE                (1<<20)
+
 /* The max revision number supported by any set type + 1 */
 #define IPSET_REVISION_MAX     9
 
index 94e17a56a9e894781a437247341d88dad5b49395..a3559d7d3a4fe686cc5350012b2e1be2c5b020e4 100644 (file)
@@ -145,6 +145,9 @@ 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)
+               return -ERANGE;
+
        if (retried) {
                ip = ntohl(h->next.ip);
                e.ip = htonl(ip);
index 1757bf84f155a95b7bca8679304712b0c2665ac0..698da284e9da9d7d83d2e5c4f3055145b2e02aec 100644 (file)
@@ -145,6 +145,9 @@ 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)
+               return -ERANGE;
+
        if (retried)
                ip = ntohl(h->next.ip);
        for (; ip <= ip_to; ip++) {
index b22f2809425a9aff19618a20168eafbf95ceb009..36ffc3b8d84f1c4abd1ad5f33fed89c314d68605 100644 (file)
@@ -174,6 +174,9 @@ 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)
+               return -ERANGE;
+
        if (retried)
                ip = ntohl(h->next.ip);
        for (; ip <= ip_to; ip++) {
index d3701519b7ea0c8aeda49302f6e530c8ea7637ab..0728b38d6a8f3d159a12961c3226f6de32635687 100644 (file)
@@ -181,6 +181,9 @@ 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)
+               return -ERANGE;
+
        if (retried)
                ip = ntohl(h->next.ip);
        for (; ip <= ip_to; ip++) {
index 64f82f296a0b565b89e48a84b9b5b3b0476dd940..94dde4714bbc89a114c8dcf4a5d55ffbee0e9be9 100644 (file)
@@ -247,6 +247,9 @@ 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)
+               return -ERANGE;
+
        port_to = port = ntohs(e.port);
        if (tb[IPSET_ATTR_PORT_TO]) {
                port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
index 54318dd96913d7b1b18377de80ceaecb9a602d7b..c2819c6f657620c72b2b4b82cf4efdaca0b441d2 100644 (file)
@@ -189,6 +189,8 @@ 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)
+               return -ERANGE;
        if (retried)
                ip = ntohl(h->next.ip);
        do {
index 58332eadc9d82e3a55d6db278780b9c5413a54fd..4bebf2adbcdf7c509e08bd4ea8bc9c35d4da61ad 100644 (file)
@@ -257,6 +257,8 @@ 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)
+               return -ERANGE;
 
        if (retried)
                ip = ntohl(h->next.ip);
index 6532f0505e66f8cab2f0f43f38a390354334899d..4ca005dd1251f7806a56c511e8422439f6aa271b 100644 (file)
@@ -244,6 +244,9 @@ 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)
+               return -ERANGE;
 
        if (retried) {
                ip = ntohl(h->next.ip[0]);
index 070736d433bd846c6146446c88020cd227e35c08..0bf866d4d27b60480e83c359be5c6515488d10cb 100644 (file)
@@ -285,6 +285,10 @@ 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)
+               return -ERANGE;
 
        if (retried) {
                ip = ntohl(h->next.ip[0]);
index b38f95e36394c102127f3b4d0652ee9e28744426..76bab742725d8f4f11656ab0ef23e6388bf10f75 100644 (file)
@@ -25,6 +25,8 @@ static const struct ipset_errcode_table core_errcode_table[] = {
          "The set with the given name does not exist" },
        { EMSGSIZE, 0,
          "Kernel error received: message could not be created" },
+       { ERANGE, 0,
+         "The specified range is too large, split it up into smaller ranges" },
        { IPSET_ERR_PROTOCOL,  0,
          "Kernel error received: ipset protocol error" },