]> git.ipfire.org Git - thirdparty/ipset.git/commitdiff
Fix possible duplicates in hashesh.
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Tue, 10 Feb 2009 14:38:32 +0000 (15:38 +0100)
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Tue, 10 Feb 2009 14:38:32 +0000 (15:38 +0100)
Bug fixed: after elements are added and deleted from a hash, an element
can successfully be added in spite it's already in the hash and thus
duplicates can occur. Bug spotted by Shih-Yi Chen.

kernel/ChangeLog
kernel/ip_set_iphash.c
kernel/ip_set_ipporthash.c
kernel/ip_set_ipportiphash.c
kernel/ip_set_ipportnethash.c
kernel/ip_set_nethash.c

index 62ecc9a3f33bf26b04c16a049cae2e97c94fc1ef..10c2f5302f7800624f04f732f9047ada669a95a6 100644 (file)
@@ -1,4 +1,7 @@
 2.4.8
+  - Bug fixed: after elements are added and deleted from a hash, an element
+    can successfully be added in spite it's already in the hash and thus
+    duplicates can occur (Shih-Yi Chen). 
   - Compatibility with old gcc without 'bool' added.
 
 2.4.7
index 976fcfc3e8f347acdcbc0a7b007474f7081979da..b1bccc14e11672479e9fb359cb2cfb9e44fe6326 100644 (file)
@@ -42,8 +42,7 @@ iphash_id(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
                elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
                if (*elem == *hash_ip)
                        return id;
-               /* No shortcut at testing - there can be deleted
-                * entries. */
+               /* No shortcut - there can be deleted entries. */
        }
        return UINT_MAX;
 }
@@ -64,18 +63,21 @@ __iphash_add(struct ip_set_iphash *map, ip_set_ip_t *ip)
 {
        __u32 probe;
        u_int16_t i;
-       ip_set_ip_t *elem;
+       ip_set_ip_t *elem, *slot = NULL;
        
        for (i = 0; i < map->probes; i++) {
                probe = jhash_ip(map, i, *ip) % map->hashsize;
                elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
                if (*elem == *ip)
                        return -EEXIST;
-               if (!*elem) {
-                       *elem = *ip;
-                       map->elements++;
-                       return 0;
-               }
+               if (!(slot || *elem))
+                       slot = elem;
+               /* There can be deleted entries, must check all slots */
+       }
+       if (slot) {
+               *slot = *ip;
+               map->elements++;
+               return 0;
        }
        /* Trigger rehashing */
        return -EAGAIN;
index 2e2bfa58f21cd3166cfbbba5cdc926d9bc2310a2..23528582242316394f45eb7341ea91c6fd17e505 100644 (file)
@@ -49,8 +49,7 @@ ipporthash_id(struct ip_set *set, ip_set_ip_t *hash_ip,
                elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
                if (*elem == *hash_ip)
                        return id;
-               /* No shortcut at testing - there can be deleted
-                * entries. */
+               /* No shortcut - there can be deleted entries. */
        }
        return UINT_MAX;
 }
@@ -86,18 +85,21 @@ __ipporthash_add(struct ip_set_ipporthash *map, ip_set_ip_t *ip)
 {
        __u32 probe;
        u_int16_t i;
-       ip_set_ip_t *elem;
+       ip_set_ip_t *elem, *slot = NULL;
 
        for (i = 0; i < map->probes; i++) {
                probe = jhash_ip(map, i, *ip) % map->hashsize;
                elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
                if (*elem == *ip)
                        return -EEXIST;
-               if (!*elem) {
-                       *elem = *ip;
-                       map->elements++;
-                       return 0;
-               }
+               if (!(slot || *elem))
+                       slot = elem;
+               /* There can be deleted entries, must check all slots */
+       }
+       if (slot) {
+               *slot = *ip;
+               map->elements++;
+               return 0;
        }
        /* Trigger rehashing */
        return -EAGAIN;
index 21305089228256f55cfc6af025fc840b8db3d2dd..e0725d9706c27a928393291e1886832d8c2a559a 100644 (file)
@@ -51,8 +51,7 @@ ipportiphash_id(struct ip_set *set, ip_set_ip_t *hash_ip,
                elem = HARRAY_ELEM(map->members, struct ipportip *, id);
                if (elem->ip == *hash_ip && elem->ip1 == ip1)
                        return id;
-               /* No shortcut at testing - there can be deleted
-                * entries. */
+               /* No shortcut - there can be deleted entries. */
        }
        return UINT_MAX;
 }
@@ -90,19 +89,22 @@ __ipportip_add(struct ip_set_ipportiphash *map,
 {
        __u32 probe;
        u_int16_t i;
-       struct ipportip *elem;
+       struct ipportip *elem, *slot = NULL;
 
        for (i = 0; i < map->probes; i++) {
                probe = jhash_ip2(map, i, hash_ip, ip1) % map->hashsize;
                elem = HARRAY_ELEM(map->members, struct ipportip *, probe);
                if (elem->ip == hash_ip && elem->ip1 == ip1)
                        return -EEXIST;
-               if (!(elem->ip || elem->ip1)) {
-                       elem->ip = hash_ip;
-                       elem->ip1 = ip1;
-                       map->elements++;
-                       return 0;
-               }
+               if (!(slot || elem->ip || elem->ip1))
+                       slot = elem;
+               /* There can be deleted entries, must check all slots */
+       }
+       if (slot) {
+               slot->ip = hash_ip;
+               slot->ip1 = ip1;
+               map->elements++;
+               return 0;
        }
        /* Trigger rehashing */
        return -EAGAIN;
index 87385a38b6a5bdee3e506013d96e269b630d613b..267370a267ddcc3420ceff161667a6f234f4007a 100644 (file)
@@ -53,8 +53,7 @@ ipportnethash_id_cidr(struct ip_set *set, ip_set_ip_t *hash_ip,
                elem = HARRAY_ELEM(map->members, struct ipportip *, id);
                if (elem->ip == *hash_ip && elem->ip1 == ip1)
                        return id;
-               /* No shortcut at testing - there can be deleted
-                * entries. */
+               /* No shortcut - there can be deleted entries. */
        }
        return UINT_MAX;
 }
@@ -137,19 +136,22 @@ __ipportnet_add(struct ip_set_ipportnethash *map,
 {
        __u32 probe;
        u_int16_t i;
-       struct ipportip *elem;
+       struct ipportip *elem, *slot = NULL;
 
        for (i = 0; i < map->probes; i++) {
                probe = jhash_ip2(map, i, hash_ip, ip1) % map->hashsize;
                elem = HARRAY_ELEM(map->members, struct ipportip *, probe);
                if (elem->ip == hash_ip && elem->ip1 == ip1)
                        return -EEXIST;
-               if (!(elem->ip || elem->ip1)) {
-                       elem->ip = hash_ip;
-                       elem->ip1 = ip1;
-                       map->elements++;
-                       return 0;
-               }
+               if (!(slot || elem->ip || elem->ip1))
+                       slot = elem;
+               /* There can be deleted entries, must check all slots */
+       }
+       if (slot) {
+               slot->ip = hash_ip;
+               slot->ip1 = ip1;
+               map->elements++;
+               return 0;
        }
        /* Trigger rehashing */
        return -EAGAIN;
index d5b7a763f9f2a4dcd4717512bc49e3e9cc813391..268fe6a74595c31652e262392d85728816b6b5d4 100644 (file)
@@ -44,6 +44,7 @@ nethash_id_cidr(const struct ip_set_nethash *map,
                elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
                if (*elem == *hash_ip)
                        return id;
+               /* No shortcut - there can be deleted entries. */
        }
        return UINT_MAX;
 }
@@ -99,17 +100,21 @@ __nethash_add(struct ip_set_nethash *map, ip_set_ip_t *ip)
 {
        __u32 probe;
        u_int16_t i;
-       ip_set_ip_t *elem;
+       ip_set_ip_t *elem, *slot = NULL;
        
        for (i = 0; i < map->probes; i++) {
                probe = jhash_ip(map, i, *ip) % map->hashsize;
                elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
                if (*elem == *ip)
                        return -EEXIST;
-               if (!*elem) {
-                       *elem = *ip;
-                       return 0;
-               }
+               if (!(slot || *elem))
+                       slot = elem;
+               /* There can be deleted entries, must check all slots */
+       }
+       if (slot) {
+               *slot = *ip;
+               map->elements++;
+               return 0;
        }
        /* Trigger rehashing */
        return -EAGAIN;